]> Untitled Git - bdk/commitdiff
Remove Option trickery from TxBuilder API
authorLLFourn <lloyd.fourn@gmail.com>
Mon, 11 Jan 2021 03:14:14 +0000 (14:14 +1100)
committerLLFourn <lloyd.fourn@gmail.com>
Fri, 22 Jan 2021 04:08:30 +0000 (15:08 +1100)
see: https://github.com/bitcoindevkit/bdk/pull/258#issuecomment-754685962

README.md
src/wallet/address_validator.rs
src/wallet/coin_selection.rs
src/wallet/mod.rs
src/wallet/tx_builder.rs
testutils-macros/src/lib.rs

index 716ad2d8e9d24f4262f769657f0d559be08b63c6..7a173658bb155cfc9c9da01092149d4d139b32ff 100644 (file)
--- a/README.md
+++ b/README.md
@@ -108,12 +108,15 @@ fn main() -> Result<(), bdk::Error> {
     wallet.sync(noop_progress(), None)?;
 
     let send_to = wallet.get_new_address()?;
-    let (psbt, details) = wallet.build_tx()
-        .add_recipient(send_to.script_pubkey(), 50_000)
-        .enable_rbf()
-        .do_not_spend_change()
-        .fee_rate(FeeRate::from_sat_per_vb(5.0))
-        .finish()?;
+    let (psbt, details) = { 
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(send_to.script_pubkey(), 50_000)
+            .enable_rbf()
+            .do_not_spend_change()
+            .fee_rate(FeeRate::from_sat_per_vb(5.0));
+        builder.finish()?
+    };
 
     println!("Transaction details: {:#?}", details);
     println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));
index b77ec4aa7e560c80acf8a44bc2afacca91386683..b84bee0c088b2f58d12773965193a60fdd6dfb4d 100644 (file)
@@ -156,10 +156,8 @@ mod test {
         wallet.add_address_validator(Arc::new(TestValidator));
 
         let addr = testutils!(@external descriptors, 10);
-        wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 25_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        builder.finish().unwrap();
     }
 }
index 71a56d8f86e420d36ed85bb9af9ca797a171912a..c57f251def483042ad3d62ce30094aed3cf2ae65 100644 (file)
 //! // create wallet, sync, ...
 //!
 //! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
-//! let (psbt, details) = wallet.build_tx().coin_selection(AlwaysSpendEverything)
-//!     .add_recipient(to_address.script_pubkey(), 50_000)
-//!     .finish()?;
+//! let (psbt, details) = {
+//!     let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
+//!     builder
+//!         .add_recipient(to_address.script_pubkey(), 50_000);
+//!     builder.finish()?
+//! };
 //!
 //! // inspect, sign, broadcast, ...
 //!
index ab73939b02af1fe4c46573791ce55666950528b7..ccebe4f739942f0b91e73adfb47af53877d067fd 100644 (file)
@@ -268,9 +268,12 @@ where
     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
     /// # let wallet = doctest_wallet!();
     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
-    /// let (psbt, details) = wallet.build_tx()
-    ///     .add_recipient(to_address.script_pubkey(), 50_000)
-    ///     .finish()?;
+    /// let (psbt, details) = {
+    ///    let mut builder =  wallet.build_tx();
+    ///    builder
+    ///        .add_recipient(to_address.script_pubkey(), 50_000);
+    ///    builder.finish()?
+    /// };
     ///
     /// // sign and broadcast ...
     /// # Ok::<(), bdk::Error>(())
@@ -280,8 +283,8 @@ where
     pub fn build_tx(&self) -> TxBuilder<'_, B, D, DefaultCoinSelectionAlgorithm, CreateTx> {
         TxBuilder {
             wallet: &self,
-            params: Some(TxParams::default()),
-            coin_selection: Some(DefaultCoinSelectionAlgorithm::default()),
+            params: TxParams::default(),
+            coin_selection: DefaultCoinSelectionAlgorithm::default(),
             phantom: core::marker::PhantomData,
         }
     }
@@ -621,16 +624,22 @@ where
     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
     /// # let wallet = doctest_wallet!();
     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
-    /// let (psbt, _) = wallet.build_tx()
-    ///     .add_recipient(to_address.script_pubkey(), 50_000)
-    ///     .enable_rbf()
-    ///     .finish()?;
+    /// let (psbt, _) = {
+    ///     let mut builder = wallet.build_tx();
+    ///     builder
+    ///         .add_recipient(to_address.script_pubkey(), 50_000)
+    ///         .enable_rbf();
+    ///     builder.finish()?
+    /// };
     /// let (psbt, _) = wallet.sign(psbt, None)?;
     /// let tx = psbt.extract_tx();
     /// // broadcast tx but it's taking too long to confirm so we want to bump the fee
-    /// let (psbt, details) = wallet.build_fee_bump(tx.txid())?
-    ///     .fee_rate(FeeRate::from_sat_per_vb(5.0))
-    ///     .finish()?;
+    /// let (psbt, _) =  {
+    ///     let mut builder = wallet.build_fee_bump(tx.txid())?;
+    ///     builder
+    ///         .fee_rate(FeeRate::from_sat_per_vb(5.0));
+    ///     builder.finish()?
+    /// };
     ///
     /// let (psbt, _) = wallet.sign(psbt, None)?;
     /// let fee_bumped_tx = psbt.extract_tx();
@@ -738,8 +747,8 @@ where
 
         Ok(TxBuilder {
             wallet: &self,
-            params: Some(params),
-            coin_selection: Some(DefaultCoinSelectionAlgorithm::default()),
+            params,
+            coin_selection: DefaultCoinSelectionAlgorithm::default(),
             phantom: core::marker::PhantomData,
         })
     }
@@ -757,7 +766,11 @@ where
     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
     /// # let wallet = doctest_wallet!();
     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
-    /// let (psbt, _) = wallet.build_tx().add_recipient(to_address.script_pubkey(), 50_000).finish()?;
+    /// let (psbt, _) = {
+    ///     let mut builder = wallet.build_tx();
+    ///     builder.add_recipient(to_address.script_pubkey(), 50_000);
+    ///     builder.finish()?
+    /// };
     /// let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
     /// assert!(finalized, "we should have signed all the inputs");
     /// # Ok::<(), bdk::Error>(())
@@ -1527,12 +1540,11 @@ mod test {
     fn test_create_tx_manually_selected_empty_utxos() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .manually_selected_only()
-            .finish()
-            .unwrap();
+            .manually_selected_only();
+        builder.finish().unwrap();
     }
 
     #[test]
