From fdf3336ed5952bd0ed961c2a4df6e5a91e2be6ba Mon Sep 17 00:00:00 2001 From: yancy Date: Mon, 23 Dec 2024 14:59:58 -0600 Subject: [PATCH 1/3] Add unchecked variant This variant is supplied in cases where a Result type does not need to be handled. --- api/units/all-features.txt | 1 + api/units/alloc-only.txt | 1 + api/units/no-features.txt | 1 + units/src/amount/signed.rs | 9 +++++++++ 4 files changed, 12 insertions(+) diff --git a/api/units/all-features.txt b/api/units/all-features.txt index 27369ab25..8822fa7e7 100644 --- a/api/units/all-features.txt +++ b/api/units/all-features.txt @@ -723,6 +723,7 @@ pub const fn bitcoin_units::SignedAmount::checked_rem(self, rhs: i64) -> core::o pub const fn bitcoin_units::SignedAmount::checked_sub(self, rhs: bitcoin_units::SignedAmount) -> core::option::Option pub const fn bitcoin_units::SignedAmount::from_int_btc_const(whole_bitcoin: i64) -> bitcoin_units::SignedAmount pub const fn bitcoin_units::SignedAmount::from_sat(satoshi: i64) -> bitcoin_units::SignedAmount +pub const fn bitcoin_units::SignedAmount::from_sat_unchecked(satoshi: i64) -> bitcoin_units::SignedAmount pub const fn bitcoin_units::SignedAmount::to_sat(self) -> i64 pub const fn bitcoin_units::block::BlockHeight::from_u32(inner: u32) -> Self pub const fn bitcoin_units::block::BlockHeight::to_u32(self) -> u32 diff --git a/api/units/alloc-only.txt b/api/units/alloc-only.txt index bfe3a73d1..847e589cf 100644 --- a/api/units/alloc-only.txt +++ b/api/units/alloc-only.txt @@ -674,6 +674,7 @@ pub const fn bitcoin_units::SignedAmount::checked_rem(self, rhs: i64) -> core::o pub const fn bitcoin_units::SignedAmount::checked_sub(self, rhs: bitcoin_units::SignedAmount) -> core::option::Option pub const fn bitcoin_units::SignedAmount::from_int_btc_const(whole_bitcoin: i64) -> bitcoin_units::SignedAmount pub const fn bitcoin_units::SignedAmount::from_sat(satoshi: i64) -> bitcoin_units::SignedAmount +pub const fn bitcoin_units::SignedAmount::from_sat_unchecked(satoshi: i64) -> bitcoin_units::SignedAmount pub const fn bitcoin_units::SignedAmount::to_sat(self) -> i64 pub const fn bitcoin_units::block::BlockHeight::from_u32(inner: u32) -> Self pub const fn bitcoin_units::block::BlockHeight::to_u32(self) -> u32 diff --git a/api/units/no-features.txt b/api/units/no-features.txt index 60c1ac1b8..4da185122 100644 --- a/api/units/no-features.txt +++ b/api/units/no-features.txt @@ -656,6 +656,7 @@ pub const fn bitcoin_units::SignedAmount::checked_rem(self, rhs: i64) -> core::o pub const fn bitcoin_units::SignedAmount::checked_sub(self, rhs: bitcoin_units::SignedAmount) -> core::option::Option pub const fn bitcoin_units::SignedAmount::from_int_btc_const(whole_bitcoin: i64) -> bitcoin_units::SignedAmount pub const fn bitcoin_units::SignedAmount::from_sat(satoshi: i64) -> bitcoin_units::SignedAmount +pub const fn bitcoin_units::SignedAmount::from_sat_unchecked(satoshi: i64) -> bitcoin_units::SignedAmount pub const fn bitcoin_units::SignedAmount::to_sat(self) -> i64 pub const fn bitcoin_units::block::BlockHeight::from_u32(inner: u32) -> Self pub const fn bitcoin_units::block::BlockHeight::to_u32(self) -> u32 diff --git a/units/src/amount/signed.rs b/units/src/amount/signed.rs index 2faa7e45f..1c93bd198 100644 --- a/units/src/amount/signed.rs +++ b/units/src/amount/signed.rs @@ -83,6 +83,15 @@ impl SignedAmount { /// ``` pub const fn to_sat(self) -> i64 { self.0 } + /// Constructs a new [`SignedAmount`] with satoshi precision and the given number of satoshis. + /// + /// Caller to guarantee that `satoshi` is within valid range. + /// + /// See [`Self::MIN`] and [`Self::MAX_MONEY`]. + pub const fn from_sat_unchecked(satoshi: i64) -> SignedAmount { + SignedAmount(satoshi) + } + /// Converts from a value expressing a decimal number of bitcoin to a [`SignedAmount`]. /// /// # Errors From 364e9ff775ca0b482576d6dbc3a3621c68b56ea9 Mon Sep 17 00:00:00 2001 From: yancy Date: Sat, 14 Dec 2024 14:17:24 -0600 Subject: [PATCH 2/3] Change method return type Any SignedAmount can now be cast to Amount since the range is the same. Specifically, the range for SignedAmount is (- 21 million, 21 million) while the range for Amount is (0, 21 million). Therefore any value from Amount can be cast to a SignedAmount and it will work. Note it's not the same and still requires checking when going from SignedAmount to Amount since Amount can't handle the negative range. As a side effect of changing the return type, TryFrom is no longer valid and does not compile. Therefore in addition to changing the return type, TryFrom is also removed. --- api/units/all-features.txt | 5 +---- api/units/alloc-only.txt | 5 +---- api/units/no-features.txt | 5 +---- bitcoin/src/blockdata/transaction.rs | 6 +++--- units/src/amount/signed.rs | 6 ------ units/src/amount/tests.rs | 12 ++---------- units/src/amount/unsigned.rs | 12 ++---------- 7 files changed, 10 insertions(+), 41 deletions(-) diff --git a/api/units/all-features.txt b/api/units/all-features.txt index 8822fa7e7..086f2c172 100644 --- a/api/units/all-features.txt +++ b/api/units/all-features.txt @@ -198,7 +198,6 @@ impl core::convert::TryFrom for bitcoin_units::locktime:: impl core::convert::TryFrom for bitcoin_units::locktime::relative::Height impl core::convert::TryFrom for bitcoin_units::locktime::relative::Time impl core::convert::TryFrom for bitcoin_units::weight::Weight -impl core::convert::TryFrom for bitcoin_units::SignedAmount impl core::convert::TryFrom for bitcoin_units::Amount impl core::convert::TryFrom for bitcoin_units::locktime::absolute::Height impl core::convert::TryFrom for bitcoin_units::locktime::relative::Height @@ -831,7 +830,7 @@ pub fn bitcoin_units::Amount::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator pub fn bitcoin_units::Amount::to_btc(self) -> f64 pub fn bitcoin_units::Amount::to_float_in(self, denom: bitcoin_units::amount::Denomination) -> f64 -pub fn bitcoin_units::Amount::to_signed(self) -> core::result::Result +pub fn bitcoin_units::Amount::to_signed(self) -> bitcoin_units::SignedAmount pub fn bitcoin_units::Amount::to_string_in(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String pub fn bitcoin_units::Amount::to_string_with_denomination(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String pub fn bitcoin_units::Amount::try_from(value: bitcoin_units::SignedAmount) -> core::result::Result @@ -890,7 +889,6 @@ pub fn bitcoin_units::SignedAmount::to_float_in(self, denom: bitcoin_units::amou pub fn bitcoin_units::SignedAmount::to_string_in(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String pub fn bitcoin_units::SignedAmount::to_string_with_denomination(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String pub fn bitcoin_units::SignedAmount::to_unsigned(self) -> core::result::Result -pub fn bitcoin_units::SignedAmount::try_from(value: bitcoin_units::Amount) -> core::result::Result pub fn bitcoin_units::SignedAmount::type_prefix(_: private::Token) -> &'static str pub fn bitcoin_units::SignedAmount::unchecked_add(self, rhs: bitcoin_units::SignedAmount) -> bitcoin_units::SignedAmount pub fn bitcoin_units::SignedAmount::unchecked_sub(self, rhs: bitcoin_units::SignedAmount) -> bitcoin_units::SignedAmount @@ -1255,7 +1253,6 @@ pub type bitcoin_units::Amount::Error = bitcoin_units::amount::OutOfRangeError pub type bitcoin_units::Amount::Output = bitcoin_units::Amount pub type bitcoin_units::Amount::Output = bitcoin_units::fee_rate::FeeRate pub type bitcoin_units::SignedAmount::Err = bitcoin_units::amount::ParseError -pub type bitcoin_units::SignedAmount::Error = bitcoin_units::amount::OutOfRangeError pub type bitcoin_units::SignedAmount::Output = bitcoin_units::SignedAmount pub type bitcoin_units::amount::Denomination::Err = bitcoin_units::amount::ParseDenominationError pub type bitcoin_units::block::BlockHeight::Err = bitcoin_units::parse::ParseIntError diff --git a/api/units/alloc-only.txt b/api/units/alloc-only.txt index 847e589cf..220ed9006 100644 --- a/api/units/alloc-only.txt +++ b/api/units/alloc-only.txt @@ -194,7 +194,6 @@ impl core::convert::TryFrom for bitcoin_units::locktime:: impl core::convert::TryFrom for bitcoin_units::locktime::relative::Height impl core::convert::TryFrom for bitcoin_units::locktime::relative::Time impl core::convert::TryFrom for bitcoin_units::weight::Weight -impl core::convert::TryFrom for bitcoin_units::SignedAmount impl core::convert::TryFrom for bitcoin_units::Amount impl core::convert::TryFrom for bitcoin_units::locktime::absolute::Height impl core::convert::TryFrom for bitcoin_units::locktime::relative::Height @@ -772,7 +771,7 @@ pub fn bitcoin_units::Amount::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator pub fn bitcoin_units::Amount::to_btc(self) -> f64 pub fn bitcoin_units::Amount::to_float_in(self, denom: bitcoin_units::amount::Denomination) -> f64 -pub fn bitcoin_units::Amount::to_signed(self) -> core::result::Result +pub fn bitcoin_units::Amount::to_signed(self) -> bitcoin_units::SignedAmount pub fn bitcoin_units::Amount::to_string_in(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String pub fn bitcoin_units::Amount::to_string_with_denomination(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String pub fn bitcoin_units::Amount::try_from(value: bitcoin_units::SignedAmount) -> core::result::Result @@ -820,7 +819,6 @@ pub fn bitcoin_units::SignedAmount::to_float_in(self, denom: bitcoin_units::amou pub fn bitcoin_units::SignedAmount::to_string_in(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String pub fn bitcoin_units::SignedAmount::to_string_with_denomination(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String pub fn bitcoin_units::SignedAmount::to_unsigned(self) -> core::result::Result -pub fn bitcoin_units::SignedAmount::try_from(value: bitcoin_units::Amount) -> core::result::Result pub fn bitcoin_units::SignedAmount::unchecked_add(self, rhs: bitcoin_units::SignedAmount) -> bitcoin_units::SignedAmount pub fn bitcoin_units::SignedAmount::unchecked_sub(self, rhs: bitcoin_units::SignedAmount) -> bitcoin_units::SignedAmount pub fn bitcoin_units::SignedAmount::unsigned_abs(self) -> bitcoin_units::Amount @@ -1117,7 +1115,6 @@ pub type bitcoin_units::Amount::Error = bitcoin_units::amount::OutOfRangeError pub type bitcoin_units::Amount::Output = bitcoin_units::Amount pub type bitcoin_units::Amount::Output = bitcoin_units::fee_rate::FeeRate pub type bitcoin_units::SignedAmount::Err = bitcoin_units::amount::ParseError -pub type bitcoin_units::SignedAmount::Error = bitcoin_units::amount::OutOfRangeError pub type bitcoin_units::SignedAmount::Output = bitcoin_units::SignedAmount pub type bitcoin_units::amount::Denomination::Err = bitcoin_units::amount::ParseDenominationError pub type bitcoin_units::block::BlockHeight::Err = bitcoin_units::parse::ParseIntError diff --git a/api/units/no-features.txt b/api/units/no-features.txt index 4da185122..31f49267d 100644 --- a/api/units/no-features.txt +++ b/api/units/no-features.txt @@ -178,7 +178,6 @@ impl core::convert::TryFrom<&str> for bitcoin_units::locktime::absolute::Time impl core::convert::TryFrom<&str> for bitcoin_units::locktime::relative::Height impl core::convert::TryFrom<&str> for bitcoin_units::locktime::relative::Time impl core::convert::TryFrom<&str> for bitcoin_units::weight::Weight -impl core::convert::TryFrom for bitcoin_units::SignedAmount impl core::convert::TryFrom for bitcoin_units::Amount impl core::convert::TryFrom for bitcoin_units::locktime::absolute::Height impl core::convert::TryFrom for bitcoin_units::locktime::relative::Height @@ -750,7 +749,7 @@ pub fn bitcoin_units::Amount::sub_assign(&mut self, rhs: &bitcoin_units::Amount) pub fn bitcoin_units::Amount::sub_assign(&mut self, rhs: bitcoin_units::Amount) pub fn bitcoin_units::Amount::sum>(iter: I) -> Self pub fn bitcoin_units::Amount::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator -pub fn bitcoin_units::Amount::to_signed(self) -> core::result::Result +pub fn bitcoin_units::Amount::to_signed(self) -> bitcoin_units::SignedAmount pub fn bitcoin_units::Amount::try_from(value: bitcoin_units::SignedAmount) -> core::result::Result pub fn bitcoin_units::Amount::unchecked_add(self, rhs: bitcoin_units::Amount) -> bitcoin_units::Amount pub fn bitcoin_units::Amount::unchecked_sub(self, rhs: bitcoin_units::Amount) -> bitcoin_units::Amount @@ -790,7 +789,6 @@ pub fn bitcoin_units::SignedAmount::sub_assign(&mut self, rhs: bitcoin_units::Si pub fn bitcoin_units::SignedAmount::sum>(iter: I) -> Self pub fn bitcoin_units::SignedAmount::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator pub fn bitcoin_units::SignedAmount::to_unsigned(self) -> core::result::Result -pub fn bitcoin_units::SignedAmount::try_from(value: bitcoin_units::Amount) -> core::result::Result pub fn bitcoin_units::SignedAmount::unchecked_add(self, rhs: bitcoin_units::SignedAmount) -> bitcoin_units::SignedAmount pub fn bitcoin_units::SignedAmount::unchecked_sub(self, rhs: bitcoin_units::SignedAmount) -> bitcoin_units::SignedAmount pub fn bitcoin_units::SignedAmount::unsigned_abs(self) -> bitcoin_units::Amount @@ -1071,7 +1069,6 @@ pub type bitcoin_units::Amount::Error = bitcoin_units::amount::OutOfRangeError pub type bitcoin_units::Amount::Output = bitcoin_units::Amount pub type bitcoin_units::Amount::Output = bitcoin_units::fee_rate::FeeRate pub type bitcoin_units::SignedAmount::Err = bitcoin_units::amount::ParseError -pub type bitcoin_units::SignedAmount::Error = bitcoin_units::amount::OutOfRangeError pub type bitcoin_units::SignedAmount::Output = bitcoin_units::SignedAmount pub type bitcoin_units::amount::Denomination::Err = bitcoin_units::amount::ParseDenominationError pub type bitcoin_units::block::BlockHeight::Err = bitcoin_units::parse::ParseIntError diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 84c53de7e..5dea49ba9 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -790,8 +790,8 @@ pub fn effective_value( value: Amount, ) -> Option { let weight = satisfaction_weight.checked_add(TX_IN_BASE_WEIGHT)?; - let signed_input_fee = fee_rate.checked_mul_by_weight(weight)?.to_signed().ok()?; - value.to_signed().ok()?.checked_sub(signed_input_fee) + let signed_input_fee = fee_rate.checked_mul_by_weight(weight)?.to_signed(); + value.to_signed().checked_sub(signed_input_fee) } /// Predicts the weight of a to-be-constructed transaction. @@ -1673,7 +1673,7 @@ mod tests { // 10 sat/kwu * (204wu + BASE_WEIGHT) = 4 sats let expected_fee = "4 sats".parse::().unwrap(); - let expected_effective_value = value.to_signed().unwrap() - expected_fee; + let expected_effective_value = value.to_signed() - expected_fee; assert_eq!(effective_value, expected_effective_value); } diff --git a/units/src/amount/signed.rs b/units/src/amount/signed.rs index 1c93bd198..717d59917 100644 --- a/units/src/amount/signed.rs +++ b/units/src/amount/signed.rs @@ -566,12 +566,6 @@ impl FromStr for SignedAmount { } } -impl TryFrom for SignedAmount { - type Error = OutOfRangeError; - - fn try_from(value: Amount) -> Result { value.to_signed() } -} - impl core::iter::Sum for SignedAmount { fn sum>(iter: I) -> Self { let sats: i64 = iter.map(|amt| amt.0).sum(); diff --git a/units/src/amount/tests.rs b/units/src/amount/tests.rs index c4f6ea9fc..a7f08efbb 100644 --- a/units/src/amount/tests.rs +++ b/units/src/amount/tests.rs @@ -71,13 +71,6 @@ fn from_int_btc() { assert_eq!(Amount::from_sat(200_000_000), amt); } -#[test] -fn test_signed_amount_try_from_amount() { - let ua_positive = Amount::from_sat(123); - let sa_positive = SignedAmount::try_from(ua_positive).unwrap(); - assert_eq!(sa_positive, SignedAmount::from_sat(123)); -} - #[test] fn test_amount_try_from_signed_amount() { let sa_positive = SignedAmount::from_sat(123); @@ -473,12 +466,11 @@ fn test_unsigned_signed_conversion() { let ua = Amount::from_sat; let max_sats: u64 = Amount::MAX.to_sat(); - assert_eq!(ua(max_sats).to_signed(), Ok(sa(max_sats as i64))); - assert_eq!(ua(i64::MAX as u64 + 1).to_signed(), Err(OutOfRangeError::too_big(true))); + assert_eq!(ua(max_sats).to_signed(), sa(max_sats as i64)); assert_eq!(sa(max_sats as i64).to_unsigned(), Ok(ua(max_sats))); - assert_eq!(sa(max_sats as i64).to_unsigned().unwrap().to_signed(), Ok(sa(max_sats as i64))); + assert_eq!(sa(max_sats as i64).to_unsigned().unwrap().to_signed(), sa(max_sats as i64)); } #[test] diff --git a/units/src/amount/unsigned.rs b/units/src/amount/unsigned.rs index 49edb71be..718c6e478 100644 --- a/units/src/amount/unsigned.rs +++ b/units/src/amount/unsigned.rs @@ -438,17 +438,9 @@ impl Amount { pub fn unchecked_sub(self, rhs: Amount) -> Amount { Self(self.0 - rhs.0) } /// Converts to a signed amount. - /// - /// # Errors - /// - /// If the amount is too big. #[rustfmt::skip] // Moves code comments to the wrong line. - pub fn to_signed(self) -> Result { - if self.to_sat() > SignedAmount::MAX.to_sat() as u64 { // Cast ok, signed max is positive and fits in u64. - Err(OutOfRangeError::too_big(true)) - } else { - Ok(SignedAmount::from_sat(self.to_sat() as i64)) // Cast ok, checked not too big above. - } + pub fn to_signed(self) -> SignedAmount { + SignedAmount::from_sat_unchecked(self.to_sat() as i64) // Cast ok, signed amount and amount share positive range. } /// Checks if the amount is below the maximum value. Returns `None` if it is above. From e13355318e61e341e7cf3f17257e44d19029c6eb Mon Sep 17 00:00:00 2001 From: yancy Date: Mon, 23 Dec 2024 15:48:16 -0600 Subject: [PATCH 3/3] Add From impl SignedAmount and Amount both share the same MAX, therefore the From impl is added in place of TryFrom. --- api/units/all-features.txt | 2 ++ api/units/alloc-only.txt | 2 ++ api/units/no-features.txt | 2 ++ units/src/amount/signed.rs | 7 +++++++ 4 files changed, 13 insertions(+) diff --git a/api/units/all-features.txt b/api/units/all-features.txt index 086f2c172..fe3509909 100644 --- a/api/units/all-features.txt +++ b/api/units/all-features.txt @@ -145,6 +145,7 @@ impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::Height impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::Time impl core::cmp::PartialOrd for bitcoin_units::weight::Weight impl core::convert::AsRef for bitcoin_units::parse::ParseIntError +impl core::convert::From for bitcoin_units::SignedAmount impl core::convert::From for bitcoin_units::amount::ParseAmountError impl core::convert::From for bitcoin_units::amount::ParseError impl core::convert::From for bitcoin_units::amount::ParseAmountError @@ -855,6 +856,7 @@ pub fn bitcoin_units::SignedAmount::div(self, rhs: i64) -> Self::Output pub fn bitcoin_units::SignedAmount::div_assign(&mut self, rhs: i64) pub fn bitcoin_units::SignedAmount::eq(&self, other: &bitcoin_units::SignedAmount) -> bool pub fn bitcoin_units::SignedAmount::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::SignedAmount::from(value: bitcoin_units::Amount) -> Self pub fn bitcoin_units::SignedAmount::from_btc(btc: f64) -> core::result::Result pub fn bitcoin_units::SignedAmount::from_float_in(value: f64, denom: bitcoin_units::amount::Denomination) -> core::result::Result pub fn bitcoin_units::SignedAmount::from_int_btc>(whole_bitcoin: T) -> core::result::Result diff --git a/api/units/alloc-only.txt b/api/units/alloc-only.txt index 220ed9006..f729d550a 100644 --- a/api/units/alloc-only.txt +++ b/api/units/alloc-only.txt @@ -141,6 +141,7 @@ impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::Height impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::Time impl core::cmp::PartialOrd for bitcoin_units::weight::Weight impl core::convert::AsRef for bitcoin_units::parse::ParseIntError +impl core::convert::From for bitcoin_units::SignedAmount impl core::convert::From for bitcoin_units::amount::ParseAmountError impl core::convert::From for bitcoin_units::amount::ParseError impl core::convert::From for bitcoin_units::amount::ParseAmountError @@ -791,6 +792,7 @@ pub fn bitcoin_units::SignedAmount::div(self, rhs: i64) -> Self::Output pub fn bitcoin_units::SignedAmount::div_assign(&mut self, rhs: i64) pub fn bitcoin_units::SignedAmount::eq(&self, other: &bitcoin_units::SignedAmount) -> bool pub fn bitcoin_units::SignedAmount::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::SignedAmount::from(value: bitcoin_units::Amount) -> Self pub fn bitcoin_units::SignedAmount::from_btc(btc: f64) -> core::result::Result pub fn bitcoin_units::SignedAmount::from_float_in(value: f64, denom: bitcoin_units::amount::Denomination) -> core::result::Result pub fn bitcoin_units::SignedAmount::from_int_btc>(whole_bitcoin: T) -> core::result::Result diff --git a/api/units/no-features.txt b/api/units/no-features.txt index 31f49267d..dfcb91f36 100644 --- a/api/units/no-features.txt +++ b/api/units/no-features.txt @@ -141,6 +141,7 @@ impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::Height impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::Time impl core::cmp::PartialOrd for bitcoin_units::weight::Weight impl core::convert::AsRef for bitcoin_units::parse::ParseIntError +impl core::convert::From for bitcoin_units::SignedAmount impl core::convert::From for bitcoin_units::amount::ParseAmountError impl core::convert::From for bitcoin_units::amount::ParseError impl core::convert::From for bitcoin_units::amount::ParseAmountError @@ -767,6 +768,7 @@ pub fn bitcoin_units::SignedAmount::div(self, rhs: i64) -> Self::Output pub fn bitcoin_units::SignedAmount::div_assign(&mut self, rhs: i64) pub fn bitcoin_units::SignedAmount::eq(&self, other: &bitcoin_units::SignedAmount) -> bool pub fn bitcoin_units::SignedAmount::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::SignedAmount::from(value: bitcoin_units::Amount) -> Self pub fn bitcoin_units::SignedAmount::from_int_btc>(whole_bitcoin: T) -> core::result::Result pub fn bitcoin_units::SignedAmount::from_str(s: &str) -> core::result::Result pub fn bitcoin_units::SignedAmount::from_str_in(s: &str, denom: bitcoin_units::amount::Denomination) -> core::result::Result diff --git a/units/src/amount/signed.rs b/units/src/amount/signed.rs index 717d59917..3c9df7f60 100644 --- a/units/src/amount/signed.rs +++ b/units/src/amount/signed.rs @@ -566,6 +566,13 @@ impl FromStr for SignedAmount { } } +impl From for SignedAmount { + fn from(value: Amount) -> Self { + let v = value.to_sat() as i64; // Cast ok, signed amount and amount share positive range. + SignedAmount::from_sat_unchecked(v) + } +} + impl core::iter::Sum for SignedAmount { fn sum>(iter: I) -> Self { let sats: i64 = iter.map(|amt| amt.0).sum();