Skip to content

Commit 0608644

Browse files
committed
Add wallet::utils::FeeInfo trait and implement for PartiallySignedBitcoinTransaction
1 parent c9b1b6d commit 0608644

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

src/wallet/mod.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5414,4 +5414,33 @@ pub(crate) mod test {
54145414
// ...and checking that everything is fine
54155415
assert_fee_rate!(psbt, details.fee.unwrap_or(0), fee_rate);
54165416
}
5417+
5418+
#[test]
5419+
fn test_finalized_single_xprv_fee_rate() {
5420+
use utils::FeeInfo;
5421+
5422+
let expected_fee_rate = 1.2345;
5423+
5424+
let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
5425+
let addr = wallet.get_address(New).unwrap();
5426+
let mut builder = wallet.build_tx();
5427+
builder.drain_to(addr.script_pubkey()).drain_wallet();
5428+
builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
5429+
let (mut psbt, _) = builder.finish().unwrap();
5430+
5431+
let fee_amount = psbt.fee_amount();
5432+
dbg!(fee_amount);
5433+
5434+
let unfinalized_fee_rate = psbt.fee_rate();
5435+
dbg!(unfinalized_fee_rate.as_sat_vb());
5436+
5437+
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
5438+
assert!(finalized);
5439+
5440+
let finalized_fee_rate = psbt.fee_rate();
5441+
dbg!(finalized_fee_rate.as_sat_vb());
5442+
5443+
assert!(finalized_fee_rate.as_sat_vb() >= expected_fee_rate);
5444+
assert!(finalized_fee_rate.as_sat_vb() < unfinalized_fee_rate.as_sat_vb());
5445+
}
54175446
}

src/wallet/utils.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
// licenses.
1111

1212
use bitcoin::blockdata::script::Script;
13+
use bitcoin::psbt::PartiallySignedTransaction;
1314
use bitcoin::secp256k1::{All, Secp256k1};
1415

16+
use crate::FeeRate;
1517
use miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
1618

1719
// MSB of the nSequence. If set there's no consensus-constraint, so it must be disabled when
@@ -137,6 +139,38 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for Older {
137139

138140
pub(crate) type SecpCtx = Secp256k1<All>;
139141

142+
/// Trait for extracting fee amount and rate information from a `PartiallySignedTransaction`.
143+
pub trait FeeInfo {
144+
/// The total transaction fee amount, sum of input amounts minus sum of output amounts, in Sats.
145+
fn fee_amount(&self) -> u64;
146+
147+
/// The transaction's fee rate. This value will only be accurate if calculated AFTER the
148+
/// `PartiallySignedTransaction` is finalized and all witness/signature data is added to the
149+
/// transaction.
150+
fn fee_rate(&self) -> FeeRate;
151+
}
152+
153+
impl FeeInfo for PartiallySignedTransaction {
154+
fn fee_amount(&self) -> u64 {
155+
let input_amount = &self
156+
.inputs
157+
.iter()
158+
.fold(0, |acc, i| acc + i.witness_utxo.as_ref().unwrap().value);
159+
let output_amount = &self
160+
.unsigned_tx
161+
.output
162+
.iter()
163+
.fold(0, |acc, o| acc + o.value);
164+
input_amount - output_amount
165+
}
166+
167+
fn fee_rate(&self) -> FeeRate {
168+
let fee_amount = self.fee_amount();
169+
let weight = self.clone().extract_tx().weight();
170+
FeeRate::from_wu(fee_amount, weight)
171+
}
172+
}
173+
140174
#[cfg(test)]
141175
mod test {
142176
use super::{

0 commit comments

Comments
 (0)