sapio_bitcoin/util/
amount.rs

1// To the extent possible under law, the author(s) have dedicated all
2// copyright and related and neighboring rights to this software to
3// the public domain worldwide. This software is distributed without
4// any warranty.
5//
6// You should have received a copy of the CC0 Public Domain Dedication
7// along with this software.
8// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
9//
10
11//! Bitcoin amounts.
12//!
13//! This module mainly introduces the [Amount] and [SignedAmount] types.
14//! We refer to the documentation on the types for more information.
15//!
16
17use prelude::*;
18
19use core::{ops, default, str::FromStr, cmp::Ordering};
20use core::fmt::{self, Write};
21use core::convert::TryFrom;
22
23/// A set of denominations in which amounts can be expressed.
24#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
25pub enum Denomination {
26    /// BTC
27    Bitcoin,
28    /// mBTC
29    MilliBitcoin,
30    /// uBTC
31    MicroBitcoin,
32    /// nBTC
33    NanoBitcoin,
34    /// pBTC
35    PicoBitcoin,
36    /// bits
37    Bit,
38    /// satoshi
39    Satoshi,
40    /// msat
41    MilliSatoshi,
42}
43
44impl Denomination {
45    /// The number of decimal places more than a satoshi.
46    fn precision(self) -> i32 {
47        match self {
48            Denomination::Bitcoin => -8,
49            Denomination::MilliBitcoin => -5,
50            Denomination::MicroBitcoin => -2,
51            Denomination::NanoBitcoin => 1,
52            Denomination::PicoBitcoin => 4,
53            Denomination::Bit => -2,
54            Denomination::Satoshi => 0,
55            Denomination::MilliSatoshi => 3,
56        }
57    }
58}
59
60impl fmt::Display for Denomination {
61    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62        f.write_str(match *self {
63            Denomination::Bitcoin => "BTC",
64            Denomination::MilliBitcoin => "mBTC",
65            Denomination::MicroBitcoin => "uBTC",
66            Denomination::NanoBitcoin => "nBTC",
67            Denomination::PicoBitcoin => "pBTC",
68            Denomination::Bit => "bits",
69            Denomination::Satoshi => "satoshi",
70            Denomination::MilliSatoshi => "msat",
71        })
72    }
73}
74
75impl FromStr for Denomination {
76    type Err = ParseAmountError;
77
78    /// Convert from a str to Denomination.
79    ///
80    /// Any combination of upper and/or lower case, excluding uppercase of SI(m, u, n, p) is considered valid.
81    /// - Singular: BTC, mBTC, uBTC, nBTC, pBTC
82    /// - Plural or singular: sat, satoshi, bit, msat
83    ///
84    /// Due to ambiguity between mega and milli, pico and peta we prohibit usage of leading capital 'M', 'P'.
85    fn from_str(s: &str) -> Result<Self, Self::Err> {
86        use self::ParseAmountError::*;
87        use self::Denomination as D;
88
89        let starts_with_uppercase = || s.starts_with(char::is_uppercase);
90        match denomination_from_str(s) {
91            None => Err(UnknownDenomination(s.to_owned())),
92            Some(D::MilliBitcoin) | Some(D::PicoBitcoin) | Some(D::MilliSatoshi) if starts_with_uppercase() => {
93                Err(PossiblyConfusingDenomination(s.to_owned()))
94            }
95            Some(D::NanoBitcoin) | Some(D::MicroBitcoin) if starts_with_uppercase() => {
96                Err(UnknownDenomination(s.to_owned()))
97            }
98            Some(d) => Ok(d),
99        }
100    }
101}
102
103fn denomination_from_str(mut s: &str) -> Option<Denomination> {
104    if s.eq_ignore_ascii_case("BTC") {
105        return Some(Denomination::Bitcoin);
106    }
107
108    if s.eq_ignore_ascii_case("mBTC") {
109        return Some(Denomination::MilliBitcoin);
110    }
111
112    if s.eq_ignore_ascii_case("uBTC") {
113        return Some(Denomination::MicroBitcoin);
114    }
115
116    if s.eq_ignore_ascii_case("nBTC") {
117        return Some(Denomination::NanoBitcoin);
118    }
119
120    if s.eq_ignore_ascii_case("pBTC") {
121        return Some(Denomination::PicoBitcoin);
122    }
123
124    if s.ends_with('s') || s.ends_with('S') {
125        s = &s[..(s.len() - 1)];
126    }
127
128    if s.eq_ignore_ascii_case("bit") {
129        return Some(Denomination::Bit);
130    }
131    if s.eq_ignore_ascii_case("satoshi") {
132        return Some(Denomination::Satoshi);
133    }
134    if s.eq_ignore_ascii_case("sat") {
135        return Some(Denomination::Satoshi);
136    }
137
138    if s.eq_ignore_ascii_case("msat") {
139        return Some(Denomination::MilliSatoshi);
140    }
141
142    None
143}
144
145/// An error during amount parsing.
146#[derive(Debug, Clone, PartialEq, Eq)]
147pub enum ParseAmountError {
148    /// Amount is negative.
149    Negative,
150    /// Amount is too big to fit inside the type.
151    TooBig,
152    /// Amount has higher precision than supported by the type.
153    TooPrecise,
154    /// Invalid number format.
155    InvalidFormat,
156    /// Input string was too large.
157    InputTooLarge,
158    /// Invalid character in input.
159    InvalidCharacter(char),
160    /// The denomination was unknown.
161    UnknownDenomination(String),
162    /// The denomination has multiple possible interpretations.
163    PossiblyConfusingDenomination(String)
164}
165
166impl fmt::Display for ParseAmountError {
167    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
168        match *self {
169            ParseAmountError::Negative => f.write_str("amount is negative"),
170            ParseAmountError::TooBig => f.write_str("amount is too big"),
171            ParseAmountError::TooPrecise => f.write_str("amount has a too high precision"),
172            ParseAmountError::InvalidFormat => f.write_str("invalid number format"),
173            ParseAmountError::InputTooLarge => f.write_str("input string was too large"),
174            ParseAmountError::InvalidCharacter(c) => write!(f, "invalid character in input: {}", c),
175            ParseAmountError::UnknownDenomination(ref d) => write!(f, "unknown denomination: {}", d),
176            ParseAmountError::PossiblyConfusingDenomination(ref d) => {
177                let (letter, upper, lower) = match d.chars().next() {
178                    Some('M') => ('M', "Mega", "milli"),
179                    Some('P') => ('P', "Peta", "pico"),
180                    // This panic could be avoided by adding enum ConfusingDenomination { Mega, Peta } but is it worth it?
181                    _ => panic!("invalid error information"),
182                };
183                write!(f, "the '{}' at the beginning of {} should technically mean '{}' but that denomination is uncommon and maybe '{}' was intended", letter, d, upper, lower)
184            }
185        }
186    }
187}
188
189#[cfg(feature = "std")]
190#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
191impl ::std::error::Error for ParseAmountError {}
192
193fn is_too_precise(s: &str, precision: usize) -> bool {
194    s.contains('.') || precision >= s.len() || s.chars().rev().take(precision).any(|d| d != '0')
195}
196
197/// Parse decimal string in the given denomination into a satoshi value and a
198/// bool indicator for a negative amount.
199fn parse_signed_to_satoshi(
200    mut s: &str,
201    denom: Denomination,
202) -> Result<(bool, u64), ParseAmountError> {
203    if s.is_empty() {
204        return Err(ParseAmountError::InvalidFormat);
205    }
206    if s.len() > 50 {
207        return Err(ParseAmountError::InputTooLarge);
208    }
209
210    let is_negative = s.starts_with('-');
211    if is_negative {
212        if s.len() == 1 {
213            return Err(ParseAmountError::InvalidFormat);
214        }
215        s = &s[1..];
216    }
217
218    let max_decimals = {
219        // The difference in precision between native (satoshi)
220        // and desired denomination.
221        let precision_diff = -denom.precision();
222        if precision_diff < 0 {
223            // If precision diff is negative, this means we are parsing
224            // into a less precise amount. That is not allowed unless
225            // there are no decimals and the last digits are zeroes as
226            // many as the difference in precision.
227            let last_n = precision_diff.abs() as usize;
228            if is_too_precise(s, last_n) {
229                return Err(ParseAmountError::TooPrecise);
230            }
231            s = &s[0..s.len() - last_n];
232            0
233        } else {
234            precision_diff
235        }
236    };
237
238    let mut decimals = None;
239    let mut value: u64 = 0; // as satoshis
240    for c in s.chars() {
241        match c {
242            '0'..='9' => {
243                // Do `value = 10 * value + digit`, catching overflows.
244                match 10_u64.checked_mul(value) {
245                    None => return Err(ParseAmountError::TooBig),
246                    Some(val) => match val.checked_add((c as u8 - b'0') as u64) {
247                        None => return Err(ParseAmountError::TooBig),
248                        Some(val) => value = val,
249                    },
250                }
251                // Increment the decimal digit counter if past decimal.
252                decimals = match decimals {
253                    None => None,
254                    Some(d) if d < max_decimals => Some(d + 1),
255                    _ => return Err(ParseAmountError::TooPrecise),
256                };
257            }
258            '.' => match decimals {
259                None => decimals = Some(0),
260                // Double decimal dot.
261                _ => return Err(ParseAmountError::InvalidFormat),
262            },
263            c => return Err(ParseAmountError::InvalidCharacter(c)),
264        }
265    }
266
267    // Decimally shift left by `max_decimals - decimals`.
268    let scale_factor = max_decimals - decimals.unwrap_or(0);
269    for _ in 0..scale_factor {
270        value = match 10_u64.checked_mul(value) {
271            Some(v) => v,
272            None => return Err(ParseAmountError::TooBig),
273        };
274    }
275
276    Ok((is_negative, value))
277}
278
279/// Format the given satoshi amount in the given denomination.
280///
281/// Does not include the denomination.
282fn fmt_satoshi_in(
283    satoshi: u64,
284    negative: bool,
285    f: &mut dyn fmt::Write,
286    denom: Denomination,
287) -> fmt::Result {
288    if negative {
289        f.write_str("-")?;
290    }
291
292    let precision = denom.precision();
293    match precision.cmp(&0) {
294        Ordering::Greater => {
295            // add zeroes in the end
296            let width = precision as usize;
297            write!(f, "{}{:0width$}", satoshi, 0, width = width)?;
298        }
299        Ordering::Less => {
300            // need to inject a comma in the number
301            let nb_decimals = precision.abs() as usize;
302            let real = format!("{:0width$}", satoshi, width = nb_decimals);
303            if real.len() == nb_decimals {
304                write!(f, "0.{}", &real[real.len() - nb_decimals..])?;
305            } else {
306                write!(
307                    f,
308                    "{}.{}",
309                    &real[0..(real.len() - nb_decimals)],
310                    &real[real.len() - nb_decimals..]
311                )?;
312            }
313        }
314        Ordering::Equal => write!(f, "{}", satoshi)?,
315    }
316    Ok(())
317}
318
319/// Amount
320///
321/// The [Amount] type can be used to express Bitcoin amounts that supports
322/// arithmetic and conversion to various denominations.
323///
324///
325/// Warning!
326///
327/// This type implements several arithmetic operations from [core::ops].
328/// To prevent errors due to overflow or underflow when using these operations,
329/// it is advised to instead use the checked arithmetic methods whose names
330/// start with `checked_`.  The operations from [core::ops] that [Amount]
331/// implements will panic when overflow or underflow occurs.  Also note that
332/// since the internal representation of amounts is unsigned, subtracting below
333/// zero is considered an underflow and will cause a panic if you're not using
334/// the checked arithmetic methods.
335///
336#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
337pub struct Amount(u64);
338
339impl Amount {
340    /// The zero amount.
341    pub const ZERO: Amount = Amount(0);
342    /// Exactly one satoshi.
343    pub const ONE_SAT: Amount = Amount(1);
344    /// Exactly one bitcoin.
345    pub const ONE_BTC: Amount = Amount(100_000_000);
346    /// The maximum value allowed as an amount. Useful for sanity checking.
347    pub const MAX_MONEY: Amount = Amount(21_000_000 * 100_000_000);
348
349    /// Create an [Amount] with satoshi precision and the given number of satoshis.
350    pub fn from_sat(satoshi: u64) -> Amount {
351        Amount(satoshi)
352    }
353
354    /// Get the number of satoshis in this [Amount].
355    pub fn as_sat(self) -> u64 {
356        self.0
357    }
358
359    /// The maximum value of an [Amount].
360    pub fn max_value() -> Amount {
361        Amount(u64::max_value())
362    }
363
364    /// The minimum value of an [Amount].
365    pub fn min_value() -> Amount {
366        Amount(u64::min_value())
367    }
368
369    /// Convert from a value expressing bitcoins to an [Amount].
370    pub fn from_btc(btc: f64) -> Result<Amount, ParseAmountError> {
371        Amount::from_float_in(btc, Denomination::Bitcoin)
372    }
373
374    /// Parse a decimal string as a value in the given denomination.
375    ///
376    /// Note: This only parses the value string.  If you want to parse a value
377    /// with denomination, use [FromStr].
378    pub fn from_str_in(s: &str, denom: Denomination) -> Result<Amount, ParseAmountError> {
379        let (negative, satoshi) = parse_signed_to_satoshi(s, denom)?;
380        if negative {
381            return Err(ParseAmountError::Negative);
382        }
383        if satoshi > i64::max_value() as u64 {
384            return Err(ParseAmountError::TooBig);
385        }
386        Ok(Amount::from_sat(satoshi))
387    }
388
389    /// Parses amounts with denomination suffix like they are produced with
390    /// [Self::to_string_with_denomination] or with [fmt::Display].
391    /// If you want to parse only the amount without the denomination,
392    /// use [Self::from_str_in].
393    pub fn from_str_with_denomination(s: &str) -> Result<Amount, ParseAmountError> {
394        let mut split = s.splitn(3, ' ');
395        let amt_str = split.next().unwrap();
396        let denom_str = split.next().ok_or(ParseAmountError::InvalidFormat)?;
397        if split.next().is_some() {
398            return Err(ParseAmountError::InvalidFormat);
399        }
400
401        Amount::from_str_in(amt_str, denom_str.parse()?)
402    }
403
404    /// Express this [Amount] as a floating-point value in the given denomination.
405    ///
406    /// Please be aware of the risk of using floating-point numbers.
407    pub fn to_float_in(self, denom: Denomination) -> f64 {
408        f64::from_str(&self.to_string_in(denom)).unwrap()
409    }
410
411    /// Express this [Amount] as a floating-point value in Bitcoin.
412    ///
413    /// Equivalent to `to_float_in(Denomination::Bitcoin)`.
414    ///
415    /// Please be aware of the risk of using floating-point numbers.
416    pub fn as_btc(self) -> f64 {
417        self.to_float_in(Denomination::Bitcoin)
418    }
419
420    /// Convert this [Amount] in floating-point notation with a given
421    /// denomination.
422    /// Can return error if the amount is too big, too precise or negative.
423    ///
424    /// Please be aware of the risk of using floating-point numbers.
425    pub fn from_float_in(value: f64, denom: Denomination) -> Result<Amount, ParseAmountError> {
426        if value < 0.0 {
427            return Err(ParseAmountError::Negative);
428        }
429        // This is inefficient, but the safest way to deal with this. The parsing logic is safe.
430        // Any performance-critical application should not be dealing with floats.
431        Amount::from_str_in(&value.to_string(), denom)
432    }
433
434    /// Format the value of this [Amount] in the given denomination.
435    ///
436    /// Does not include the denomination.
437    pub fn fmt_value_in(self, f: &mut dyn fmt::Write, denom: Denomination) -> fmt::Result {
438        fmt_satoshi_in(self.as_sat(), false, f, denom)
439    }
440
441    /// Get a string number of this [Amount] in the given denomination.
442    ///
443    /// Does not include the denomination.
444    pub fn to_string_in(self, denom: Denomination) -> String {
445        let mut buf = String::new();
446        self.fmt_value_in(&mut buf, denom).unwrap();
447        buf
448    }
449
450    /// Get a formatted string of this [Amount] in the given denomination,
451    /// suffixed with the abbreviation for the denomination.
452    pub fn to_string_with_denomination(self, denom: Denomination) -> String {
453        let mut buf = String::new();
454        self.fmt_value_in(&mut buf, denom).unwrap();
455        write!(buf, " {}", denom).unwrap();
456        buf
457    }
458
459    // Some arithmetic that doesn't fit in `core::ops` traits.
460
461    /// Checked addition.
462    /// Returns [None] if overflow occurred.
463    pub fn checked_add(self, rhs: Amount) -> Option<Amount> {
464        self.0.checked_add(rhs.0).map(Amount)
465    }
466
467    /// Checked subtraction.
468    /// Returns [None] if overflow occurred.
469    pub fn checked_sub(self, rhs: Amount) -> Option<Amount> {
470        self.0.checked_sub(rhs.0).map(Amount)
471    }
472
473    /// Checked multiplication.
474    /// Returns [None] if overflow occurred.
475    pub fn checked_mul(self, rhs: u64) -> Option<Amount> {
476        self.0.checked_mul(rhs).map(Amount)
477    }
478
479    /// Checked integer division.
480    /// Be aware that integer division loses the remainder if no exact division
481    /// can be made.
482    /// Returns [None] if overflow occurred.
483    pub fn checked_div(self, rhs: u64) -> Option<Amount> {
484        self.0.checked_div(rhs).map(Amount)
485    }
486
487    /// Checked remainder.
488    /// Returns [None] if overflow occurred.
489    pub fn checked_rem(self, rhs: u64) -> Option<Amount> {
490        self.0.checked_rem(rhs).map(Amount)
491    }
492
493    /// Convert to a signed amount.
494    pub fn to_signed(self) -> Result<SignedAmount, ParseAmountError> {
495        if self.as_sat() > SignedAmount::max_value().as_sat() as u64 {
496            Err(ParseAmountError::TooBig)
497        } else {
498            Ok(SignedAmount::from_sat(self.as_sat() as i64))
499        }
500    }
501}
502
503impl default::Default for Amount {
504    fn default() -> Self {
505        Amount::ZERO
506    }
507}
508
509impl fmt::Debug for Amount {
510    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
511        write!(f, "Amount({:.8} BTC)", self.as_btc())
512    }
513}
514
515// No one should depend on a binding contract for Display for this type.
516// Just using Bitcoin denominated string.
517impl fmt::Display for Amount {
518    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
519        self.fmt_value_in(f, Denomination::Bitcoin)?;
520        write!(f, " {}", Denomination::Bitcoin)
521    }
522}
523
524impl ops::Add for Amount {
525    type Output = Amount;
526
527    fn add(self, rhs: Amount) -> Self::Output {
528        self.checked_add(rhs).expect("Amount addition error")
529    }
530}
531
532impl ops::AddAssign for Amount {
533    fn add_assign(&mut self, other: Amount) {
534        *self = *self + other
535    }
536}
537
538impl ops::Sub for Amount {
539    type Output = Amount;
540
541    fn sub(self, rhs: Amount) -> Self::Output {
542        self.checked_sub(rhs).expect("Amount subtraction error")
543    }
544}
545
546impl ops::SubAssign for Amount {
547    fn sub_assign(&mut self, other: Amount) {
548        *self = *self - other
549    }
550}
551
552impl ops::Rem<u64> for Amount {
553    type Output = Amount;
554
555    fn rem(self, modulus: u64) -> Self {
556        self.checked_rem(modulus).expect("Amount remainder error")
557    }
558}
559
560impl ops::RemAssign<u64> for Amount {
561    fn rem_assign(&mut self, modulus: u64) {
562        *self = *self % modulus
563    }
564}
565
566impl ops::Mul<u64> for Amount {
567    type Output = Amount;
568
569    fn mul(self, rhs: u64) -> Self::Output {
570        self.checked_mul(rhs).expect("Amount multiplication error")
571    }
572}
573
574impl ops::MulAssign<u64> for Amount {
575    fn mul_assign(&mut self, rhs: u64) {
576        *self = *self * rhs
577    }
578}
579
580impl ops::Div<u64> for Amount {
581    type Output = Amount;
582
583    fn div(self, rhs: u64) -> Self::Output {
584        self.checked_div(rhs).expect("Amount division error")
585    }
586}
587
588impl ops::DivAssign<u64> for Amount {
589    fn div_assign(&mut self, rhs: u64) {
590        *self = *self / rhs
591    }
592}
593
594impl FromStr for Amount {
595    type Err = ParseAmountError;
596
597    fn from_str(s: &str) -> Result<Self, Self::Err> {
598        Amount::from_str_with_denomination(s)
599    }
600}
601
602impl ::core::iter::Sum for Amount {
603    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
604        let sats: u64 = iter.map(|amt| amt.0).sum();
605        Amount::from_sat(sats)
606    }
607}
608
609/// SignedAmount
610///
611/// The [SignedAmount] type can be used to express Bitcoin amounts that supports
612/// arithmetic and conversion to various denominations.
613///
614///
615/// Warning!
616///
617/// This type implements several arithmetic operations from [core::ops].
618/// To prevent errors due to overflow or underflow when using these operations,
619/// it is advised to instead use the checked arithmetic methods whose names
620/// start with `checked_`.  The operations from [core::ops] that [Amount]
621/// implements will panic when overflow or underflow occurs.
622///
623#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
624pub struct SignedAmount(i64);
625
626impl SignedAmount {
627    /// The zero amount.
628    pub const ZERO: SignedAmount = SignedAmount(0);
629    /// Exactly one satoshi.
630    pub const ONE_SAT: SignedAmount = SignedAmount(1);
631    /// Exactly one bitcoin.
632    pub const ONE_BTC: SignedAmount = SignedAmount(100_000_000);
633    /// The maximum value allowed as an amount. Useful for sanity checking.
634    pub const MAX_MONEY: SignedAmount = SignedAmount(21_000_000 * 100_000_000);
635
636    /// Create an [SignedAmount] with satoshi precision and the given number of satoshis.
637    pub fn from_sat(satoshi: i64) -> SignedAmount {
638        SignedAmount(satoshi)
639    }
640
641    /// Get the number of satoshis in this [SignedAmount].
642    pub fn as_sat(self) -> i64 {
643        self.0
644    }
645
646    /// The maximum value of an [SignedAmount].
647    pub fn max_value() -> SignedAmount {
648        SignedAmount(i64::max_value())
649    }
650
651    /// The minimum value of an [SignedAmount].
652    pub fn min_value() -> SignedAmount {
653        SignedAmount(i64::min_value())
654    }
655
656    /// Convert from a value expressing bitcoins to an [SignedAmount].
657    pub fn from_btc(btc: f64) -> Result<SignedAmount, ParseAmountError> {
658        SignedAmount::from_float_in(btc, Denomination::Bitcoin)
659    }
660
661    /// Parse a decimal string as a value in the given denomination.
662    ///
663    /// Note: This only parses the value string.  If you want to parse a value
664    /// with denomination, use [FromStr].
665    pub fn from_str_in(s: &str, denom: Denomination) -> Result<SignedAmount, ParseAmountError> {
666        let (negative, satoshi) = parse_signed_to_satoshi(s, denom)?;
667        if satoshi > i64::max_value() as u64 {
668            return Err(ParseAmountError::TooBig);
669        }
670        Ok(match negative {
671            true => SignedAmount(-(satoshi as i64)),
672            false => SignedAmount(satoshi as i64),
673        })
674    }
675
676    /// Parses amounts with denomination suffix like they are produced with
677    /// [Self::to_string_with_denomination] or with [fmt::Display].
678    /// If you want to parse only the amount without the denomination,
679    /// use [Self::from_str_in].
680    pub fn from_str_with_denomination(s: &str) -> Result<SignedAmount, ParseAmountError> {
681        let mut split = s.splitn(3, ' ');
682        let amt_str = split.next().unwrap();
683        let denom_str = split.next().ok_or(ParseAmountError::InvalidFormat)?;
684        if split.next().is_some() {
685            return Err(ParseAmountError::InvalidFormat);
686        }
687
688        SignedAmount::from_str_in(amt_str, denom_str.parse()?)
689    }
690
691    /// Express this [SignedAmount] as a floating-point value in the given denomination.
692    ///
693    /// Please be aware of the risk of using floating-point numbers.
694    pub fn to_float_in(self, denom: Denomination) -> f64 {
695        f64::from_str(&self.to_string_in(denom)).unwrap()
696    }
697
698    /// Express this [SignedAmount] as a floating-point value in Bitcoin.
699    ///
700    /// Equivalent to `to_float_in(Denomination::Bitcoin)`.
701    ///
702    /// Please be aware of the risk of using floating-point numbers.
703    pub fn as_btc(self) -> f64 {
704        self.to_float_in(Denomination::Bitcoin)
705    }
706
707    /// Convert this [SignedAmount] in floating-point notation with a given
708    /// denomination.
709    /// Can return error if the amount is too big, too precise or negative.
710    ///
711    /// Please be aware of the risk of using floating-point numbers.
712    pub fn from_float_in(
713        value: f64,
714        denom: Denomination,
715    ) -> Result<SignedAmount, ParseAmountError> {
716        // This is inefficient, but the safest way to deal with this. The parsing logic is safe.
717        // Any performance-critical application should not be dealing with floats.
718        SignedAmount::from_str_in(&value.to_string(), denom)
719    }
720
721    /// Format the value of this [SignedAmount] in the given denomination.
722    ///
723    /// Does not include the denomination.
724    pub fn fmt_value_in(self, f: &mut dyn fmt::Write, denom: Denomination) -> fmt::Result {
725        let sats = self.as_sat().checked_abs().map(|a: i64| a as u64).unwrap_or_else(|| {
726            // We could also hard code this into `9223372036854775808`
727            u64::max_value() - self.as_sat() as u64 +1
728        });
729        fmt_satoshi_in(sats, self.is_negative(), f, denom)
730    }
731
732    /// Get a string number of this [SignedAmount] in the given denomination.
733    ///
734    /// Does not include the denomination.
735    pub fn to_string_in(self, denom: Denomination) -> String {
736        let mut buf = String::new();
737        self.fmt_value_in(&mut buf, denom).unwrap();
738        buf
739    }
740
741    /// Get a formatted string of this [SignedAmount] in the given denomination,
742    /// suffixed with the abbreviation for the denomination.
743    pub fn to_string_with_denomination(self, denom: Denomination) -> String {
744        let mut buf = String::new();
745        self.fmt_value_in(&mut buf, denom).unwrap();
746        write!(buf, " {}", denom).unwrap();
747        buf
748    }
749
750    // Some arithmetic that doesn't fit in `core::ops` traits.
751
752    /// Get the absolute value of this [SignedAmount].
753    pub fn abs(self) -> SignedAmount {
754        SignedAmount(self.0.abs())
755    }
756
757    /// Returns a number representing sign of this [SignedAmount].
758    ///
759    /// - `0` if the amount is zero
760    /// - `1` if the amount is positive
761    /// - `-1` if the amount is negative
762    pub fn signum(self) -> i64 {
763        self.0.signum()
764    }
765
766    /// Returns `true` if this [SignedAmount] is positive and `false` if
767    /// this [SignedAmount] is zero or negative.
768    pub fn is_positive(self) -> bool {
769        self.0.is_positive()
770    }
771
772    /// Returns `true` if this [SignedAmount] is negative and `false` if
773    /// this [SignedAmount] is zero or positive.
774    pub fn is_negative(self) -> bool {
775        self.0.is_negative()
776    }
777
778
779    /// Get the absolute value of this [SignedAmount].
780    /// Returns [None] if overflow occurred. (`self == min_value()`)
781    pub fn checked_abs(self) -> Option<SignedAmount> {
782        self.0.checked_abs().map(SignedAmount)
783    }
784
785    /// Checked addition.
786    /// Returns [None] if overflow occurred.
787    pub fn checked_add(self, rhs: SignedAmount) -> Option<SignedAmount> {
788        self.0.checked_add(rhs.0).map(SignedAmount)
789    }
790
791    /// Checked subtraction.
792    /// Returns [None] if overflow occurred.
793    pub fn checked_sub(self, rhs: SignedAmount) -> Option<SignedAmount> {
794        self.0.checked_sub(rhs.0).map(SignedAmount)
795    }
796
797    /// Checked multiplication.
798    /// Returns [None] if overflow occurred.
799    pub fn checked_mul(self, rhs: i64) -> Option<SignedAmount> {
800        self.0.checked_mul(rhs).map(SignedAmount)
801    }
802
803    /// Checked integer division.
804    /// Be aware that integer division loses the remainder if no exact division
805    /// can be made.
806    /// Returns [None] if overflow occurred.
807    pub fn checked_div(self, rhs: i64) -> Option<SignedAmount> {
808        self.0.checked_div(rhs).map(SignedAmount)
809    }
810
811    /// Checked remainder.
812    /// Returns [None] if overflow occurred.
813    pub fn checked_rem(self, rhs: i64) -> Option<SignedAmount> {
814        self.0.checked_rem(rhs).map(SignedAmount)
815    }
816
817    /// Subtraction that doesn't allow negative [SignedAmount]s.
818    /// Returns [None] if either [self], `rhs` or the result is strictly negative.
819    pub fn positive_sub(self, rhs: SignedAmount) -> Option<SignedAmount> {
820        if self.is_negative() || rhs.is_negative() || rhs > self {
821            None
822        } else {
823            self.checked_sub(rhs)
824        }
825    }
826
827    /// Convert to an unsigned amount.
828    pub fn to_unsigned(self) -> Result<Amount, ParseAmountError> {
829        if self.is_negative() {
830            Err(ParseAmountError::Negative)
831        } else {
832            Ok(Amount::from_sat(self.as_sat() as u64))
833        }
834    }
835}
836
837impl default::Default for SignedAmount {
838    fn default() -> Self {
839        SignedAmount::ZERO
840    }
841}
842
843impl fmt::Debug for SignedAmount {
844    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
845        write!(f, "SignedAmount({:.8} BTC)", self.as_btc())
846    }
847}
848
849// No one should depend on a binding contract for Display for this type.
850// Just using Bitcoin denominated string.
851impl fmt::Display for SignedAmount {
852    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
853        self.fmt_value_in(f, Denomination::Bitcoin)?;
854        write!(f, " {}", Denomination::Bitcoin)
855    }
856}
857
858impl ops::Add for SignedAmount {
859    type Output = SignedAmount;
860
861    fn add(self, rhs: SignedAmount) -> Self::Output {
862        self.checked_add(rhs).expect("SignedAmount addition error")
863    }
864}
865
866impl ops::AddAssign for SignedAmount {
867    fn add_assign(&mut self, other: SignedAmount) {
868        *self = *self + other
869    }
870}
871
872impl ops::Sub for SignedAmount {
873    type Output = SignedAmount;
874
875    fn sub(self, rhs: SignedAmount) -> Self::Output {
876        self.checked_sub(rhs).expect("SignedAmount subtraction error")
877    }
878}
879
880impl ops::SubAssign for SignedAmount {
881    fn sub_assign(&mut self, other: SignedAmount) {
882        *self = *self - other
883    }
884}
885
886impl ops::Rem<i64> for SignedAmount {
887    type Output = SignedAmount;
888
889    fn rem(self, modulus: i64) -> Self {
890        self.checked_rem(modulus).expect("SignedAmount remainder error")
891    }
892}
893
894impl ops::RemAssign<i64> for SignedAmount {
895    fn rem_assign(&mut self, modulus: i64) {
896        *self = *self % modulus
897    }
898}
899
900impl ops::Mul<i64> for SignedAmount {
901    type Output = SignedAmount;
902
903    fn mul(self, rhs: i64) -> Self::Output {
904        self.checked_mul(rhs).expect("SignedAmount multiplication error")
905    }
906}
907
908impl ops::MulAssign<i64> for SignedAmount {
909    fn mul_assign(&mut self, rhs: i64) {
910        *self = *self * rhs
911    }
912}
913
914impl ops::Div<i64> for SignedAmount {
915    type Output = SignedAmount;
916
917    fn div(self, rhs: i64) -> Self::Output {
918        self.checked_div(rhs).expect("SignedAmount division error")
919    }
920}
921
922impl ops::DivAssign<i64> for SignedAmount {
923    fn div_assign(&mut self, rhs: i64) {
924        *self = *self / rhs
925    }
926}
927
928impl FromStr for SignedAmount {
929    type Err = ParseAmountError;
930
931    fn from_str(s: &str) -> Result<Self, Self::Err> {
932        SignedAmount::from_str_with_denomination(s)
933    }
934}
935
936impl ::core::iter::Sum for SignedAmount {
937    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
938        let sats: i64 = iter.map(|amt| amt.0).sum();
939        SignedAmount::from_sat(sats)
940    }
941}
942
943/// Calculate the sum over the iterator using checked arithmetic.
944pub trait CheckedSum<R>: private::SumSeal<R> {
945    /// Calculate the sum over the iterator using checked arithmetic. If an over or underflow would
946    /// happen it returns `None`.
947    fn checked_sum(self) -> Option<R>;
948}
949
950impl<T> CheckedSum<Amount> for T where T: Iterator<Item=Amount> {
951    fn checked_sum(mut self) -> Option<Amount> {
952        let first = Some(self.next().unwrap_or_default());
953
954        self.fold(
955            first,
956            |acc, item| acc.and_then(|acc| acc.checked_add(item))
957        )
958    }
959}
960
961impl<T> CheckedSum<SignedAmount> for T where T: Iterator<Item=SignedAmount> {
962    fn checked_sum(mut self) -> Option<SignedAmount> {
963        let first = Some(self.next().unwrap_or_default());
964
965        self.fold(first, |acc, item| acc.and_then(|acc| acc.checked_add(item)))
966    }
967}
968
969mod private {
970    use ::{Amount, SignedAmount};
971
972    /// Used to seal the `CheckedSum` trait
973    pub trait SumSeal<A> {}
974
975    impl<T> SumSeal<Amount> for T where T: Iterator<Item=Amount> {}
976    impl<T> SumSeal<SignedAmount> for T where T: Iterator<Item=SignedAmount> {}
977}
978
979#[cfg(feature = "serde")]
980#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
981pub mod serde {
982    // methods are implementation of a standardized serde-specific signature
983    #![allow(missing_docs)]
984
985    //! This module adds serde serialization and deserialization support for Amounts.
986    //! Since there is not a default way to serialize and deserialize Amounts, multiple
987    //! ways are supported and it's up to the user to decide which serialiation to use.
988    //! The provided modules can be used as follows:
989    //!
990    //! ```rust,ignore
991    //! use serde::{Serialize, Deserialize};
992    //! use bitcoin::Amount;
993    //!
994    //! #[derive(Serialize, Deserialize)]
995    //! pub struct HasAmount {
996    //!     #[serde(with = "bitcoin::util::amount::serde::as_btc")]
997    //!     pub amount: Amount,
998    //! }
999    //! ```
1000
1001    use serde::{Deserialize, Deserializer, Serialize, Serializer};
1002    use util::amount::{Amount, Denomination, SignedAmount};
1003
1004    /// This trait is used only to avoid code duplication and naming collisions
1005    /// of the different serde serialization crates.
1006    ///
1007    /// TODO: Add the private::Sealed bound in next breaking release
1008    pub trait SerdeAmount: Copy + Sized {
1009        fn ser_sat<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error>;
1010        fn des_sat<'d, D: Deserializer<'d>>(d: D) -> Result<Self, D::Error>;
1011        fn ser_btc<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error>;
1012        fn des_btc<'d, D: Deserializer<'d>>(d: D) -> Result<Self, D::Error>;
1013    }
1014
1015    mod private {
1016        /// add this as a trait bound to traits which consumers of this library
1017        /// should not be able to implement.
1018        pub trait Sealed {}
1019        impl Sealed for super::Amount {}
1020        impl Sealed for super::SignedAmount {}
1021    }
1022
1023    /// This trait is only for internal Amount type serialization/deserialization
1024    pub trait SerdeAmountForOpt: Copy + Sized + SerdeAmount + private::Sealed {
1025        fn type_prefix() -> &'static str;
1026        fn ser_sat_opt<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error>;
1027        fn ser_btc_opt<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error>;
1028    }
1029
1030    impl SerdeAmount for Amount {
1031        fn ser_sat<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error> {
1032            u64::serialize(&self.as_sat(), s)
1033        }
1034        fn des_sat<'d, D: Deserializer<'d>>(d: D) -> Result<Self, D::Error> {
1035            Ok(Amount::from_sat(u64::deserialize(d)?))
1036        }
1037        fn ser_btc<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error> {
1038            f64::serialize(&self.to_float_in(Denomination::Bitcoin), s)
1039        }
1040        fn des_btc<'d, D: Deserializer<'d>>(d: D) -> Result<Self, D::Error> {
1041            use serde::de::Error;
1042            Ok(Amount::from_btc(f64::deserialize(d)?).map_err(D::Error::custom)?)
1043        }
1044    }
1045
1046    impl SerdeAmountForOpt for Amount {
1047        fn type_prefix() -> &'static str {
1048            "u"
1049        }
1050        fn ser_sat_opt<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error> {
1051            s.serialize_some(&self.as_sat())
1052        }
1053        fn ser_btc_opt<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error> {
1054            s.serialize_some(&self.as_btc())
1055        }
1056    }
1057
1058    impl SerdeAmount for SignedAmount {
1059        fn ser_sat<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error> {
1060            i64::serialize(&self.as_sat(), s)
1061        }
1062        fn des_sat<'d, D: Deserializer<'d>>(d: D) -> Result<Self, D::Error> {
1063            Ok(SignedAmount::from_sat(i64::deserialize(d)?))
1064        }
1065        fn ser_btc<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error> {
1066            f64::serialize(&self.to_float_in(Denomination::Bitcoin), s)
1067        }
1068        fn des_btc<'d, D: Deserializer<'d>>(d: D) -> Result<Self, D::Error> {
1069            use serde::de::Error;
1070            Ok(SignedAmount::from_btc(f64::deserialize(d)?).map_err(D::Error::custom)?)
1071        }
1072    }
1073
1074    impl SerdeAmountForOpt for SignedAmount {
1075        fn type_prefix() -> &'static str {
1076            "i"
1077        }
1078        fn ser_sat_opt<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error> {
1079            s.serialize_some(&self.as_sat())
1080        }
1081        fn ser_btc_opt<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error> {
1082            s.serialize_some(&self.as_btc())
1083        }
1084    }
1085
1086    pub mod as_sat {
1087        //! Serialize and deserialize [`Amount`](crate::Amount) as real numbers denominated in satoshi.
1088        //! Use with `#[serde(with = "amount::serde::as_sat")]`.
1089
1090        use serde::{Deserializer, Serializer};
1091        use util::amount::serde::SerdeAmount;
1092
1093        pub fn serialize<A: SerdeAmount, S: Serializer>(a: &A, s: S) -> Result<S::Ok, S::Error> {
1094            a.ser_sat(s)
1095        }
1096
1097        pub fn deserialize<'d, A: SerdeAmount, D: Deserializer<'d>>(d: D) -> Result<A, D::Error> {
1098            A::des_sat(d)
1099        }
1100
1101        pub mod opt {
1102            //! Serialize and deserialize [`Option<Amount>`](crate::Amount) as real numbers denominated in satoshi.
1103            //! Use with `#[serde(default, with = "amount::serde::as_sat::opt")]`.
1104
1105            use serde::{Deserializer, Serializer, de};
1106            use util::amount::serde::SerdeAmountForOpt;
1107            use core::fmt;
1108            use core::marker::PhantomData;
1109
1110            pub fn serialize<A: SerdeAmountForOpt, S: Serializer>(
1111                a: &Option<A>,
1112                s: S,
1113            ) -> Result<S::Ok, S::Error> {
1114                match *a {
1115                    Some(a) => a.ser_sat_opt(s),
1116                    None => s.serialize_none(),
1117                }
1118            }
1119
1120            pub fn deserialize<'d, A: SerdeAmountForOpt, D: Deserializer<'d>>(
1121                d: D,
1122            ) -> Result<Option<A>, D::Error> {
1123                struct VisitOptAmt<X>(PhantomData<X>);
1124
1125                impl<'de, X: SerdeAmountForOpt> de::Visitor<'de> for VisitOptAmt<X> {
1126                    type Value = Option<X>;
1127
1128                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1129                        write!(formatter, "An Option<{}64>", X::type_prefix())
1130                    }
1131
1132                    fn visit_none<E>(self) -> Result<Self::Value, E>
1133                    where
1134                        E: de::Error,
1135                    {
1136                        Ok(None)
1137                    }
1138                    fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
1139                    where
1140                        D: Deserializer<'de>,
1141                    {
1142                        Ok(Some(X::des_sat(d)?))
1143                    }
1144                }
1145                d.deserialize_option(VisitOptAmt::<A>(PhantomData))
1146            }
1147        }
1148    }
1149
1150    pub mod as_btc {
1151        //! Serialize and deserialize [`Amount`](crate::Amount) as JSON numbers denominated in BTC.
1152        //! Use with `#[serde(with = "amount::serde::as_btc")]`.
1153
1154        use serde::{Deserializer, Serializer};
1155        use util::amount::serde::SerdeAmount;
1156
1157        pub fn serialize<A: SerdeAmount, S: Serializer>(a: &A, s: S) -> Result<S::Ok, S::Error> {
1158            a.ser_btc(s)
1159        }
1160
1161        pub fn deserialize<'d, A: SerdeAmount, D: Deserializer<'d>>(d: D) -> Result<A, D::Error> {
1162            A::des_btc(d)
1163        }
1164
1165        pub mod opt {
1166            //! Serialize and deserialize [Option<Amount>] as JSON numbers denominated in BTC.
1167            //! Use with `#[serde(default, with = "amount::serde::as_btc::opt")]`.
1168
1169            use serde::{Deserializer, Serializer, de};
1170            use util::amount::serde::SerdeAmountForOpt;
1171            use core::fmt;
1172            use core::marker::PhantomData;
1173
1174            pub fn serialize<A: SerdeAmountForOpt, S: Serializer>(
1175                a: &Option<A>,
1176                s: S,
1177            ) -> Result<S::Ok, S::Error> {
1178                match *a {
1179                    Some(a) => a.ser_btc_opt(s),
1180                    None => s.serialize_none(),
1181                }
1182            }
1183
1184            pub fn deserialize<'d, A: SerdeAmountForOpt, D: Deserializer<'d>>(
1185                d: D,
1186            ) -> Result<Option<A>, D::Error> {
1187                struct VisitOptAmt<X>(PhantomData<X>);
1188
1189                impl<'de, X: SerdeAmountForOpt> de::Visitor<'de> for VisitOptAmt<X> {
1190                    type Value = Option<X>;
1191
1192                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1193                        write!(formatter, "An Option<f64>")
1194                    }
1195
1196                    fn visit_none<E>(self) -> Result<Self::Value, E>
1197                    where
1198                        E: de::Error,
1199                    {
1200                        Ok(None)
1201                    }
1202                    fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
1203                    where
1204                        D: Deserializer<'de>,
1205                    {
1206                        Ok(Some(X::des_btc(d)?))
1207                    }
1208                }
1209                d.deserialize_option(VisitOptAmt::<A>(PhantomData))
1210            }
1211        }
1212    }
1213}
1214
1215/// An amount of Bitcoin in either Satoshis (sats) or Bitcoin (btc).
1216#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1217#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
1218pub enum CoinAmount {
1219    /// # Satoshis
1220    /// Satoshis (sats) as an exact integer.
1221    Sats(u64),
1222    /// # Bitcoin
1223    /// Bitcoin (btc) as a floating point.
1224    Btc(f64),
1225}
1226
1227/// Derived externally using serde_derive
1228#[cfg(feature = "serde")]
1229#[doc(hidden)]
1230#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
1231const _: () = {
1232    use std::marker::PhantomData;
1233    use std::fmt::Formatter;
1234    #[allow(rust_2018_idioms, clippy::useless_attribute)]
1235    extern crate serde as _serde;
1236    impl _serde::Serialize for CoinAmount {
1237        fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
1238        where
1239            __S: _serde::Serializer,
1240        {
1241            match *self {
1242                CoinAmount::Sats(ref __field0) => _serde::Serializer::serialize_newtype_variant(
1243                    __serializer,
1244                    "CoinAmount",
1245                    0u32,
1246                    "Sats",
1247                    __field0,
1248                ),
1249                CoinAmount::Btc(ref __field0) => _serde::Serializer::serialize_newtype_variant(
1250                    __serializer,
1251                    "CoinAmount",
1252                    1u32,
1253                    "Btc",
1254                    __field0,
1255                ),
1256            }
1257        }
1258    }
1259    impl<'de> _serde::Deserialize<'de> for CoinAmount {
1260        fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
1261        where
1262            __D: _serde::Deserializer<'de>,
1263        {
1264            #[allow(non_camel_case_types)]
1265            enum __Field {
1266                __field0,
1267                __field1,
1268            }
1269            struct __FieldVisitor;
1270            impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
1271                type Value = __Field;
1272                fn expecting(
1273                    &self,
1274                    __formatter: &mut Formatter,
1275                ) -> fmt::Result {
1276                    Formatter::write_str(__formatter, "variant identifier")
1277                }
1278                fn visit_u64<__E>(self, __value: u64) -> Result<Self::Value, __E>
1279                where
1280                    __E: _serde::de::Error,
1281                {
1282                    match __value {
1283                        0u64 => Ok(__Field::__field0),
1284                        1u64 => Ok(__Field::__field1),
1285                        _ => Err(_serde::de::Error::invalid_value(
1286                            _serde::de::Unexpected::Unsigned(__value),
1287                            &"variant index 0 <= i < 2",
1288                        )),
1289                    }
1290                }
1291                fn visit_str<__E>(self, __value: &str) -> Result<Self::Value, __E>
1292                where
1293                    __E: _serde::de::Error,
1294                {
1295                    match __value {
1296                        "Sats" => Ok(__Field::__field0),
1297                        "Btc" => Ok(__Field::__field1),
1298                        _ => Err(_serde::de::Error::unknown_variant(
1299                            __value, VARIANTS,
1300                        )),
1301                    }
1302                }
1303                fn visit_bytes<__E>(
1304                    self,
1305                    __value: &[u8],
1306                ) -> Result<Self::Value, __E>
1307                where
1308                    __E: _serde::de::Error,
1309                {
1310                    match __value {
1311                        b"Sats" => Ok(__Field::__field0),
1312                        b"Btc" => Ok(__Field::__field1),
1313                        _ => {
1314                            let __value = &String::from_utf8_lossy(__value);
1315                            Err(_serde::de::Error::unknown_variant(
1316                                __value, VARIANTS,
1317                            ))
1318                        }
1319                    }
1320                }
1321            }
1322            impl<'de> _serde::Deserialize<'de> for __Field {
1323                #[inline]
1324                fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
1325                where
1326                    __D: _serde::Deserializer<'de>,
1327                {
1328                    _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
1329                }
1330            }
1331            struct __Visitor<'de> {
1332                marker: PhantomData<CoinAmount>,
1333                lifetime: PhantomData<&'de ()>,
1334            }
1335            impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
1336                type Value = CoinAmount;
1337                fn expecting(
1338                    &self,
1339                    __formatter: &mut Formatter,
1340                ) -> fmt::Result {
1341                    Formatter::write_str(__formatter, "enum CoinAmount")
1342                }
1343                fn visit_enum<__A>(
1344                    self,
1345                    __data: __A,
1346                ) -> Result<Self::Value, __A::Error>
1347                where
1348                    __A: _serde::de::EnumAccess<'de>,
1349                {
1350                    match match _serde::de::EnumAccess::variant(__data) {
1351                        Ok(__val) => __val,
1352                        Err(__err) => {
1353                            return Err(__err);
1354                        }
1355                    } {
1356                        (__Field::__field0, __variant) => Result::map(
1357                            _serde::de::VariantAccess::newtype_variant::<u64>(__variant),
1358                            CoinAmount::Sats,
1359                        ),
1360                        (__Field::__field1, __variant) => Result::map(
1361                            _serde::de::VariantAccess::newtype_variant::<f64>(__variant),
1362                            CoinAmount::Btc,
1363                        ),
1364                    }
1365                }
1366            }
1367            const VARIANTS: &'static [&'static str] = &["Sats", "Btc"];
1368            _serde::Deserializer::deserialize_enum(
1369                __deserializer,
1370                "CoinAmount",
1371                VARIANTS,
1372                __Visitor {
1373                    marker: PhantomData::<CoinAmount>,
1374                    lifetime: PhantomData,
1375                },
1376            )
1377        }
1378    }
1379};
1380
1381impl TryFrom<CoinAmount> for  Amount {
1382    type Error = ParseAmountError;
1383    fn try_from(value: CoinAmount) -> Result<Self, Self::Error> {
1384        match value {
1385            CoinAmount::Sats(x) => Ok(Amount::from_sat(x)),
1386            CoinAmount::Btc(y) => Amount::from_btc(y),
1387        }
1388    }
1389}
1390
1391impl From<Amount> for CoinAmount {
1392    fn from(a:Amount) -> Self {
1393        CoinAmount::Sats(a.as_sat())
1394    }
1395}
1396
1397
1398#[cfg(test)]
1399mod tests {
1400    use super::*;
1401    #[cfg(feature = "std")]
1402    use std::panic;
1403    use core::str::FromStr;
1404
1405    #[cfg(feature = "serde")]
1406    use serde_test;
1407
1408    #[test]
1409    fn add_sub_mul_div() {
1410        let sat = Amount::from_sat;
1411        let ssat = SignedAmount::from_sat;
1412
1413        assert_eq!(sat(15) + sat(15), sat(30));
1414        assert_eq!(sat(15) - sat(15), sat(0));
1415        assert_eq!(sat(14) * 3, sat(42));
1416        assert_eq!(sat(14) / 2, sat(7));
1417        assert_eq!(sat(14) % 3, sat(2));
1418        assert_eq!(ssat(15) - ssat(20), ssat(-5));
1419        assert_eq!(ssat(-14) * 3, ssat(-42));
1420        assert_eq!(ssat(-14) / 2, ssat(-7));
1421        assert_eq!(ssat(-14) % 3, ssat(-2));
1422
1423        let mut b = ssat(-5);
1424        b += ssat(13);
1425        assert_eq!(b, ssat(8));
1426        b -= ssat(3);
1427        assert_eq!(b, ssat(5));
1428        b *= 6;
1429        assert_eq!(b, ssat(30));
1430        b /= 3;
1431        assert_eq!(b, ssat(10));
1432        b %= 3;
1433        assert_eq!(b, ssat(1));
1434    }
1435
1436    #[cfg(feature = "std")]
1437    #[test]
1438    fn test_overflows() {
1439        // panic on overflow
1440        let result = panic::catch_unwind(|| Amount::max_value() + Amount::from_sat(1));
1441        assert!(result.is_err());
1442        let result = panic::catch_unwind(|| Amount::from_sat(8446744073709551615) * 3);
1443        assert!(result.is_err());
1444    }
1445
1446    #[test]
1447    fn checked_arithmetic() {
1448        let sat = Amount::from_sat;
1449        let ssat = SignedAmount::from_sat;
1450
1451        assert_eq!(sat(42).checked_add(sat(1)), Some(sat(43)));
1452        assert_eq!(SignedAmount::max_value().checked_add(ssat(1)), None);
1453        assert_eq!(SignedAmount::min_value().checked_sub(ssat(1)), None);
1454        assert_eq!(Amount::max_value().checked_add(sat(1)), None);
1455        assert_eq!(Amount::min_value().checked_sub(sat(1)), None);
1456
1457        assert_eq!(sat(5).checked_sub(sat(3)), Some(sat(2)));
1458        assert_eq!(sat(5).checked_sub(sat(6)), None);
1459        assert_eq!(ssat(5).checked_sub(ssat(6)), Some(ssat(-1)));
1460        assert_eq!(sat(5).checked_rem(2), Some(sat(1)));
1461
1462        assert_eq!(sat(5).checked_div(2), Some(sat(2))); // integer division
1463        assert_eq!(ssat(-6).checked_div(2), Some(ssat(-3)));
1464
1465        assert_eq!(ssat(-5).positive_sub(ssat(3)), None);
1466        assert_eq!(ssat(5).positive_sub(ssat(-3)), None);
1467        assert_eq!(ssat(3).positive_sub(ssat(5)), None);
1468        assert_eq!(ssat(3).positive_sub(ssat(3)), Some(ssat(0)));
1469        assert_eq!(ssat(5).positive_sub(ssat(3)), Some(ssat(2)));
1470    }
1471
1472    #[test]
1473    fn floating_point() {
1474        use super::Denomination as D;
1475        let f = Amount::from_float_in;
1476        let sf = SignedAmount::from_float_in;
1477        let sat = Amount::from_sat;
1478        let ssat = SignedAmount::from_sat;
1479
1480        assert_eq!(f(11.22, D::Bitcoin), Ok(sat(1122000000)));
1481        assert_eq!(sf(-11.22, D::MilliBitcoin), Ok(ssat(-1122000)));
1482        assert_eq!(f(11.22, D::Bit), Ok(sat(1122)));
1483        assert_eq!(sf(-1000.0, D::MilliSatoshi), Ok(ssat(-1)));
1484        assert_eq!(f(0.0001234, D::Bitcoin), Ok(sat(12340)));
1485        assert_eq!(sf(-0.00012345, D::Bitcoin), Ok(ssat(-12345)));
1486
1487        assert_eq!(f(-100.0, D::MilliSatoshi), Err(ParseAmountError::Negative));
1488        assert_eq!(f(11.22, D::Satoshi), Err(ParseAmountError::TooPrecise));
1489        assert_eq!(sf(-100.0, D::MilliSatoshi), Err(ParseAmountError::TooPrecise));
1490        assert_eq!(sf(-100.0, D::MilliSatoshi), Err(ParseAmountError::TooPrecise));
1491        assert_eq!(f(42.123456781, D::Bitcoin), Err(ParseAmountError::TooPrecise));
1492        assert_eq!(sf(-184467440738.0, D::Bitcoin), Err(ParseAmountError::TooBig));
1493        assert_eq!(f(18446744073709551617.0, D::Satoshi), Err(ParseAmountError::TooBig));
1494        assert_eq!(
1495            f(SignedAmount::max_value().to_float_in(D::Satoshi) + 1.0, D::Satoshi),
1496            Err(ParseAmountError::TooBig)
1497        );
1498        assert_eq!(
1499            f(Amount::max_value().to_float_in(D::Satoshi) + 1.0, D::Satoshi),
1500            Err(ParseAmountError::TooBig)
1501        );
1502
1503        let btc = move |f| SignedAmount::from_btc(f).unwrap();
1504        assert_eq!(btc(2.5).to_float_in(D::Bitcoin), 2.5);
1505        assert_eq!(btc(-2.5).to_float_in(D::MilliBitcoin), -2500.0);
1506        assert_eq!(btc(2.5).to_float_in(D::Satoshi), 250000000.0);
1507        assert_eq!(btc(-2.5).to_float_in(D::MilliSatoshi), -250000000000.0);
1508
1509        let btc = move |f| Amount::from_btc(f).unwrap();
1510        assert_eq!(&btc(0.0012).to_float_in(D::Bitcoin).to_string(), "0.0012")
1511    }
1512
1513    #[test]
1514    fn parsing() {
1515        use super::ParseAmountError as E;
1516        let btc = Denomination::Bitcoin;
1517        let sat = Denomination::Satoshi;
1518        let p = Amount::from_str_in;
1519        let sp = SignedAmount::from_str_in;
1520
1521        assert_eq!(p("x", btc), Err(E::InvalidCharacter('x')));
1522        assert_eq!(p("-", btc), Err(E::InvalidFormat));
1523        assert_eq!(sp("-", btc), Err(E::InvalidFormat));
1524        assert_eq!(p("-1.0x", btc), Err(E::InvalidCharacter('x')));
1525        assert_eq!(p("0.0 ", btc), Err(ParseAmountError::InvalidCharacter(' ')));
1526        assert_eq!(p("0.000.000", btc), Err(E::InvalidFormat));
1527        let more_than_max = format!("1{}", Amount::max_value());
1528        assert_eq!(p(&more_than_max, btc), Err(E::TooBig));
1529        assert_eq!(p("0.000000042", btc), Err(E::TooPrecise));
1530
1531        assert_eq!(p("1", btc), Ok(Amount::from_sat(1_000_000_00)));
1532        assert_eq!(sp("-.5", btc), Ok(SignedAmount::from_sat(-500_000_00)));
1533        assert_eq!(p("1.1", btc), Ok(Amount::from_sat(1_100_000_00)));
1534        assert_eq!(p("100", sat), Ok(Amount::from_sat(100)));
1535        assert_eq!(p("55", sat), Ok(Amount::from_sat(55)));
1536        assert_eq!(p("5500000000000000000", sat), Ok(Amount::from_sat(5_500_000_000_000_000_000)));
1537        // Should this even pass?
1538        assert_eq!(p("5500000000000000000.", sat), Ok(Amount::from_sat(5_500_000_000_000_000_000)));
1539        assert_eq!(
1540            p("12345678901.12345678", btc),
1541            Ok(Amount::from_sat(12_345_678_901__123_456_78))
1542        );
1543
1544        // make sure satoshi > i64::max_value() is checked.
1545        let amount = Amount::from_sat(i64::max_value() as u64);
1546        assert_eq!(Amount::from_str_in(&amount.to_string_in(sat), sat), Ok(amount));
1547        assert_eq!(Amount::from_str_in(&(amount+Amount(1)).to_string_in(sat), sat), Err(E::TooBig));
1548
1549        assert_eq!(p("12.000", Denomination::MilliSatoshi), Err(E::TooPrecise));
1550        // exactly 50 chars.
1551        assert_eq!(p("100000000000000.0000000000000000000000000000000000", Denomination::Bitcoin), Err(E::TooBig));
1552        // more than 50 chars.
1553        assert_eq!(p("100000000000000.00000000000000000000000000000000000", Denomination::Bitcoin), Err(E::InputTooLarge));
1554    }
1555
1556    #[test]
1557    fn to_string() {
1558        use super::Denomination as D;
1559
1560        assert_eq!(Amount::ONE_BTC.to_string_in(D::Bitcoin), "1.00000000");
1561        assert_eq!(Amount::ONE_BTC.to_string_in(D::Satoshi), "100000000");
1562        assert_eq!(Amount::ONE_SAT.to_string_in(D::Bitcoin), "0.00000001");
1563        assert_eq!(SignedAmount::from_sat(-42).to_string_in(D::Bitcoin), "-0.00000042");
1564
1565        assert_eq!(Amount::ONE_BTC.to_string_with_denomination(D::Bitcoin), "1.00000000 BTC");
1566        assert_eq!(Amount::ONE_SAT.to_string_with_denomination(D::MilliSatoshi), "1000 msat");
1567        assert_eq!(
1568            SignedAmount::ONE_BTC.to_string_with_denomination(D::Satoshi),
1569            "100000000 satoshi"
1570        );
1571        assert_eq!(Amount::ONE_SAT.to_string_with_denomination(D::Bitcoin), "0.00000001 BTC");
1572        assert_eq!(
1573            SignedAmount::from_sat(-42).to_string_with_denomination(D::Bitcoin),
1574            "-0.00000042 BTC"
1575        );
1576    }
1577
1578    #[test]
1579    fn test_unsigned_signed_conversion() {
1580        use super::ParseAmountError as E;
1581        let sa = SignedAmount::from_sat;
1582        let ua = Amount::from_sat;
1583
1584        assert_eq!(Amount::max_value().to_signed(), Err(E::TooBig));
1585        assert_eq!(ua(i64::max_value() as u64).to_signed(),  Ok(sa(i64::max_value())));
1586        assert_eq!(ua(0).to_signed(), Ok(sa(0)));
1587        assert_eq!(ua(1).to_signed(), Ok( sa(1)));
1588        assert_eq!(ua(1).to_signed(), Ok(sa(1)));
1589        assert_eq!(ua(i64::max_value() as u64 + 1).to_signed(), Err(E::TooBig));
1590
1591        assert_eq!(sa(-1).to_unsigned(), Err(E::Negative));
1592        assert_eq!(sa(i64::max_value()).to_unsigned(), Ok(ua(i64::max_value() as u64)));
1593
1594        assert_eq!(sa(0).to_unsigned().unwrap().to_signed(), Ok(sa(0)));
1595        assert_eq!(sa(1).to_unsigned().unwrap().to_signed(), Ok(sa(1)));
1596        assert_eq!(sa(i64::max_value()).to_unsigned().unwrap().to_signed(), Ok(sa(i64::max_value())));
1597    }
1598
1599    #[test]
1600    fn from_str() {
1601        use super::ParseAmountError as E;
1602        let p = Amount::from_str;
1603        let sp = SignedAmount::from_str;
1604
1605        assert_eq!(p("x BTC"), Err(E::InvalidCharacter('x')));
1606        assert_eq!(p("5 BTC BTC"), Err(E::InvalidFormat));
1607        assert_eq!(p("5 5 BTC"), Err(E::InvalidFormat));
1608
1609        assert_eq!(p("5 BCH"), Err(E::UnknownDenomination("BCH".to_owned())));
1610
1611        assert_eq!(p("-1 BTC"), Err(E::Negative));
1612        assert_eq!(p("-0.0 BTC"), Err(E::Negative));
1613        assert_eq!(p("0.123456789 BTC"), Err(E::TooPrecise));
1614        assert_eq!(sp("-0.1 satoshi"), Err(E::TooPrecise));
1615        assert_eq!(p("0.123456 mBTC"), Err(E::TooPrecise));
1616        assert_eq!(sp("-1.001 bits"), Err(E::TooPrecise));
1617        assert_eq!(sp("-200000000000 BTC"), Err(E::TooBig));
1618        assert_eq!(p("18446744073709551616 sat"), Err(E::TooBig));
1619
1620        assert_eq!(sp("0 msat"), Err(E::TooPrecise));
1621        assert_eq!(sp("-0 msat"), Err(E::TooPrecise));
1622        assert_eq!(sp("000 msat"), Err(E::TooPrecise));
1623        assert_eq!(sp("-000 msat"), Err(E::TooPrecise));
1624        assert_eq!(p("0 msat"), Err(E::TooPrecise));
1625        assert_eq!(p("-0 msat"), Err(E::TooPrecise));
1626        assert_eq!(p("000 msat"), Err(E::TooPrecise));
1627        assert_eq!(p("-000 msat"), Err(E::TooPrecise));
1628
1629        assert_eq!(p(".5 bits"), Ok(Amount::from_sat(50)));
1630        assert_eq!(sp("-.5 bits"), Ok(SignedAmount::from_sat(-50)));
1631        assert_eq!(p("0.00253583 BTC"), Ok(Amount::from_sat(253583)));
1632        assert_eq!(sp("-5 satoshi"), Ok(SignedAmount::from_sat(-5)));
1633        assert_eq!(p("0.10000000 BTC"), Ok(Amount::from_sat(100_000_00)));
1634        assert_eq!(sp("-100 bits"), Ok(SignedAmount::from_sat(-10_000)));
1635    }
1636
1637    #[test]
1638    fn to_from_string_in() {
1639        use super::Denomination as D;
1640        let ua_str = Amount::from_str_in;
1641        let ua_sat = Amount::from_sat;
1642        let sa_str = SignedAmount::from_str_in;
1643        let sa_sat = SignedAmount::from_sat;
1644
1645        assert_eq!("0.50", Amount::from_sat(50).to_string_in(D::Bit));
1646        assert_eq!("-0.50", SignedAmount::from_sat(-50).to_string_in(D::Bit));
1647        assert_eq!("0.00253583", Amount::from_sat(253583).to_string_in(D::Bitcoin));
1648        assert_eq!("-5", SignedAmount::from_sat(-5).to_string_in(D::Satoshi));
1649        assert_eq!("0.10000000", Amount::from_sat(100_000_00).to_string_in(D::Bitcoin));
1650        assert_eq!("-100.00", SignedAmount::from_sat(-10_000).to_string_in(D::Bit));
1651        assert_eq!("2535830", Amount::from_sat(253583).to_string_in(D::NanoBitcoin));
1652        assert_eq!("-100000", SignedAmount::from_sat(-10_000).to_string_in(D::NanoBitcoin));
1653        assert_eq!("2535830000", Amount::from_sat(253583).to_string_in(D::PicoBitcoin));
1654        assert_eq!("-100000000", SignedAmount::from_sat(-10_000).to_string_in(D::PicoBitcoin));
1655
1656
1657
1658        assert_eq!(ua_str(&ua_sat(0).to_string_in(D::Satoshi), D::Satoshi), Ok(ua_sat(0)));
1659        assert_eq!(ua_str(&ua_sat(500).to_string_in(D::Bitcoin), D::Bitcoin), Ok(ua_sat(500)));
1660        assert_eq!(ua_str(&ua_sat(21_000_000).to_string_in(D::Bit), D::Bit), Ok(ua_sat(21_000_000)));
1661        assert_eq!(ua_str(&ua_sat(1).to_string_in(D::MicroBitcoin), D::MicroBitcoin), Ok(ua_sat(1)));
1662        assert_eq!(ua_str(&ua_sat(1_000_000_000_000).to_string_in(D::MilliBitcoin), D::MilliBitcoin), Ok(ua_sat(1_000_000_000_000)));
1663        assert_eq!(ua_str(&ua_sat(u64::max_value()).to_string_in(D::MilliBitcoin), D::MilliBitcoin),  Err(ParseAmountError::TooBig));
1664
1665        assert_eq!(sa_str(&sa_sat(-1).to_string_in(D::MicroBitcoin), D::MicroBitcoin), Ok(sa_sat(-1)));
1666
1667        assert_eq!(sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::MicroBitcoin), Err(ParseAmountError::TooBig));
1668        // Test an overflow bug in `abs()`
1669        assert_eq!(sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::MicroBitcoin), Err(ParseAmountError::TooBig));
1670
1671        assert_eq!(sa_str(&sa_sat(-1).to_string_in(D::NanoBitcoin), D::NanoBitcoin), Ok(sa_sat(-1)));
1672        assert_eq!(sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::NanoBitcoin), Err(ParseAmountError::TooPrecise));
1673        assert_eq!(sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::NanoBitcoin), Err(ParseAmountError::TooPrecise));
1674
1675        assert_eq!(sa_str(&sa_sat(-1).to_string_in(D::PicoBitcoin), D::PicoBitcoin), Ok(sa_sat(-1)));
1676        assert_eq!(sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::PicoBitcoin), Err(ParseAmountError::TooPrecise));
1677        assert_eq!(sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::PicoBitcoin), Err(ParseAmountError::TooPrecise));
1678
1679
1680    }
1681
1682    #[test]
1683    fn to_string_with_denomination_from_str_roundtrip() {
1684        use super::Denomination as D;
1685        let amt = Amount::from_sat(42);
1686        let denom = Amount::to_string_with_denomination;
1687        assert_eq!(Amount::from_str(&denom(amt, D::Bitcoin)), Ok(amt));
1688        assert_eq!(Amount::from_str(&denom(amt, D::MilliBitcoin)), Ok(amt));
1689        assert_eq!(Amount::from_str(&denom(amt, D::MicroBitcoin)), Ok(amt));
1690        assert_eq!(Amount::from_str(&denom(amt, D::Bit)), Ok(amt));
1691        assert_eq!(Amount::from_str(&denom(amt, D::Satoshi)), Ok(amt));
1692        assert_eq!(Amount::from_str(&denom(amt, D::NanoBitcoin)), Ok(amt));
1693        assert_eq!(Amount::from_str(&denom(amt, D::MilliSatoshi)), Ok(amt));
1694        assert_eq!(Amount::from_str(&denom(amt, D::PicoBitcoin)), Ok(amt));
1695
1696        assert_eq!(Amount::from_str("42 satoshi BTC"), Err(ParseAmountError::InvalidFormat));
1697        assert_eq!(SignedAmount::from_str("-42 satoshi BTC"), Err(ParseAmountError::InvalidFormat));
1698    }
1699
1700    #[cfg(feature = "serde")]
1701    #[test]
1702    fn serde_as_sat() {
1703
1704        #[derive(Serialize, Deserialize, PartialEq, Debug)]
1705        struct T {
1706            #[serde(with = "::util::amount::serde::as_sat")]
1707            pub amt: Amount,
1708            #[serde(with = "::util::amount::serde::as_sat")]
1709            pub samt: SignedAmount,
1710        }
1711
1712        serde_test::assert_tokens(
1713            &T {
1714                amt: Amount::from_sat(123456789),
1715                samt: SignedAmount::from_sat(-123456789),
1716            },
1717            &[
1718                serde_test::Token::Struct { name: "T", len: 2 },
1719                serde_test::Token::Str("amt"),
1720                serde_test::Token::U64(123456789),
1721                serde_test::Token::Str("samt"),
1722                serde_test::Token::I64(-123456789),
1723                serde_test::Token::StructEnd,
1724            ],
1725        );
1726    }
1727
1728    #[cfg(feature = "serde")]
1729    #[test]
1730    fn serde_as_btc() {
1731        use serde_json;
1732
1733        #[derive(Serialize, Deserialize, PartialEq, Debug)]
1734        struct T {
1735            #[serde(with = "::util::amount::serde::as_btc")]
1736            pub amt: Amount,
1737            #[serde(with = "::util::amount::serde::as_btc")]
1738            pub samt: SignedAmount,
1739        }
1740
1741        let orig = T {
1742            amt: Amount::from_sat(21_000_000__000_000_01),
1743            samt: SignedAmount::from_sat(-21_000_000__000_000_01),
1744        };
1745
1746        let json = "{\"amt\": 21000000.00000001, \
1747                    \"samt\": -21000000.00000001}";
1748        let t: T = serde_json::from_str(&json).unwrap();
1749        assert_eq!(t, orig);
1750
1751        let value: serde_json::Value = serde_json::from_str(&json).unwrap();
1752        assert_eq!(t, serde_json::from_value(value).unwrap());
1753
1754        // errors
1755        let t: Result<T, serde_json::Error> =
1756            serde_json::from_str("{\"amt\": 1000000.000000001, \"samt\": 1}");
1757        assert!(t.unwrap_err().to_string().contains(&ParseAmountError::TooPrecise.to_string()));
1758        let t: Result<T, serde_json::Error> = serde_json::from_str("{\"amt\": -1, \"samt\": 1}");
1759        assert!(t.unwrap_err().to_string().contains(&ParseAmountError::Negative.to_string()));
1760    }
1761
1762    #[cfg(feature = "serde")]
1763    #[test]
1764    fn serde_as_btc_opt() {
1765        use serde_json;
1766
1767        #[derive(Serialize, Deserialize, PartialEq, Debug, Eq)]
1768        struct T {
1769            #[serde(default, with = "::util::amount::serde::as_btc::opt")]
1770            pub amt: Option<Amount>,
1771            #[serde(default, with = "::util::amount::serde::as_btc::opt")]
1772            pub samt: Option<SignedAmount>,
1773        }
1774
1775        let with = T {
1776            amt: Some(Amount::from_sat(2__500_000_00)),
1777            samt: Some(SignedAmount::from_sat(-2__500_000_00)),
1778        };
1779        let without = T {
1780            amt: None,
1781            samt: None,
1782        };
1783
1784        // Test Roundtripping
1785        for s in [&with, &without].iter() {
1786            let v = serde_json::to_string(s).unwrap();
1787            let w : T = serde_json::from_str(&v).unwrap();
1788            assert_eq!(w, **s);
1789        }
1790
1791        let t: T = serde_json::from_str("{\"amt\": 2.5, \"samt\": -2.5}").unwrap();
1792        assert_eq!(t, with);
1793
1794        let t: T = serde_json::from_str("{}").unwrap();
1795        assert_eq!(t, without);
1796
1797        let value_with: serde_json::Value =
1798            serde_json::from_str("{\"amt\": 2.5, \"samt\": -2.5}").unwrap();
1799        assert_eq!(with, serde_json::from_value(value_with).unwrap());
1800
1801        let value_without: serde_json::Value = serde_json::from_str("{}").unwrap();
1802        assert_eq!(without, serde_json::from_value(value_without).unwrap());
1803    }
1804
1805    #[cfg(feature = "serde")]
1806    #[test]
1807    fn serde_as_sat_opt() {
1808        use serde_json;
1809
1810        #[derive(Serialize, Deserialize, PartialEq, Debug, Eq)]
1811        struct T {
1812            #[serde(default, with = "::util::amount::serde::as_sat::opt")]
1813            pub amt: Option<Amount>,
1814            #[serde(default, with = "::util::amount::serde::as_sat::opt")]
1815            pub samt: Option<SignedAmount>,
1816        }
1817
1818        let with = T {
1819            amt: Some(Amount::from_sat(2__500_000_00)),
1820            samt: Some(SignedAmount::from_sat(-2__500_000_00)),
1821        };
1822        let without = T {
1823            amt: None,
1824            samt: None,
1825        };
1826
1827        // Test Roundtripping
1828        for s in [&with, &without].iter() {
1829            let v = serde_json::to_string(s).unwrap();
1830            let w : T = serde_json::from_str(&v).unwrap();
1831            assert_eq!(w, **s);
1832        }
1833
1834        let t: T = serde_json::from_str("{\"amt\": 250000000, \"samt\": -250000000}").unwrap();
1835        assert_eq!(t, with);
1836
1837        let t: T = serde_json::from_str("{}").unwrap();
1838        assert_eq!(t, without);
1839
1840        let value_with: serde_json::Value =
1841            serde_json::from_str("{\"amt\": 250000000, \"samt\": -250000000}").unwrap();
1842        assert_eq!(with, serde_json::from_value(value_with).unwrap());
1843
1844        let value_without: serde_json::Value = serde_json::from_str("{}").unwrap();
1845        assert_eq!(without, serde_json::from_value(value_without).unwrap());
1846    }
1847
1848    #[test]
1849    fn sum_amounts() {
1850        assert_eq!(Amount::from_sat(0), vec![].into_iter().sum::<Amount>());
1851        assert_eq!(SignedAmount::from_sat(0), vec![].into_iter().sum::<SignedAmount>());
1852
1853        let amounts = vec![
1854            Amount::from_sat(42),
1855            Amount::from_sat(1337),
1856            Amount::from_sat(21)
1857        ];
1858        let sum = amounts.into_iter().sum::<Amount>();
1859        assert_eq!(Amount::from_sat(1400), sum);
1860
1861        let amounts = vec![
1862            SignedAmount::from_sat(-42),
1863            SignedAmount::from_sat(1337),
1864            SignedAmount::from_sat(21)
1865        ];
1866        let sum = amounts.into_iter().sum::<SignedAmount>();
1867        assert_eq!(SignedAmount::from_sat(1316), sum);
1868    }
1869
1870    #[test]
1871    fn checked_sum_amounts() {
1872        assert_eq!(Some(Amount::from_sat(0)), vec![].into_iter().checked_sum());
1873        assert_eq!(Some(SignedAmount::from_sat(0)), vec![].into_iter().checked_sum());
1874
1875        let amounts = vec![
1876            Amount::from_sat(42),
1877            Amount::from_sat(1337),
1878            Amount::from_sat(21)
1879        ];
1880        let sum = amounts.into_iter().checked_sum();
1881        assert_eq!(Some(Amount::from_sat(1400)), sum);
1882
1883        let amounts = vec![
1884            Amount::from_sat(u64::max_value()),
1885            Amount::from_sat(1337),
1886            Amount::from_sat(21)
1887        ];
1888        let sum = amounts.into_iter().checked_sum();
1889        assert_eq!(None, sum);
1890
1891        let amounts = vec![
1892            SignedAmount::from_sat(i64::min_value()),
1893            SignedAmount::from_sat(-1),
1894            SignedAmount::from_sat(21)
1895        ];
1896        let sum = amounts.into_iter().checked_sum();
1897        assert_eq!(None, sum);
1898
1899        let amounts = vec![
1900            SignedAmount::from_sat(i64::max_value()),
1901            SignedAmount::from_sat(1),
1902            SignedAmount::from_sat(21)
1903        ];
1904        let sum = amounts.into_iter().checked_sum();
1905        assert_eq!(None, sum);
1906
1907        let amounts = vec![
1908            SignedAmount::from_sat(42),
1909            SignedAmount::from_sat(3301),
1910            SignedAmount::from_sat(21)
1911        ];
1912        let sum = amounts.into_iter().checked_sum();
1913        assert_eq!(Some(SignedAmount::from_sat(3364)), sum);
1914    }
1915
1916    #[test]
1917    fn denomination_string_acceptable_forms() {
1918        // Non-exhaustive list of valid forms.
1919        let valid = vec!["BTC", "btc", "mBTC", "mbtc", "uBTC", "ubtc", "SATOSHI","Satoshi", "Satoshis", "satoshis", "SAT", "Sat", "sats", "bit", "bits", "nBTC", "pBTC"];
1920        for denom in valid.iter() {
1921            assert!(Denomination::from_str(denom).is_ok());
1922        }
1923    }
1924
1925    #[test]
1926    fn disallow_confusing_forms() {
1927        // Non-exhaustive list of confusing forms.
1928        let confusing = vec!["Msat", "Msats", "MSAT", "MSATS", "MSat", "MSats", "MBTC", "Mbtc", "PBTC"];
1929        for denom in confusing.iter() {
1930            match  Denomination::from_str(denom) {
1931                Ok(_) => panic!("from_str should error for {}", denom),
1932                Err(ParseAmountError::PossiblyConfusingDenomination(_)) => {},
1933                Err(e) => panic!("unexpected error: {}", e),
1934            }
1935        }
1936    }
1937
1938    #[test]
1939    fn disallow_unknown_denomination() {
1940        // Non-exhaustive list of unknown forms.
1941        let unknown = vec!["NBTC", "UBTC", "ABC", "abc"];
1942        for denom in unknown.iter() {
1943            match  Denomination::from_str(denom) {
1944                Ok(_) => panic!("from_str should error for {}", denom),
1945                Err(ParseAmountError::UnknownDenomination(_)) => {},
1946                Err(e) => panic!("unexpected error: {}", e),
1947            }
1948        }
1949    }
1950
1951    #[cfg(all(feature = "serde", feature = "schemars"))]
1952    #[test]
1953    fn coinamount() {
1954        use serde_json;
1955
1956        #[derive(Serialize, Deserialize, Debug, PartialEq, schemars::JsonSchema)]
1957        struct T(Vec<CoinAmount>);
1958
1959        let obj_schem = schemars::schema_for!(T);
1960        let string_schema = serde_json::to_string_pretty(&obj_schem).unwrap();
1961        let schema = serde_json::from_str(&string_schema).unwrap();
1962
1963        let v = T(vec![CoinAmount::Sats(10), CoinAmount::Btc(5.0)]);
1964        let s = "[{\"Sats\":10},{\"Btc\":5.0}]";
1965        assert!(jsonschema_valid::is_valid(
1966            &serde_json::from_str(s).unwrap(),
1967            &schema,
1968            None,
1969            true
1970        ));
1971        let t: T = serde_json::from_str(s).unwrap();
1972        assert_eq!(t, v);
1973        let o = serde_json::to_value(&v).unwrap().to_string();
1974        assert!(jsonschema_valid::is_valid(
1975            &serde_json::from_str(&o).unwrap(),
1976            &schema,
1977            None,
1978            true
1979        ));
1980        assert_eq!(s, o);
1981    }
1982}
1983