@@ -1540,12 +1552,11 @@ mod test {
     fn test_create_tx_version_0() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .version(0)
-            .finish()
-            .unwrap();
+            .version(0);
+        builder.finish().unwrap();
     }
 
     #[test]
@@ -1555,24 +1566,22 @@ mod test {
     fn test_create_tx_version_1_csv() {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
         let addr = wallet.get_new_address().unwrap();
-        wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .version(1)
-            .finish()
-            .unwrap();
+            .version(1);
+        builder.finish().unwrap();
     }
 
     #[test]
     fn test_create_tx_custom_version() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .version(42)
-            .finish()
-            .unwrap();
+            .version(42);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.version, 42);
     }
@@ -1581,11 +1590,9 @@ mod test {
     fn test_create_tx_default_locktime() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 25_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.lock_time, 0);
     }
@@ -1594,11 +1601,9 @@ mod test {
     fn test_create_tx_default_locktime_cltv() {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 25_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.lock_time, 100_000);
     }
@@ -1607,12 +1612,11 @@ mod test {
     fn test_create_tx_custom_locktime() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .nlocktime(630_000)
-            .finish()
-            .unwrap();
+            .nlocktime(630_000);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
     }
@@ -1621,12 +1625,11 @@ mod test {
     fn test_create_tx_custom_locktime_compatible_with_cltv() {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .nlocktime(630_000)
-            .finish()
-            .unwrap();
+            .nlocktime(630_000);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
     }
@@ -1638,23 +1641,20 @@ mod test {
     fn test_create_tx_custom_locktime_incompatible_with_cltv() {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
         let addr = wallet.get_new_address().unwrap();
-        wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .nlocktime(50000)
-            .finish()
-            .unwrap();
+            .nlocktime(50000);
+        builder.finish().unwrap();
     }
 
     #[test]
     fn test_create_tx_no_rbf_csv() {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 25_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
     }
@@ -1663,12 +1663,11 @@ mod test {
     fn test_create_tx_with_default_rbf_csv() {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, _) = builder.finish().unwrap();
         // When CSV is enabled it takes precedence over the rbf value (unless forced by the user).
         // It will be set to the OP_CSV value, in this case 6
         assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
@@ -1681,23 +1680,20 @@ mod test {
     fn test_create_tx_with_custom_rbf_csv() {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
         let addr = wallet.get_new_address().unwrap();
-        wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .enable_rbf_with_sequence(3)
-            .finish()
-            .unwrap();
+            .enable_rbf_with_sequence(3);
+        builder.finish().unwrap();
     }
 
     #[test]
     fn test_create_tx_no_rbf_cltv() {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 25_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFE);
     }
@@ -1707,24 +1703,22 @@ mod test {
     fn test_create_tx_invalid_rbf_sequence() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .enable_rbf_with_sequence(0xFFFFFFFE)
-            .finish()
-            .unwrap();
+            .enable_rbf_with_sequence(0xFFFFFFFE);
+        builder.finish().unwrap();
     }
 
     #[test]
     fn test_create_tx_custom_rbf_sequence() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .enable_rbf_with_sequence(0xDEADBEEF)
-            .finish()
-            .unwrap();
+            .enable_rbf_with_sequence(0xDEADBEEF);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xDEADBEEF);
     }
@@ -1733,11 +1727,9 @@ mod test {
     fn test_create_tx_default_sequence() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 25_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
     }
@@ -1749,24 +1741,22 @@ mod test {
     fn test_create_tx_change_policy_no_internal() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .do_not_spend_change()
-            .finish()
-            .unwrap();
+            .do_not_spend_change();
+        builder.finish().unwrap();
     }
 
     #[test]
     fn test_create_tx_single_recipient_drain_wallet() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
         assert_eq!(
@@ -1779,11 +1769,9 @@ mod test {
     fn test_create_tx_default_fee_rate() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 25_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::default(), @add_signature);
     }
@@ -1792,12 +1780,11 @@ mod test {
     fn test_create_tx_custom_fee_rate() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .fee_rate(FeeRate::from_sat_per_vb(5.0))
-            .finish()
-            .unwrap();
+            .fee_rate(FeeRate::from_sat_per_vb(5.0));
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
     }
@@ -1806,13 +1793,12 @@ mod test {
     fn test_create_tx_absolute_fee() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
             .drain_wallet()
-            .fee_absolute(100)
-            .finish()
-            .unwrap();
+            .fee_absolute(100);
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(details.fees, 100);
         assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
@@ -1826,13 +1812,12 @@ mod test {
     fn test_create_tx_absolute_zero_fee() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
             .drain_wallet()
-            .fee_absolute(0)
-            .finish()
-            .unwrap();
+            .fee_absolute(0);
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(details.fees, 0);
         assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
@@ -1847,13 +1832,12 @@ mod test {
     fn test_create_tx_absolute_high_fee() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (_psbt, _details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
             .drain_wallet()
-            .fee_absolute(60_000)
-            .finish()
-            .unwrap();
+            .fee_absolute(60_000);
+        let (_psbt, _details) = builder.finish().unwrap();
     }
 
     #[test]
@@ -1862,12 +1846,11 @@ mod test {
 
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .ordering(TxOrdering::Untouched)
-            .finish()
-            .unwrap();
+            .ordering(TxOrdering::Untouched);
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.output.len(), 2);
         assert_eq!(psbt.global.unsigned_tx.output[0].value, 25_000);
@@ -1881,11 +1864,9 @@ mod test {
     fn test_create_tx_skip_change_dust() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 49_800)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 49_800);
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
         assert_eq!(psbt.global.unsigned_tx.output[0].value, 49_800);
@@ -1898,26 +1879,24 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         // very high fee rate, so that the only output would be below dust
-        wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
             .drain_wallet()
-            .fee_rate(FeeRate::from_sat_per_vb(453.0))
-            .finish()
-            .unwrap();
+            .fee_rate(FeeRate::from_sat_per_vb(453.0));
+        builder.finish().unwrap();
     }
 
     #[test]
     fn test_create_tx_ordering_respected() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 30_000)
             .add_recipient(addr.script_pubkey(), 10_000)
-            .ordering(super::tx_builder::TxOrdering::BIP69Lexicographic)
-            .finish()
-            .unwrap();
+            .ordering(super::tx_builder::TxOrdering::BIP69Lexicographic);
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
         assert_eq!(
@@ -1932,11 +1911,9 @@ mod test {
     fn test_create_tx_default_sighash() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 30_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 30_000);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.inputs[0].sighash_type, None);
     }
