Skip to Content
Scalus Club is now open! Join us to get an early access to new features 🎉

Payment Methods: Send ADA and Native Tokens

TxBuilder provides several methods for creating transaction outputs with different levels of control. This guide covers the various ways to send ADA and native tokens.

How to Make Simple ADA Payment

The most basic payment sends ADA to an address without any datum:

TxBuilder(env) .spend(utxo) .payTo(recipientAddress, Value.ada(10)) // Send 10 ADA .changeTo(changeAddress) .build()

Sending Native Tokens on Cardano

Send native tokens along with ADA:

import scalus.cardano.ledger.{AssetName, PolicyId, MultiAsset, Value} import scalus.builtin.ByteString.hex import scala.collection.immutable.SortedMap val policyId = PolicyId(hex"...") val assetName = AssetName(hex"...") val tokenValue = Value.asset( policyId, assetName, amount = 100L, // 100 tokens ada = Coin.ada(2) // Plus 2 ADA ) TxBuilder(env) .spend(utxo) .payTo(recipientAddress, tokenValue) .changeTo(changeAddress) .build()

TxBuilder automatically ensures outputs meet the minimum ADA requirement based on the protocol parameters.

Payment with Inline Datum

Send funds to a script address with an inline datum:

import scalus.builtin.Data import scalus.builtin.ToData case class MyDatum(owner: PubKeyHash, amount: Long) derives ToData val datum = MyDatum(ownerPubKeyHash, 1000) TxBuilder(env) .spend(utxo) .payTo(scriptAddress, Value.ada(10), datum) // Datum is inlined .changeTo(changeAddress) .build()

The datum is automatically serialized to Data and included inline in the output.

Payment with Datum Hash

Send funds with a datum hash and attach the datum to the witness set:

val datum = MyDatum(ownerPubKeyHash, 1000) TxBuilder(env) .spend(utxo) .attach(datum) // Add datum to witness set .payTo(scriptAddress, Value.ada(10), datumHash) .changeTo(changeAddress) .build()

The attach() method computes the datum hash and stores the datum for inclusion in the witness set.

Multiple Payments

Chain multiple payTo() calls to create multiple outputs:

TxBuilder(env) .spend(utxo) .payTo(recipient1, Value.ada(5)) .payTo(recipient2, Value.ada(3)) .payTo(recipient3, Value.ada(2)) .changeTo(changeAddress) .build()

Each call creates a separate UTxO at the recipient address.

Custom Transaction Output

For full control, use the output() method with a complete TransactionOutput:

import scalus.cardano.ledger.{TransactionOutput, DatumOption, Script} val customOutput = TransactionOutput( address = recipientAddress, value = Value.ada(10), datumOption = Some(DatumOption.Inline(myDatum.toData)), scriptRef = Some(Script.PlutusV3(myScript)) // Attach reference script ) TxBuilder(env) .spend(utxo) .output(customOutput) .changeTo(changeAddress) .build()

This gives you complete control over all output fields, including attaching reference scripts.

Token Change Handling

When spending UTxOs with tokens, TxBuilder automatically returns unused tokens to the change address:

// UTxO contains 10 ADA + 1000 tokens val utxoWithTokens: Utxo = // ... TxBuilder(env) .spend(utxoWithTokens) .payTo(recipient, Value.ada(5)) // Only send ADA .changeTo(changeAddress) // Tokens automatically returned here .build()

The change output will contain the remaining ADA and all 1000 tokens.

Next Steps

Last updated on