pub struct TxBuilder<'a, D, Cs, Ctx> { /* private fields */ }
Expand description

A transaction builder

A TxBuilder is created by calling build_tx or build_fee_bump on a wallet. After assigning it, you set options on it until finally calling finish to consume the builder and generate the transaction.

Each option setting method on TxBuilder takes and returns &mut self so you can chain calls as in the following example:

// chaining
let (psbt1, details) = {
    let mut builder = wallet.build_tx();
    builder
        .ordering(TxOrdering::Untouched)
        .add_recipient(addr1.script_pubkey(), 50_000)
        .add_recipient(addr2.script_pubkey(), 50_000);
    builder.finish()?
};

// non-chaining
let (psbt2, details) = {
    let mut builder = wallet.build_tx();
    builder.ordering(TxOrdering::Untouched);
    for addr in &[addr1, addr2] {
        builder.add_recipient(addr.script_pubkey(), 50_000);
    }
    builder.finish()?
};

assert_eq!(psbt1.unsigned_tx.output[..2], psbt2.unsigned_tx.output[..2]);

At the moment coin_selection is an exception to the rule as it consumes self. This means it is usually best to call coin_selection on the return value of build_tx before assigning it.

For further examples see this module’s documentation;

Implementations§

source§

impl<'a, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> TxBuilder<'a, D, Cs, Ctx>

source

pub fn fee_rate(&mut self, fee_rate: FeeRate) -> &mut Self

Set a custom fee rate

source

pub fn fee_absolute(&mut self, fee_amount: u64) -> &mut Self

Set an absolute fee

source

pub fn policy_path( &mut self, policy_path: BTreeMap<String, Vec<usize>>, keychain: KeychainKind ) -> &mut Self

Set the policy path to use while creating the transaction for a given keychain.

This method accepts a map where the key is the policy node id (see Policy::id) and the value is the list of the indexes of the items that are intended to be satisfied from the policy node (see SatisfiableItem::Thresh::items).

Example

An example of when the policy path is needed is the following descriptor: wsh(thresh(2,pk(A),sj:and_v(v:pk(B),n:older(6)),snj:and_v(v:pk(C),after(630000)))), derived from the miniscript policy thresh(2,pk(A),and(pk(B),older(6)),and(pk(C),after(630000))). It declares three descriptor fragments, and at the top level it uses thresh() to ensure that at least two of them are satisfied. The individual fragments are:

  1. pk(A)
  2. and(pk(B),older(6))
  3. and(pk(C),after(630000))

When those conditions are combined in pairs, it’s clear that the transaction needs to be created differently depending on how the user intends to satisfy the policy afterwards:

  • If fragments 1 and 2 are used, the transaction will need to use a specific n_sequence in order to spend an OP_CSV branch.
  • If fragments 1 and 3 are used, the transaction will need to use a specific locktime in order to spend an OP_CLTV branch.
  • If fragments 2 and 3 are used, the transaction will need both.

When the spending policy is represented as a tree (see Wallet::policies), every node is assigned a unique identifier that can be used in the policy path to specify which of the node’s children the user intends to satisfy: for instance, assuming the thresh() root node of this example has an id of aabbccdd, the policy path map would look like:

{ "aabbccdd" => [0, 1] }

where the key is the node’s id, and the value is a list of the children that should be used, in no particular order.

If a particularly complex descriptor has multiple ambiguous thresholds in its structure, multiple entries can be added to the map, one for each node that requires an explicit path.

Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
    .unwrap()
    .assume_checked();
let mut path = BTreeMap::new();
path.insert("aabbccdd".to_string(), vec![0, 1]);

let builder = wallet
    .build_tx()
    .add_recipient(to_address.script_pubkey(), 50_000)
    .policy_path(path, KeychainKind::External);
source

pub fn add_utxos(&mut self, outpoints: &[OutPoint]) -> Result<&mut Self, Error>

Add the list of outpoints to the internal list of UTXOs that must be spent.

If an error occurs while adding any of the UTXOs then none of them are added and the error is returned.

These have priority over the “unspendable” utxos, meaning that if a utxo is present both in the “utxos” and the “unspendable” list, it will be spent.

source

pub fn add_utxo(&mut self, outpoint: OutPoint) -> Result<&mut Self, Error>

Add a utxo to the internal list of utxos that must be spent

These have priority over the “unspendable” utxos, meaning that if a utxo is present both in the “utxos” and the “unspendable” list, it will be spent.

source

pub fn add_foreign_utxo( &mut self, outpoint: OutPoint, psbt_input: Input, satisfaction_weight: usize ) -> Result<&mut Self, Error>

Add a foreign UTXO i.e. a UTXO not owned by this wallet.

At a minimum to add a foreign UTXO we need:

  1. outpoint: To add it to the raw transaction.
  2. psbt_input: To know the value.
  3. satisfaction_weight: To know how much weight/vbytes the input will add to the transaction for fee calculation.

