Merge bitcoindevkit/bdk#1411: feat: update keychain::Balance to use bitcoin::Amount
				
					
				
			22aa534d7648e5808414ea3adfcfb702572bd6c9 feat: use `Amount` on `TxBuilder::add_recipient` (Leonardo Lima) d5c0e7200cba0c3b4d3e3fbea168cd07ee6c1d2c feat: use `Amount` on `spk_txout_index` and related (Leonardo Lima) 8a33d98db977a07e130ad57fa9c658a5c90d4a4b feat: update `wallet::Balance` to use `bitcoin::Amount` (Leonardo Lima) Pull request description: fixes #823 <!-- You can erase any parts of this template not applicable to your Pull Request. --> ### Description It's being used on `Balance`, and throughout the code, an `u64` represents the amount, which relies on the user to infer its sats, not millisats, or any other representation. It updates the usage of `u64` on `Balance`, and other APIs: - `TxParams::add_recipient` - `KeyChainTxOutIndex::sent_and_received`, `KeyChainTxOutIndex::net_value` - `SpkTxOutIndex::sent_and_received`, `SpkTxOutIndex::net_value` <!-- Describe the purpose of this PR, what's being adding and/or fixed --> ### Notes to the reviewers <!-- In this section you can include notes directed to the reviewers, like explaining why some parts of the PR were done in a specific way --> It updates some of the APIs to expect the `bitcoin::Amount`, but it does not update internal usage of u64, such as `TxParams` still expects and uses `u64`, please see the PR comments for related discussion. ### Changelog notice <!-- Notice the release manager should include in the release tag message changelog --> <!-- See https://keepachangelog.com/en/1.0.0/ for examples --> - Changed the `keychain::Balance` struct fields to use `Amount` instead of `u64`. - Changed the `add_recipient` method on `TxBuilder` implementation to expect `bitcoin::Amount`. - Changed the `sent_and_received`, and `net_value` methods on `KeyChainTxOutIndex` to expect `bitcoin::Amount`. - Changed the `sent_and_received`, and `net_value` methods on `SpkTxOutIndex` to expect `bitcoin::Amount`. ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing #### New Features: * [x] I've added tests for the new feature * [x] I've added docs for the new feature #### Bugfixes: * [x] This pull request breaks the existing API * [ ] I've added tests to reproduce the issue which are now passing * [x] I'm linking the issue being fixed by this PR ACKs for top commit: evanlinjin: ACK 22aa534d7648e5808414ea3adfcfb702572bd6c9 Tree-SHA512: c4e8198d96c0d66cc3d2e4149e8a56bb7565b9cd49ff42113eaebd24b1d7bfeecd7124db0b06524b78b8891ee1bde1546705b80afad408f48495cf3c02446d02
This commit is contained in:
		
						commit
						dcd2d4741d
					
				| @ -92,7 +92,7 @@ | |||||||
| //!     .unwrap();
 | //!     .unwrap();
 | ||||||
| //! let psbt = {
 | //! let psbt = {
 | ||||||
| //!     let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
 | //!     let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
 | ||||||
| //!     builder.add_recipient(to_address.script_pubkey(), 50_000);
 | //!     builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
 | ||||||
| //!     builder.finish()?
 | //!     builder.finish()?
 | ||||||
| //! };
 | //! };
 | ||||||
| //!
 | //!
 | ||||||
