near_token/trait_impls/
display.rs

1use crate::{NearToken, ONE_MILLINEAR};
2
3/// NearToken Display implementation rounds up the token amount to the relevant precision point.
4/// There are 4 breakpoints:
5/// 1. exactly 0 NEAR
6/// 2. <0.001 NEAR
7/// 3. 0.001 - 0.999 NEAR (uses 3 digits after the floating point)
8/// 4. >1 NEAR (uses 2 digits after the floating point)
9impl std::fmt::Display for NearToken {
10    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11        if *self == NearToken::from_yoctonear(0) {
12            write!(f, "0 NEAR")
13        } else if *self < NearToken::from_millinear(1) {
14            write!(f, "<0.001 NEAR")
15        } else if *self <= NearToken::from_millinear(999) {
16            let millinear_rounded_up =
17                self.as_yoctonear().saturating_add(ONE_MILLINEAR - 1) / ONE_MILLINEAR;
18            write!(f, "0.{:03} NEAR", millinear_rounded_up)
19        } else {
20            let near_rounded_up =
21                self.as_yoctonear().saturating_add(10 * ONE_MILLINEAR - 1) / ONE_MILLINEAR / 10;
22            write!(
23                f,
24                "{}.{:02} NEAR",
25                near_rounded_up / 100,
26                near_rounded_up % 100
27            )
28        }
29    }
30}
31
32#[cfg(test)]
33mod test {
34    use crate::NearToken;
35
36    #[test]
37    fn test_display() {
38        for (near_tokens, expected_display) in [
39            (NearToken::from_yoctonear(0), "0 NEAR"),
40            (NearToken::from_yoctonear(1), "<0.001 NEAR"),
41            (NearToken::from_yoctonear(10u128.pow(21) - 1), "<0.001 NEAR"),
42            (NearToken::from_yoctonear(10u128.pow(21)), "0.001 NEAR"),
43            (NearToken::from_yoctonear(10u128.pow(21) + 1), "0.002 NEAR"),
44            (NearToken::from_yoctonear(10u128.pow(21) * 2), "0.002 NEAR"),
45            (
46                NearToken::from_yoctonear(10u128.pow(21) * 200),
47                "0.200 NEAR",
48            ),
49            (
50                NearToken::from_yoctonear(10u128.pow(21) * 999),
51                "0.999 NEAR",
52            ),
53            (
54                NearToken::from_yoctonear(10u128.pow(21) * 999 + 1),
55                "1.00 NEAR",
56            ),
57            (NearToken::from_yoctonear(10u128.pow(24) - 1), "1.00 NEAR"),
58            (NearToken::from_yoctonear(10u128.pow(24)), "1.00 NEAR"),
59            (NearToken::from_yoctonear(10u128.pow(24) + 1), "1.01 NEAR"),
60            (
61                NearToken::from_yoctonear(10u128.pow(21) * 1234),
62                "1.24 NEAR",
63            ),
64            (
65                NearToken::from_yoctonear(10u128.pow(21) * 1500),
66                "1.50 NEAR",
67            ),
68            (
69                NearToken::from_yoctonear(10u128.pow(21) * 10000),
70                "10.00 NEAR",
71            ),
72            (
73                NearToken::from_yoctonear(10u128.pow(21) * 10500),
74                "10.50 NEAR",
75            ),
76            (
77                NearToken::from_yoctonear(10u128.pow(21) * 100000 - 1),
78                "100.00 NEAR",
79            ),
80            (
81                NearToken::from_yoctonear(10u128.pow(21) * 100000),
82                "100.00 NEAR",
83            ),
84            (
85                NearToken::from_yoctonear(10u128.pow(21) * 100500),
86                "100.50 NEAR",
87            ),
88            (
89                NearToken::from_yoctonear(10u128.pow(21) * 100000000),
90                "100000.00 NEAR",
91            ),
92            (
93                NearToken::from_yoctonear(10u128.pow(21) * 100000500),
94                "100000.50 NEAR",
95            ),
96        ] {
97            assert_eq!(
98                near_tokens.to_string(),
99                expected_display,
100                "tokens: {}",
101                near_tokens.as_yoctonear()
102            );
103        }
104    }
105}