Skip to content

Commit 080b517

Browse files
committed
primitives - UnifiedNum - impl num::pow::Pow & to_preicison()
1 parent be47342 commit 080b517

File tree

1 file changed

+81
-5
lines changed

1 file changed

+81
-5
lines changed

primitives/src/unified_num.rs

+81-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use num::{CheckedSub, Integer, One};
1+
use num::{pow::Pow, CheckedSub, Integer, One};
22
use num_derive::{Num, NumOps, Zero};
33
use std::{
4+
cmp::Ordering,
45
fmt,
56
iter::Sum,
67
ops::{Add, AddAssign, Div, Mul, Sub},
@@ -13,7 +14,7 @@ use crate::BigNum;
1314
pub struct UnifiedNum(BigNum);
1415

1516
impl UnifiedNum {
16-
pub const PRECISION: usize = 8;
17+
pub const PRECISION: u8 = 8;
1718

1819
pub fn div_floor(&self, other: &Self) -> Self {
1920
Self(self.0.div_floor(&other.0))
@@ -26,6 +27,17 @@ impl UnifiedNum {
2627
pub fn to_u64(&self) -> Option<u64> {
2728
self.0.to_u64()
2829
}
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+
}
2941
}
3042

3143
impl From<u64> for UnifiedNum {
@@ -44,9 +56,10 @@ impl fmt::Display for UnifiedNum {
4456
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4557
let mut string_value = self.0.to_str_radix(10);
4658
let value_length = string_value.len();
59+
let precision: usize = Self::PRECISION.into();
4760

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, ".");
5063

5164
f.write_str(&string_value)
5265
} else {
@@ -107,6 +120,38 @@ impl Integer for UnifiedNum {
107120
}
108121
}
109122

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+
110155
impl Add<&UnifiedNum> for &UnifiedNum {
111156
type Output = UnifiedNum;
112157

@@ -201,7 +246,7 @@ impl CheckedSub for UnifiedNum {
201246

202247
#[cfg(test)]
203248
mod test {
204-
use crate::UnifiedNum;
249+
use super::*;
205250

206251
#[test]
207252
fn unified_num_displays_correctly() {
@@ -215,4 +260,35 @@ mod test {
215260
assert_eq!("0.00000001", &smallest_value.to_string());
216261
assert_eq!("1449030.00567000", &random_value.to_string());
217262
}
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+
}
218294
}

0 commit comments

Comments
 (0)