|  | |||||||
| @ -32,14 +32,14 @@ use bdk_chain::{ | |||||||
|     IndexedTxGraph, |     IndexedTxGraph, | ||||||
| }; | }; | ||||||
| use bdk_persist::{Persist, PersistBackend}; | use bdk_persist::{Persist, PersistBackend}; | ||||||
| use bitcoin::constants::genesis_block; |  | ||||||
| use bitcoin::secp256k1::{All, Secp256k1}; | use bitcoin::secp256k1::{All, Secp256k1}; | ||||||
| use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; | use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; | ||||||
| use bitcoin::{ | use bitcoin::{ | ||||||
|     absolute, psbt, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence, |     absolute, psbt, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence, | ||||||
|     Transaction, TxOut, Txid, Witness, |     Transaction, TxOut, Txid, Witness, | ||||||
| }; | }; | ||||||
| use bitcoin::{consensus::encode::serialize, transaction, Amount, BlockHash, Psbt}; | use bitcoin::{consensus::encode::serialize, transaction, BlockHash, Psbt}; | ||||||
|  | use bitcoin::{constants::genesis_block, Amount}; | ||||||
| use core::fmt; | use core::fmt; | ||||||
| use core::ops::Deref; | use core::ops::Deref; | ||||||
| use descriptor::error::Error as DescriptorError; | use descriptor::error::Error as DescriptorError; | ||||||
| @ -950,10 +950,10 @@ impl Wallet { | |||||||
|     /// [`insert_txout`]: Self::insert_txout
 |     /// [`insert_txout`]: Self::insert_txout
 | ||||||
|     pub fn calculate_fee_rate(&self, tx: &Transaction) -> Result<FeeRate, CalculateFeeError> { |     pub fn calculate_fee_rate(&self, tx: &Transaction) -> Result<FeeRate, CalculateFeeError> { | ||||||
|         self.calculate_fee(tx) |         self.calculate_fee(tx) | ||||||
|             .map(|fee| bitcoin::Amount::from_sat(fee) / tx.weight()) |             .map(|fee| Amount::from_sat(fee) / tx.weight()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Compute the `tx`'s sent and received amounts (in satoshis).
 |     /// Compute the `tx`'s sent and received [`Amount`]s.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// This method returns a tuple `(sent, received)`. Sent is the sum of the txin amounts
 |     /// This method returns a tuple `(sent, received)`. Sent is the sum of the txin amounts
 | ||||||
|     /// that spend from previous txouts tracked by this wallet. Received is the summation
 |     /// that spend from previous txouts tracked by this wallet. Received is the summation
 | ||||||
| @ -978,7 +978,7 @@ impl Wallet { | |||||||
|     /// let tx = &psbt.clone().extract_tx().expect("tx");
 |     /// let tx = &psbt.clone().extract_tx().expect("tx");
 | ||||||
|     /// let (sent, received) = wallet.sent_and_received(tx);
 |     /// let (sent, received) = wallet.sent_and_received(tx);
 | ||||||
|     /// ```
 |     /// ```
 | ||||||
|     pub fn sent_and_received(&self, tx: &Transaction) -> (u64, u64) { |     pub fn sent_and_received(&self, tx: &Transaction) -> (Amount, Amount) { | ||||||
|         self.indexed_graph.index.sent_and_received(tx, ..) |         self.indexed_graph.index.sent_and_received(tx, ..) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -1197,7 +1197,7 @@ impl Wallet { | |||||||
|     /// let psbt = {
 |     /// let psbt = {
 | ||||||
|     ///    let mut builder =  wallet.build_tx();
 |     ///    let mut builder =  wallet.build_tx();
 | ||||||
|     ///    builder
 |     ///    builder
 | ||||||
|     ///        .add_recipient(to_address.script_pubkey(), 50_000);
 |     ///        .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
 | ||||||
|     ///    builder.finish()?
 |     ///    builder.finish()?
 | ||||||
|     /// };
 |     /// };
 | ||||||
|     ///
 |     ///
 | ||||||
| @ -1579,7 +1579,7 @@ impl Wallet { | |||||||
|     /// let mut psbt = {
 |     /// let mut psbt = {
 | ||||||
|     ///     let mut builder = wallet.build_tx();
 |     ///     let mut builder = wallet.build_tx();
 | ||||||
|     ///     builder
 |     ///     builder
 | ||||||
|     ///         .add_recipient(to_address.script_pubkey(), 50_000)
 |     ///         .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
 | ||||||
|     ///         .enable_rbf();
 |     ///         .enable_rbf();
 | ||||||
|     ///     builder.finish()?
 |     ///     builder.finish()?
 | ||||||
|     /// };
 |     /// };
 | ||||||
| @ -1752,7 +1752,7 @@ impl Wallet { | |||||||
|     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
 |     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
 | ||||||
|     /// let mut psbt = {
 |     /// let mut psbt = {
 | ||||||
|     ///     let mut builder = wallet.build_tx();
 |     ///     let mut builder = wallet.build_tx();
 | ||||||
|     ///     builder.add_recipient(to_address.script_pubkey(), 50_000);
 |     ///     builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
 | ||||||
|     ///     builder.finish()?
 |     ///     builder.finish()?
 | ||||||
|     /// };
 |     /// };
 | ||||||
|     /// let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
 |     /// let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
 | ||||||
|  | |||||||
| @ -29,7 +29,7 @@ | |||||||
| //!
 | //!
 | ||||||
| //! tx_builder
 | //! tx_builder
 | ||||||
| //!     // Create a transaction with one output to `to_address` of 50_000 satoshi
 | //!     // Create a transaction with one output to `to_address` of 50_000 satoshi
 | ||||||
| //!     .add_recipient(to_address.script_pubkey(), 50_000)
 | //!     .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
 | ||||||
| //!     // With a custom fee rate of 5.0 satoshi/vbyte
 | //!     // With a custom fee rate of 5.0 satoshi/vbyte
 | ||||||
| //!     .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
 | //!     .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
 | ||||||
| //!     // Only spend non-change outputs
 | //!     // Only spend non-change outputs
 | ||||||
| @ -47,7 +47,7 @@ use core::marker::PhantomData; | |||||||
| 
 | 
 | ||||||
| use bitcoin::psbt::{self, Psbt}; | use bitcoin::psbt::{self, Psbt}; | ||||||
| use bitcoin::script::PushBytes; | use bitcoin::script::PushBytes; | ||||||
| use bitcoin::{absolute, FeeRate, OutPoint, ScriptBuf, Sequence, Transaction, Txid}; | use bitcoin::{absolute, Amount, FeeRate, OutPoint, ScriptBuf, Sequence, Transaction, Txid}; | ||||||
| 
 | 
 | ||||||
| use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm}; | use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm}; | ||||||
| use super::{CreateTxError, Wallet}; | use super::{CreateTxError, Wallet}; | ||||||
| @ -94,8 +94,8 @@ impl TxBuilderContext for BumpFee {} | |||||||
| ///     let mut builder = wallet.build_tx();
 | ///     let mut builder = wallet.build_tx();
 | ||||||
| ///     builder
 | ///     builder
 | ||||||
| ///         .ordering(TxOrdering::Untouched)
 | ///         .ordering(TxOrdering::Untouched)
 | ||||||
| ///         .add_recipient(addr1.script_pubkey(), 50_000)
 | ///         .add_recipient(addr1.script_pubkey(), Amount::from_sat(50_000))
 | ||||||
| ///         .add_recipient(addr2.script_pubkey(), 50_000);
 | ///         .add_recipient(addr2.script_pubkey(), Amount::from_sat(50_000));
 | ||||||
| ///     builder.finish()?
 | ///     builder.finish()?
 | ||||||
| /// };
 | /// };
 | ||||||
| ///
 | ///
 | ||||||
| @ -104,7 +104,7 @@ impl TxBuilderContext for BumpFee {} | |||||||
| ///     let mut builder = wallet.build_tx();
 | ///     let mut builder = wallet.build_tx();
 | ||||||
| ///     builder.ordering(TxOrdering::Untouched);
 | ///     builder.ordering(TxOrdering::Untouched);
 | ||||||
| ///     for addr in &[addr1, addr2] {
 | ///     for addr in &[addr1, addr2] {
 | ||||||
| ///         builder.add_recipient(addr.script_pubkey(), 50_000);
 | ///         builder.add_recipient(addr.script_pubkey(), Amount::from_sat(50_000));
 | ||||||
| ///     }
 | ///     }
 | ||||||
| ///     builder.finish()?
 | ///     builder.finish()?
 | ||||||
| /// };
 | /// };
 | ||||||
| @ -274,7 +274,7 @@ impl<'a, Cs, Ctx> TxBuilder<'a, Cs, Ctx> { | |||||||
|     ///
 |     ///
 | ||||||
|     /// let builder = wallet
 |     /// let builder = wallet
 | ||||||
|     ///     .build_tx()
 |     ///     .build_tx()
 | ||||||
|     ///     .add_recipient(to_address.script_pubkey(), 50_000)
 |     ///     .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
 | ||||||
|     ///     .policy_path(path, KeychainKind::External);
 |     ///     .policy_path(path, KeychainKind::External);
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// # Ok::<(), anyhow::Error>(())
 |     /// # Ok::<(), anyhow::Error>(())
 | ||||||
| @ -713,21 +713,26 @@ impl std::error::Error for AllowShrinkingError {} | |||||||
| 
 | 
 | ||||||
| impl<'a, Cs: CoinSelectionAlgorithm> TxBuilder<'a, Cs, CreateTx> { | impl<'a, Cs: CoinSelectionAlgorithm> TxBuilder<'a, Cs, CreateTx> { | ||||||
|     /// Replace the recipients already added with a new list
 |     /// Replace the recipients already added with a new list
 | ||||||
|     pub fn set_recipients(&mut self, recipients: Vec<(ScriptBuf, u64)>) -> &mut Self { |     pub fn set_recipients(&mut self, recipients: Vec<(ScriptBuf, Amount)>) -> &mut Self { | ||||||
|         self.params.recipients = recipients; |         self.params.recipients = recipients | ||||||
|  |             .into_iter() | ||||||
|  |             .map(|(script, amount)| (script, amount.to_sat())) | ||||||
|  |             .collect(); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Add a recipient to the internal list
 |     /// Add a recipient to the internal list
 | ||||||
|     pub fn add_recipient(&mut self, script_pubkey: ScriptBuf, amount: u64) -> &mut Self { |     pub fn add_recipient(&mut self, script_pubkey: ScriptBuf, amount: Amount) -> &mut Self { | ||||||
|         self.params.recipients.push((script_pubkey, amount)); |         self.params | ||||||
|  |             .recipients | ||||||
|  |             .push((script_pubkey, amount.to_sat())); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Add data as an output, using OP_RETURN
 |     /// Add data as an output, using OP_RETURN
 | ||||||
|     pub fn add_data<T: AsRef<PushBytes>>(&mut self, data: &T) -> &mut Self { |     pub fn add_data<T: AsRef<PushBytes>>(&mut self, data: &T) -> &mut Self { | ||||||
|         let script = ScriptBuf::new_op_return(data); |         let script = ScriptBuf::new_op_return(data); | ||||||
|         self.add_recipient(script, 0u64); |         self.add_recipient(script, Amount::ZERO); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ fn test_psbt_malformed_psbt_input_legacy() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); |     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); | ||||||
|     let send_to = wallet.peek_address(KeychainKind::External, 0); |     let send_to = wallet.peek_address(KeychainKind::External, 0); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(send_to.script_pubkey(), 10_000); |     builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000)); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
|     psbt.inputs.push(psbt_bip.inputs[0].clone()); |     psbt.inputs.push(psbt_bip.inputs[0].clone()); | ||||||
|     let options = SignOptions { |     let options = SignOptions { | ||||||
| @ -31,7 +31,7 @@ fn test_psbt_malformed_psbt_input_segwit() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); |     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); | ||||||
|     let send_to = wallet.peek_address(KeychainKind::External, 0); |     let send_to = wallet.peek_address(KeychainKind::External, 0); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(send_to.script_pubkey(), 10_000); |     builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000)); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
|     psbt.inputs.push(psbt_bip.inputs[1].clone()); |     psbt.inputs.push(psbt_bip.inputs[1].clone()); | ||||||
|     let options = SignOptions { |     let options = SignOptions { | ||||||
| @ -47,7 +47,7 @@ fn test_psbt_malformed_tx_input() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); |     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); | ||||||
|     let send_to = wallet.peek_address(KeychainKind::External, 0); |     let send_to = wallet.peek_address(KeychainKind::External, 0); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(send_to.script_pubkey(), 10_000); |     builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000)); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
|     psbt.unsigned_tx.input.push(TxIn::default()); |     psbt.unsigned_tx.input.push(TxIn::default()); | ||||||
|     let options = SignOptions { |     let options = SignOptions { | ||||||
| @ -63,7 +63,7 @@ fn test_psbt_sign_with_finalized() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); |     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); | ||||||
|     let send_to = wallet.peek_address(KeychainKind::External, 0); |     let send_to = wallet.peek_address(KeychainKind::External, 0); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(send_to.script_pubkey(), 10_000); |     builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000)); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     // add a finalized input
 |     // add a finalized input
 | ||||||
| @ -201,7 +201,7 @@ fn test_psbt_multiple_internalkey_signers() { | |||||||
|     // the prevout we're spending
 |     // the prevout we're spending
 | ||||||
|     let prevouts = &[TxOut { |     let prevouts = &[TxOut { | ||||||
|         script_pubkey: send_to.script_pubkey(), |         script_pubkey: send_to.script_pubkey(), | ||||||
|         value: Amount::from_sat(to_spend), |         value: to_spend, | ||||||
|     }]; |     }]; | ||||||
|     let prevouts = Prevouts::All(prevouts); |     let prevouts = Prevouts::All(prevouts); | ||||||
|     let input_index = 0; |     let input_index = 0; | ||||||
|  | |||||||
| @ -200,14 +200,14 @@ fn test_get_funded_wallet_balance() { | |||||||
|     // The funded wallet contains a tx with a 76_000 sats input and two outputs, one spending 25_000
 |     // The funded wallet contains a tx with a 76_000 sats input and two outputs, one spending 25_000
 | ||||||
|     // to a foreign address and one returning 50_000 back to the wallet as change. The remaining 1000
 |     // to a foreign address and one returning 50_000 back to the wallet as change. The remaining 1000
 | ||||||
|     // sats are the transaction fee.
 |     // sats are the transaction fee.
 | ||||||
|     assert_eq!(wallet.get_balance().confirmed, 50_000); |     assert_eq!(wallet.get_balance().confirmed, Amount::from_sat(50_000)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn test_get_funded_wallet_sent_and_received() { | fn test_get_funded_wallet_sent_and_received() { | ||||||
|     let (wallet, txid) = get_funded_wallet(get_test_wpkh()); |     let (wallet, txid) = get_funded_wallet(get_test_wpkh()); | ||||||
| 
 | 
 | ||||||
|     let mut tx_amounts: Vec<(Txid, (u64, u64))> = wallet |     let mut tx_amounts: Vec<(Txid, (Amount, Amount))> = wallet | ||||||
|         .transactions() |         .transactions() | ||||||
|         .map(|ct| (ct.tx_node.txid, wallet.sent_and_received(&ct.tx_node))) |         .map(|ct| (ct.tx_node.txid, wallet.sent_and_received(&ct.tx_node))) | ||||||
|         .collect(); |         .collect(); | ||||||
| @ -219,8 +219,8 @@ fn test_get_funded_wallet_sent_and_received() { | |||||||
|     // The funded wallet contains a tx with a 76_000 sats input and two outputs, one spending 25_000
 |     // The funded wallet contains a tx with a 76_000 sats input and two outputs, one spending 25_000
 | ||||||
|     // to a foreign address and one returning 50_000 back to the wallet as change. The remaining 1000
 |     // to a foreign address and one returning 50_000 back to the wallet as change. The remaining 1000
 | ||||||
|     // sats are the transaction fee.
 |     // sats are the transaction fee.
 | ||||||
|     assert_eq!(sent, 76_000); |     assert_eq!(sent.to_sat(), 76_000); | ||||||
|     assert_eq!(received, 50_000); |     assert_eq!(received.to_sat(), 50_000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| @ -347,7 +347,7 @@ fn test_create_tx_manually_selected_empty_utxos() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .manually_selected_only(); |         .manually_selected_only(); | ||||||
|     builder.finish().unwrap(); |     builder.finish().unwrap(); | ||||||
| } | } | ||||||
| @ -358,7 +358,7 @@ fn test_create_tx_version_0() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .version(0); |         .version(0); | ||||||
|     assert!(matches!(builder.finish(), Err(CreateTxError::Version0))); |     assert!(matches!(builder.finish(), Err(CreateTxError::Version0))); | ||||||
| } | } | ||||||
| @ -369,7 +369,7 @@ fn test_create_tx_version_1_csv() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .version(1); |         .version(1); | ||||||
|     assert!(matches!(builder.finish(), Err(CreateTxError::Version1Csv))); |     assert!(matches!(builder.finish(), Err(CreateTxError::Version1Csv))); | ||||||
| } | } | ||||||
| @ -380,7 +380,7 @@ fn test_create_tx_custom_version() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .version(42); |         .version(42); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -393,7 +393,7 @@ fn test_create_tx_default_locktime_is_last_sync_height() { | |||||||
| 
 | 
 | ||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     // Since we never synced the wallet we don't have a last_sync_height
 |     // Since we never synced the wallet we don't have a last_sync_height
 | ||||||
| @ -406,7 +406,7 @@ fn test_create_tx_fee_sniping_locktime_last_sync() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); |     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); | ||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
| 
 | 
 | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -422,7 +422,7 @@ fn test_create_tx_default_locktime_cltv() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_single_sig_cltv()); |     let (mut wallet, _) = get_funded_wallet(get_test_single_sig_cltv()); | ||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     assert_eq!(psbt.unsigned_tx.lock_time.to_consensus_u32(), 100_000); |     assert_eq!(psbt.unsigned_tx.lock_time.to_consensus_u32(), 100_000); | ||||||
| @ -434,7 +434,7 @@ fn test_create_tx_custom_locktime() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .current_height(630_001) |         .current_height(630_001) | ||||||
|         .nlocktime(absolute::LockTime::from_height(630_000).unwrap()); |         .nlocktime(absolute::LockTime::from_height(630_000).unwrap()); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| @ -451,7 +451,7 @@ fn test_create_tx_custom_locktime_compatible_with_cltv() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .nlocktime(absolute::LockTime::from_height(630_000).unwrap()); |         .nlocktime(absolute::LockTime::from_height(630_000).unwrap()); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -464,7 +464,7 @@ fn test_create_tx_custom_locktime_incompatible_with_cltv() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .nlocktime(absolute::LockTime::from_height(50000).unwrap()); |         .nlocktime(absolute::LockTime::from_height(50000).unwrap()); | ||||||
|     assert!(matches!(builder.finish(), |     assert!(matches!(builder.finish(), | ||||||
|         Err(CreateTxError::LockTime { requested, required }) |         Err(CreateTxError::LockTime { requested, required }) | ||||||
| @ -476,7 +476,7 @@ fn test_create_tx_no_rbf_csv() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_single_sig_csv()); |     let (mut wallet, _) = get_funded_wallet(get_test_single_sig_csv()); | ||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(6)); |     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(6)); | ||||||
| @ -488,7 +488,7 @@ fn test_create_tx_with_default_rbf_csv() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .enable_rbf(); |         .enable_rbf(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     // When CSV is enabled it takes precedence over the rbf value (unless forced by the user).
 |     // When CSV is enabled it takes precedence over the rbf value (unless forced by the user).
 | ||||||
| @ -502,7 +502,7 @@ fn test_create_tx_with_custom_rbf_csv() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .enable_rbf_with_sequence(Sequence(3)); |         .enable_rbf_with_sequence(Sequence(3)); | ||||||
|     assert!(matches!(builder.finish(), |     assert!(matches!(builder.finish(), | ||||||
|         Err(CreateTxError::RbfSequenceCsv { rbf, csv }) |         Err(CreateTxError::RbfSequenceCsv { rbf, csv }) | ||||||
| @ -514,7 +514,7 @@ fn test_create_tx_no_rbf_cltv() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_single_sig_cltv()); |     let (mut wallet, _) = get_funded_wallet(get_test_single_sig_cltv()); | ||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xFFFFFFFE)); |     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xFFFFFFFE)); | ||||||
| @ -526,7 +526,7 @@ fn test_create_tx_invalid_rbf_sequence() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .enable_rbf_with_sequence(Sequence(0xFFFFFFFE)); |         .enable_rbf_with_sequence(Sequence(0xFFFFFFFE)); | ||||||
|     assert!(matches!(builder.finish(), Err(CreateTxError::RbfSequence))); |     assert!(matches!(builder.finish(), Err(CreateTxError::RbfSequence))); | ||||||
| } | } | ||||||
| @ -537,7 +537,7 @@ fn test_create_tx_custom_rbf_sequence() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .enable_rbf_with_sequence(Sequence(0xDEADBEEF)); |         .enable_rbf_with_sequence(Sequence(0xDEADBEEF)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -549,7 +549,7 @@ fn test_create_tx_default_sequence() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); |     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); | ||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xFFFFFFFE)); |     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xFFFFFFFE)); | ||||||
| @ -561,7 +561,7 @@ fn test_create_tx_change_policy_no_internal() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .do_not_spend_change(); |         .do_not_spend_change(); | ||||||
|     assert!(matches!( |     assert!(matches!( | ||||||
|         builder.finish(), |         builder.finish(), | ||||||
| @ -603,7 +603,7 @@ fn test_create_tx_drain_wallet_and_drain_to_and_with_recipient() { | |||||||
|     let drain_addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let drain_addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 20_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(20_000)) | ||||||
|         .drain_to(drain_addr.script_pubkey()) |         .drain_to(drain_addr.script_pubkey()) | ||||||
|         .drain_wallet(); |         .drain_wallet(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| @ -658,7 +658,7 @@ fn test_create_tx_default_fee_rate() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); |     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); | ||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let fee = check_fee!(wallet, psbt); |     let fee = check_fee!(wallet, psbt); | ||||||
| 
 | 
 | ||||||
| @ -671,7 +671,7 @@ fn test_create_tx_custom_fee_rate() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .fee_rate(FeeRate::from_sat_per_vb_unchecked(5)); |         .fee_rate(FeeRate::from_sat_per_vb_unchecked(5)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let fee = check_fee!(wallet, psbt); |     let fee = check_fee!(wallet, psbt); | ||||||
| @ -740,7 +740,7 @@ fn test_create_tx_add_change() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .ordering(TxOrdering::Untouched); |         .ordering(TxOrdering::Untouched); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let fee = check_fee!(wallet, psbt); |     let fee = check_fee!(wallet, psbt); | ||||||
| @ -758,7 +758,7 @@ fn test_create_tx_skip_change_dust() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); |     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); | ||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 49_800); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(49_800)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let fee = check_fee!(wallet, psbt); |     let fee = check_fee!(wallet, psbt); | ||||||
| 
 | 
 | ||||||
| @ -787,8 +787,8 @@ fn test_create_tx_ordering_respected() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 30_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000)) | ||||||
|         .add_recipient(addr.script_pubkey(), 10_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(10_000)) | ||||||
|         .ordering(bdk::wallet::tx_builder::TxOrdering::Bip69Lexicographic); |         .ordering(bdk::wallet::tx_builder::TxOrdering::Bip69Lexicographic); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let fee = check_fee!(wallet, psbt); |     let fee = check_fee!(wallet, psbt); | ||||||
| @ -807,7 +807,7 @@ fn test_create_tx_default_sighash() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); |     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); | ||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 30_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(30_000)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     assert_eq!(psbt.inputs[0].sighash_type, None); |     assert_eq!(psbt.inputs[0].sighash_type, None); | ||||||
| @ -819,7 +819,7 @@ fn test_create_tx_custom_sighash() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 30_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000)) | ||||||
|         .sighash(EcdsaSighashType::Single.into()); |         .sighash(EcdsaSighashType::Single.into()); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -1018,7 +1018,7 @@ fn test_create_tx_add_utxo() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 30_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000)) | ||||||
|         .add_utxo(OutPoint { |         .add_utxo(OutPoint { | ||||||
|             txid: small_output_tx.txid(), |             txid: small_output_tx.txid(), | ||||||
|             vout: 0, |             vout: 0, | ||||||
| @ -1034,7 +1034,8 @@ fn test_create_tx_add_utxo() { | |||||||
|         "should add an additional input since 25_000 < 30_000" |         "should add an additional input since 25_000 < 30_000" | ||||||
|     ); |     ); | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         sent_received.0, 75_000, |         sent_received.0, | ||||||
|  |         Amount::from_sat(75_000), | ||||||
|         "total should be sum of both inputs" |         "total should be sum of both inputs" | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| @ -1068,7 +1069,7 @@ fn test_create_tx_manually_selected_insufficient() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 30_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000)) | ||||||
|         .add_utxo(OutPoint { |         .add_utxo(OutPoint { | ||||||
|             txid: small_output_tx.txid(), |             txid: small_output_tx.txid(), | ||||||
|             vout: 0, |             vout: 0, | ||||||
| @ -1087,7 +1088,7 @@ fn test_create_tx_policy_path_required() { | |||||||
|         .unwrap() |         .unwrap() | ||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 30_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(10_000)); | ||||||
|     builder.finish().unwrap(); |     builder.finish().unwrap(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1122,7 +1123,7 @@ fn test_create_tx_policy_path_no_csv() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 30_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000)) | ||||||
|         .policy_path(path, KeychainKind::External); |         .policy_path(path, KeychainKind::External); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -1143,7 +1144,7 @@ fn test_create_tx_policy_path_use_csv() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 30_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000)) | ||||||
|         .policy_path(path, KeychainKind::External); |         .policy_path(path, KeychainKind::External); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -1164,7 +1165,7 @@ fn test_create_tx_policy_path_ignored_subtree_with_csv() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 30_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000)) | ||||||
|         .policy_path(path, KeychainKind::External); |         .policy_path(path, KeychainKind::External); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -1180,7 +1181,7 @@ fn test_create_tx_global_xpubs_with_origin() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .add_global_xpubs(); |         .add_global_xpubs(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -1214,7 +1215,7 @@ fn test_add_foreign_utxo() { | |||||||
| 
 | 
 | ||||||
|     let mut builder = wallet1.build_tx(); |     let mut builder = wallet1.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 60_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(60_000)) | ||||||
|         .only_witness_utxo() |         .only_witness_utxo() | ||||||
|         .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction) |         .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction) | ||||||
|         .unwrap(); |         .unwrap(); | ||||||
| @ -1225,7 +1226,7 @@ fn test_add_foreign_utxo() { | |||||||
|         wallet1.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); |         wallet1.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); | ||||||
| 
 | 
 | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         sent_received.0 - sent_received.1, |         (sent_received.0 - sent_received.1).to_sat(), | ||||||
