Module bdk::wallet::coin_selection

source ·
Expand description

Coin selection

This module provides the trait CoinSelectionAlgorithm that can be implemented to define custom coin selection algorithms.

You can specify a custom coin selection algorithm through the coin_selection method on TxBuilder. DefaultCoinSelectionAlgorithm aliases the coin selection algorithm that will be used if it is not explicitly set.

Example

#[derive(Debug)]
struct AlwaysSpendEverything;

impl CoinSelectionAlgorithm for AlwaysSpendEverything {
    fn coin_select(
        &self,
        required_utxos: Vec<WeightedUtxo>,
        optional_utxos: Vec<WeightedUtxo>,
        fee_rate: FeeRate,
        target_amount: u64,
        drain_script: &Script,
    ) -> Result<CoinSelectionResult, coin_selection::Error> {
        let mut selected_amount = 0;
        let mut additional_weight = Weight::ZERO;
        let all_utxos_selected = required_utxos
            .into_iter()
            .chain(optional_utxos)
            .scan(
                (&mut selected_amount, &mut additional_weight),
                |(selected_amount, additional_weight), weighted_utxo| {
                    **selected_amount += weighted_utxo.utxo.txout().value.to_sat();
                    **additional_weight += Weight::from_wu(
                        (TxIn::default().segwit_weight().to_wu()
                            + weighted_utxo.satisfaction_weight as u64)
                            as u64,
                    );
                    Some(weighted_utxo.utxo)
                },
            )
            .collect::<Vec<_>>();
        let additional_fees = (fee_rate * additional_weight).to_sat();
        let amount_needed_with_fees = additional_fees + target_amount;
        if selected_amount < amount_needed_with_fees {
            return Err(coin_selection::Error::InsufficientFunds {
                needed: amount_needed_with_fees,
                available: selected_amount,
            });
        }

        let remaining_amount = selected_amount - amount_needed_with_fees;

        let excess = decide_change(remaining_amount, fee_rate, drain_script);

        Ok(CoinSelectionResult {
            selected: all_utxos_selected,
            fee_amount: additional_fees,
            excess,
        })
    }
}

// create wallet, sync, ...

let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
    .unwrap()
    .require_network(Network::Testnet)
    .unwrap();
let psbt = {
    let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
    builder.add_recipient(to_address.script_pubkey(), 50_000);
    builder.finish()?
};

// inspect, sign, broadcast, ...

Structs

Branch and bound coin selection
Result of a successful coin selection
Simple and dumb coin selection
OldestFirstCoinSelection always picks the utxo with the smallest blockheight to add to the selected coins next

Enums

Errors that can be thrown by the coin_selection module
Remaining amount after performing coin selection

Traits

Trait for generalized coin selection algorithms

Functions

Decide if change can be created

Type Definitions

Default coin selection algorithm used by TxBuilder if not overridden