Skip to content

Commit 8a33d98

Browse files
committed
feat: update wallet::Balance to use bitcoin::Amount
- update all fields `immature`, ` trusted_pending`, `unstrusted_pending` and `confirmed` to use the `bitcoin::Amount` instead of `u64` - update all `impl Balance` methods to use `bitcoin::Amount` - update all tests that relies on `keychain::Balance`
1 parent 08fac47 commit 8a33d98

File tree

15 files changed

+127
-120
lines changed

15 files changed

+127
-120
lines changed

crates/bdk/src/wallet/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ use bdk_chain::{
3232
IndexedTxGraph,
3333
};
3434
use bdk_persist::{Persist, PersistBackend};
35-
use bitcoin::constants::genesis_block;
3635
use bitcoin::secp256k1::{All, Secp256k1};
3736
use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
3837
use bitcoin::{
3938
absolute, psbt, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence,
4039
Transaction, TxOut, Txid, Witness,
4140
};
42-
use bitcoin::{consensus::encode::serialize, transaction, Amount, BlockHash, Psbt};
41+
use bitcoin::{consensus::encode::serialize, transaction, BlockHash, Psbt};
42+
use bitcoin::{constants::genesis_block, Amount};
4343
use core::fmt;
4444
use core::ops::Deref;
4545
use descriptor::error::Error as DescriptorError;
@@ -950,7 +950,7 @@ impl Wallet {
950950
/// [`insert_txout`]: Self::insert_txout
951951
pub fn calculate_fee_rate(&self, tx: &Transaction) -> Result<FeeRate, CalculateFeeError> {
952952
self.calculate_fee(tx)
953-
.map(|fee| bitcoin::Amount::from_sat(fee) / tx.weight())
953+
.map(|fee| Amount::from_sat(fee) / tx.weight())
954954
}
955955

956956
/// Compute the `tx`'s sent and received amounts (in satoshis).

crates/bdk/src/wallet/tx_builder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ impl<'a, Cs: CoinSelectionAlgorithm> TxBuilder<'a, Cs, CreateTx> {
718718
self
719719
}
720720

721+
// TODO: (@leonardo) Should this expect/use `bitcoin::Amount` instead ? Would it be a huge breaking change ?
721722
/// Add a recipient to the internal list
722723
pub fn add_recipient(&mut self, script_pubkey: ScriptBuf, amount: u64) -> &mut Self {
723724
self.params.recipients.push((script_pubkey, amount));

crates/bdk/tests/psbt.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use bdk::bitcoin::{Amount, FeeRate, Psbt, TxIn};
1+
use bdk::bitcoin::{FeeRate, Psbt, TxIn};
22
use bdk::{psbt, KeychainKind, SignOptions};
33
use core::str::FromStr;
44
mod common;
@@ -201,7 +201,7 @@ fn test_psbt_multiple_internalkey_signers() {
201201
// the prevout we're spending
202202
let prevouts = &[TxOut {
203203
script_pubkey: send_to.script_pubkey(),
204-
value: Amount::from_sat(to_spend),
204+
value: to_spend,
205205
}];
206206
let prevouts = Prevouts::All(prevouts);
207207
let input_index = 0;

crates/bdk/tests/wallet.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ fn test_get_funded_wallet_balance() {
200200
// The funded wallet contains a tx with a 76_000 sats input and two outputs, one spending 25_000
201201
// to a foreign address and one returning 50_000 back to the wallet as change. The remaining 1000
202202
// sats are the transaction fee.
203-
assert_eq!(wallet.get_balance().confirmed, 50_000);
203+
assert_eq!(wallet.get_balance().confirmed.to_sat(), 50_000);
204204
}
205205

206206
#[test]
@@ -3582,10 +3582,10 @@ fn test_spend_coinbase() {
35823582
assert_eq!(
35833583
balance,
35843584
Balance {
3585-
immature: 25_000,
3586-
trusted_pending: 0,
3587-
untrusted_pending: 0,
3588-
confirmed: 0
3585+
immature: Amount::from_sat(25_000),
3586+
trusted_pending: Amount::ZERO,
3587+
untrusted_pending: Amount::ZERO,
3588+
confirmed: Amount::ZERO
35893589
}
35903590
);
35913591

@@ -3596,7 +3596,7 @@ fn test_spend_coinbase() {
35963596
.assume_checked();
35973597
let mut builder = wallet.build_tx();
35983598
builder
3599-
.add_recipient(addr.script_pubkey(), balance.immature / 2)
3599+
.add_recipient(addr.script_pubkey(), balance.immature.to_sat() / 2)
36003600
.current_height(confirmation_height);
36013601
assert!(matches!(
36023602
builder.finish(),
@@ -3611,7 +3611,7 @@ fn test_spend_coinbase() {
36113611
// Still unspendable...
36123612
let mut builder = wallet.build_tx();
36133613
builder
3614-
.add_recipient(addr.script_pubkey(), balance.immature / 2)
3614+
.add_recipient(addr.script_pubkey(), balance.immature.to_sat() / 2)
36153615
.current_height(not_yet_mature_time);
36163616
assert_matches!(
36173617
builder.finish(),
@@ -3633,15 +3633,15 @@ fn test_spend_coinbase() {
36333633
assert_eq!(
36343634
balance,
36353635
Balance {
3636-
immature: 0,
3637-
trusted_pending: 0,
3638-
untrusted_pending: 0,
3639-
confirmed: 25_000
3636+
immature: Amount::ZERO,
3637+
trusted_pending: Amount::ZERO,
3638+
untrusted_pending: Amount::ZERO,
3639+
confirmed: Amount::from_sat(25_000)
36403640
}
36413641
);
36423642
let mut builder = wallet.build_tx();
36433643
builder
3644-
.add_recipient(addr.script_pubkey(), balance.confirmed / 2)
3644+
.add_recipient(addr.script_pubkey(), balance.confirmed.to_sat() / 2)
36453645
.current_height(maturity_time);
36463646
builder.finish().unwrap();
36473647
}

crates/bitcoind_rpc/tests/test_emitter.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
377377
assert_eq!(
378378
get_balance(&recv_chain, &recv_graph)?,
379379
Balance {
380-
confirmed: SEND_AMOUNT.to_sat() * ADDITIONAL_COUNT as u64,
380+
confirmed: SEND_AMOUNT * ADDITIONAL_COUNT as u64,
381381
..Balance::default()
382382
},
383383
"initial balance must be correct",
@@ -391,8 +391,8 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
391391
assert_eq!(
392392
get_balance(&recv_chain, &recv_graph)?,
393393
Balance {
394-
confirmed: SEND_AMOUNT.to_sat() * (ADDITIONAL_COUNT - reorg_count) as u64,
395-
trusted_pending: SEND_AMOUNT.to_sat() * reorg_count as u64,
394+
confirmed: SEND_AMOUNT * (ADDITIONAL_COUNT - reorg_count) as u64,
395+
trusted_pending: SEND_AMOUNT * reorg_count as u64,
396396
..Balance::default()
397397
},
398398
"reorg_count: {}",

crates/chain/src/keychain.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::{collections::BTreeMap, Append};
1414

1515
#[cfg(feature = "miniscript")]
1616
mod txout_index;
17+
use bitcoin::Amount;
1718
#[cfg(feature = "miniscript")]
1819
pub use txout_index::*;
1920

@@ -90,26 +91,26 @@ impl<K> AsRef<BTreeMap<K, u32>> for ChangeSet<K> {
9091
)]
9192
pub struct Balance {
9293
/// All coinbase outputs not yet matured
93-
pub immature: u64,
94+
pub immature: Amount,
9495
/// Unconfirmed UTXOs generated by a wallet tx
95-
pub trusted_pending: u64,
96+
pub trusted_pending: Amount,
9697
/// Unconfirmed UTXOs received from an external wallet
97-
pub untrusted_pending: u64,
98+
pub untrusted_pending: Amount,
9899
/// Confirmed and immediately spendable balance
99-
pub confirmed: u64,
100+
pub confirmed: Amount,
100101
}
101102

102103
impl Balance {
103104
/// Get sum of trusted_pending and confirmed coins.
104105
///
105106
/// This is the balance you can spend right now that shouldn't get cancelled via another party
106107
/// double spending it.
107-
pub fn trusted_spendable(&self) -> u64 {
108+
pub fn trusted_spendable(&self) -> Amount {
108109
self.confirmed + self.trusted_pending
109110
}
110111

111112
/// Get the whole balance visible to the wallet.
112-
pub fn total(&self) -> u64 {
113+
pub fn total(&self) -> Amount {
113114
self.confirmed + self.trusted_pending + self.untrusted_pending + self.immature
114115
}
115116
}

crates/chain/src/spk_txout_index.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ impl<I: Clone + Ord> SpkTxOutIndex<I> {
270270
self.spk_indices.get(script)
271271
}
272272

273+
// TODO: (@leonardo) Should this also be updated to return `(bitcoin::Amount, bitcoin::Amount)` instead of (u64, u64)
273274
/// Computes the total value transfer effect `tx` has on the script pubkeys in `range`. Value is
274275
/// *sent* when a script pubkey in the `range` is on an input and *received* when it is on an
275276
/// output. For `sent` to be computed correctly, the output being spent must have already been

crates/chain/src/tx_graph.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ use crate::{
9595
use alloc::collections::vec_deque::VecDeque;
9696
use alloc::sync::Arc;
9797
use alloc::vec::Vec;
98-
use bitcoin::{OutPoint, Script, Transaction, TxOut, Txid};
98+
use bitcoin::{Amount, OutPoint, Script, Transaction, TxOut, Txid};
9999
use core::fmt::{self, Formatter};
100100
use core::{
101101
convert::Infallible,
@@ -1155,27 +1155,28 @@ impl<A: Anchor> TxGraph<A> {
11551155
outpoints: impl IntoIterator<Item = (OI, OutPoint)>,
11561156
mut trust_predicate: impl FnMut(&OI, &Script) -> bool,
11571157
) -> Result<Balance, C::Error> {
1158-
let mut immature = 0;
1159-
let mut trusted_pending = 0;
1160-
let mut untrusted_pending = 0;
1161-
let mut confirmed = 0;
1158+
let mut immature = Amount::ZERO;
1159+
let mut trusted_pending = Amount::ZERO;
1160+
let mut untrusted_pending = Amount::ZERO;
1161+
let mut confirmed = Amount::ZERO;
11621162

11631163
for res in self.try_filter_chain_unspents(chain, chain_tip, outpoints) {
11641164
let (spk_i, txout) = res?;
11651165

1166+
// TODO: (@leonardo) Should these operations use `bitcoin::Amount::checked_add()` instead ?
11661167
match &txout.chain_position {
11671168
ChainPosition::Confirmed(_) => {
11681169
if txout.is_confirmed_and_spendable(chain_tip.height) {
1169-
confirmed += txout.txout.value.to_sat();
1170+
confirmed += txout.txout.value;
11701171
} else if !txout.is_mature(chain_tip.height) {
1171-
immature += txout.txout.value.to_sat();
1172+
immature += txout.txout.value;
11721173
}
11731174
}
11741175
ChainPosition::Unconfirmed(_) => {
11751176
if trust_predicate(&spk_i, &txout.txout.script_pubkey) {
1176-
trusted_pending += txout.txout.value.to_sat();
1177+
trusted_pending += txout.txout.value;
11771178
} else {
1178-
untrusted_pending += txout.txout.value.to_sat();
1179+
untrusted_pending += txout.txout.value;
11791180
}
11801181
}
11811182
}

crates/chain/tests/test_indexed_tx_graph.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -341,10 +341,10 @@ fn test_list_owned_txouts() {
341341
assert_eq!(
342342
balance,
343343
Balance {
344-
immature: 70000, // immature coinbase
345-
trusted_pending: 25000, // tx3 + tx5
346-
untrusted_pending: 20000, // tx4
347-
confirmed: 0 // Nothing is confirmed yet
344+
immature: Amount::from_sat(70000), // immature coinbase
345+
trusted_pending: Amount::from_sat(25000), // tx3 + tx5
346+
untrusted_pending: Amount::from_sat(20000), // tx4
347+
confirmed: Amount::ZERO // Nothing is confirmed yet
348348
}
349349
);
350350
}
@@ -376,10 +376,10 @@ fn test_list_owned_txouts() {
376376
assert_eq!(
377377
balance,
378378
Balance {
379-
immature: 70000, // immature coinbase
380-
trusted_pending: 25000, // tx3 + tx5
381-
untrusted_pending: 20000, // tx4
382-
confirmed: 0 // Nothing is confirmed yet
379+
immature: Amount::from_sat(70000), // immature coinbase
380+
trusted_pending: Amount::from_sat(25000), // tx3 + tx5
381+
untrusted_pending: Amount::from_sat(20000), // tx4
382+
confirmed: Amount::ZERO // Nothing is confirmed yet
383383
}
384384
);
385385
}
@@ -408,10 +408,10 @@ fn test_list_owned_txouts() {
408408
assert_eq!(
409409
balance,
410410
Balance {
411-
immature: 70000, // immature coinbase
412-
trusted_pending: 15000, // tx5
413-
untrusted_pending: 20000, // tx4
414-
confirmed: 10000 // tx3 got confirmed
411+
immature: Amount::from_sat(70000), // immature coinbase
412+
trusted_pending: Amount::from_sat(15000), // tx5
413+
untrusted_pending: Amount::from_sat(20000), // tx4
414+
confirmed: Amount::from_sat(10000) // tx3 got confirmed
415415
}
416416
);
417417
}
@@ -439,10 +439,10 @@ fn test_list_owned_txouts() {
439439
assert_eq!(
440440
balance,
441441
Balance {
442-
immature: 70000, // immature coinbase
443-
trusted_pending: 15000, // tx5
444-
untrusted_pending: 20000, // tx4
445-
confirmed: 10000 // tx1 got matured
442+
immature: Amount::from_sat(70000), // immature coinbase
443+
trusted_pending: Amount::from_sat(15000), // tx5
444+
untrusted_pending: Amount::from_sat(20000), // tx4
445+
confirmed: Amount::from_sat(10000) // tx1 got matured
446446
}
447447
);
448448
}
@@ -455,10 +455,10 @@ fn test_list_owned_txouts() {
455455
assert_eq!(
456456
balance,
457457
Balance {
458-
immature: 0, // coinbase matured
459-
trusted_pending: 15000, // tx5
460-
untrusted_pending: 20000, // tx4
461-
confirmed: 80000 // tx1 + tx3
458+
immature: Amount::ZERO, // coinbase matured
459+
trusted_pending: Amount::from_sat(15000), // tx5
460+
untrusted_pending: Amount::from_sat(20000), // tx4
461+
confirmed: Amount::from_sat(80000) // tx1 + tx3
462462
}
463463
);
464464
}

0 commit comments

Comments
 (0)