From 2a4ffb1c58120005568147b4ed3a6aec3b9110d7 Mon Sep 17 00:00:00 2001 From: 448 OG Date: Sat, 16 Mar 2024 16:05:06 +0300 Subject: [PATCH] Enforce displaying Amount with trailing zeros It is common to display bitcoins using trailing zeros upto 8 decimals. This commit enforces: - Displaying Amount in BTC with trailing zeroes by eight decimal places if a precision on the Amount is not specified. - Displaying Amount in BTC upto the precision specified truncating the insignificant zeros. - Displaying amount in BTC without any decimals if the remainder of the amount divided by the satoshis in 1 BTC is equal to zero using formula `satoshis.rem_euclid(Amount::ONE_BTC.to_sat()) != 0` These are not breaking changes and all previous tests pass. A testcase is added to for changes introduced. Resolves: #2136 --- units/src/amount.rs | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/units/src/amount.rs b/units/src/amount.rs index 963a248f65..f16d76d5e6 100644 --- a/units/src/amount.rs +++ b/units/src/amount.rs @@ -1064,8 +1064,18 @@ impl fmt::Debug for Amount { // Just using Bitcoin denominated string. impl fmt::Display for Amount { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.fmt_value_in(f, Denomination::Bitcoin)?; - write!(f, " {}", Denomination::Bitcoin) + let satoshis = self.to_sat(); + let denomination = Denomination::Bitcoin; + let mut buffer = String::new(); + let mut format_options = FormatOptions::from_formatter(f); + + if f.precision().is_none() && satoshis.rem_euclid(Amount::ONE_BTC.to_sat()) != 0{ + format_options.precision = Some(8); + } + + fmt_satoshi_in(satoshis, false, &mut buffer, denomination, true, format_options)?; + + write!(f, "{}", buffer) } } @@ -2907,4 +2917,34 @@ mod tests { } } } + + #[test] + fn trailing_zeros_for_amount() { + assert_eq!(format!("{}", Amount::ONE_SAT), "0.00000001 BTC"); + assert_eq!(format!("{}", Amount::ONE_BTC), "1 BTC"); + assert_eq!(format!("{}", Amount::from_sat(1)), "0.00000001 BTC"); + assert_eq!(format!("{}", Amount::from_sat(10)), "0.00000010 BTC"); + assert_eq!(format!("{:.2}", Amount::from_sat(10)), "0.0000001 BTC"); + assert_eq!(format!("{:.2}", Amount::from_sat(100)), "0.000001 BTC"); + assert_eq!(format!("{:.2}", Amount::from_sat(1000)), "0.00001 BTC"); + assert_eq!(format!("{:.2}", Amount::from_sat(10_000)), "0.0001 BTC"); + assert_eq!(format!("{:.2}", Amount::from_sat(100_000)), "0.001 BTC"); + assert_eq!(format!("{:.2}", Amount::from_sat(1_000_000)), "0.01 BTC"); + assert_eq!(format!("{:.2}", Amount::from_sat(10_000_000)), "0.10 BTC"); + assert_eq!(format!("{:.2}", Amount::from_sat(100_000_000)), "1.00 BTC"); + assert_eq!(format!("{}", Amount::from_sat(100_000_000)), "1 BTC"); + assert_eq!(format!("{}", Amount::from_sat(40_000_000_000)), "400 BTC"); + assert_eq!( + format!("{:.10}", Amount::from_sat(100_000_000)), + "1.0000000000 BTC" + ); + assert_eq!( + format!("{}", Amount::from_sat(400_000_000_000_010)), + "4000000.00000010 BTC" + ); + assert_eq!( + format!("{}", Amount::from_sat(400_000_000_000_000)), + "4000000 BTC" + ); + } }