|         10_000 + fee.unwrap_or(0), |         10_000 + fee.unwrap_or(0), | ||||||
|         "we should have only net spent ~10_000" |         "we should have only net spent ~10_000" | ||||||
|     ); |     ); | ||||||
| @ -1290,7 +1291,7 @@ fn test_calculate_fee_with_missing_foreign_utxo() { | |||||||
| 
 | 
 | ||||||
|     let mut builder = wallet1.build_tx(); |     let mut builder = wallet1.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 60_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(60_000)) | ||||||
|         .only_witness_utxo() |         .only_witness_utxo() | ||||||
|         .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction) |         .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction) | ||||||
|         .unwrap(); |         .unwrap(); | ||||||
| @ -1374,7 +1375,7 @@ fn test_add_foreign_utxo_only_witness_utxo() { | |||||||
|         .unwrap(); |         .unwrap(); | ||||||
| 
 | 
 | ||||||
|     let mut builder = wallet1.build_tx(); |     let mut builder = wallet1.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 60_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(60_000)); | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
|         let mut builder = builder.clone(); |         let mut builder = builder.clone(); | ||||||
| @ -1443,7 +1444,7 @@ fn test_create_tx_global_xpubs_origin_missing() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .add_global_xpubs(); |         .add_global_xpubs(); | ||||||
|     builder.finish().unwrap(); |     builder.finish().unwrap(); | ||||||
| } | } | ||||||
| @ -1457,7 +1458,7 @@ fn test_create_tx_global_xpubs_master_without_origin() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .add_global_xpubs(); |         .add_global_xpubs(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -1477,7 +1478,7 @@ fn test_bump_fee_irreplaceable_tx() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); |     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); | ||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     let tx = psbt.extract_tx().expect("failed to extract tx"); |     let tx = psbt.extract_tx().expect("failed to extract tx"); | ||||||
| @ -1494,7 +1495,7 @@ fn test_bump_fee_confirmed_tx() { | |||||||
|     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); |     let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); | ||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     let tx = psbt.extract_tx().expect("failed to extract tx"); |     let tx = psbt.extract_tx().expect("failed to extract tx"); | ||||||
| @ -1519,7 +1520,7 @@ fn test_bump_fee_low_fee_rate() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .enable_rbf(); |         .enable_rbf(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let feerate = psbt.fee_rate().unwrap(); |     let feerate = psbt.fee_rate().unwrap(); | ||||||
| @ -1553,7 +1554,7 @@ fn test_bump_fee_low_abs() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .enable_rbf(); |         .enable_rbf(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -1576,7 +1577,7 @@ fn test_bump_fee_zero_abs() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .enable_rbf(); |         .enable_rbf(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -1599,7 +1600,7 @@ fn test_bump_fee_reduce_change() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .enable_rbf(); |         .enable_rbf(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let original_sent_received = |     let original_sent_received = | ||||||
| @ -1622,8 +1623,8 @@ fn test_bump_fee_reduce_change() { | |||||||
| 
 | 
 | ||||||
|     assert_eq!(sent_received.0, original_sent_received.0); |     assert_eq!(sent_received.0, original_sent_received.0); | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         sent_received.1 + fee.unwrap_or(0), |         sent_received.1 + Amount::from_sat(fee.unwrap_or(0)), | ||||||
|         original_sent_received.1 + original_fee.unwrap_or(0) |         original_sent_received.1 + Amount::from_sat(original_fee.unwrap_or(0)) | ||||||
|     ); |     ); | ||||||
|     assert!(fee.unwrap_or(0) > original_fee.unwrap_or(0)); |     assert!(fee.unwrap_or(0) > original_fee.unwrap_or(0)); | ||||||
| 
 | 
 | ||||||
| @ -1642,8 +1643,7 @@ fn test_bump_fee_reduce_change() { | |||||||
|             .iter() |             .iter() | ||||||
|             .find(|txout| txout.script_pubkey != addr.script_pubkey()) |             .find(|txout| txout.script_pubkey != addr.script_pubkey()) | ||||||
|             .unwrap() |             .unwrap() | ||||||
|             .value |             .value, | ||||||
|             .to_sat(), |  | ||||||
|         sent_received.1 |         sent_received.1 | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -1659,8 +1659,8 @@ fn test_bump_fee_reduce_change() { | |||||||
| 
 | 
 | ||||||
|     assert_eq!(sent_received.0, original_sent_received.0); |     assert_eq!(sent_received.0, original_sent_received.0); | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         sent_received.1 + fee.unwrap_or(0), |         sent_received.1 + Amount::from_sat(fee.unwrap_or(0)), | ||||||
|         original_sent_received.1 + original_fee.unwrap_or(0) |         original_sent_received.1 + Amount::from_sat(original_fee.unwrap_or(0)) | ||||||
|     ); |     ); | ||||||
|     assert!( |     assert!( | ||||||
|         fee.unwrap_or(0) > original_fee.unwrap_or(0), |         fee.unwrap_or(0) > original_fee.unwrap_or(0), | ||||||
| @ -1684,8 +1684,7 @@ fn test_bump_fee_reduce_change() { | |||||||
|             .iter() |             .iter() | ||||||
|             .find(|txout| txout.script_pubkey != addr.script_pubkey()) |             .find(|txout| txout.script_pubkey != addr.script_pubkey()) | ||||||
|             .unwrap() |             .unwrap() | ||||||
|             .value |             .value, | ||||||
|             .to_sat(), |  | ||||||
|         sent_received.1 |         sent_received.1 | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -1729,7 +1728,7 @@ fn test_bump_fee_reduce_single_recipient() { | |||||||
|     let tx = &psbt.unsigned_tx; |     let tx = &psbt.unsigned_tx; | ||||||
|     assert_eq!(tx.output.len(), 1); |     assert_eq!(tx.output.len(), 1); | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         tx.output[0].value.to_sat() + fee.unwrap_or(0), |         tx.output[0].value + Amount::from_sat(fee.unwrap_or(0)), | ||||||
|         sent_received.0 |         sent_received.0 | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -1771,7 +1770,7 @@ fn test_bump_fee_absolute_reduce_single_recipient() { | |||||||
| 
 | 
 | ||||||
|     assert_eq!(tx.output.len(), 1); |     assert_eq!(tx.output.len(), 1); | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         tx.output[0].value.to_sat() + fee.unwrap_or(0), |         tx.output[0].value + Amount::from_sat(fee.unwrap_or(0)), | ||||||
|         sent_received.0 |         sent_received.0 | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -1825,7 +1824,7 @@ fn test_bump_fee_drain_wallet() { | |||||||
|     wallet |     wallet | ||||||
|         .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) |         .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) | ||||||
|         .unwrap(); |         .unwrap(); | ||||||
|     assert_eq!(original_sent_received.0, 25_000); |     assert_eq!(original_sent_received.0, Amount::from_sat(25_000)); | ||||||
| 
 | 
 | ||||||
|     // for the new feerate, it should be enough to reduce the output, but since we specify
 |     // for the new feerate, it should be enough to reduce the output, but since we specify
 | ||||||
|     // `drain_wallet` we expect to spend everything
 |     // `drain_wallet` we expect to spend everything
 | ||||||
| @ -1838,7 +1837,7 @@ fn test_bump_fee_drain_wallet() { | |||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let sent_received = wallet.sent_and_received(&psbt.extract_tx().expect("failed to extract tx")); |     let sent_received = wallet.sent_and_received(&psbt.extract_tx().expect("failed to extract tx")); | ||||||
| 
 | 
 | ||||||
|     assert_eq!(sent_received.0, 75_000); |     assert_eq!(sent_received.0, Amount::from_sat(75_000)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| @ -1895,7 +1894,7 @@ fn test_bump_fee_remove_output_manually_selected_only() { | |||||||
|     wallet |     wallet | ||||||
|         .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) |         .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) | ||||||
|         .unwrap(); |         .unwrap(); | ||||||
|     assert_eq!(original_sent_received.0, 25_000); |     assert_eq!(original_sent_received.0, Amount::from_sat(25_000)); | ||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_fee_bump(txid).unwrap(); |     let mut builder = wallet.build_fee_bump(txid).unwrap(); | ||||||
|     builder |     builder | ||||||
| @ -1933,7 +1932,7 @@ fn test_bump_fee_add_input() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx().coin_selection(LargestFirstCoinSelection); |     let mut builder = wallet.build_tx().coin_selection(LargestFirstCoinSelection); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 45_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000)) | ||||||
|         .enable_rbf(); |         .enable_rbf(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let tx = psbt.extract_tx().expect("failed to extract tx"); |     let tx = psbt.extract_tx().expect("failed to extract tx"); | ||||||
| @ -1949,8 +1948,14 @@ fn test_bump_fee_add_input() { | |||||||
|     let sent_received = |     let sent_received = | ||||||
|         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); |         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); | ||||||
|     let fee = check_fee!(wallet, psbt); |     let fee = check_fee!(wallet, psbt); | ||||||
|     assert_eq!(sent_received.0, original_details.0 + 25_000); |     assert_eq!( | ||||||
|     assert_eq!(fee.unwrap_or(0) + sent_received.1, 30_000); |         sent_received.0, | ||||||
|  |         original_details.0 + Amount::from_sat(25_000) | ||||||
|  |     ); | ||||||
|  |     assert_eq!( | ||||||
|  |         Amount::from_sat(fee.unwrap_or(0)) + sent_received.1, | ||||||
|  |         Amount::from_sat(30_000) | ||||||
|  |     ); | ||||||
| 
 | 
 | ||||||
|     let tx = &psbt.unsigned_tx; |     let tx = &psbt.unsigned_tx; | ||||||
|     assert_eq!(tx.input.len(), 2); |     assert_eq!(tx.input.len(), 2); | ||||||
| @ -1968,8 +1973,7 @@ fn test_bump_fee_add_input() { | |||||||
|             .iter() |             .iter() | ||||||
|             .find(|txout| txout.script_pubkey != addr.script_pubkey()) |             .find(|txout| txout.script_pubkey != addr.script_pubkey()) | ||||||
|             .unwrap() |             .unwrap() | ||||||
|             .value |             .value, | ||||||
|             .to_sat(), |  | ||||||
|         sent_received.1 |         sent_received.1 | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -1985,7 +1989,7 @@ fn test_bump_fee_absolute_add_input() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx().coin_selection(LargestFirstCoinSelection); |     let mut builder = wallet.build_tx().coin_selection(LargestFirstCoinSelection); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 45_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000)) | ||||||
|         .enable_rbf(); |         .enable_rbf(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let tx = psbt.extract_tx().expect("failed to extract tx"); |     let tx = psbt.extract_tx().expect("failed to extract tx"); | ||||||
| @ -2002,8 +2006,14 @@ fn test_bump_fee_absolute_add_input() { | |||||||
|         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); |         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); | ||||||
|     let fee = check_fee!(wallet, psbt); |     let fee = check_fee!(wallet, psbt); | ||||||
| 
 | 
 | ||||||
|     assert_eq!(sent_received.0, original_sent_received.0 + 25_000); |     assert_eq!( | ||||||
|     assert_eq!(fee.unwrap_or(0) + sent_received.1, 30_000); |         sent_received.0, | ||||||
|  |         original_sent_received.0 + Amount::from_sat(25_000) | ||||||
|  |     ); | ||||||
|  |     assert_eq!( | ||||||
|  |         Amount::from_sat(fee.unwrap_or(0)) + sent_received.1, | ||||||
|  |         Amount::from_sat(30_000) | ||||||
|  |     ); | ||||||
| 
 | 
 | ||||||
|     let tx = &psbt.unsigned_tx; |     let tx = &psbt.unsigned_tx; | ||||||
|     assert_eq!(tx.input.len(), 2); |     assert_eq!(tx.input.len(), 2); | ||||||
| @ -2021,8 +2031,7 @@ fn test_bump_fee_absolute_add_input() { | |||||||
|             .iter() |             .iter() | ||||||
|             .find(|txout| txout.script_pubkey != addr.script_pubkey()) |             .find(|txout| txout.script_pubkey != addr.script_pubkey()) | ||||||
|             .unwrap() |             .unwrap() | ||||||
|             .value |             .value, | ||||||
|             .to_sat(), |  | ||||||
|         sent_received.1 |         sent_received.1 | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -2065,11 +2074,15 @@ fn test_bump_fee_no_change_add_input_and_change() { | |||||||
|         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); |         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); | ||||||
|     let fee = check_fee!(wallet, psbt); |     let fee = check_fee!(wallet, psbt); | ||||||
| 
 | 
 | ||||||
|     let original_send_all_amount = original_sent_received.0 - original_fee.unwrap_or(0); |     let original_send_all_amount = | ||||||
|     assert_eq!(sent_received.0, original_sent_received.0 + 50_000); |         original_sent_received.0 - Amount::from_sat(original_fee.unwrap_or(0)); | ||||||
|  |     assert_eq!( | ||||||
|  |         sent_received.0, | ||||||
|  |         original_sent_received.0 + Amount::from_sat(50_000) | ||||||
|  |     ); | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         sent_received.1, |         sent_received.1, | ||||||
|         75_000 - original_send_all_amount - fee.unwrap_or(0) |         Amount::from_sat(75_000) - original_send_all_amount - Amount::from_sat(fee.unwrap_or(0)) | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     let tx = &psbt.unsigned_tx; |     let tx = &psbt.unsigned_tx; | ||||||
| @ -2081,16 +2094,15 @@ fn test_bump_fee_no_change_add_input_and_change() { | |||||||
|             .find(|txout| txout.script_pubkey == addr.script_pubkey()) |             .find(|txout| txout.script_pubkey == addr.script_pubkey()) | ||||||
|             .unwrap() |             .unwrap() | ||||||
|             .value, |             .value, | ||||||
|         Amount::from_sat(original_send_all_amount) |         original_send_all_amount | ||||||
|     ); |     ); | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         tx.output |         tx.output | ||||||
|             .iter() |             .iter() | ||||||
|             .find(|txout| txout.script_pubkey != addr.script_pubkey()) |             .find(|txout| txout.script_pubkey != addr.script_pubkey()) | ||||||
|             .unwrap() |             .unwrap() | ||||||
|             .value |             .value, | ||||||
|             .to_sat(), |         Amount::from_sat(75_000) - original_send_all_amount - Amount::from_sat(fee.unwrap_or(0)) | ||||||
|         75_000 - original_send_all_amount - fee.unwrap_or(0) |  | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     assert_fee_rate!(psbt, fee.unwrap_or(0), FeeRate::from_sat_per_vb_unchecked(50), @add_signature); |     assert_fee_rate!(psbt, fee.unwrap_or(0), FeeRate::from_sat_per_vb_unchecked(50), @add_signature); | ||||||
| @ -2105,7 +2117,7 @@ fn test_bump_fee_add_input_change_dust() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx().coin_selection(LargestFirstCoinSelection); |     let mut builder = wallet.build_tx().coin_selection(LargestFirstCoinSelection); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 45_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000)) | ||||||
|         .enable_rbf(); |         .enable_rbf(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let original_sent_received = |     let original_sent_received = | ||||||
| @ -2145,11 +2157,17 @@ fn test_bump_fee_add_input_change_dust() { | |||||||
|         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); |         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); | ||||||
|     let fee = check_fee!(wallet, psbt); |     let fee = check_fee!(wallet, psbt); | ||||||
| 
 | 
 | ||||||
|     assert_eq!(original_sent_received.1, 5_000 - original_fee.unwrap_or(0)); |     assert_eq!( | ||||||
|  |         original_sent_received.1, | ||||||
|  |         Amount::from_sat(5_000 - original_fee.unwrap_or(0)) | ||||||
|  |     ); | ||||||
| 
 | 
 | ||||||
|     assert_eq!(sent_received.0, original_sent_received.0 + 25_000); |     assert_eq!( | ||||||
|  |         sent_received.0, | ||||||
|  |         original_sent_received.0 + Amount::from_sat(25_000) | ||||||
|  |     ); | ||||||
|     assert_eq!(fee.unwrap_or(0), 30_000); |     assert_eq!(fee.unwrap_or(0), 30_000); | ||||||
|     assert_eq!(sent_received.1, 0); |     assert_eq!(sent_received.1, Amount::ZERO); | ||||||
| 
 | 
 | ||||||
|     let tx = &psbt.unsigned_tx; |     let tx = &psbt.unsigned_tx; | ||||||
|     assert_eq!(tx.input.len(), 2); |     assert_eq!(tx.input.len(), 2); | ||||||
| @ -2176,7 +2194,7 @@ fn test_bump_fee_force_add_input() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx().coin_selection(LargestFirstCoinSelection); |     let mut builder = wallet.build_tx().coin_selection(LargestFirstCoinSelection); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 45_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000)) | ||||||
|         .enable_rbf(); |         .enable_rbf(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let mut tx = psbt.extract_tx().expect("failed to extract tx"); |     let mut tx = psbt.extract_tx().expect("failed to extract tx"); | ||||||
| @ -2200,8 +2218,14 @@ fn test_bump_fee_force_add_input() { | |||||||
|         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); |         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); | ||||||
|     let fee = check_fee!(wallet, psbt); |     let fee = check_fee!(wallet, psbt); | ||||||
| 
 | 
 | ||||||
