1
- use num:: { CheckedSub , Integer , One } ;
1
+ use num:: { pow :: Pow , CheckedSub , Integer , One } ;
2
2
use num_derive:: { Num , NumOps , Zero } ;
3
3
use std:: {
4
+ cmp:: Ordering ,
4
5
fmt,
5
6
iter:: Sum ,
6
7
ops:: { Add , AddAssign , Div , Mul , Sub } ,
@@ -13,7 +14,7 @@ use crate::BigNum;
13
14
pub struct UnifiedNum ( BigNum ) ;
14
15
15
16
impl UnifiedNum {
16
- pub const PRECISION : usize = 8 ;
17
+ pub const PRECISION : u8 = 8 ;
17
18
18
19
pub fn div_floor ( & self , other : & Self ) -> Self {
19
20
Self ( self . 0 . div_floor ( & other. 0 ) )
@@ -26,6 +27,17 @@ impl UnifiedNum {
26
27
pub fn to_u64 ( & self ) -> Option < u64 > {
27
28
self . 0 . to_u64 ( )
28
29
}
30
+
31
+ /// Transform the UnifiedNum precision 8 to a new precision
32
+ pub fn to_precision ( & self , precision : u8 ) -> BigNum {
33
+ match precision. cmp ( & Self :: PRECISION ) {
34
+ Ordering :: Equal => self . 0 . clone ( ) ,
35
+ Ordering :: Less => self
36
+ . 0
37
+ . div_floor ( & BigNum :: from ( 10 ) . pow ( Self :: PRECISION - precision) ) ,
38
+ Ordering :: Greater => ( & self . 0 ) . mul ( & BigNum :: from ( 10 ) . pow ( precision - Self :: PRECISION ) ) ,
39
+ }
40
+ }
29
41
}
30
42
31
43
impl From < u64 > for UnifiedNum {
@@ -44,9 +56,10 @@ impl fmt::Display for UnifiedNum {
44
56
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
45
57
let mut string_value = self . 0 . to_str_radix ( 10 ) ;
46
58
let value_length = string_value. len ( ) ;
59
+ let precision: usize = Self :: PRECISION . into ( ) ;
47
60
48
- if value_length > Self :: PRECISION {
49
- string_value. insert_str ( value_length - Self :: PRECISION , "." ) ;
61
+ if value_length > precision {
62
+ string_value. insert_str ( value_length - precision , "." ) ;
50
63
51
64
f. write_str ( & string_value)
52
65
} else {
@@ -107,6 +120,38 @@ impl Integer for UnifiedNum {
107
120
}
108
121
}
109
122
123
+ impl Pow < UnifiedNum > for UnifiedNum {
124
+ type Output = UnifiedNum ;
125
+
126
+ fn pow ( self , rhs : UnifiedNum ) -> Self :: Output {
127
+ Self ( self . 0 . pow ( rhs. 0 ) )
128
+ }
129
+ }
130
+
131
+ impl Pow < & UnifiedNum > for UnifiedNum {
132
+ type Output = UnifiedNum ;
133
+
134
+ fn pow ( self , rhs : & UnifiedNum ) -> Self :: Output {
135
+ UnifiedNum ( self . 0 . pow ( & rhs. 0 ) )
136
+ }
137
+ }
138
+
139
+ impl Pow < UnifiedNum > for & UnifiedNum {
140
+ type Output = UnifiedNum ;
141
+
142
+ fn pow ( self , rhs : UnifiedNum ) -> Self :: Output {
143
+ UnifiedNum ( ( & self . 0 ) . pow ( rhs. 0 ) )
144
+ }
145
+ }
146
+
147
+ impl Pow < & UnifiedNum > for & UnifiedNum {
148
+ type Output = UnifiedNum ;
149
+
150
+ fn pow ( self , rhs : & UnifiedNum ) -> Self :: Output {
151
+ UnifiedNum ( ( & self . 0 ) . pow ( & rhs. 0 ) )
152
+ }
153
+ }
154
+
110
155
impl Add < & UnifiedNum > for & UnifiedNum {
111
156
type Output = UnifiedNum ;
112
157
@@ -201,7 +246,7 @@ impl CheckedSub for UnifiedNum {
201
246
202
247
#[ cfg( test) ]
203
248
mod test {
204
- use crate :: UnifiedNum ;
249
+ use super :: * ;
205
250
206
251
#[ test]
207
252
fn unified_num_displays_correctly ( ) {
@@ -215,4 +260,35 @@ mod test {
215
260
assert_eq ! ( "0.00000001" , & smallest_value. to_string( ) ) ;
216
261
assert_eq ! ( "1449030.00567000" , & random_value. to_string( ) ) ;
217
262
}
263
+
264
+ #[ test]
265
+ fn test_convert_unified_num_to_new_precision ( ) {
266
+ let dai_precision: u8 = 18 ;
267
+ let usdt_precision: u8 = 6 ;
268
+ let same_precision = UnifiedNum :: PRECISION ;
269
+
270
+ let dai_power = BigNum :: from ( 10 ) . pow ( BigNum :: from ( dai_precision as u64 ) ) ;
271
+
272
+ // 321.00000000
273
+ let dai_unified = UnifiedNum :: from ( 32_100_000_000_u64 ) ;
274
+ let dai_expected = BigNum :: from ( 321_u64 ) * dai_power;
275
+ assert_eq ! ( dai_expected, dai_unified. to_precision( dai_precision) ) ;
276
+
277
+ // 321.00000777 - should floor to 321.000007 (precision 6)
278
+ let usdt_unified = UnifiedNum :: from ( 32_100_000_777_u64 ) ;
279
+ let usdt_expected = BigNum :: from ( 321_000_007_u64 ) ;
280
+ assert_eq ! (
281
+ usdt_expected,
282
+ usdt_unified. to_precision( usdt_precision) ,
283
+ "It should floor the result of USDT"
284
+ ) ;
285
+
286
+ // 321.00000999
287
+ let same_unified = UnifiedNum :: from ( 32_100_000_777_u64 ) ;
288
+ assert_eq ! (
289
+ same_unified. 0 ,
290
+ same_unified. to_precision( same_precision) ,
291
+ "It should not make any adjustments to the precision"
292
+ ) ;
293
+ }
218
294
}
0 commit comments