From 3e5b0c526e604fe32e156d642652e13946bdb1dc Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Thu, 16 Nov 2023 20:20:40 -0500 Subject: [PATCH] temp --- bdk-ffi/src/bdk.udl | 14 +++++ bdk-ffi/src/lib.rs | 1 + bdk-ffi/src/wallet.rs | 140 ++++++++++++++++++++++-------------------- 3 files changed, 88 insertions(+), 67 deletions(-) diff --git a/bdk-ffi/src/bdk.udl b/bdk-ffi/src/bdk.udl index 2eaf30f9..4fb834cd 100644 --- a/bdk-ffi/src/bdk.udl +++ b/bdk-ffi/src/bdk.udl @@ -43,6 +43,12 @@ enum BdkError { "Psbt", }; +enum ChangeSpendPolicy { + "ChangeAllowed", + "OnlyChange", + "ChangeForbidden" +}; + interface Balance { u64 immature(); @@ -101,6 +107,14 @@ interface TxBuilder { TxBuilder add_utxo(OutPoint outpoint); + TxBuilder change_policy(ChangeSpendPolicy change_policy); + + TxBuilder do_not_spend_change(); + + TxBuilder only_spend_change(); + + TxBuilder manually_selected_only(); + TxBuilder fee_rate(float sat_per_vbyte); [Throws=BdkError] diff --git a/bdk-ffi/src/lib.rs b/bdk-ffi/src/lib.rs index 5cd4935f..185529b4 100644 --- a/bdk-ffi/src/lib.rs +++ b/bdk-ffi/src/lib.rs @@ -22,6 +22,7 @@ use crate::wallet::Update; use crate::wallet::Wallet; use bdk::keys::bip39::WordCount; +use bdk::wallet::tx_builder::ChangeSpendPolicy; use bdk::wallet::AddressIndex as BdkAddressIndex; use bdk::wallet::AddressInfo as BdkAddressInfo; use bdk::wallet::Balance as BdkBalance; diff --git a/bdk-ffi/src/wallet.rs b/bdk-ffi/src/wallet.rs index 9895a6cd..4e569d7b 100644 --- a/bdk-ffi/src/wallet.rs +++ b/bdk-ffi/src/wallet.rs @@ -5,10 +5,12 @@ use crate::{Balance, Script}; use std::collections::HashSet; use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf; +use bdk::bitcoin::OutPoint as BdkOutPoint; use bdk::wallet::Update as BdkUpdate; use bdk::Wallet as BdkWallet; use bdk::{Error as BdkError, FeeRate}; +use bdk::wallet::tx_builder::ChangeSpendPolicy; use std::sync::{Arc, Mutex, MutexGuard}; #[derive(Debug)] @@ -265,7 +267,7 @@ pub struct TxBuilder { pub(crate) utxos: Vec, pub(crate) unspendable: HashSet, pub(crate) change_policy: ChangeSpendPolicy, - // pub(crate) manually_selected_only: bool, + pub(crate) manually_selected_only: bool, pub(crate) fee_rate: Option, // pub(crate) fee_absolute: Option, // pub(crate) drain_wallet: bool, @@ -281,7 +283,7 @@ impl TxBuilder { utxos: Vec::new(), unspendable: HashSet::new(), change_policy: ChangeSpendPolicy::ChangeAllowed, - // manually_selected_only: false, + manually_selected_only: false, fee_rate: None, // fee_absolute: None, // drain_wallet: false, @@ -324,49 +326,56 @@ impl TxBuilder { }) } - /// Add an outpoint 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. - pub(crate) fn add_utxo(&self, outpoint: OutPoint) -> Arc { - self.add_utxos(vec![outpoint]) - } + /// Add an outpoint 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. + pub(crate) fn add_utxo(&self, outpoint: OutPoint) -> Arc { + self.add_utxos(vec![outpoint]) + } - /// 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. - pub(crate) fn add_utxos(&self, mut outpoints: Vec) -> Arc { - let mut utxos = self.utxos.to_vec(); - utxos.append(&mut outpoints); - Arc::new(TxBuilder { - utxos, - ..self.clone() - }) - } + /// 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. + pub(crate) fn add_utxos(&self, mut outpoints: Vec) -> Arc { + let mut utxos = self.utxos.to_vec(); + utxos.append(&mut outpoints); + Arc::new(TxBuilder { + utxos, + ..self.clone() + }) + } + + pub(crate) fn change_policy(&self, change_policy: ChangeSpendPolicy) -> Arc { + Arc::new(TxBuilder { + change_policy, + ..self.clone() + }) + } + + /// Do not spend change outputs. This effectively adds all the change outputs to the "unspendable" list. See TxBuilder.unspendable. + pub(crate) fn do_not_spend_change(&self) -> Arc { + Arc::new(TxBuilder { + change_policy: ChangeSpendPolicy::ChangeForbidden, + ..self.clone() + }) + } + + /// Only spend change outputs. This effectively adds all the non-change outputs to the "unspendable" list. See TxBuilder.unspendable. + pub(crate) fn only_spend_change(&self) -> Arc { + Arc::new(TxBuilder { + change_policy: ChangeSpendPolicy::OnlyChange, + ..self.clone() + }) + } + + /// 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. + pub(crate) fn manually_selected_only(&self) -> Arc { + Arc::new(TxBuilder { + manually_selected_only: true, + ..self.clone() + }) + } - /// Do not spend change outputs. This effectively adds all the change outputs to the "unspendable" list. See TxBuilder.unspendable. - // pub(crate) fn do_not_spend_change(&self) -> Arc { - // Arc::new(TxBuilder { - // change_policy: ChangeSpendPolicy::ChangeForbidden, - // ..self.clone() - // }) - // } - // - // /// 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. - pub(crate) fn manually_selected_only(&self) -> Arc { - Arc::new(TxBuilder { - manually_selected_only: true, - ..self.clone() - }) - } - // - // /// Only spend change outputs. This effectively adds all the non-change outputs to the "unspendable" list. See TxBuilder.unspendable. - // pub(crate) fn only_spend_change(&self) -> Arc { - // Arc::new(TxBuilder { - // change_policy: ChangeSpendPolicy::OnlyChange, - // ..self.clone() - // }) - // } - // // /// 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.addUtxo have priority over these. See the Rust docs of the two linked methods for more details. // pub(crate) fn unspendable(&self, unspendable: Vec) -> Arc { @@ -375,7 +384,7 @@ impl TxBuilder { // ..self.clone() // }) // } - // + /// Set a custom fee rate. pub(crate) fn fee_rate(&self, sat_per_vb: f32) -> Arc { Arc::new(TxBuilder { @@ -383,7 +392,7 @@ impl TxBuilder { ..self.clone() }) } - // + // /// Set an absolute fee. // pub(crate) fn fee_absolute(&self, fee_amount: u64) -> Arc { // Arc::new(TxBuilder { @@ -432,17 +441,16 @@ impl TxBuilder { // ..self.clone() // }) // } - // - // /// Add data as an output using OP_RETURN. - // pub(crate) fn add_data(&self, data: Vec) -> Arc { - // Arc::new(TxBuilder { - // data, - // ..self.clone() - // }) - // } - // + + /// Add data as an output using OP_RETURN. + // pub(crate) fn add_data(&self, data: Vec) -> Arc { + // Arc::new(TxBuilder { + // data, + // ..self.clone() + // }) + // } + /// Finish building the transaction. Returns the BIP174 PSBT. - /// TODO: The TxBuilder in bdk returns a Psbt type pub(crate) fn finish( &self, wallet: &Wallet, @@ -450,25 +458,23 @@ impl TxBuilder { // TODO: I had to change the wallet here to be mutable. Why is that now required with the 1.0 API? let mut wallet = wallet.get_wallet(); let mut tx_builder = wallet.build_tx(); - // TODO: I'm not yet clear on the Script/ScriptBuf differences and whether this is the best - // way to do this. for (script, amount) in &self.recipients { tx_builder.add_recipient(script.clone(), *amount); } - // tx_builder.change_policy(self.change_policy); - // if !self.utxos.is_empty() { - // let bdk_utxos: Vec = self.utxos.iter().map(BdkOutPoint::from).collect(); - // let utxos: &[BdkOutPoint] = &bdk_utxos; - // tx_builder.add_utxos(utxos)?; - // } + tx_builder.change_policy(self.change_policy); + if !self.utxos.is_empty() { + let bdk_utxos: Vec = self.utxos.iter().map(BdkOutPoint::from).collect(); + let utxos: &[BdkOutPoint] = &bdk_utxos; + tx_builder.add_utxos(utxos)?; + } // if !self.unspendable.is_empty() { // let bdk_unspendable: Vec = // self.unspendable.iter().map(BdkOutPoint::from).collect(); // tx_builder.unspendable(bdk_unspendable); // } - // if self.manually_selected_only { - // tx_builder.manually_selected_only(); - // } + if self.manually_selected_only { + tx_builder.manually_selected_only(); + } if let Some(sat_per_vb) = self.fee_rate { tx_builder.fee_rate(FeeRate::from_sat_per_vb(sat_per_vb)); } @@ -502,7 +508,7 @@ impl TxBuilder { Ok(Arc::new(psbt.into())) } } -// + // /// The BumpFeeTxBuilder is used to bump the fee on a transaction that has been broadcast and has its RBF flag set to true. // #[derive(Clone)] // pub(crate) struct BumpFeeTxBuilder {