|     assert_eq!(sent_received.0, original_sent_received.0 + 25_000); |     assert_eq!( | ||||||
|     assert_eq!(fee.unwrap_or(0) + sent_received.1, 30_000); |         sent_received.0, | ||||||
|  |         original_sent_received.0 + Amount::from_sat(25_000) | ||||||
|  |     ); | ||||||
|  |     assert_eq!( | ||||||
|  |         Amount::from_sat(fee.unwrap_or(0)) + sent_received.1, | ||||||
|  |         Amount::from_sat(30_000) | ||||||
|  |     ); | ||||||
| 
 | 
 | ||||||
|     let tx = &psbt.unsigned_tx; |     let tx = &psbt.unsigned_tx; | ||||||
|     assert_eq!(tx.input.len(), 2); |     assert_eq!(tx.input.len(), 2); | ||||||
| @ -2219,8 +2243,7 @@ fn test_bump_fee_force_add_input() { | |||||||
|             .iter() |             .iter() | ||||||
|             .find(|txout| txout.script_pubkey != addr.script_pubkey()) |             .find(|txout| txout.script_pubkey != addr.script_pubkey()) | ||||||
|             .unwrap() |             .unwrap() | ||||||
|             .value |             .value, | ||||||
|             .to_sat(), |  | ||||||
|         sent_received.1 |         sent_received.1 | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -2237,7 +2260,7 @@ fn test_bump_fee_absolute_force_add_input() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx().coin_selection(LargestFirstCoinSelection); |     let mut builder = wallet.build_tx().coin_selection(LargestFirstCoinSelection); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 45_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000)) | ||||||
|         .enable_rbf(); |         .enable_rbf(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
|     let mut tx = psbt.extract_tx().expect("failed to extract tx"); |     let mut tx = psbt.extract_tx().expect("failed to extract tx"); | ||||||
| @ -2260,8 +2283,14 @@ fn test_bump_fee_absolute_force_add_input() { | |||||||
|         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); |         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); | ||||||
|     let fee = check_fee!(wallet, psbt); |     let fee = check_fee!(wallet, psbt); | ||||||
| 
 | 
 | ||||||
