Skip to content

TxPlan Overview

Preview feature: available in the latest preview. APIs may change before the stable release.

TxPlan provides a configuration-driven approach to defining Cardano transactions. Instead of writing Java code for every transaction, you can define transactions in YAML with variable substitution, context properties, and signer registry references — then execute them through the standard QuickTxBuilder pipeline.

  • Configuration-driven — define transactions in YAML files, separate from application code
  • Variable resolution — use ${variable} placeholders for dynamic values
  • Context properties — centralize fee payer, collateral, validity, and signer configuration
  • Version control friendly — human-readable transaction definitions
  • No extra dependency — TxPlan is part of the quicktx module

TxPlan is included in the quicktx module. If you already use cardano-client-lib or cardano-client-quicktx, no additional dependency is needed.

dependencies {
implementation 'com.bloxbean.cardano:cardano-client-lib:<version>'
}
Tx tx = new Tx()
.from("addr_test1...")
.payToAddress("addr_test1_receiver", Amount.ada(5));
TxPlan plan = TxPlan.from(tx)
.feePayer("addr_test1_fee_payer")
.validTo(2000L);
// Serialize to YAML
String yaml = plan.toYaml();
TxPlan plan = TxPlan.from(yamlString);
// Access transactions
List<AbstractTx<?>> transactions = plan.getTxs();
version: 1.0
variables:
sender: addr_test1_sender_address
receiver: addr_test1_receiver_address
amount: 5000000
context:
fee_payer: ${sender}
valid_to_slot: 5000
transaction:
- tx:
from: ${sender}
intents:
- type: payment
address: ${receiver}
amounts:
- unit: lovelace
quantity: ${amount}

The variables section defines key-value pairs that can be referenced anywhere in the YAML using ${variable_name} syntax. Variables are resolved before deserialization, on the raw text. An undefined ${x}, even in a comment, fails with Variable not found: x, and a value containing YAML syntax such as : or # can change the document’s structure.

variables:
treasury: addr_test1_treasury
alice: addr_test1_alice
payment_amount: 10000000
pool_id: pool1abc123

The context section configures transaction-level settings that apply to the QuickTxBuilder.TxContext.

PropertyDescription
fee_payerAddress that pays transaction fees
fee_payer_refRegistry reference for fee payer (e.g., account://ops)
collateral_payerAddress that provides collateral for script transactions
collateral_payer_refRegistry reference for collateral payer
signersArray of {ref, scope} entries for additional signers
required_signersList of required signer credential hashes (hex)
valid_from_slotTransaction validity start slot
valid_to_slotTransaction validity end slot
additional_signers_countExtra signers to count in fee estimation when they sign later, such as a multisig. Integer from 0 to 1000. Available from 0.8.0-pre7
deposit_payerAddress that pays deposit (e.g., for stake registration)
deposit_modeDeposit handling mode (AUTO, CHANGE_OUTPUT, ANY_OUTPUT, NEW_UTXO_SELECTION)

Each entry in the transaction list contains a tx block with:

  • from / from_ref — sender address or registry reference
  • change_address — optional explicit change address
  • change_datum / change_datum_hash — datum for change output (script transactions)
  • inputs — inputs to consume or reference: script_collect_from, collect_from, reference_input
  • intents — what the transaction does (see below)
  • scripts — script attachments: validator, native_script

Intent types:

AreaTypes
Corepayment, donation, minting, script_minting, metadata
Stakingstake_registration, stake_deregistration, stake_delegation, stake_withdrawal
Poolspool_registration, pool_update, pool_retirement
Governancedrep_registration, drep_deregistration, drep_update, governance_proposal, voting, voting_delegation

Unknown keys under the document root, tx or context fail, but unknown fields inside an intent are dropped silently, so check your spelling there.

TxPlan.from and toYaml handle core intents only. For extension intents, such as programmable tokens, use TxPlanCodec:

TxPlanCodec codec = TxPlanCodec.builder().withExtension(extension).build();
String yaml = codec.toYaml(plan);
TxPlan restored = codec.fromYaml(yaml, runtimeVariables);
new QuickTxBuilder(backend).withExtension(extension).compose(restored);
QuickTxBuilder builder = new QuickTxBuilder(backendService);
TxPlan plan = TxPlan.from(yamlString);
TxResult result = builder.compose(plan)
.withSigner(SignerProviders.signerFrom(account))
.completeAndWait();

Important: Variables are resolved during TxPlan.from() — calling addVariable() after parsing only updates the variable map for toYaml() serialization. It does not re-resolve already-parsed transaction fields.

To use dynamic variables, set them in the YAML string before calling from():

String yaml = baseYaml
.replace("${amount}", "10000000")
.replace("${receiver}", dynamicReceiverAddress);
TxPlan plan = TxPlan.from(yaml);

Alternatively, define variables in the YAML variables section with their final values before parsing.

String yamlPlan = """
version: 1.0
variables:
sender: addr_test1_sender
receiver: addr_test1_receiver
context:
fee_payer: ${sender}
valid_to_slot: 5000
transaction:
- tx:
from: ${sender}
intents:
- type: payment
address: ${receiver}
amounts:
- unit: lovelace
quantity: '5000000'
""";
QuickTxBuilder builder = new QuickTxBuilder(backendService);
TxPlan plan = TxPlan.from(yamlPlan);
TxResult result = builder.compose(plan)
.withSigner(SignerProviders.signerFrom(account))
.completeAndWait();