There are several security concerns about adding foreign UTXOs that application developers should consider. First, how do you know the value of the input is correct? If a non_witness_utxo is provided in the psbt_input then this method implicitly verifies the value by checking it against the transaction. If only a witness_utxo is provided then this method doesn’t verify the value but just takes it as a given – it is up to you to check that whoever sent you the input_psbt was not lying!

Secondly, you must somehow provide satisfaction_weight of the input. Depending on your application it may be important that this be known precisely. If not, a malicious counterparty may fool you into putting in a value that is too low, giving the transaction a lower than expected feerate. They could also fool you into putting a value that is too high causing you to pay a fee that is too high. The party who is broadcasting the transaction can of course check the real input weight matches the expected weight prior to broadcasting.

To guarantee the satisfaction_weight is correct, you can require the party providing the psbt_input provide a miniscript descriptor for the input so you can check it against the script_pubkey and then ask it for the max_satisfaction_weight.

This is an EXPERIMENTAL feature, API and other major changes are expected.

Errors

This method returns errors in the following circumstances:

  1. The psbt_input does not contain a witness_utxo or non_witness_utxo.
  2. The data in non_witness_utxo does not match what is in outpoint.

Note unless you set only_witness_utxo any non-taproot psbt_input you pass to this method must have non_witness_utxo set otherwise you will get an error when finish is called.

source

pub fn manually_selected_only(&mut self) -> &mut Self

Only spend utxos added by add_utxo.

The wallet will not add additional utxos to the transaction even if they are needed to make the transaction valid.

source

pub fn unspendable(&mut self, unspendable: Vec<OutPoint>) -> &mut Self

Replace the internal list of unspendable utxos with a new list

It’s important to note that the “must-be-spent” utxos added with TxBuilder::add_utxo have priority over these. See the docs of the two linked methods for more details.

source

pub fn add_unspendable(&mut self, unspendable: OutPoint) -> &mut Self

Add a utxo to the internal list of unspendable utxos

It’s important to note that the “must-be-spent” utxos added with TxBuilder::add_utxo have priority over this. See the docs of the two linked methods for more details.

source

pub fn sighash(&mut self, sighash: PsbtSighashType) -> &mut Self

Sign with a specific sig hash

Use this option very carefully

source

pub fn ordering(&mut self, ordering: TxOrdering) -> &mut Self

Choose the ordering for inputs and outputs of the transaction

source

pub fn nlocktime(&mut self, locktime: LockTime) -> &mut Self

Use a specific nLockTime while creating the transaction

This can cause conflicts if the wallet’s descriptors contain an “after” (OP_CLTV) operator.

source

pub fn version(&mut self, version: i32) -> &mut Self

Build a transaction with a specific version

The version should always be greater than 0 and greater than 1 if the wallet’s descriptors contain an “older” (OP_CSV) operator.

source

pub fn do_not_spend_change(&mut self) -> &mut Self

Do not spend change outputs

This effectively adds all the change outputs to the “unspendable” list. See TxBuilder::unspendable.

source

pub fn only_spend_change(&mut self) -> &mut Self

Only spend change outputs

This effectively adds all the non-change outputs to the “unspendable” list. See TxBuilder::unspendable.

source

pub fn change_policy(&mut self, change_policy: ChangeSpendPolicy) -> &mut Self

source

pub fn only_witness_utxo(&mut self) -> &mut Self

Only Fill-in the psbt::Input::witness_utxo field when spending from SegWit descriptors.

This reduces the size of the PSBT, but some signers might reject them due to the lack of the non_witness_utxo.

source

pub fn include_output_redeem_witness_script(&mut self) -> &mut Self

Fill-in the psbt::Output::redeem_script and psbt::Output::witness_script fields.

This is useful for signers which always require it, like ColdCard hardware wallets.

source

pub fn add_global_xpubs(&mut self) -> &mut Self

Fill-in the PSBT_GLOBAL_XPUB field with the extended keys contained in both the external and internal descriptors

This is useful for offline signers that take part to a multisig. Some hardware wallets like BitBox and ColdCard are known to require this.

source

pub fn drain_wallet(&mut self) -> &mut Self

Spend all the available inputs. This respects filters like TxBuilder::unspendable and the change policy.

source

pub fn coin_selection<P: CoinSelectionAlgorithm<D>>( self, coin_selection: P ) -> TxBuilder<'a, D, P, Ctx>

Choose the coin selection algorithm

Overrides the DefaultCoinSelectionAlgorithm.

Note that this function consumes the builder and returns it so it is usually best to put this as the first call on the builder.

source

pub fn finish(self) -> Result<(Psbt, TransactionDetails), Error>

Finish building the transaction.

Returns the BIP174 “PSBT” and summary details about the transaction.

