@@ -23,7 +23,15 @@ impl fmt::Debug for Amount {
2323 }
2424}
2525
26+ const MAX_MSATS : u64 = 21_000_000_0000_0000_000 ;
27+
2628impl Amount {
29+ /// The maximum possible [`Amount`], equal to 21 million BTC
30+ pub const MAX : Amount = Amount ( MAX_MSATS ) ;
31+
32+ /// Zero milli-satoshis
33+ pub const ZERO : Amount = Amount ( 0 ) ;
34+
2735 /// The amount in milli-satoshis
2836 #[ inline]
2937 pub const fn milli_sats ( & self ) -> u64 {
@@ -47,20 +55,39 @@ impl Amount {
4755 }
4856
4957 /// Constructs a new [`Amount`] for the given number of milli-satoshis.
58+ ///
59+ /// Fails only if `msats` is greater than 21 million Bitcoin (in milli-satoshis).
5060 #[ inline]
51- pub const fn from_milli_sats ( msats : u64 ) -> Self {
52- Amount ( msats)
61+ pub const fn from_milli_sats ( msats : u64 ) -> Result < Self , ( ) > {
62+ if msats > MAX_MSATS {
63+ Err ( ( ) )
64+ } else {
65+ Ok ( Amount ( msats) )
66+ }
5367 }
5468
5569 /// Constructs a new [`Amount`] for the given number of satoshis.
70+ ///
71+ /// Fails only if `sats` is greater than 21 million Bitcoin (in satoshis).
5672 #[ inline]
57- pub const fn from_sats ( sats : u64 ) -> Self {
58- Amount ( sats * 1000 )
73+ pub const fn from_sats ( sats : u64 ) -> Result < Self , ( ) > {
74+ Self :: from_milli_sats ( sats. saturating_mul ( 1000 ) )
75+ }
76+
77+ /// Constructs a new [`Amount`] for the given number of satoshis, panicking if the amount is
78+ /// too large.
79+ pub ( crate ) const fn from_sats_panicy ( sats : u64 ) -> Self {
80+ let amt = sats. saturating_mul ( 1000 ) ;
81+ if amt > MAX_MSATS {
82+ panic ! ( "Sats value greater than 21 million Bitcoin" ) ;
83+ } else {
84+ Amount ( amt)
85+ }
5986 }
6087
6188 /// Adds an [`Amount`] to this [`Amount`], saturating to avoid overflowing 21 million bitcoin.
6289 #[ inline]
63- pub fn saturating_add ( self , rhs : Amount ) -> Amount {
90+ pub const fn saturating_add ( self , rhs : Amount ) -> Amount {
6491 match self . 0 . checked_add ( rhs. 0 ) {
6592 Some ( amt) if amt <= 21_000_000_0000_0000_000 => Amount ( amt) ,
6693 _ => Amount ( 21_000_000_0000_0000_000 ) ,
@@ -69,7 +96,7 @@ impl Amount {
6996
7097 /// Subtracts an [`Amount`] from this [`Amount`], saturating to avoid underflowing.
7198 #[ inline]
72- pub fn saturating_sub ( self , rhs : Amount ) -> Amount {
99+ pub const fn saturating_sub ( self , rhs : Amount ) -> Amount {
73100 Amount ( self . 0 . saturating_sub ( rhs. 0 ) )
74101 }
75102
@@ -120,15 +147,15 @@ mod test {
120147 #[ test]
121148 #[ rustfmt:: skip]
122149 fn test_display ( ) {
123- assert_eq ! ( Amount :: from_milli_sats( 0 ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0" ) ;
124- assert_eq ! ( Amount :: from_milli_sats( 1 ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.00000001" ) ;
125- assert_eq ! ( Amount :: from_sats( 1 ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.00000001" ) ;
126- assert_eq ! ( Amount :: from_sats( 10 ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.0000001" ) ;
127- assert_eq ! ( Amount :: from_sats( 15 ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.00000015" ) ;
128- assert_eq ! ( Amount :: from_sats( 1_0000 ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.0001" ) ;
129- assert_eq ! ( Amount :: from_sats( 1_2345 ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.00012345" ) ;
130- assert_eq ! ( Amount :: from_sats( 1_2345_6789 ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "1.23456789" ) ;
131- assert_eq ! ( Amount :: from_sats( 1_0000_0000 ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "1" ) ;
132- assert_eq ! ( Amount :: from_sats( 5_0000_0000 ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "5" ) ;
150+ assert_eq ! ( Amount :: from_milli_sats( 0 ) . unwrap ( ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0" ) ;
151+ assert_eq ! ( Amount :: from_milli_sats( 1 ) . unwrap ( ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.00000001" ) ;
152+ assert_eq ! ( Amount :: from_sats( 1 ) . unwrap ( ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.00000001" ) ;
153+ assert_eq ! ( Amount :: from_sats( 10 ) . unwrap ( ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.0000001" ) ;
154+ assert_eq ! ( Amount :: from_sats( 15 ) . unwrap ( ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.00000015" ) ;
155+ assert_eq ! ( Amount :: from_sats( 1_0000 ) . unwrap ( ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.0001" ) ;
156+ assert_eq ! ( Amount :: from_sats( 1_2345 ) . unwrap ( ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "0.00012345" ) ;
157+ assert_eq ! ( Amount :: from_sats( 1_2345_6789 ) . unwrap ( ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "1.23456789" ) ;
158+ assert_eq ! ( Amount :: from_sats( 1_0000_0000 ) . unwrap ( ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "1" ) ;
159+ assert_eq ! ( Amount :: from_sats( 5_0000_0000 ) . unwrap ( ) . btc_decimal_rounding_up_to_sats( ) . to_string( ) , "5" ) ;
133160 }
134161}
0 commit comments