From c1a760bf603e49931425a1b6a6ba2b8450c8da11 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 10 Jun 2025 09:30:56 +1000 Subject: [PATCH 1/2] units: Use singular in rustdoc Satoshis per virtual byte is grammatically better than satoshis per virtual bytes - I think. --- units/src/fee_rate/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/units/src/fee_rate/mod.rs b/units/src/fee_rate/mod.rs index f0db11cf0..f2ba94852 100644 --- a/units/src/fee_rate/mod.rs +++ b/units/src/fee_rate/mod.rs @@ -62,7 +62,7 @@ impl FeeRate { } } - /// Constructs a new [`FeeRate`] from satoshis per virtual bytes, + /// Constructs a new [`FeeRate`] from satoshis per virtual byte, /// returning `None` if overflow occurred. pub const fn from_sat_per_vb(sat_vb: u64) -> Option { // No `map()` in const context. From 6ed3fd6234a6d9e44d2cf187108cc22955471d27 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 10 Jun 2025 09:32:27 +1000 Subject: [PATCH 2/2] Add fee rate constructors that take Amount as arg Some users may find it more ergonomic to pass in an `Amount` when constructing fee rates. Also the strong type adds some semantic meaning as well as imposes the `Amount::MAX` limit. Add an equivalent constructor for each of the existing ones that uses an argument of type `Amount` instead of `u64` sats. --- units/src/fee_rate/mod.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/units/src/fee_rate/mod.rs b/units/src/fee_rate/mod.rs index f2ba94852..75c516ea5 100644 --- a/units/src/fee_rate/mod.rs +++ b/units/src/fee_rate/mod.rs @@ -11,6 +11,10 @@ use core::ops; #[cfg(feature = "arbitrary")] use arbitrary::{Arbitrary, Unstructured}; +use NumOpResult as R; + +use crate::{Amount,MathOp, NumOpError as E, NumOpResult}; + mod encapsulate { /// Fee rate. /// @@ -62,6 +66,15 @@ impl FeeRate { } } + /// Constructs a new [`FeeRate`] from amount per 1000 weight units. + pub const fn from_per_kwu(rate: Amount) -> NumOpResult { + // No `map()` in const context. + match rate.checked_mul(4_000) { + Some(per_mvb) => R::Valid(FeeRate::from_sat_per_mvb(per_mvb.to_sat())), + None => R::Error(E::while_doing(MathOp::Mul)), + } + } + /// Constructs a new [`FeeRate`] from satoshis per virtual byte, /// returning `None` if overflow occurred. pub const fn from_sat_per_vb(sat_vb: u64) -> Option { @@ -72,6 +85,15 @@ impl FeeRate { } } + /// Constructs a new [`FeeRate`] from amount per virtual byte. + pub const fn from_per_vb(rate: Amount) -> NumOpResult { + // No `map()` in const context. + match rate.checked_mul(1_000_000) { + Some(per_mvb) => R::Valid(FeeRate::from_sat_per_mvb(per_mvb.to_sat())), + None => R::Error(E::while_doing(MathOp::Mul)), + } + } + /// Constructs a new [`FeeRate`] from satoshis per virtual bytes. pub const fn from_sat_per_vb_u32(sat_vb: u32) -> Self { let sat_vb = sat_vb as u64; // No `Into` in const context. @@ -88,6 +110,15 @@ impl FeeRate { } } + /// Constructs a new [`FeeRate`] from satoshis per kilo virtual bytes (1,000 vbytes). + pub const fn from_per_kvb(rate: Amount) -> NumOpResult { + // No `map()` in const context. + match rate.checked_mul(1_000) { + Some(per_mvb) => R::Valid(FeeRate::from_sat_per_mvb(per_mvb.to_sat())), + None => R::Error(E::while_doing(MathOp::Mul)), + } + } + /// Converts to sat/kwu rounding down. pub const fn to_sat_per_kwu_floor(self) -> u64 { self.to_sat_per_mvb() / 4_000 }