source

pub fn enable_rbf(&mut self) -> &mut Self

Enable signaling RBF

This will use the default nSequence value of 0xFFFFFFFD.

source

pub fn enable_rbf_with_sequence(&mut self, nsequence: Sequence) -> &mut Self

Enable signaling RBF with a specific nSequence value

This can cause conflicts if the wallet’s descriptors contain an “older” (OP_CSV) operator and the given nsequence is lower than the CSV value.

If the nsequence is higher than 0xFFFFFFFD an error will be thrown, since it would not be a valid nSequence to signal RBF.

source

pub fn current_height(&mut self, height: u32) -> &mut Self

Set the current blockchain height.

This will be used to:

  1. Set the nLockTime for preventing fee sniping. Note: This will be ignored if you manually specify a nlocktime using TxBuilder::nlocktime.
  2. Decide whether coinbase outputs are mature or not. If the coinbase outputs are not mature at current_height, we ignore them in the coin selection. If you want to create a transaction that spends immature coinbase inputs, manually add them using TxBuilder::add_utxos.

In both cases, if you don’t provide a current height, we use the last sync height.

source

pub fn allow_dust(&mut self, allow_dust: bool) -> &mut Self

Set whether or not the dust limit is checked.

Note: by avoiding a dust limit check you may end up with a transaction that is non-standard.

source§

impl<'a, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>> TxBuilder<'a, D, Cs, CreateTx>

source

pub fn set_recipients(&mut self, recipients: Vec<(ScriptBuf, u64)>) -> &mut Self

Replace the recipients already added with a new list

source

pub fn add_recipient( &mut self, script_pubkey: ScriptBuf, amount: u64 ) -> &mut Self

Add a recipient to the internal list

source

pub fn add_data<T: AsRef<PushBytes>>(&mut self, data: &T) -> &mut Self

Add data as an output, using OP_RETURN

source

pub fn drain_to(&mut self, script_pubkey: ScriptBuf) -> &mut Self

Sets the address to drain excess coins to.

Usually, when there are excess coins they are sent to a change address generated by the wallet. This option replaces the usual change address with an arbitrary script_pubkey of your choosing. Just as with a change output, if the drain output is not needed (the excess coins are too small) it will not be included in the resulting transaction. The only difference is that it is valid to use drain_to without setting any ordinary recipients with add_recipient (but it is perfectly fine to add recipients as well).

If you choose not to set any recipients, you should either provide the utxos that the transaction should spend via add_utxos, or set drain_wallet to spend all of them.

When bumping the fees of a transaction made with this option, you probably want to use allow_shrinking to allow this output to be reduced to pay for the extra fees.

Example

drain_to is very useful for draining all the coins in a wallet with drain_wallet to a single address.

Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
    .unwrap()
    .assume_checked();
let mut tx_builder = wallet.build_tx();

tx_builder
    // Spend all outputs in this wallet.
    .drain_wallet()
    // Send the excess (which is all the coins minus the fee) to this address.
    .drain_to(to_address.script_pubkey())
    .fee_rate(bdk::FeeRate::from_sat_per_vb(5.0))
    .enable_rbf();
let (psbt, tx_details) = tx_builder.finish()?;
source§

impl<'a, D: BatchDatabase> TxBuilder<'a, D, DefaultCoinSelectionAlgorithm, BumpFee>

source

pub fn allow_shrinking( &mut self, script_pubkey: ScriptBuf ) -> Result<&mut Self, Error>

Explicitly tells the wallet that it is allowed to reduce the amount of the output matching this script_pubkey in order to bump the transaction fee. Without specifying this the wallet will attempt to find a change output to shrink instead.

Note that the output may shrink to below the dust limit and therefore be removed. If it is preserved then it is currently not guaranteed to be in the same position as it was originally.

Returns an Err if script_pubkey can’t be found among the recipients of the transaction we are bumping.

Trait Implementations§

source§

impl<'a, Cs: Clone, Ctx, D> Clone for TxBuilder<'a, D, Cs, Ctx>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<'a, D: Debug, Cs: Debug, Ctx: Debug> Debug for TxBuilder<'a, D, Cs, Ctx>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a, D, Cs, Ctx> !RefUnwindSafe for TxBuilder<'a, D, Cs, Ctx>

§

impl<'a, D, Cs, Ctx> !Send for TxBuilder<'a, D, Cs, Ctx>

§

impl<'a, D, Cs, Ctx> !Sync for TxBuilder<'a, D, Cs, Ctx>

§

impl<'a, D, Cs, Ctx> Unpin for TxBuilder<'a, D, Cs, Ctx>where Cs: Unpin, Ctx: Unpin,

§

impl<'a, D, Cs, Ctx> !UnwindSafe for TxBuilder<'a, D, Cs, Ctx>

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> ToOwned for Twhere T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V