Spending UTxOs: Inputs, Scripts, and Collateral
This guide covers how to spend different types of UTxOs: from regular addresses, from script addresses, and using reference inputs.
Spending from Wallet / Public Key Address
The simplest case is spending a UTxO locked by a public key:
val utxo: Utxo = // ... UTxO from a regular address
TxBuilder(env)
.spend(utxo) // Add as input
.payTo(recipient, Value.ada(10))
.changeTo(changeAddress)
.build()
.sign(signer) // Must be signed by the address ownerYou can also spend multiple UTxOs at once:
val utxos: Utxos = Map(
input1 -> output1,
input2 -> output2
)
TxBuilder(env)
.spend(utxos) // Spend all UTxOs
.payTo(recipient, Value.ada(20))
.changeTo(changeAddress)
.build()Spending from Script Address
When spending UTxOs locked by a validator script, you must provide a redeemer and the script itself:
import scalus.builtin.Data
val scriptUtxo: Utxo = // ... UTxO at script address
val redeemer = MyRedeemer(...) // Your redeemer type
// Spend with inline script
TxBuilder(env)
.spend(scriptUtxo, redeemer, script)
.collaterals(collateralUtxo) // Required for script execution
.payTo(recipient, scriptUtxo.output.value)
.changeTo(changeAddress)
.build()Script transactions require collateral inputs. These are only consumed if the script fails validation.
With Required Signers
If your validator requires additional signatures:
val requiredSigners = Set(pubKeyHash1, pubKeyHash2)
TxBuilder(env)
.spend(scriptUtxo, redeemer, script, requiredSigners)
.collaterals(collateralUtxo)
.payTo(recipient, scriptUtxo.output.value)
.changeTo(changeAddress)
.build()
.sign(signer1)
.sign(signer2) // Must provide all required signaturesThe requiredSigners set is added to the transaction’s required signers field, and the validator can check for these signatures in the transaction context.
Spending with Attached Scripts
If you’ve attached a script earlier using attach(), you can reference it when spending:
TxBuilder(env)
.attach(script) // Attach once
.spend(scriptUtxo1, redeemer1) // References attached script
.spend(scriptUtxo2, redeemer2) // Can reuse for multiple inputs
.collaterals(collateralUtxo)
.payTo(recipient, totalValue)
.changeTo(changeAddress)
.build()TxBuilder will automatically find the script in the attached scripts map and use it for validation.
Delayed Redeemers
For advanced cases where the redeemer depends on the final transaction structure:
def buildRedeemer(tx: Transaction): Data = {
// Compute redeemer based on final transaction
val outputCount = tx.body.value.outputs.size
MyRedeemer(outputCount).toData
}
TxBuilder(env)
.attach(script) // Must attach script first
.spend(scriptUtxo, buildRedeemer) // Redeemer computed after assembly
.collaterals(collateralUtxo)
.payTo(recipient, scriptUtxo.output.value)
.changeTo(changeAddress)
.build()The redeemer function is called after the transaction is assembled but before script evaluation, allowing self-referential validation logic.
Reference Inputs
Reference inputs allow scripts to read UTxOs without consuming them:
val referenceUtxo: Utxo = // ... UTxO with reference data
TxBuilder(env)
.spend(myUtxo)
.references(referenceUtxo) // Add as reference input
.payTo(recipient, Value.ada(10))
.changeTo(changeAddress)
.build()Multiple reference inputs can be added:
TxBuilder(env)
.spend(myUtxo)
.references(refUtxo1, refUtxo2, refUtxo3)
.payTo(recipient, Value.ada(10))
.changeTo(changeAddress)
.build()Reference inputs are visible in the script context but are not spent.
Collateral Inputs
Script transactions require collateral to cover fees if validation fails:
val collateral: Utxo = // ... Pure ADA UTxO
TxBuilder(env)
.spend(scriptUtxo, redeemer, script)
.collaterals(collateral) // Add single collateral
.payTo(recipient, scriptUtxo.output.value)
.changeTo(changeAddress)
.build()Multiple collateral inputs:
TxBuilder(env)
.spend(scriptUtxo, redeemer, script)
.collaterals(collateral1, collateral2)
.payTo(recipient, scriptUtxo.output.value)
.changeTo(changeAddress)
.build()When using complete(), collateral inputs are automatically selected and added if the transaction includes script execution. TxBuilder also automatically creates collateral return outputs when needed and respects the protocol’s collateral requirements.
Next Steps
- Minting & Burning - Create and destroy native tokens
- Validator Interactions - Detailed guide on working with validators
- Advanced Features - Learn about
complete()and automatic input selection