@@ -1945,12 +1922,11 @@ mod test {
     fn test_create_tx_custom_sighash() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 30_000)
-            .sighash(bitcoin::SigHashType::Single)
-            .finish()
-            .unwrap();
+            .sighash(bitcoin::SigHashType::Single);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(
             psbt.inputs[0].sighash_type,
@@ -1965,12 +1941,11 @@ mod test {
 
         let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.inputs[0].hd_keypaths.len(), 1);
         assert_eq!(
@@ -1992,12 +1967,11 @@ mod test {
         wallet.get_new_address().unwrap();
 
         let addr = testutils!(@external descriptors, 5);
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.outputs[0].hd_keypaths.len(), 1);
         assert_eq!(
@@ -2016,12 +1990,11 @@ mod test {
         let (wallet, _, _) =
             get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(
             psbt.inputs[0].redeem_script,
@@ -2042,12 +2015,11 @@ mod test {
         let (wallet, _, _) =
             get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.inputs[0].redeem_script, None);
         assert_eq!(
@@ -2068,12 +2040,11 @@ mod test {
         let (wallet, _, _) =
             get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         let script = Script::from(
             Vec::<u8>::from_hex(
@@ -2091,12 +2062,11 @@ mod test {
         let (wallet, _, _) =
             get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         assert!(psbt.inputs[0].non_witness_utxo.is_some());
         assert!(psbt.inputs[0].witness_utxo.is_none());
@@ -2107,12 +2077,11 @@ mod test {
         let (wallet, _, _) =
             get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         assert!(psbt.inputs[0].non_witness_utxo.is_none());
         assert!(psbt.inputs[0].witness_utxo.is_some());
@@ -2123,12 +2092,11 @@ mod test {
         let (wallet, _, _) =
             get_funded_wallet("sh(wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         assert!(psbt.inputs[0].non_witness_utxo.is_none());
         assert!(psbt.inputs[0].witness_utxo.is_some());
@@ -2139,13 +2107,12 @@ mod test {
         let (wallet, _, _) =
             get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
             .drain_wallet()
-            .force_non_witness_utxo()
-            .finish()
-            .unwrap();
+            .force_non_witness_utxo();
+        let (psbt, _) = builder.finish().unwrap();
 
         assert!(psbt.inputs[0].non_witness_utxo.is_some());
         assert!(psbt.inputs[0].witness_utxo.is_some());
@@ -2161,16 +2128,15 @@ mod test {
         );
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 30_000)
             .add_utxo(OutPoint {
                 txid: small_output_txid,
                 vout: 0,
             })
-            .unwrap()
-            .finish()
             .unwrap();
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(
             psbt.global.unsigned_tx.input.len(),
@@ -2191,17 +2157,16 @@ mod test {
         );
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 30_000)
             .add_utxo(OutPoint {
                 txid: small_output_txid,
                 vout: 0,
             })
             .unwrap()
-            .manually_selected_only()
-            .finish()
-            .unwrap();
+            .manually_selected_only();
+        builder.finish().unwrap();
     }
 
     #[test]
@@ -2210,11 +2175,9 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 30_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 30_000);
+        builder.finish().unwrap();
     }
 
     #[test]
@@ -2227,12 +2190,11 @@ mod test {
         let path = vec![(root_id, vec![0])].into_iter().collect();
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 30_000)
-            .policy_path(path, KeychainKind::External)
-            .finish()
-            .unwrap();
+            .policy_path(path, KeychainKind::External);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
     }
@@ -2247,12 +2209,11 @@ mod test {
         let path = vec![(root_id, vec![1])].into_iter().collect();
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 30_000)
-            .policy_path(path, KeychainKind::External)
-            .finish()
-            .unwrap();
+            .policy_path(path, KeychainKind::External);
+        let (psbt, _) = builder.finish().unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 144);
     }
@@ -2265,12 +2226,11 @@ mod test {
 
         let (wallet, _, _) = get_funded_wallet("wpkh([73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .add_global_xpubs()
-            .finish()
-            .unwrap();
+            .add_global_xpubs();
+        let (psbt, _) = builder.finish().unwrap();
 
         let type_value = 0x01;
         let key = base58::from_check("tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3").unwrap();
@@ -2291,12 +2251,11 @@ mod test {
     fn test_create_tx_global_xpubs_origin_missing() {
         let (wallet, _, _) = get_funded_wallet("wpkh(tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
         let addr = wallet.get_new_address().unwrap();
-        wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .add_global_xpubs()
-            .finish()
-            .unwrap();
+            .add_global_xpubs();
+        builder.finish().unwrap();
     }
 
     #[test]
@@ -2307,12 +2266,11 @@ mod test {
 
         let (wallet, _, _) = get_funded_wallet("wpkh(tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL/0/*)");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .add_global_xpubs()
-            .finish()
-            .unwrap();
+            .add_global_xpubs();
+        let (psbt, _) = builder.finish().unwrap();
 
         let type_value = 0x01;
         let key = base58::from_check("tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL").unwrap();
@@ -2332,11 +2290,9 @@ mod test {
     fn test_bump_fee_irreplaceable_tx() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, mut details) = wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 25_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, mut details) = builder.finish().unwrap();
 
         let tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -2352,11 +2308,9 @@ mod test {
     fn test_bump_fee_confirmed_tx() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, mut details) = wallet
-            .build_tx()
-            .add_recipient(addr.script_pubkey(), 25_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, mut details) = builder.finish().unwrap();
 
         let tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -2373,12 +2327,11 @@ mod test {
     fn test_bump_fee_low_fee_rate() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, mut details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut details) = builder.finish().unwrap();
 
         let tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -2386,12 +2339,9 @@ mod test {
         details.transaction = Some(tx);
         wallet.database.borrow_mut().set_tx(&details).unwrap();
 
-        wallet
-            .build_fee_bump(txid)
-            .unwrap()
-            .fee_rate(FeeRate::from_sat_per_vb(1.0))
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_rate(FeeRate::from_sat_per_vb(1.0));
+        builder.finish().unwrap();
     }
 
     #[test]
@@ -2399,12 +2349,11 @@ mod test {
     fn test_bump_fee_low_abs() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, mut details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut details) = builder.finish().unwrap();
 
         let tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -2412,12 +2361,9 @@ mod test {
         details.transaction = Some(tx);
         wallet.database.borrow_mut().set_tx(&details).unwrap();
 
-        wallet
-            .build_fee_bump(txid)
-            .unwrap()
-            .fee_absolute(10)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_absolute(10);
+        builder.finish().unwrap();
     }
 
     #[test]
@@ -2425,12 +2371,11 @@ mod test {
     fn test_bump_fee_zero_abs() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, mut details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut details) = builder.finish().unwrap();
 
         let tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -2438,24 +2383,20 @@ mod test {
         details.transaction = Some(tx);
         wallet.database.borrow_mut().set_tx(&details).unwrap();
 
-        wallet
-            .build_fee_bump(txid)
-            .unwrap()
-            .fee_absolute(0)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_absolute(0);
+        builder.finish().unwrap();
     }
 
     #[test]
     fn test_bump_fee_reduce_change() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
         // skip saving the new utxos, we know they can't be used anyways
@@ -2474,12 +2415,9 @@ mod test {
             .set_tx(&original_details)
             .unwrap();
 
-        let (psbt, details) = wallet
-            .build_fee_bump(txid)
-            .unwrap()
-            .fee_rate(FeeRate::from_sat_per_vb(2.5))
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_rate(FeeRate::from_sat_per_vb(2.5));
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(details.sent, original_details.sent);
         assert_eq!(
@@ -2514,12 +2452,11 @@ mod test {
     fn test_bump_fee_absolute_reduce_change() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 25_000)
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
         // skip saving the new utxos, we know they can't be used anyways
@@ -2538,12 +2475,9 @@ mod test {
             .set_tx(&original_details)
             .unwrap();
 
-        let (psbt, details) = wallet
-            .build_fee_bump(txid)
-            .unwrap()
-            .fee_absolute(200)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_absolute(200);
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(details.sent, original_details.sent);
         assert_eq!(
@@ -2583,13 +2517,12 @@ mod test {
     fn test_bump_fee_reduce_single_recipient() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
             .drain_wallet()
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
         for txin in &mut tx.input {
@@ -2607,13 +2540,11 @@ mod test {
             .set_tx(&original_details)
             .unwrap();
 
-        let (psbt, details) = wallet
-            .build_fee_bump(txid)
-            .unwrap()
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder
             .fee_rate(FeeRate::from_sat_per_vb(2.5))
-            .maintain_single_recipient()
-            .finish()
-            .unwrap();
+            .maintain_single_recipient();
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(details.sent, original_details.sent);
         assert!(details.fees > original_details.fees);
@@ -2629,13 +2560,12 @@ mod test {
     fn test_bump_fee_absolute_reduce_single_recipient() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
             .drain_wallet()
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
         for txin in &mut tx.input {
@@ -2653,13 +2583,9 @@ mod test {
             .set_tx(&original_details)
             .unwrap();
 
-        let (psbt, details) = wallet
-            .build_fee_bump(txid)
-            .unwrap()
-            .maintain_single_recipient()
-            .fee_absolute(300)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.maintain_single_recipient().fee_absolute(300);
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(details.sent, original_details.sent);
         assert!(details.fees > original_details.fees);
@@ -2685,15 +2611,14 @@ mod test {
             vout: 0,
         };
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
             .add_utxo(outpoint)
             .unwrap()
             .manually_selected_only()
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
         for txin in &mut tx.input {
@@ -2714,14 +2639,12 @@ mod test {
 
         // for the new feerate, it should be enough to reduce the output, but since we specify
         // `drain_wallet` we expect to spend everything
-        let (_, details) = wallet
-            .build_fee_bump(txid)
-            .unwrap()
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder
             .drain_wallet()
             .maintain_single_recipient()
-            .fee_rate(FeeRate::from_sat_per_vb(5.0))
-            .finish()
-            .unwrap();
+            .fee_rate(FeeRate::from_sat_per_vb(5.0));
+        let (_, details) = builder.finish().unwrap();
         assert_eq!(details.sent, 75_000);
     }
 
@@ -2743,15 +2666,14 @@ mod test {
             vout: 0,
         };
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
             .add_utxo(outpoint)
             .unwrap()
             .manually_selected_only()
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
         for txin in &mut tx.input {
@@ -2770,15 +2692,13 @@ mod test {
             .unwrap();
         assert_eq!(original_details.sent, 25_000);
 
-        wallet
-            .build_fee_bump(txid)
-            .unwrap()
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder
             .add_utxo(outpoint)
             .unwrap()
             .manually_selected_only()
-            .fee_rate(FeeRate::from_sat_per_vb(255.0))
-            .finish()
-            .unwrap();
+            .fee_rate(FeeRate::from_sat_per_vb(255.0));
+        builder.finish().unwrap();
     }
 
     #[test]
@@ -2791,12 +2711,11 @@ mod test {
         );
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 45_000)
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
         // skip saving the new utxos, we know they can't be used anyways
@@ -2815,12 +2734,9 @@ mod test {
             .set_tx(&original_details)
             .unwrap();
 
-        let (psbt, details) = wallet
-            .build_fee_bump(txid)
-            .unwrap()
-            .fee_rate(FeeRate::from_sat_per_vb(50.0))
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_rate(FeeRate::from_sat_per_vb(50.0));
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(details.sent, original_details.sent + 25_000);
         assert_eq!(details.fees + details.received, 30_000);
@@ -2858,12 +2774,11 @@ mod test {
         );
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 45_000)
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
         // skip saving the new utxos, we know they can't be used anyways
@@ -2882,12 +2797,9 @@ mod test {
             .set_tx(&original_details)
             .unwrap();
 
-        let (psbt, details) = wallet
-            .build_fee_bump(txid)
-            .unwrap()
-            .fee_absolute(6_000)
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_absolute(6_000);
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(details.sent, original_details.sent + 25_000);
         assert_eq!(details.fees + details.received, 30_000);
@@ -2926,8 +2838,8 @@ mod test {
 
         // initially make a tx without change by using `set_single_recipient`
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
             .add_utxo(OutPoint {
                 txid: incoming_txid,
@@ -2935,9 +2847,8 @@ mod test {
             })
             .unwrap()
             .manually_selected_only()
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
 
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -2959,12 +2870,9 @@ mod test {
 
         // now bump the fees without using `maintain_single_recipient`. the wallet should add an
         // extra input and a change output, and leave the original output untouched
-        let (psbt, details) = wallet
-            .build_fee_bump(txid)
-            .unwrap()
-            .fee_rate(FeeRate::from_sat_per_vb(50.0))
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_rate(FeeRate::from_sat_per_vb(50.0));
+        let (psbt, details) = builder.finish().unwrap();
 
         let original_send_all_amount = original_details.sent - original_details.fees;
         assert_eq!(details.sent, original_details.sent + 50_000);
@@ -3006,12 +2914,11 @@ mod test {
         );
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 45_000)
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
         let mut tx = psbt.extract_tx();
         assert_eq!(tx.input.len(), 1);
         assert_eq!(tx.output.len(), 2);
@@ -3032,12 +2939,9 @@ mod test {
             .set_tx(&original_details)
             .unwrap();
 
-        let (psbt, details) = wallet
-            .build_fee_bump(txid)
-            .unwrap()
-            .fee_rate(FeeRate::from_sat_per_vb(140.0))
-            .finish()
-            .unwrap();
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_rate(FeeRate::from_sat_per_vb(140.0));
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(original_details.received, 5_000 - original_details.fees);
 
@@ -3070,12 +2974,11 @@ mod test {
         );
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 45_000)
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
         // skip saving the new utxos, we know they can't be used anyways
@@ -3096,17 +2999,15 @@ mod test {
 
         // the new fee_rate is low enough that just reducing the change would be fine, but we force
         // the addition of an extra input with `add_utxo()`
-        let (psbt, details) = wallet
-            .build_fee_bump(txid)
-            .unwrap()
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder
             .add_utxo(OutPoint {
                 txid: incoming_txid,
                 vout: 0,
             })
             .unwrap()
-            .fee_rate(FeeRate::from_sat_per_vb(5.0))
-            .finish()
-            .unwrap();
+            .fee_rate(FeeRate::from_sat_per_vb(5.0));
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(details.sent, original_details.sent + 25_000);
         assert_eq!(details.fees + details.received, 30_000);
@@ -3144,12 +3045,11 @@ mod test {
         );
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, mut original_details) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 45_000)
-            .enable_rbf()
-            .finish()
-            .unwrap();
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
         // skip saving the new utxos, we know they can't be used anyways
@@ -3170,17 +3070,15 @@ mod test {
 
         // the new fee_rate is low enough that just reducing the change would be fine, but we force
         // the addition of an extra input with `add_utxo()`
-        let (psbt, details) = wallet
-            .build_fee_bump(txid)
-            .unwrap()
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder
             .add_utxo(OutPoint {
                 txid: incoming_txid,
                 vout: 0,
             })
             .unwrap()
-            .fee_absolute(250)
-            .finish()
-            .unwrap();
+            .fee_absolute(250);
+        let (psbt, details) = builder.finish().unwrap();
 
         assert_eq!(details.sent, original_details.sent + 25_000);
         assert_eq!(details.fees + details.received, 30_000);
@@ -3212,12 +3110,11 @@ mod test {
     fn test_sign_single_xprv() {
         let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
         assert_eq!(finalized, true);
@@ -3230,12 +3127,11 @@ mod test {
     fn test_sign_single_xprv_bip44_path() {
         let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/44'/0'/0'/0/*)");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
         assert_eq!(finalized, true);
@@ -3248,12 +3144,11 @@ mod test {
     fn test_sign_single_xprv_sh_wpkh() {
         let (wallet, _, _) = get_funded_wallet("sh(wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*))");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
         assert_eq!(finalized, true);
@@ -3267,12 +3162,11 @@ mod test {
         let (wallet, _, _) =
             get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
         let addr = wallet.get_new_address().unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
 
         let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
         assert_eq!(finalized, true);
@@ -3285,12 +3179,11 @@ mod test {
     fn test_sign_single_xprv_no_hd_keypaths() {
         let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
         let addr = wallet.get_new_address().unwrap();
-        let (mut psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .set_single_recipient(addr.script_pubkey())
-            .drain_wallet()
-            .finish()
-            .unwrap();
+            .drain_wallet();
+        let (mut psbt, _) = builder.finish().unwrap();
 
         psbt.inputs[0].hd_keypaths.clear();
         assert_eq!(psbt.inputs[0].hd_keypaths.len(), 0);
@@ -3306,12 +3199,11 @@ mod test {
     fn test_include_output_redeem_witness_script() {
         let (wallet, _, _) = get_funded_wallet("sh(wsh(multi(1,cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW,cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu)))");
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 45_000)
-            .include_output_redeem_witness_script()
-            .finish()
-            .unwrap();
+            .include_output_redeem_witness_script();
+        let (psbt, _) = builder.finish().unwrap();
 
         // p2sh-p2wsh transaction should contain both witness and redeem scripts
         assert!(psbt
@@ -3324,12 +3216,11 @@ mod test {
     fn test_signing_only_one_of_multiple_inputs() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
-        let (mut psbt, _) = wallet
-            .build_tx()
+        let mut builder = wallet.build_tx();
+        builder
             .add_recipient(addr.script_pubkey(), 45_000)
-            .include_output_redeem_witness_script()
-            .finish()
-            .unwrap();
+            .include_output_redeem_witness_script();
+        let (mut psbt, _) = builder.finish().unwrap();
 
         // add another input to the psbt that is at least passable.
         let mut dud_input = bitcoin::util::psbt::Input::default();
index a9ed5d8bccb0927606102956f82a59b4412640d8..fce15827a80119215a022a34ffc197db13378b7a 100644 (file)
@@ -36,7 +36,7 @@
 //! // create a TxBuilder from a wallet
 //! let mut tx_builder = wallet.build_tx();
 //!
-//! let (psbt, tx_details) = tx_builder
+//! tx_builder
 //!     // Create a transaction with one output to `to_address` of 50_000 satoshi
 //!     .add_recipient(to_address.script_pubkey(), 50_000)
 //!     // With a custom fee rate of 5.0 satoshi/vbyte
@@ -44,9 +44,8 @@
 //!     // Only spend non-change outputs
 //!     .do_not_spend_change()
 //!     // Turn on RBF signaling
-//!     .enable_rbf()
-//!     .finish()?;
-//!
+//!     .enable_rbf();
+//! let (psbt, tx_details) = tx_builder.finish()?;
 //! # Ok::<(), bdk::Error>(())
 //! ```
 
@@ -80,11 +79,12 @@ impl TxBuilderContext for BumpFee {}
 
 /// A transaction builder
 ///
-/// A `TxBuilder` is initially created by calling [`build_tx`] or [`build_fee_bump`] on a wallet.
-/// From there you set sepcific options on the builder until finally calling [`finish`] to get the transaction.
+/// 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 method on TxBuilder takes and returns `&mut self` so you can use either use a chaining call
-/// or assign the builder and call normally as in the following example:
+/// Each option setting method on `TxBuilder` takes and returns `&mut self` so you can chain calls
+/// as in the following example:
 ///
 /// ```
 /// # use bdk::*;
@@ -95,27 +95,31 @@ impl TxBuilderContext for BumpFee {}
 /// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
 /// # let addr2 = addr1.clone();
 /// // chaining
-/// let (psbt1, details) =  wallet.build_tx()
+/// 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)
-///        .finish()?;
+///        .add_recipient(addr2.script_pubkey(), 50_000);
+///     builder.finish()?
+/// };
 ///
 /// // non-chaining
-/// let mut builder = wallet.build_tx();
-/// for addr in &[addr1, addr2] {
-///     builder.add_recipient(addr.script_pubkey(), 50_000);
-/// }
-/// let (psbt2, details) = builder.ordering(TxOrdering::Untouched).finish()?;
-/// //
+/// 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.global.unsigned_tx.output[..2], psbt2.global.unsigned_tx.output[..2]);
 /// # Ok::<(), bdk::Error>(())
 /// ```
 ///
-/// At the moment [`coin_selection`] is an exception - it consumes `self`.
-/// This means it is usually best to call [`coin_selection`] first before calling other methods.
-///
-/// Note that calling methods on the builder after calling [`finish`] will result in a panic.
+/// 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](super::tx_builder)'s documentation;
 ///
@@ -128,8 +132,8 @@ pub struct TxBuilder<'a, B, D, Cs, Ctx> {
     // params and coin_selection are Options not becasue they are optionally set (they are always
     // there) but because `.finish()` uses `Option::take` to get an owned value from a &mut self.
     // They are only `None` after `.finish()` is called.
-    pub(crate) params: Option<TxParams>,
-    pub(crate) coin_selection: Option<Cs>,
+    pub(crate) params: TxParams,
+    pub(crate) coin_selection: Cs,
     pub(crate) phantom: PhantomData<Ctx>,
 }
 
@@ -180,20 +184,15 @@ impl std::default::Default for FeePolicy {
 impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext>
     TxBuilder<'a, B, D, Cs, Ctx>
 {
-    fn params(&mut self) -> &mut TxParams {
-        self.params
-            .as_mut()
-            .expect("method called on transaction builder after it was finalized")
-    }
     /// Set a custom fee rate
     pub fn fee_rate(&mut self, fee_rate: FeeRate) -> &mut Self {
-        self.params().fee_policy = Some(FeePolicy::FeeRate(fee_rate));
+        self.params.fee_policy = Some(FeePolicy::FeeRate(fee_rate));
         self
     }
 
     /// Set an absolute fee
     pub fn fee_absolute(&mut self, fee_amount: u64) -> &mut Self {
-        self.params().fee_policy = Some(FeePolicy::FeeAmount(fee_amount));
+        self.params.fee_policy = Some(FeePolicy::FeeAmount(fee_amount));
         self
     }
 
@@ -261,8 +260,8 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
         keychain: KeychainKind,
     ) -> &mut Self {
         let to_update = match keychain {
-            KeychainKind::Internal => &mut self.params().internal_policy_path,
-            KeychainKind::External => &mut self.params().external_policy_path,
+            KeychainKind::Internal => &mut self.params.internal_policy_path,
+            KeychainKind::External => &mut self.params.external_policy_path,
         };
 
         *to_update = Some(policy_path);
@@ -274,12 +273,12 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     /// 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 fn add_utxo(&mut self, outpoint: OutPoint) -> Result<&mut Self, Error> {
-        if self.params().utxos.get(&outpoint).is_none() {
+        if self.params.utxos.get(&outpoint).is_none() {
             let deriv_ctx = crate::wallet::descriptor_to_pk_ctx(self.wallet.secp_ctx());
             let utxo = self.wallet.get_utxo(outpoint)?.ok_or(Error::UnknownUTXO)?;
             let descriptor = self.wallet.get_descriptor_for_keychain(utxo.keychain);
             let satisfaction_weight = descriptor.max_satisfaction_weight(deriv_ctx).unwrap();
-            self.params()
+            self.params
                 .utxos
                 .insert(outpoint, (utxo, satisfaction_weight));
         }
@@ -293,7 +292,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     ///
     /// [`add_utxo`]: Self::add_utxo
     pub fn manually_selected_only(&mut self) -> &mut Self {
-        self.params().manually_selected_only = true;
+        self.params.manually_selected_only = true;
         self
     }
 
@@ -302,7 +301,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     /// 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.
     pub fn unspendable(&mut self, unspendable: Vec<OutPoint>) -> &mut Self {
-        self.params().unspendable = unspendable.into_iter().collect();
+        self.params.unspendable = unspendable.into_iter().collect();
         self
     }
 
@@ -311,7 +310,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     /// 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.
     pub fn add_unspendable(&mut self, unspendable: OutPoint) -> &mut Self {
-        self.params().unspendable.insert(unspendable);
+        self.params.unspendable.insert(unspendable);
         self
     }
 
@@ -319,13 +318,13 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     ///
     /// **Use this option very carefully**
     pub fn sighash(&mut self, sighash: SigHashType) -> &mut Self {
-        self.params().sighash = Some(sighash);
+        self.params.sighash = Some(sighash);
         self
     }
 
     /// Choose the ordering for inputs and outputs of the transaction
     pub fn ordering(&mut self, ordering: TxOrdering) -> &mut Self {
-        self.params().ordering = ordering;
+        self.params.ordering = ordering;
         self
     }
 
@@ -333,7 +332,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     ///
     /// This can cause conflicts if the wallet's descriptors contain an "after" (OP_CLTV) operator.
     pub fn nlocktime(&mut self, locktime: u32) -> &mut Self {
-        self.params().locktime = Some(locktime);
+        self.params.locktime = Some(locktime);
         self
     }
 
@@ -342,7 +341,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     /// The `version` should always be greater than `0` and greater than `1` if the wallet's
     /// descriptors contain an "older" (OP_CSV) operator.
     pub fn version(&mut self, version: i32) -> &mut Self {
-        self.params().version = Some(Version(version));
+        self.params.version = Some(Version(version));
         self
     }
 
@@ -351,7 +350,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     /// This effectively adds all the change outputs to the "unspendable" list. See
     /// [`TxBuilder::unspendable`].
     pub fn do_not_spend_change(&mut self) -> &mut Self {
-        self.params().change_policy = ChangeSpendPolicy::ChangeForbidden;
+        self.params.change_policy = ChangeSpendPolicy::ChangeForbidden;
         self
     }
 
@@ -360,14 +359,14 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     /// This effectively adds all the non-change outputs to the "unspendable" list. See
     /// [`TxBuilder::unspendable`].
     pub fn only_spend_change(&mut self) -> &mut Self {
-        self.params().change_policy = ChangeSpendPolicy::OnlyChange;
+        self.params.change_policy = ChangeSpendPolicy::OnlyChange;
         self
     }
 
     /// Set a specific [`ChangeSpendPolicy`]. See [`TxBuilder::do_not_spend_change`] and
     /// [`TxBuilder::only_spend_change`] for some shortcuts.
     pub fn change_policy(&mut self, change_policy: ChangeSpendPolicy) -> &mut Self {
-        self.params().change_policy = change_policy;
+        self.params.change_policy = change_policy;
         self
     }
 
@@ -376,7 +375,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     ///
     /// This is useful for signers which always require it, like Trezor hardware wallets.
     pub fn force_non_witness_utxo(&mut self) -> &mut Self {
-        self.params().force_non_witness_utxo = true;
+        self.params.force_non_witness_utxo = true;
         self
     }
 
@@ -385,7 +384,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     ///
     /// This is useful for signers which always require it, like ColdCard hardware wallets.
     pub fn include_output_redeem_witness_script(&mut self) -> &mut Self {
-        self.params().include_output_redeem_witness_script = true;
+        self.params.include_output_redeem_witness_script = true;
         self
     }
 
@@ -395,13 +394,13 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     /// This is useful for offline signers that take part to a multisig. Some hardware wallets like
     /// BitBox and ColdCard are known to require this.
     pub fn add_global_xpubs(&mut self) -> &mut Self {
-        self.params().add_global_xpubs = true;
+        self.params.add_global_xpubs = true;
         self
     }
 
     /// Spend all the available inputs. This respects filters like [`TxBuilder::unspendable`] and the change policy.
     pub fn drain_wallet(&mut self) -> &mut Self {
-        self.params().drain_wallet = true;
+        self.params.drain_wallet = true;
         self
     }
 
@@ -414,14 +413,10 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
         self,
         coin_selection: P,
     ) -> TxBuilder<'a, B, D, P, Ctx> {
-        assert!(
-            self.coin_selection.is_some(),
-            "can't set coin_selection after finish() has been called"
-        );
         TxBuilder {
             wallet: self.wallet,
             params: self.params,
-            coin_selection: Some(coin_selection),
+            coin_selection,
             phantom: PhantomData,
         }
     }
@@ -431,24 +426,21 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
     /// Returns the [`BIP174`] "PSBT" and summary details about the transaction.
     ///
     /// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
-    pub fn finish(&mut self) -> Result<(PSBT, TransactionDetails), Error> {
-        self.wallet.create_tx(
-            self.coin_selection.take().unwrap(),
-            self.params.take().unwrap(),
-        )
+    pub fn finish(self) -> Result<(PSBT, TransactionDetails), Error> {
+        self.wallet.create_tx(self.coin_selection, self.params)
     }
 }
 
 impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>> TxBuilder<'a, B, D, Cs, CreateTx> {
     /// Replace the recipients already added with a new list
     pub fn set_recipients(&mut self, recipients: Vec<(Script, u64)>) -> &mut Self {
-        self.params().recipients = recipients;
+        self.params.recipients = recipients;
         self
     }
 
     /// Add a recipient to the internal list
     pub fn add_recipient(&mut self, script_pubkey: Script, amount: u64) -> &mut Self {
-        self.params().recipients.push((script_pubkey, amount));
+        self.params.recipients.push((script_pubkey, amount));
         self
     }
 
@@ -467,8 +459,8 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>> TxBuilder<'a, B, D,
     /// add [`maintain_single_recipient`](Self::maintain_single_recipient) to correctly update the
     /// single output instead of adding one more for the change.
     pub fn set_single_recipient(&mut self, recipient: Script) -> &mut Self {
-        self.params().single_recipient = Some(recipient);
-        self.params().recipients.clear();
+        self.params.single_recipient = Some(recipient);
+        self.params.recipients.clear();
 
         self
     }
@@ -477,7 +469,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>> TxBuilder<'a, B, D,
     ///
     /// This will use the default nSequence value of `0xFFFFFFFD`.
     pub fn enable_rbf(&mut self) -> &mut Self {
-        self.params().rbf = Some(RBFValue::Default);
+        self.params.rbf = Some(RBFValue::Default);
         self
     }
 
@@ -489,7 +481,7 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>> TxBuilder<'a, B, D,
     /// If the `nsequence` is higher than `0xFFFFFFFD` an error will be thrown, since it would not
     /// be a valid nSequence to signal RBF.
     pub fn enable_rbf_with_sequence(&mut self, nsequence: u32) -> &mut Self {
-        self.params().rbf = Some(RBFValue::Value(nsequence));
+        self.params.rbf = Some(RBFValue::Value(nsequence));
         self
     }
 }
@@ -509,9 +501,9 @@ impl<'a, B, D: BatchDatabase> TxBuilder<'a, B, D, DefaultCoinSelectionAlgorithm,
     ///
     /// [`add_utxo`]: Self::add_utxo
     pub fn maintain_single_recipient(&mut self) -> &mut Self {
-        let mut recipients = self.params().recipients.drain(..).collect::<Vec<_>>();
+        let mut recipients = self.params.recipients.drain(..).collect::<Vec<_>>();
         assert_eq!(recipients.len(), 1, "maintain_single_recipient must not be called while bumping a transactions with more than one output");
-        self.params().single_recipient = Some(recipients.pop().unwrap().0);
+        self.params.single_recipient = Some(recipients.pop().unwrap().0);
         // Since we are fee bumping and maintaining a single recipient we never want to add any more non-manual inputs.
         self
     }
index 7f5528530f6bc8deb8260c47a84ff787fc33dcf2..776fde60db21534ff50b974ec0f1a26f4d2ff4e1 100644 (file)
@@ -307,7 +307,9 @@ pub fn bdk_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenStream
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 50_000);
 
-                    let (psbt, details) = wallet.build_tx().add_recipient(node_addr.script_pubkey(), 25_000).finish().unwrap();
+                    let mut builder = wallet.build_tx();
+                    builder.add_recipient(node_addr.script_pubkey(), 25_000);
+                    let (psbt, details) = builder.finish().unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     let tx = psbt.extract_tx();
@@ -334,7 +336,9 @@ pub fn bdk_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenStream
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 50_000);
 
-                    let (psbt, details) = wallet.build_tx().add_recipient(node_addr.script_pubkey(), 25_000).finish().unwrap();
+                    let mut builder = wallet.build_tx();
+                    builder.add_recipient(node_addr.script_pubkey(), 25_000);
+                    let (psbt, details) = builder.finish().unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     let sent_txid = wallet.broadcast(psbt.extract_tx()).unwrap();
@@ -373,7 +377,9 @@ pub fn bdk_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenStream
 
                     let mut total_sent = 0;
                     for _ in 0..5 {
-                        let (psbt, details) = wallet.build_tx().add_recipient(node_addr.script_pubkey(), 5_000).finish().unwrap();
+                        let mut builder = wallet.build_tx();
+                        builder.add_recipient(node_addr.script_pubkey(), 5_000);
+                        let (psbt, details) = builder.finish().unwrap();
                         let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                         assert!(finalized, "Cannot finalize transaction");
                         wallet.broadcast(psbt.extract_tx()).unwrap();
@@ -405,7 +411,9 @@ pub fn bdk_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenStream
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 50_000);
 
-                    let (psbt, details) = wallet.build_tx().add_recipient(node_addr.script_pubkey().clone(), 5_000).enable_rbf().finish().unwrap();
+                    let mut builder = wallet.build_tx();
+                    builder.add_recipient(node_addr.script_pubkey().clone(), 5_000).enable_rbf();
+                    let (psbt, details) = builder.finish().unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     wallet.broadcast(psbt.extract_tx()).unwrap();
@@ -413,7 +421,9 @@ pub fn bdk_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenStream
                     assert_eq!(wallet.get_balance().unwrap(), 50_000 - details.fees - 5_000);
                     assert_eq!(wallet.get_balance().unwrap(), details.received);
 
-                    let (new_psbt, new_details) = wallet.build_fee_bump(details.txid).unwrap().fee_rate(FeeRate::from_sat_per_vb(2.1)).finish().unwrap();
+                    let mut builder = wallet.build_fee_bump(details.txid).unwrap();
+                    builder.fee_rate(FeeRate::from_sat_per_vb(2.1));
+                    let (new_psbt, new_details) = builder.finish().unwrap();
                     let (new_psbt, finalized) = wallet.sign(new_psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     wallet.broadcast(new_psbt.extract_tx()).unwrap();
@@ -437,7 +447,9 @@ pub fn bdk_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenStream
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 50_000);
 
-                    let (psbt, details) = wallet.build_tx().add_recipient(node_addr.script_pubkey().clone(), 49_000).enable_rbf().finish().unwrap();
+                    let mut builder = wallet.build_tx();
+                    builder.add_recipient(node_addr.script_pubkey().clone(), 49_000).enable_rbf();
+                    let (psbt, details) = builder.finish().unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     wallet.broadcast(psbt.extract_tx()).unwrap();
@@ -445,7 +457,9 @@ pub fn bdk_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenStream
                     assert_eq!(wallet.get_balance().unwrap(), 1_000 - details.fees);
                     assert_eq!(wallet.get_balance().unwrap(), details.received);
 
-                    let (new_psbt, new_details) = wallet.build_fee_bump(details.txid).unwrap().fee_rate(FeeRate::from_sat_per_vb(5.0)).finish().unwrap();
+                    let mut builder = wallet.build_fee_bump(details.txid).unwrap();
+                    builder.fee_rate(FeeRate::from_sat_per_vb(5.0));
+                    let (new_psbt, new_details) = builder.finish().unwrap();
                     let (new_psbt, finalized) = wallet.sign(new_psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     wallet.broadcast(new_psbt.extract_tx()).unwrap();
@@ -469,7 +483,9 @@ pub fn bdk_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenStream
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 75_000);
 
-                    let (psbt, details) = wallet.build_tx().add_recipient(node_addr.script_pubkey().clone(), 49_000).enable_rbf().finish().unwrap();
+                    let mut builder = wallet.build_tx();
+                    builder.add_recipient(node_addr.script_pubkey().clone(), 49_000).enable_rbf();
+                    let (psbt, details) = builder.finish().unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     wallet.broadcast(psbt.extract_tx()).unwrap();
@@ -477,7 +493,9 @@ pub fn bdk_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenStream
                     assert_eq!(wallet.get_balance().unwrap(), 26_000 - details.fees);
                     assert_eq!(details.received, 1_000 - details.fees);
 
-                    let (new_psbt, new_details) = wallet.build_fee_bump(details.txid).unwrap().fee_rate(FeeRate::from_sat_per_vb(10.0)).finish().unwrap();
+                    let mut builder = wallet.build_fee_bump(details.txid).unwrap();
+                    builder.fee_rate(FeeRate::from_sat_per_vb(10.0));
+                    let (new_psbt, new_details) = builder.finish().unwrap();
                     let (new_psbt, finalized) = wallet.sign(new_psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     wallet.broadcast(new_psbt.extract_tx()).unwrap();
@@ -499,7 +517,9 @@ pub fn bdk_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenStream
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 75_000);
 
-                    let (psbt, details) = wallet.build_tx().add_recipient(node_addr.script_pubkey().clone(), 49_000).enable_rbf().finish().unwrap();
+                    let mut builder = wallet.build_tx();
+                    builder.add_recipient(node_addr.script_pubkey().clone(), 49_000).enable_rbf();
+                    let (psbt, details) = builder.finish().unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     wallet.broadcast(psbt.extract_tx()).unwrap();
@@ -507,7 +527,9 @@ pub fn bdk_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenStream
                     assert_eq!(wallet.get_balance().unwrap(), 26_000 - details.fees);
                     assert_eq!(details.received, 1_000 - details.fees);
 
-                    let (new_psbt, new_details) = wallet.build_fee_bump(details.txid).unwrap().fee_rate(FeeRate::from_sat_per_vb(123.0)).finish().unwrap();
+                    let mut builder = wallet.build_fee_bump(details.txid).unwrap();
+                    builder.fee_rate(FeeRate::from_sat_per_vb(123.0));
+                    let (new_psbt, new_details) = builder.finish().unwrap();
                     println!("{:#?}", new_details);
 
                     let (new_psbt, finalized) = wallet.sign(new_psbt, None).unwrap();