1pub mod decimal;
3
4pub use self::decimal::{Decimal, DecimalError};
5use anchor_lang::prelude::*;
6
7pub use ruint::aliases::U192;
8
9pub const TEN: U192 = U192::from_limbs([10, 0, 0]);
11
12#[derive(Debug, AnchorSerialize, AnchorDeserialize, Clone, Copy, InitSpace)]
14pub struct Price {
15 pub min: Decimal,
17 pub max: Decimal,
19}
20
21fn get_power_bounds() -> &'static [U192; 20] {
22 const BOUNDS: [U192; 20] = [
23 U192::from_limbs([18446744073709551615, 18446744073709551615, 0]),
24 U192::from_limbs([18446744073709551606, 18446744073709551615, 9]),
25 U192::from_limbs([18446744073709551516, 18446744073709551615, 99]),
26 U192::from_limbs([18446744073709550616, 18446744073709551615, 999]),
27 U192::from_limbs([18446744073709541616, 18446744073709551615, 9999]),
28 U192::from_limbs([18446744073709451616, 18446744073709551615, 99999]),
29 U192::from_limbs([18446744073708551616, 18446744073709551615, 999999]),
30 U192::from_limbs([18446744073699551616, 18446744073709551615, 9999999]),
31 U192::from_limbs([18446744073609551616, 18446744073709551615, 99999999]),
32 U192::from_limbs([18446744072709551616, 18446744073709551615, 999999999]),
33 U192::from_limbs([18446744063709551616, 18446744073709551615, 9999999999]),
34 U192::from_limbs([18446743973709551616, 18446744073709551615, 99999999999]),
35 U192::from_limbs([18446743073709551616, 18446744073709551615, 999999999999]),
36 U192::from_limbs([18446734073709551616, 18446744073709551615, 9999999999999]),
37 U192::from_limbs([18446644073709551616, 18446744073709551615, 99999999999999]),
38 U192::from_limbs([18445744073709551616, 18446744073709551615, 999999999999999]),
39 U192::from_limbs([18436744073709551616, 18446744073709551615, 9999999999999999]),
40 U192::from_limbs([
41 18346744073709551616,
42 18446744073709551615,
43 99999999999999999,
44 ]),
45 U192::from_limbs([
46 17446744073709551616,
47 18446744073709551615,
48 999999999999999999,
49 ]),
50 U192::from_limbs([
51 8446744073709551616,
52 18446744073709551615,
53 9999999999999999999,
54 ]),
55 ];
56
57 &BOUNDS
58}
59
60pub fn find_divisor_decimals(num: &U192) -> u8 {
63 let bounds = get_power_bounds();
64
65 match bounds.binary_search(num) {
66 Ok(idx) | Err(idx) => idx as u8,
67 }
68}
69
70pub fn convert_to_u128_storage(mut num: U192, decimals: u8) -> Option<(u128, u8)> {
72 let divisor_decimals = find_divisor_decimals(&num);
73
74 if divisor_decimals > decimals {
75 return None;
76 }
77
78 num /= TEN.pow(U192::from(divisor_decimals));
79
80 Some((num.try_into().unwrap(), decimals - divisor_decimals))
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn test_bounds() {
89 let bounds = get_power_bounds();
90
91 assert_eq!(bounds.len(), 20);
92 assert_eq!(u128::try_from(bounds[0]).unwrap(), u128::MAX);
93 assert!(bounds[19].checked_mul(U192::from(10)).is_none());
94
95 assert_eq!(find_divisor_decimals(&U192::from(u128::MAX)), 0);
96 assert_eq!(find_divisor_decimals(&U192::MAX), 20);
97 }
98
99 #[test]
100 fn test_convert_to_u128_storage() {
101 assert_eq!(
102 convert_to_u128_storage(U192::from(u128::MAX), 18),
103 Some((u128::MAX, 18))
104 );
105
106 assert_eq!(
107 convert_to_u128_storage(U192::from(u128::MAX) + U192::from(1), 18),
108 Some((34028236692093846346337460743176821145, 17))
109 );
110
111 assert_eq!(
112 convert_to_u128_storage(U192::MAX, 20),
113 Some((62771017353866807638357894232076664161, 0))
114 );
115
116 assert_eq!(
117 convert_to_u128_storage(
118 U192::from(u128::MAX)
119 .checked_mul(U192::from(10).pow(U192::from(19)))
120 .unwrap()
121 - U192::from(11),
122 20
123 ),
124 Some((340282366920938463463374607431768211454, 1))
125 );
126 assert_eq!(
127 convert_to_u128_storage(
128 U192::from(u128::MAX)
129 .checked_mul(U192::from(10).pow(U192::from(19)))
130 .unwrap()
131 + U192::from(1),
132 20
133 ),
134 Some((34028236692093846346337460743176821145, 0))
135 );
136
137 assert_eq!(
138 convert_to_u128_storage(
139 U192::from(u128::MAX)
140 .checked_mul(U192::from(10).pow(U192::from(18)))
141 .unwrap(),
142 18
143 ),
144 Some((340282366920938463463374607431768211455, 0))
145 );
146 }
147}