From 96bf1e3a8164dbf81622c66241f0808450cf7d59 Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Thu, 11 Sep 2025 14:32:44 -0400 Subject: [PATCH 1/3] docs: add api docs for FeeRate type --- bdk-ffi/src/bitcoin.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bdk-ffi/src/bitcoin.rs b/bdk-ffi/src/bitcoin.rs index 06f2ea35..bc1545fa 100644 --- a/bdk-ffi/src/bitcoin.rs +++ b/bdk-ffi/src/bitcoin.rs @@ -125,6 +125,7 @@ pub struct FeeRate(pub BdkFeeRate); #[uniffi::export] impl FeeRate { + // Constructs `FeeRate` from satoshis per virtual bytes. #[uniffi::constructor] pub fn from_sat_per_vb(sat_vb: u64) -> Result { let fee_rate: Option = BdkFeeRate::from_sat_per_vb(sat_vb); @@ -134,19 +135,23 @@ impl FeeRate { } } + // Constructs `FeeRate` from satoshis per 1000 weight units. #[uniffi::constructor] pub fn from_sat_per_kwu(sat_kwu: u64) -> Self { FeeRate(BdkFeeRate::from_sat_per_kwu(sat_kwu)) } + /// Converts to sat/vB rounding up. pub fn to_sat_per_vb_ceil(&self) -> u64 { self.0.to_sat_per_vb_ceil() } + /// Converts to sat/vB rounding down. pub fn to_sat_per_vb_floor(&self) -> u64 { self.0.to_sat_per_vb_floor() } + /// Returns raw fee rate. pub fn to_sat_per_kwu(&self) -> u64 { self.0.to_sat_per_kwu() } From 05a5e6600a8bc19d3e0448900b8359b9931ccd5b Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Thu, 11 Sep 2025 15:05:40 -0400 Subject: [PATCH 2/3] feat: implement display trait for FeeRate type --- bdk-ffi/src/bitcoin.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bdk-ffi/src/bitcoin.rs b/bdk-ffi/src/bitcoin.rs index bc1545fa..578103ec 100644 --- a/bdk-ffi/src/bitcoin.rs +++ b/bdk-ffi/src/bitcoin.rs @@ -121,6 +121,7 @@ impl HashableOutPoint { /// This is an integer type representing fee rate in sat/kwu. It provides protection against mixing /// up the types as well as basic formatting features. #[derive(Clone, Debug, uniffi::Object)] +#[uniffi::export(Display)] pub struct FeeRate(pub BdkFeeRate); #[uniffi::export] @@ -157,6 +158,12 @@ impl FeeRate { } } +impl Display for FeeRate { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{} sat/kwu", self.0) + } +} + impl_from_core_type!(BdkFeeRate, FeeRate); impl_into_core_type!(FeeRate, BdkFeeRate); From 7ea0162d442571eedcd9f136fc6bf0330e129e56 Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Thu, 11 Sep 2025 16:01:52 -0400 Subject: [PATCH 3/3] feat: expose FeeRate::fee_vb and FeeRate::fee_wu methods --- bdk-ffi/src/bitcoin.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/bdk-ffi/src/bitcoin.rs b/bdk-ffi/src/bitcoin.rs index 578103ec..738447ea 100644 --- a/bdk-ffi/src/bitcoin.rs +++ b/bdk-ffi/src/bitcoin.rs @@ -26,6 +26,7 @@ use bdk_wallet::bitcoin::Transaction as BdkTransaction; use bdk_wallet::bitcoin::TxIn as BdkTxIn; use bdk_wallet::bitcoin::TxOut as BdkTxOut; use bdk_wallet::bitcoin::Txid as BitcoinTxid; +use bdk_wallet::bitcoin::Weight; use bdk_wallet::bitcoin::Wtxid as BitcoinWtxid; use bdk_wallet::miniscript::psbt::PsbtExt; use bdk_wallet::serde_json; @@ -156,6 +157,30 @@ impl FeeRate { pub fn to_sat_per_kwu(&self) -> u64 { self.0.to_sat_per_kwu() } + + /// Calculates fee in satoshis by multiplying this fee rate by weight, in virtual bytes, returning `None` if overflow occurred. + /// + /// This is equivalent to converting vb to weight using Weight::from_vb and then calling Self::fee_wu(weight). + pub fn fee_vb(&self, vb: u64) -> Option> { + let rust_amount: BdkAmount = self.0.fee_vb(vb)?; + let amount: Amount = rust_amount.into(); + Some(Arc::new(amount)) + + // The whole code above should be replaceable by the following line: + // self.0.fee_vb(vb).map(Arc::new(Amount::from)) + // But in practice you get uniffi compilation errors on it. Not sure what is going on with it, + // but the code we use works just as well. + } + + /// Calculates fee by multiplying this fee rate by weight, in weight units, returning `None` if overflow occurred. + // + // This is equivalent to Self::checked_mul_by_weight(). + pub fn fee_wu(&self, wu: u64) -> Option> { + let weight: Weight = Weight::from_wu(wu); + let rust_amount: BdkAmount = self.0.fee_wu(weight)?; + let amount: Amount = rust_amount.into(); + Some(Arc::new(amount)) + } } impl Display for FeeRate {