Coin Selection API
The Coin Selection API provides strategies for selecting UTXOs when building transactions. It includes built-in algorithms and extension points for custom selection logic.
Overview
Section titled “Overview”- Multiple strategies: default, largest-first, random-improve
- Configurable limits and datum handling
- Inline datum and datum hash aware
- Fallback chaining for robustness
- UTXO discovery helpers via
UtxoSelector
Core Interfaces
Section titled “Core Interfaces”UtxoSelectionStrategy
Section titled “UtxoSelectionStrategy”public interface UtxoSelectionStrategy { Set<Utxo> select(AddressIterator addressIterator, List<Amount> outputAmounts, String datumHash, PlutusData inlineDatum, Set<Utxo> utxosToExclude, int maxUtxoSelectionLimit);
UtxoSelectionStrategy fallback(); void setIgnoreUtxosWithDatumHash(boolean ignore);}UtxoSelector
Section titled “UtxoSelector”Utility interface to query UTXOs by predicate:
Optional<Utxo> findFirst(String address, Predicate<Utxo> predicate);List<Utxo> findAll(String address, Predicate<Utxo> predicate);default void setSearchByAddressVkh(boolean flag) { }Built-in Selection Strategies
Section titled “Built-in Selection Strategies”Default
Section titled “Default”UtxoSelectionStrategy strategy = new DefaultUtxoSelectionStrategyImpl(utxoSupplier);
strategy.setIgnoreUtxosWithDatumHash(true); // default true
Set<Utxo> selected = strategy.select( AddressIterators.of(senderAddress), List.of(Amount.ada(10)), null, // datumHash null, // inline datum Collections.emptySet(), 20);Largest First
Section titled “Largest First”UtxoSelectionStrategy strategy = new LargestFirstUtxoSelectionStrategy(utxoSupplier);
Set<Utxo> selected = strategy.select( AddressIterators.of(senderAddress), List.of(Amount.ada(5)), null, null, Collections.emptySet(), 10);Random Improve
Section titled “Random Improve”UtxoSelectionStrategy strategy = new RandomImproveUtxoSelectionStrategy(utxoSupplier);strategy.setIgnoreUtxosWithDatumHash(false);
Set<Utxo> selected = strategy.select( AddressIterators.of(senderAddress), List.of(Amount.ada(15)), null, null, Collections.emptySet(), 15);Using UtxoSelector
Section titled “Using UtxoSelector”UtxoSelector utxoSelector = new DefaultUtxoSelector(utxoSupplier);
List<Utxo> adaUtxos = utxoSelector.findAll( senderAddress, utxo -> utxo.getAmount().stream().anyMatch(a -> "lovelace".equals(a.getUnit())));
Optional<Utxo> firstScriptUtxo = utxoSelector.findFirst( scriptAddress, utxo -> utxo.getReferenceScriptHash() != null);If your backend supports lookup by address verification hash (addr_vkh), enable it:
utxoSelector.setSearchByAddressVkh(true);utxoSupplier.setSearchByAddressVkh(true); // only if supported by your supplier/backendAdvanced Scenarios
Section titled “Advanced Scenarios”Multi-Address Selection
Section titled “Multi-Address Selection”select takes an AddressIterator and moves to the next address until the amount is covered. To search your own list of addresses, implement AddressIterator. For an HD wallet, use Tx.from(wallet), which scans the wallet’s addresses for you.
Datum Requirements
Section titled “Datum Requirements”String requiredDatumHash = "...";PlutusData requiredInlineDatum = BytesPlutusData.of("hello");
// UTXOs with a datum hash are skipped by default, so turn that off to select by hashstrategy.setIgnoreUtxosWithDatumHash(false);
Set<Utxo> withHash = strategy.select( AddressIterators.of(contractAddress), List.of(Amount.ada(5)), requiredDatumHash, null, Collections.emptySet(), 10);
Set<Utxo> withInline = strategy.select( AddressIterators.of(contractAddress), List.of(Amount.ada(5)), null, requiredInlineDatum, Collections.emptySet(), 10);Excluding Specific UTXOs
Section titled “Excluding Specific UTXOs”Set<Utxo> exclusions = Set.of(pendingUtxo1, pendingUtxo2);
Set<Utxo> selected = strategy.select( AddressIterators.of(senderAddress), List.of(Amount.ada(10)), null, null, exclusions, 20);Global Configuration
Section titled “Global Configuration”CoinselectionConfig.INSTANCE.setCoinSelectionLimit(50);int current = CoinselectionConfig.INSTANCE.getCoinSelectionLimit();Custom Strategy
Section titled “Custom Strategy”public class CustomUtxoSelectionStrategy implements UtxoSelectionStrategy { private final UtxoSupplier utxoSupplier; private boolean ignoreUtxosWithDatumHash = true;
public CustomUtxoSelectionStrategy(UtxoSupplier utxoSupplier) { this.utxoSupplier = utxoSupplier; }
// implement select(...) using your own ordering/filtering
@Override public UtxoSelectionStrategy fallback() { return new DefaultUtxoSelectionStrategyImpl(utxoSupplier); }
@Override public void setIgnoreUtxosWithDatumHash(boolean ignore) { this.ignoreUtxosWithDatumHash = ignore; }}QuickTx Integration
Section titled “QuickTx Integration”Provide a custom strategy per composition:
UtxoSelectionStrategy custom = new LargestFirstUtxoSelectionStrategy(utxoSupplier);
Tx tx = new Tx() .payToAddress(receiverAddress, Amount.ada(10)) .from(senderAddress);
TxResult result = new QuickTxBuilder(backendService) .compose(tx) .withUtxoSelectionStrategy(custom) .withSigner(SignerProviders.signerFrom(sender)) .complete();