Craft Customized Transactions

Build all possible transaction with our cardano-cli like APIs.

For a complete walkthrough of all available cardano-cli like APIs, please refer to the MeshTxBuilder - All API Endpoints page.

Getting started

To start building an customized transaction, you need to first initialize MeshTxBuilder with MaestroProvider:

const maestro = new MaestroProvider({
  network: 'Preprod',
  apiKey: MAESTRO_API_KEY,
});
const mesh = new MeshTxBuilder({
  fetcher: maestro,
  submitter: maestro,
  evaluator: maestro,
});

There are 4 optional fields to pass in to initialized the lower level APIs instance:

1. fetcher: When you build the transaction without sufficient fields as required by the serialization library, we would index the blockchain to fill the information for you. Affected APIs aretxIn,txInCollateral,spendingTxInReference.

2. submitter: It is used if you would like to use the fetchersubmitTx API directly from the instance.

3. evaluator: It would perform redeemer execution unit optimization.

4. isHydra: Use another set of default protocol parameters for building transactions

Below provides some examples of transaction building. Complete working examples can be found in mesh-lower-level-api-demo

Build a simple transaction to send values

The following shows a simple example of building a transaction to send values to a recipient:

await mesh
  .txIn(txInHash, txInId)
  .txOut(this.constants.walletAddress, [{ unit: "lovelace", quantity: amount.toString() }])
  .changeAddress(this.constants.walletAddress)
  .signingKey(this.constants.skey)
  .complete();

const signedTx = mesh.completeSigning()

Full Code Snippet in Github

Build a transaction to send fund to smart contract

The following shows a simple example of building a transaction to lock fund in a smart contact. It is equivalent to the following CLI command in PPBL Module 102.4.

await mesh
  .txIn(txInHash, txInId)
  .txOut(validatorAddress, [])
  .txOutInlineDatumValue(1618)
  .changeAddress(this.constants.walletAddress)
  .signingKey(this.constants.skey)
  .complete();

const signedTx = mesh.completeSigning()

Full Code Snippet in Github

Build a transaction to unlock fund from smart contract

The following shows a simple example of building a transaction to unlock fund from a smart contract. It is equivalent to the following CLI command in PPBL Module 102.5

await mesh
  .txIn(txInHash, txInId)
  .spendingPlutusScriptV2()
  .txIn(validatorInput.txHash, validatorInput.outputIndex)
  .txInInlineDatumPresent()
  .txInRedeemerValue(mConStr0([]))
  .txInScript(getScriptCbor("Spending"))
  .txOut(this.constants.walletAddress, [])
  .changeAddress(this.constants.walletAddress)
  .txInCollateral(this.constants.collateralUTxO.txHash, this.constants.collateralUTxO.outputIndex)
  .signingKey(this.constants.skey)
  .complete();

const signedTx = mesh.completeSigning()

Full Code Snippet in Github

Build a transaction to mint tokens

The following shows a simple example of building a transaction to mint a token with smart contract:

await mesh
  .txIn(txInHash, txInId)
  .mintPlutusScriptV2()
  .mint("1", policyId, tokenName)
  .mintingScript(mintingScript)
  .mintRedeemerValue(mConStr0([]))
  .txOut(this.constants.walletAddress, [{ unit: policyId + tokenName, quantity: "1" }])
  .changeAddress(this.constants.walletAddress)
  .txInCollateral(this.constants.collateralUTxO.txHash, this.constants.collateralUTxO.outputIndex)
  .signingKey(this.constants.skey)
  .complete();

const signedTx = mesh.completeSigning()

Full Code Snippet in Github

Build a transaction to (register stake certificate and) delegate stake to a pool

The following shows a simple example of building a transaction to (register stake certificate and) delegate stake to a pool for the first time.

const usedAddress = await wallet.getUnusedAddresses();
const { stakeCredential } = serializeBech32Address(usedAddress[0]);
await mesh
  .txIn(txInHash, txInId)
  .registerStakeCertificate(stakeCredential) // Skip this line if you are not staking for the first time
  .delegateStakeCertificate(
    stakeCredential,
    'poolxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
  )
  .changeAddress(changeAddress)
  .complete();

const signedTx = mesh.completeSigning()

Build a complex transaction

The following shows a simple example of building a transaction of both unlocking from script and minting tokens:

await mesh
  .txIn(txInHash, txInId)
  .spendingPlutusScriptV2()
  .txIn(validatorInput.txHash, validatorInput.outputIndex)
  .txInInlineDatumPresent()
  .txInRedeemerValue(mConStr0([]))
  .txInScript(getScriptCbor("Spending"))
  .mintPlutusScriptV2()
  .mint("1", policyId, tokenName)
  .mintingScript(mintingScript)
  .mintRedeemerValue(mConStr0([]))
  .txOut(this.constants.walletAddress, [{ unit: policyId + tokenName, quantity: "1" }])
  .changeAddress(this.constants.walletAddress)
  .txInCollateral(this.constants.collateralUTxO.txHash, this.constants.collateralUTxO.outputIndex)
  .signingKey(this.constants.skey)
  .complete();

const signedTx = mesh.completeSigning()

Full Code Snippet in Github

Build a transaction without any dependency

The following shows a example of building transaction without any dependency:

const signedTx = mesh
  .txIn('572bca237e440b596f4f71374b4b610a995095c6b62a6dcc8549089b93ba0e33', 0, [{ unit: 'lovelace', quantity: '2000000' }], myAddress)
  .txIn('572bca237e440b596f4f71374b4b610a995095c6b62a6dcc8549089b93ba0e33', 3, [{ unit: 'lovelace', quantity: '2000000' }], myAddress)
  .txOut(recipient, [
    { unit: 'lovelace', quantity: '2000000' },
    { unit: policyIdHex + tokenNameHex, quantity: '1' },
  ])
  .changeAddress(walletAddress)
  .txInCollateral('3fbdf2b0b4213855dd9b87f7c94a50cf352ba6edfdded85ecb22cf9ceb75f814', 6, [{ unit: 'lovelace', quantity: '5000000' }], myAddress)
  .signingKey(privateKey)
  .completeSync();
  .completeSigning();

Build a transaction with an object

One alternative to use the lower level APIs is to build the transaction with an object in type MeshTxBuilderBody.

The following shows a example of building the same transaction in the Build a transaction without any dependency section with an object:

const meshTxBody: MeshTxBuilderBody = {
  inputs: [
    {
      type: "PubKey",
      txIn: {
        txHash: txHash1,
        txIndex: txIndex1,
      },
    },
    {
      type: "PubKey",
      txIn: {
        txHash: txHash2,
        txIndex: txIndex2,
      },
    },
  ],
  outputs: [
    {
      address: walletAddress,
      amount: [{ unit: "lovelace", quantity: "1000000" }],
    },
  ],
  collaterals: [
    {
      type: "PubKey",
      txIn: {
        txHash: "ee8369ffadd6ed6efdd939639b393f08974fca388b2c43d03a96a1fa4840c5f8",
        txIndex: 0,
      },
    },
  ],
  requiredSignatures: [],
  referenceInputs: [],
  mints: [],
  changeAddress: walletAddress,
  metadata: [],
  validityRange: {},
  signingKey: [skey],
};

await mesh.complete(meshTxBody);
const signedTx = mesh.completeSigning();

Full Code Snippet in Github