|     assert_eq!(sent_received.0, original_sent_received.0 + 25_000); |     assert_eq!( | ||||||
|     assert_eq!(fee.unwrap_or(0) + sent_received.1, 30_000); |         sent_received.0, | ||||||
|  |         original_sent_received.0 + Amount::from_sat(25_000) | ||||||
|  |     ); | ||||||
|  |     assert_eq!( | ||||||
|  |         Amount::from_sat(fee.unwrap_or(0)) + sent_received.1, | ||||||
|  |         Amount::from_sat(30_000) | ||||||
|  |     ); | ||||||
| 
 | 
 | ||||||
|     let tx = &psbt.unsigned_tx; |     let tx = &psbt.unsigned_tx; | ||||||
|     assert_eq!(tx.input.len(), 2); |     assert_eq!(tx.input.len(), 2); | ||||||
| @ -2279,8 +2308,7 @@ fn test_bump_fee_absolute_force_add_input() { | |||||||
|             .iter() |             .iter() | ||||||
|             .find(|txout| txout.script_pubkey != addr.script_pubkey()) |             .find(|txout| txout.script_pubkey != addr.script_pubkey()) | ||||||
|             .unwrap() |             .unwrap() | ||||||
|             .value |             .value, | ||||||
|             .to_sat(), |  | ||||||
|         sent_received.1 |         sent_received.1 | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -2382,7 +2410,7 @@ fn test_fee_amount_negative_drain_val() { | |||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(send_to.script_pubkey(), 8630) |         .add_recipient(send_to.script_pubkey(), Amount::from_sat(8630)) | ||||||
|         .add_utxo(incoming_op) |         .add_utxo(incoming_op) | ||||||
|         .unwrap() |         .unwrap() | ||||||
|         .enable_rbf() |         .enable_rbf() | ||||||
| @ -2496,7 +2524,7 @@ fn test_include_output_redeem_witness_script() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 45_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000)) | ||||||
|         .include_output_redeem_witness_script(); |         .include_output_redeem_witness_script(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -2515,7 +2543,7 @@ fn test_signing_only_one_of_multiple_inputs() { | |||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 45_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000)) | ||||||
|         .include_output_redeem_witness_script(); |         .include_output_redeem_witness_script(); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -2860,7 +2888,7 @@ fn test_sending_to_bip350_bech32m_address() { | |||||||
|         .unwrap() |         .unwrap() | ||||||
|         .assume_checked(); |         .assume_checked(); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 45_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(45_000)); | ||||||
|     builder.finish().unwrap(); |     builder.finish().unwrap(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -2993,7 +3021,7 @@ fn test_taproot_psbt_populate_tap_key_origins() { | |||||||
|     let addr = wallet.reveal_next_address(KeychainKind::External).unwrap(); |     let addr = wallet.reveal_next_address(KeychainKind::External).unwrap(); | ||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
| @ -3033,7 +3061,7 @@ fn test_taproot_psbt_populate_tap_key_origins_repeated_key() { | |||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 25_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)) | ||||||
|         .policy_path(path, KeychainKind::External); |         .policy_path(path, KeychainKind::External); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
| @ -3217,7 +3245,7 @@ fn test_taproot_foreign_utxo() { | |||||||
| 
 | 
 | ||||||
|     let mut builder = wallet1.build_tx(); |     let mut builder = wallet1.build_tx(); | ||||||
|     builder |     builder | ||||||
|         .add_recipient(addr.script_pubkey(), 60_000) |         .add_recipient(addr.script_pubkey(), Amount::from_sat(60_000)) | ||||||
|         .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction) |         .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction) | ||||||
|         .unwrap(); |         .unwrap(); | ||||||
|     let psbt = builder.finish().unwrap(); |     let psbt = builder.finish().unwrap(); | ||||||
| @ -3228,7 +3256,7 @@ fn test_taproot_foreign_utxo() { | |||||||
| 
 | 
 | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         sent_received.0 - sent_received.1, |         sent_received.0 - sent_received.1, | ||||||
|         10_000 + fee.unwrap_or(0), |         Amount::from_sat(10_000 + fee.unwrap_or(0)), | ||||||
|         "we should have only net spent ~10_000" |         "we should have only net spent ~10_000" | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -3245,7 +3273,7 @@ fn test_spend_from_wallet(mut wallet: Wallet) { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     assert!( |     assert!( | ||||||
| @ -3269,7 +3297,7 @@ fn test_taproot_no_key_spend() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     assert!( |     assert!( | ||||||
| @ -3304,7 +3332,7 @@ fn test_taproot_script_spend_sign_all_leaves() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     assert!( |     assert!( | ||||||
| @ -3335,7 +3363,7 @@ fn test_taproot_script_spend_sign_include_some_leaves() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
|     let mut script_leaves: Vec<_> = psbt.inputs[0] |     let mut script_leaves: Vec<_> = psbt.inputs[0] | ||||||
|         .tap_scripts |         .tap_scripts | ||||||
| @ -3375,7 +3403,7 @@ fn test_taproot_script_spend_sign_exclude_some_leaves() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
|     let mut script_leaves: Vec<_> = psbt.inputs[0] |     let mut script_leaves: Vec<_> = psbt.inputs[0] | ||||||
|         .tap_scripts |         .tap_scripts | ||||||
| @ -3413,7 +3441,7 @@ fn test_taproot_script_spend_sign_no_leaves() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     wallet |     wallet | ||||||
| @ -3436,7 +3464,7 @@ fn test_taproot_sign_derive_index_from_psbt() { | |||||||
|     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); |     let addr = wallet.next_unused_address(KeychainKind::External).unwrap(); | ||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
|     builder.add_recipient(addr.script_pubkey(), 25_000); |     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000)); | ||||||
|     let mut psbt = builder.finish().unwrap(); |     let mut psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|     // re-create the wallet with an empty db
 |     // re-create the wallet with an empty db
 | ||||||
| @ -3582,10 +3610,10 @@ fn test_spend_coinbase() { | |||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         balance, |         balance, | ||||||
|         Balance { |         Balance { | ||||||
|             immature: 25_000, |             immature: Amount::from_sat(25_000), | ||||||
|             trusted_pending: 0, |             trusted_pending: Amount::ZERO, | ||||||
|             untrusted_pending: 0, |             untrusted_pending: Amount::ZERO, | ||||||
|             confirmed: 0 |             confirmed: Amount::ZERO | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -3633,10 +3661,10 @@ fn test_spend_coinbase() { | |||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         balance, |         balance, | ||||||
|         Balance { |         Balance { | ||||||
|             immature: 0, |             immature: Amount::ZERO, | ||||||
|             trusted_pending: 0, |             trusted_pending: Amount::ZERO, | ||||||
|             untrusted_pending: 0, |             untrusted_pending: Amount::ZERO, | ||||||
|             confirmed: 25_000 |             confirmed: Amount::from_sat(25_000) | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
| @ -3654,7 +3682,7 @@ fn test_allow_dust_limit() { | |||||||
| 
 | 
 | ||||||
|     let mut builder = wallet.build_tx(); |     let mut builder = wallet.build_tx(); | ||||||
| 
 | 
 | ||||||
|     builder.add_recipient(addr.script_pubkey(), 0); |     builder.add_recipient(addr.script_pubkey(), Amount::ZERO); | ||||||
| 
 | 
 | ||||||
|     assert_matches!( |     assert_matches!( | ||||||
|         builder.finish(), |         builder.finish(), | ||||||
| @ -3665,7 +3693,7 @@ fn test_allow_dust_limit() { | |||||||
| 
 | 
 | ||||||
|     builder |     builder | ||||||
|         .allow_dust(true) |         .allow_dust(true) | ||||||
|         .add_recipient(addr.script_pubkey(), 0); |         .add_recipient(addr.script_pubkey(), Amount::ZERO); | ||||||
| 
 | 
 | ||||||
|     assert!(builder.finish().is_ok()); |     assert!(builder.finish().is_ok()); | ||||||
| } | } | ||||||
| @ -3793,7 +3821,7 @@ fn test_tx_cancellation() { | |||||||
|                 .unwrap() |                 .unwrap() | ||||||
|                 .assume_checked(); |                 .assume_checked(); | ||||||
|             let mut builder = $wallet.build_tx(); |             let mut builder = $wallet.build_tx(); | ||||||
|             builder.add_recipient(addr.script_pubkey(), 10_000); |             builder.add_recipient(addr.script_pubkey(), Amount::from_sat(10_000)); | ||||||
| 
 | 
 | ||||||
|             let psbt = builder.finish().unwrap(); |             let psbt = builder.finish().unwrap(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -377,7 +377,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> { | |||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         get_balance(&recv_chain, &recv_graph)?, |         get_balance(&recv_chain, &recv_graph)?, | ||||||
|         Balance { |         Balance { | ||||||
|             confirmed: SEND_AMOUNT.to_sat() * ADDITIONAL_COUNT as u64, |             confirmed: SEND_AMOUNT * ADDITIONAL_COUNT as u64, | ||||||
|             ..Balance::default() |             ..Balance::default() | ||||||
|         }, |         }, | ||||||
|         "initial balance must be correct", |         "initial balance must be correct", | ||||||
| @ -391,8 +391,8 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> { | |||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             get_balance(&recv_chain, &recv_graph)?, |             get_balance(&recv_chain, &recv_graph)?, | ||||||
|             Balance { |             Balance { | ||||||
|                 confirmed: SEND_AMOUNT.to_sat() * (ADDITIONAL_COUNT - reorg_count) as u64, |                 confirmed: SEND_AMOUNT * (ADDITIONAL_COUNT - reorg_count) as u64, | ||||||
|                 trusted_pending: SEND_AMOUNT.to_sat() * reorg_count as u64, |                 trusted_pending: SEND_AMOUNT * reorg_count as u64, | ||||||
|                 ..Balance::default() |                 ..Balance::default() | ||||||
|             }, |             }, | ||||||
|             "reorg_count: {}", |             "reorg_count: {}", | ||||||
|  | |||||||
| @ -14,6 +14,7 @@ use crate::{collections::BTreeMap, Append}; | |||||||
| 
 | 
 | ||||||
| #[cfg(feature = "miniscript")] | #[cfg(feature = "miniscript")] | ||||||
| mod txout_index; | mod txout_index; | ||||||
|  | use bitcoin::Amount; | ||||||
| #[cfg(feature = "miniscript")] | #[cfg(feature = "miniscript")] | ||||||
| pub use txout_index::*; | pub use txout_index::*; | ||||||
| 
 | 
 | ||||||
| @ -90,13 +91,13 @@ impl<K> AsRef<BTreeMap<K, u32>> for ChangeSet<K> { | |||||||
| )] | )] | ||||||
| pub struct Balance { | pub struct Balance { | ||||||
|     /// All coinbase outputs not yet matured
 |     /// All coinbase outputs not yet matured
 | ||||||
|     pub immature: u64, |     pub immature: Amount, | ||||||
|     /// Unconfirmed UTXOs generated by a wallet tx
 |     /// Unconfirmed UTXOs generated by a wallet tx
 | ||||||
|     pub trusted_pending: u64, |     pub trusted_pending: Amount, | ||||||
|     /// Unconfirmed UTXOs received from an external wallet
 |     /// Unconfirmed UTXOs received from an external wallet
 | ||||||
|     pub untrusted_pending: u64, |     pub untrusted_pending: Amount, | ||||||
|     /// Confirmed and immediately spendable balance
 |     /// Confirmed and immediately spendable balance
 | ||||||
|     pub confirmed: u64, |     pub confirmed: Amount, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Balance { | impl Balance { | ||||||
| @ -104,12 +105,12 @@ impl Balance { | |||||||
|     ///
 |     ///
 | ||||||
|     /// This is the balance you can spend right now that shouldn't get cancelled via another party
 |     /// This is the balance you can spend right now that shouldn't get cancelled via another party
 | ||||||
|     /// double spending it.
 |     /// double spending it.
 | ||||||
|     pub fn trusted_spendable(&self) -> u64 { |     pub fn trusted_spendable(&self) -> Amount { | ||||||
|         self.confirmed + self.trusted_pending |         self.confirmed + self.trusted_pending | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Get the whole balance visible to the wallet.
 |     /// Get the whole balance visible to the wallet.
 | ||||||
|     pub fn total(&self) -> u64 { |     pub fn total(&self) -> Amount { | ||||||
|         self.confirmed + self.trusted_pending + self.untrusted_pending + self.immature |         self.confirmed + self.trusted_pending + self.untrusted_pending + self.immature | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ use crate::{ | |||||||
|     spk_iter::BIP32_MAX_INDEX, |     spk_iter::BIP32_MAX_INDEX, | ||||||
|     SpkIterator, SpkTxOutIndex, |     SpkIterator, SpkTxOutIndex, | ||||||
| }; | }; | ||||||
| use bitcoin::{OutPoint, Script, Transaction, TxOut, Txid}; | use bitcoin::{Amount, OutPoint, Script, SignedAmount, Transaction, TxOut, Txid}; | ||||||
| use core::{ | use core::{ | ||||||
|     fmt::Debug, |     fmt::Debug, | ||||||
|     ops::{Bound, RangeBounds}, |     ops::{Bound, RangeBounds}, | ||||||
| @ -273,7 +273,11 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> { | |||||||
|     /// *received* when it is on an output. For `sent` to be computed correctly, the output being
 |     /// *received* when it is on an output. For `sent` to be computed correctly, the output being
 | ||||||
|     /// spent must have already been scanned by the index. Calculating received just uses the
 |     /// spent must have already been scanned by the index. Calculating received just uses the
 | ||||||
|     /// [`Transaction`] outputs directly, so it will be correct even if it has not been scanned.
 |     /// [`Transaction`] outputs directly, so it will be correct even if it has not been scanned.
 | ||||||
|     pub fn sent_and_received(&self, tx: &Transaction, range: impl RangeBounds<K>) -> (u64, u64) { |     pub fn sent_and_received( | ||||||
|  |         &self, | ||||||
|  |         tx: &Transaction, | ||||||
|  |         range: impl RangeBounds<K>, | ||||||
|  |     ) -> (Amount, Amount) { | ||||||
|         self.inner |         self.inner | ||||||
|             .sent_and_received(tx, Self::map_to_inner_bounds(range)) |             .sent_and_received(tx, Self::map_to_inner_bounds(range)) | ||||||
|     } |     } | ||||||
| @ -285,7 +289,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> { | |||||||
|     /// This calls [`SpkTxOutIndex::net_value`] internally.
 |     /// This calls [`SpkTxOutIndex::net_value`] internally.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// [`sent_and_received`]: Self::sent_and_received
 |     /// [`sent_and_received`]: Self::sent_and_received
 | ||||||
|     pub fn net_value(&self, tx: &Transaction, range: impl RangeBounds<K>) -> i64 { |     pub fn net_value(&self, tx: &Transaction, range: impl RangeBounds<K>) -> SignedAmount { | ||||||
|         self.inner.net_value(tx, Self::map_to_inner_bounds(range)) |         self.inner.net_value(tx, Self::map_to_inner_bounds(range)) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ use crate::{ | |||||||
|     collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap}, |     collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap}, | ||||||
|     indexed_tx_graph::Indexer, |     indexed_tx_graph::Indexer, | ||||||
| }; | }; | ||||||
| use bitcoin::{OutPoint, Script, ScriptBuf, Transaction, TxOut, Txid}; | use bitcoin::{Amount, OutPoint, Script, ScriptBuf, SignedAmount, Transaction, TxOut, Txid}; | ||||||
| 
 | 
 | ||||||
| /// An index storing [`TxOut`]s that have a script pubkey that matches those in a list.
 | /// An index storing [`TxOut`]s that have a script pubkey that matches those in a list.
 | ||||||
| ///
 | ///
 | ||||||
| @ -275,21 +275,25 @@ impl<I: Clone + Ord> SpkTxOutIndex<I> { | |||||||
|     /// output. For `sent` to be computed correctly, the output being spent must have already been
 |     /// output. For `sent` to be computed correctly, the output being spent must have already been
 | ||||||
|     /// scanned by the index. Calculating received just uses the [`Transaction`] outputs directly,
 |     /// scanned by the index. Calculating received just uses the [`Transaction`] outputs directly,
 | ||||||
|     /// so it will be correct even if it has not been scanned.
 |     /// so it will be correct even if it has not been scanned.
 | ||||||
|     pub fn sent_and_received(&self, tx: &Transaction, range: impl RangeBounds<I>) -> (u64, u64) { |     pub fn sent_and_received( | ||||||
|         let mut sent = 0; |         &self, | ||||||
|         let mut received = 0; |         tx: &Transaction, | ||||||
|  |         range: impl RangeBounds<I>, | ||||||
|  |     ) -> (Amount, Amount) { | ||||||
|  |         let mut sent = Amount::ZERO; | ||||||
|  |         let mut received = Amount::ZERO; | ||||||
| 
 | 
 | ||||||
|         for txin in &tx.input { |         for txin in &tx.input { | ||||||
|             if let Some((index, txout)) = self.txout(txin.previous_output) { |             if let Some((index, txout)) = self.txout(txin.previous_output) { | ||||||
|                 if range.contains(index) { |                 if range.contains(index) { | ||||||
|                     sent += txout.value.to_sat(); |                     sent += txout.value; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         for txout in &tx.output { |         for txout in &tx.output { | ||||||
|             if let Some(index) = self.index_of_spk(&txout.script_pubkey) { |             if let Some(index) = self.index_of_spk(&txout.script_pubkey) { | ||||||
|                 if range.contains(index) { |                 if range.contains(index) { | ||||||
|                     received += txout.value.to_sat(); |                     received += txout.value; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -301,9 +305,10 @@ impl<I: Clone + Ord> SpkTxOutIndex<I> { | |||||||
|     /// for calling [`sent_and_received`] and subtracting sent from received.
 |     /// for calling [`sent_and_received`] and subtracting sent from received.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// [`sent_and_received`]: Self::sent_and_received
 |     /// [`sent_and_received`]: Self::sent_and_received
 | ||||||
|     pub fn net_value(&self, tx: &Transaction, range: impl RangeBounds<I>) -> i64 { |     pub fn net_value(&self, tx: &Transaction, range: impl RangeBounds<I>) -> SignedAmount { | ||||||
|         let (sent, received) = self.sent_and_received(tx, range); |         let (sent, received) = self.sent_and_received(tx, range); | ||||||
|         received as i64 - sent as i64 |         received.to_signed().expect("valid `SignedAmount`") | ||||||
|  |             - sent.to_signed().expect("valid `SignedAmount`") | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Whether any of the inputs of this transaction spend a txout tracked or whether any output
 |     /// Whether any of the inputs of this transaction spend a txout tracked or whether any output
 | ||||||
|  | |||||||
| @ -95,7 +95,7 @@ use crate::{ | |||||||
| use alloc::collections::vec_deque::VecDeque; | use alloc::collections::vec_deque::VecDeque; | ||||||
| use alloc::sync::Arc; | use alloc::sync::Arc; | ||||||
| use alloc::vec::Vec; | use alloc::vec::Vec; | ||||||
| use bitcoin::{OutPoint, Script, Transaction, TxOut, Txid}; | use bitcoin::{Amount, OutPoint, Script, Transaction, TxOut, Txid}; | ||||||
| use core::fmt::{self, Formatter}; | use core::fmt::{self, Formatter}; | ||||||
| use core::{ | use core::{ | ||||||
|     convert::Infallible, |     convert::Infallible, | ||||||
| @ -1155,10 +1155,10 @@ impl<A: Anchor> TxGraph<A> { | |||||||
|         outpoints: impl IntoIterator<Item = (OI, OutPoint)>, |         outpoints: impl IntoIterator<Item = (OI, OutPoint)>, | ||||||
|         mut trust_predicate: impl FnMut(&OI, &Script) -> bool, |         mut trust_predicate: impl FnMut(&OI, &Script) -> bool, | ||||||
|     ) -> Result<Balance, C::Error> { |     ) -> Result<Balance, C::Error> { | ||||||
|         let mut immature = 0; |         let mut immature = Amount::ZERO; | ||||||
|         let mut trusted_pending = 0; |         let mut trusted_pending = Amount::ZERO; | ||||||
|         let mut untrusted_pending = 0; |         let mut untrusted_pending = Amount::ZERO; | ||||||
|         let mut confirmed = 0; |         let mut confirmed = Amount::ZERO; | ||||||
| 
 | 
 | ||||||
|         for res in self.try_filter_chain_unspents(chain, chain_tip, outpoints) { |         for res in self.try_filter_chain_unspents(chain, chain_tip, outpoints) { | ||||||
|             let (spk_i, txout) = res?; |             let (spk_i, txout) = res?; | ||||||
| @ -1166,16 +1166,16 @@ impl<A: Anchor> TxGraph<A> { | |||||||
|             match &txout.chain_position { |             match &txout.chain_position { | ||||||
|                 ChainPosition::Confirmed(_) => { |                 ChainPosition::Confirmed(_) => { | ||||||
|                     if txout.is_confirmed_and_spendable(chain_tip.height) { |                     if txout.is_confirmed_and_spendable(chain_tip.height) { | ||||||
|                         confirmed += txout.txout.value.to_sat(); |                         confirmed += txout.txout.value; | ||||||
|                     } else if !txout.is_mature(chain_tip.height) { |                     } else if !txout.is_mature(chain_tip.height) { | ||||||
|                         immature += txout.txout.value.to_sat(); |                         immature += txout.txout.value; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 ChainPosition::Unconfirmed(_) => { |                 ChainPosition::Unconfirmed(_) => { | ||||||
|                     if trust_predicate(&spk_i, &txout.txout.script_pubkey) { |                     if trust_predicate(&spk_i, &txout.txout.script_pubkey) { | ||||||
|                         trusted_pending += txout.txout.value.to_sat(); |                         trusted_pending += txout.txout.value; | ||||||
|                     } else { |                     } else { | ||||||
|                         untrusted_pending += txout.txout.value.to_sat(); |                         untrusted_pending += txout.txout.value; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -341,10 +341,10 @@ fn test_list_owned_txouts() { | |||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             balance, |             balance, | ||||||
|             Balance { |             Balance { | ||||||
|                 immature: 70000,          // immature coinbase
 |                 immature: Amount::from_sat(70000),          // immature coinbase
 | ||||||
|                 trusted_pending: 25000,   // tx3 + tx5
 |                 trusted_pending: Amount::from_sat(25000),   // tx3 + tx5
 | ||||||
|                 untrusted_pending: 20000, // tx4
 |                 untrusted_pending: Amount::from_sat(20000), // tx4
 | ||||||
|                 confirmed: 0              // Nothing is confirmed yet
 |                 confirmed: Amount::ZERO                     // Nothing is confirmed yet
 | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| @ -376,10 +376,10 @@ fn test_list_owned_txouts() { | |||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             balance, |             balance, | ||||||
|             Balance { |             Balance { | ||||||
|                 immature: 70000,          // immature coinbase
 |                 immature: Amount::from_sat(70000),          // immature coinbase
 | ||||||
|                 trusted_pending: 25000,   // tx3 + tx5
 |                 trusted_pending: Amount::from_sat(25000),   // tx3 + tx5
 | ||||||
|                 untrusted_pending: 20000, // tx4
 |                 untrusted_pending: Amount::from_sat(20000), // tx4
 | ||||||
|                 confirmed: 0              // Nothing is confirmed yet
 |                 confirmed: Amount::ZERO                     // Nothing is confirmed yet
 | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| @ -408,10 +408,10 @@ fn test_list_owned_txouts() { | |||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             balance, |             balance, | ||||||
|             Balance { |             Balance { | ||||||
|                 immature: 70000,          // immature coinbase
 |                 immature: Amount::from_sat(70000),          // immature coinbase
 | ||||||
|                 trusted_pending: 15000,   // tx5
 |                 trusted_pending: Amount::from_sat(15000),   // tx5
 | ||||||
|                 untrusted_pending: 20000, // tx4
 |                 untrusted_pending: Amount::from_sat(20000), // tx4
 | ||||||
|                 confirmed: 10000          // tx3 got confirmed
 |                 confirmed: Amount::from_sat(10000)          // tx3 got confirmed
 | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| @ -439,10 +439,10 @@ fn test_list_owned_txouts() { | |||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             balance, |             balance, | ||||||
|             Balance { |             Balance { | ||||||
|                 immature: 70000,          // immature coinbase
 |                 immature: Amount::from_sat(70000),          // immature coinbase
 | ||||||
|                 trusted_pending: 15000,   // tx5
 |                 trusted_pending: Amount::from_sat(15000),   // tx5
 | ||||||
|                 untrusted_pending: 20000, // tx4
 |                 untrusted_pending: Amount::from_sat(20000), // tx4
 | ||||||
|                 confirmed: 10000          // tx1 got matured
 |                 confirmed: Amount::from_sat(10000)          // tx1 got matured
 | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| @ -455,10 +455,10 @@ fn test_list_owned_txouts() { | |||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             balance, |             balance, | ||||||
|             Balance { |             Balance { | ||||||
|                 immature: 0,              // coinbase matured
 |                 immature: Amount::ZERO,                     // coinbase matured
 | ||||||
|                 trusted_pending: 15000,   // tx5
 |                 trusted_pending: Amount::from_sat(15000),   // tx5
 | ||||||
|                 untrusted_pending: 20000, // tx4
 |                 untrusted_pending: Amount::from_sat(20000), // tx4
 | ||||||
|                 confirmed: 80000          // tx1 + tx3
 |                 confirmed: Amount::from_sat(80000)          // tx1 + tx3
 | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| use bdk_chain::{indexed_tx_graph::Indexer, SpkTxOutIndex}; | use bdk_chain::{indexed_tx_graph::Indexer, SpkTxOutIndex}; | ||||||
| use bitcoin::{absolute, transaction, Amount, OutPoint, ScriptBuf, Transaction, TxIn, TxOut}; | use bitcoin::{ | ||||||
|  |     absolute, transaction, Amount, OutPoint, ScriptBuf, SignedAmount, Transaction, TxIn, TxOut, | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn spk_txout_sent_and_received() { | fn spk_txout_sent_and_received() { | ||||||
| @ -20,14 +22,23 @@ fn spk_txout_sent_and_received() { | |||||||
|         }], |         }], | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     assert_eq!(index.sent_and_received(&tx1, ..), (0, 42_000)); |     assert_eq!( | ||||||
|     assert_eq!(index.sent_and_received(&tx1, ..1), (0, 42_000)); |         index.sent_and_received(&tx1, ..), | ||||||
|     assert_eq!(index.sent_and_received(&tx1, 1..), (0, 0)); |         (Amount::from_sat(0), Amount::from_sat(42_000)) | ||||||
|     assert_eq!(index.net_value(&tx1, ..), 42_000); |     ); | ||||||
|  |     assert_eq!( | ||||||
|  |         index.sent_and_received(&tx1, ..1), | ||||||
|  |         (Amount::from_sat(0), Amount::from_sat(42_000)) | ||||||
|  |     ); | ||||||
|  |     assert_eq!( | ||||||
|  |         index.sent_and_received(&tx1, 1..), | ||||||
|  |         (Amount::from_sat(0), Amount::from_sat(0)) | ||||||
|  |     ); | ||||||
|  |     assert_eq!(index.net_value(&tx1, ..), SignedAmount::from_sat(42_000)); | ||||||
|     index.index_tx(&tx1); |     index.index_tx(&tx1); | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         index.sent_and_received(&tx1, ..), |         index.sent_and_received(&tx1, ..), | ||||||
|         (0, 42_000), |         (Amount::from_sat(0), Amount::from_sat(42_000)), | ||||||
|         "shouldn't change after scanning" |         "shouldn't change after scanning" | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -53,10 +64,19 @@ fn spk_txout_sent_and_received() { | |||||||
|         ], |         ], | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     assert_eq!(index.sent_and_received(&tx2, ..), (42_000, 50_000)); |     assert_eq!( | ||||||
|     assert_eq!(index.sent_and_received(&tx2, ..1), (42_000, 30_000)); |         index.sent_and_received(&tx2, ..), | ||||||
|     assert_eq!(index.sent_and_received(&tx2, 1..), (0, 20_000)); |         (Amount::from_sat(42_000), Amount::from_sat(50_000)) | ||||||
|     assert_eq!(index.net_value(&tx2, ..), 8_000); |     ); | ||||||
|  |     assert_eq!( | ||||||
|  |         index.sent_and_received(&tx2, ..1), | ||||||
|  |         (Amount::from_sat(42_000), Amount::from_sat(30_000)) | ||||||
|  |     ); | ||||||
|  |     assert_eq!( | ||||||
|  |         index.sent_and_received(&tx2, 1..), | ||||||
|  |         (Amount::from_sat(0), Amount::from_sat(20_000)) | ||||||
|  |     ); | ||||||
|  |     assert_eq!(index.net_value(&tx2, ..), SignedAmount::from_sat(8_000)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ mod common; | |||||||
| use std::collections::{BTreeSet, HashSet}; | use std::collections::{BTreeSet, HashSet}; | ||||||
| 
 | 
 | ||||||
| use bdk_chain::{keychain::Balance, BlockId}; | use bdk_chain::{keychain::Balance, BlockId}; | ||||||
| use bitcoin::{OutPoint, Script}; | use bitcoin::{Amount, OutPoint, Script}; | ||||||
| use common::*; | use common::*; | ||||||
| 
 | 
 | ||||||
| #[allow(dead_code)] | #[allow(dead_code)] | ||||||
| @ -79,10 +79,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("confirmed_genesis", 0), ("confirmed_conflict", 0)]), |             exp_chain_txouts: HashSet::from([("confirmed_genesis", 0), ("confirmed_conflict", 0)]), | ||||||
|             exp_unspents: HashSet::from([("confirmed_conflict", 0)]), |             exp_unspents: HashSet::from([("confirmed_conflict", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 0, |                 trusted_pending: Amount::ZERO, | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 20000, |                 confirmed: Amount::from_sat(20000), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -115,10 +115,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx_conflict_2", 0)]), |             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx_conflict_2", 0)]), | ||||||
|             exp_unspents: HashSet::from([("tx_conflict_2", 0)]), |             exp_unspents: HashSet::from([("tx_conflict_2", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 30000, |                 trusted_pending: Amount::from_sat(30000), | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 0, |                 confirmed: Amount::ZERO, | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -150,10 +150,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx1", 1), ("tx_conflict_2", 0)]), |             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx1", 1), ("tx_conflict_2", 0)]), | ||||||
|             exp_unspents: HashSet::from([("tx_conflict_2", 0)]), |             exp_unspents: HashSet::from([("tx_conflict_2", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 30000, |                 trusted_pending: Amount::from_sat(30000), | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 0, |                 confirmed: Amount::ZERO, | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -192,10 +192,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx_conflict_3", 0)]), |             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx_conflict_3", 0)]), | ||||||
|             exp_unspents: HashSet::from([("tx_conflict_3", 0)]), |             exp_unspents: HashSet::from([("tx_conflict_3", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 40000, |                 trusted_pending: Amount::from_sat(40000), | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 0, |                 confirmed: Amount::ZERO, | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -227,10 +227,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx_orphaned_conflict", 0)]), |             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx_orphaned_conflict", 0)]), | ||||||
|             exp_unspents: HashSet::from([("tx_orphaned_conflict", 0)]), |             exp_unspents: HashSet::from([("tx_orphaned_conflict", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 30000, |                 trusted_pending: Amount::from_sat(30000), | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 0, |                 confirmed: Amount::ZERO, | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -262,10 +262,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx_conflict_1", 0)]), |             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx_conflict_1", 0)]), | ||||||
|             exp_unspents: HashSet::from([("tx_conflict_1", 0)]), |             exp_unspents: HashSet::from([("tx_conflict_1", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 20000, |                 trusted_pending: Amount::from_sat(20000), | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 0, |                 confirmed: Amount::ZERO, | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -311,10 +311,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx_confirmed_conflict", 0)]), |             exp_chain_txouts: HashSet::from([("tx1", 0), ("tx_confirmed_conflict", 0)]), | ||||||
|             exp_unspents: HashSet::from([("tx_confirmed_conflict", 0)]), |             exp_unspents: HashSet::from([("tx_confirmed_conflict", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 0, |                 trusted_pending: Amount::ZERO, | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 50000, |                 confirmed: Amount::from_sat(50000), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -356,10 +356,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("A", 0), ("B", 0), ("C", 0)]), |             exp_chain_txouts: HashSet::from([("A", 0), ("B", 0), ("C", 0)]), | ||||||
|             exp_unspents: HashSet::from([("C", 0)]), |             exp_unspents: HashSet::from([("C", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 30000, |                 trusted_pending: Amount::from_sat(30000), | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 0, |                 confirmed: Amount::ZERO, | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -397,10 +397,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("A", 0), ("B'", 0)]), |             exp_chain_txouts: HashSet::from([("A", 0), ("B'", 0)]), | ||||||
|             exp_unspents: HashSet::from([("B'", 0)]), |             exp_unspents: HashSet::from([("B'", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 0, |                 trusted_pending: Amount::ZERO, | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 20000, |                 confirmed: Amount::from_sat(20000), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -442,10 +442,10 @@ fn test_tx_conflict_handling() { | |||||||
|             ]), |             ]), | ||||||
|             exp_unspents: HashSet::from([("C", 0)]), |             exp_unspents: HashSet::from([("C", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 30000, |                 trusted_pending: Amount::from_sat(30000), | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 0, |                 confirmed: Amount::ZERO, | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -487,10 +487,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("A", 0), ("B'", 0)]), |             exp_chain_txouts: HashSet::from([("A", 0), ("B'", 0)]), | ||||||
|             exp_unspents: HashSet::from([("B'", 0)]), |             exp_unspents: HashSet::from([("B'", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 30000, |                 trusted_pending: Amount::from_sat(30000), | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 0, |                 confirmed: Amount::ZERO, | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -532,10 +532,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("A", 0), ("B'", 0)]), |             exp_chain_txouts: HashSet::from([("A", 0), ("B'", 0)]), | ||||||
|             exp_unspents: HashSet::from([("B'", 0)]), |             exp_unspents: HashSet::from([("B'", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 0, |                 trusted_pending: Amount::ZERO, | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 50000, |                 confirmed: Amount::from_sat(50000), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         Scenario { |         Scenario { | ||||||
| @ -583,10 +583,10 @@ fn test_tx_conflict_handling() { | |||||||
|             exp_chain_txouts: HashSet::from([("A", 0), ("B'", 0)]), |             exp_chain_txouts: HashSet::from([("A", 0), ("B'", 0)]), | ||||||
|             exp_unspents: HashSet::from([("B'", 0)]), |             exp_unspents: HashSet::from([("B'", 0)]), | ||||||
|             exp_balance: Balance { |             exp_balance: Balance { | ||||||
|                 immature: 0, |                 immature: Amount::ZERO, | ||||||
|                 trusted_pending: 0, |                 trusted_pending: Amount::ZERO, | ||||||
|                 untrusted_pending: 0, |                 untrusted_pending: Amount::ZERO, | ||||||
|                 confirmed: 50000, |                 confirmed: Amount::from_sat(50000), | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|     ]; |     ]; | ||||||
|  | |||||||
| @ -76,7 +76,7 @@ fn scan_detects_confirmed_tx() -> Result<()> { | |||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         get_balance(&recv_chain, &recv_graph)?, |         get_balance(&recv_chain, &recv_graph)?, | ||||||
|         Balance { |         Balance { | ||||||
|             confirmed: SEND_AMOUNT.to_sat(), |             confirmed: SEND_AMOUNT, | ||||||
|             ..Balance::default() |             ..Balance::default() | ||||||
|         }, |         }, | ||||||
|     ); |     ); | ||||||
| @ -145,7 +145,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> Result<()> { | |||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         get_balance(&recv_chain, &recv_graph)?, |         get_balance(&recv_chain, &recv_graph)?, | ||||||
|         Balance { |         Balance { | ||||||
|             confirmed: SEND_AMOUNT.to_sat() * REORG_COUNT as u64, |             confirmed: SEND_AMOUNT * REORG_COUNT as u64, | ||||||
|             ..Balance::default() |             ..Balance::default() | ||||||
|         }, |         }, | ||||||
|         "initial balance must be correct", |         "initial balance must be correct", | ||||||
| @ -176,8 +176,8 @@ fn tx_can_become_unconfirmed_after_reorg() -> Result<()> { | |||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             get_balance(&recv_chain, &recv_graph)?, |             get_balance(&recv_chain, &recv_graph)?, | ||||||
|             Balance { |             Balance { | ||||||
|                 confirmed: SEND_AMOUNT.to_sat() * (REORG_COUNT - depth) as u64, |                 confirmed: SEND_AMOUNT * (REORG_COUNT - depth) as u64, | ||||||
|                 trusted_pending: SEND_AMOUNT.to_sat() * depth as u64, |                 trusted_pending: SEND_AMOUNT * depth as u64, | ||||||
|                 ..Balance::default() |                 ..Balance::default() | ||||||
|             }, |             }, | ||||||
|             "reorg_count: {}", |             "reorg_count: {}", | ||||||
|  | |||||||
| @ -506,11 +506,11 @@ where | |||||||
|             let chain = &*chain.lock().unwrap(); |             let chain = &*chain.lock().unwrap(); | ||||||
|             fn print_balances<'a>( |             fn print_balances<'a>( | ||||||
|                 title_str: &'a str, |                 title_str: &'a str, | ||||||
|                 items: impl IntoIterator<Item = (&'a str, u64)>, |                 items: impl IntoIterator<Item = (&'a str, Amount)>, | ||||||
|             ) { |             ) { | ||||||
|                 println!("{}:", title_str); |                 println!("{}:", title_str); | ||||||
|                 for (name, amount) in items.into_iter() { |                 for (name, amount) in items.into_iter() { | ||||||
|                     println!("    {:<10} {:>12} sats", name, amount) |                     println!("    {:<10} {:>12} sats", name, amount.to_sat()) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| const DB_MAGIC: &str = "bdk_wallet_electrum_example"; | const DB_MAGIC: &str = "bdk_wallet_electrum_example"; | ||||||
| const SEND_AMOUNT: u64 = 5000; | const SEND_AMOUNT: Amount = Amount::from_sat(5000); | ||||||
| const STOP_GAP: usize = 50; | const STOP_GAP: usize = 50; | ||||||
| const BATCH_SIZE: usize = 5; | const BATCH_SIZE: usize = 5; | ||||||
| 
 | 
 | ||||||
| use std::io::Write; | use std::io::Write; | ||||||
| use std::str::FromStr; | use std::str::FromStr; | ||||||
| 
 | 
 | ||||||
| use bdk::bitcoin::Address; | use bdk::bitcoin::{Address, Amount}; | ||||||
| use bdk::wallet::Update; | use bdk::wallet::Update; | ||||||
| use bdk::{bitcoin::Network, Wallet}; | use bdk::{bitcoin::Network, Wallet}; | ||||||
| use bdk::{KeychainKind, SignOptions}; | use bdk::{KeychainKind, SignOptions}; | ||||||
|  | |||||||
| @ -1,14 +1,14 @@ | |||||||
| use std::{collections::BTreeSet, io::Write, str::FromStr}; | use std::{collections::BTreeSet, io::Write, str::FromStr}; | ||||||
| 
 | 
 | ||||||
| use bdk::{ | use bdk::{ | ||||||
|     bitcoin::{Address, Network, Script}, |     bitcoin::{Address, Amount, Network, Script}, | ||||||
|     KeychainKind, SignOptions, Wallet, |     KeychainKind, SignOptions, Wallet, | ||||||
| }; | }; | ||||||
| use bdk_esplora::{esplora_client, EsploraAsyncExt}; | use bdk_esplora::{esplora_client, EsploraAsyncExt}; | ||||||
| use bdk_file_store::Store; | use bdk_file_store::Store; | ||||||
| 
 | 
 | ||||||
| const DB_MAGIC: &str = "bdk_wallet_esplora_async_example"; | const DB_MAGIC: &str = "bdk_wallet_esplora_async_example"; | ||||||
| const SEND_AMOUNT: u64 = 5000; | const SEND_AMOUNT: Amount = Amount::from_sat(5000); | ||||||
| const STOP_GAP: usize = 50; | const STOP_GAP: usize = 50; | ||||||
| const PARALLEL_REQUESTS: usize = 5; | const PARALLEL_REQUESTS: usize = 5; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| const DB_MAGIC: &str = "bdk_wallet_esplora_example"; | const DB_MAGIC: &str = "bdk_wallet_esplora_example"; | ||||||
| const SEND_AMOUNT: u64 = 1000; | const SEND_AMOUNT: Amount = Amount::from_sat(1000); | ||||||
| const STOP_GAP: usize = 5; | const STOP_GAP: usize = 5; | ||||||
| const PARALLEL_REQUESTS: usize = 1; | const PARALLEL_REQUESTS: usize = 1; | ||||||
| 
 | 
 | ||||||
| use std::{collections::BTreeSet, io::Write, str::FromStr}; | use std::{collections::BTreeSet, io::Write, str::FromStr}; | ||||||
| 
 | 
 | ||||||
| use bdk::{ | use bdk::{ | ||||||
|     bitcoin::{Address, Network}, |     bitcoin::{Address, Amount, Network}, | ||||||
|     KeychainKind, SignOptions, Wallet, |     KeychainKind, SignOptions, Wallet, | ||||||
| }; | }; | ||||||
| use bdk_esplora::{esplora_client, EsploraExt}; | use bdk_esplora::{esplora_client, EsploraExt}; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user