1pub mod decimal;
3
4pub mod feed_price;
6
7pub use self::{
8 decimal::{Decimal, DecimalError},
9 feed_price::PriceFeedPrice,
10};
11use anchor_lang::prelude::*;
12
13pub use ruint::aliases::U192;
14
15pub const TEN: U192 = U192::from_limbs([10, 0, 0]);
17
18pub const MAX_PRICE_FLAG: usize = 8;
20
21pub const MAX_ORACLE_PRICE_FLAG: usize = 8;
23
24#[derive(Debug, AnchorSerialize, AnchorDeserialize, Clone, Copy, InitSpace)]
26pub struct Price {
27 pub min: Decimal,
29 pub max: Decimal,
31}
32
33fn get_power_bounds() -> &'static [U192; 20] {
34 const BOUNDS: [U192; 20] = [
35 U192::from_limbs([18446744073709551615, 18446744073709551615, 0]),
36 U192::from_limbs([18446744073709551606, 18446744073709551615, 9]),
37 U192::from_limbs([18446744073709551516, 18446744073709551615, 99]),
38 U192::from_limbs([18446744073709550616, 18446744073709551615, 999]),
39 U192::from_limbs([18446744073709541616, 18446744073709551615, 9999]),
40 U192::from_limbs([18446744073709451616, 18446744073709551615, 99999]),
41 U192::from_limbs([18446744073708551616, 18446744073709551615, 999999]),
42 U192::from_limbs([18446744073699551616, 18446744073709551615, 9999999]),
43 U192::from_limbs([18446744073609551616, 18446744073709551615, 99999999]),
44 U192::from_limbs([18446744072709551616, 18446744073709551615, 999999999]),
45 U192::from_limbs([18446744063709551616, 18446744073709551615, 9999999999]),
46 U192::from_limbs([18446743973709551616, 18446744073709551615, 99999999999]),
47 U192::from_limbs([18446743073709551616, 18446744073709551615, 999999999999]),
48 U192::from_limbs([18446734073709551616, 18446744073709551615, 9999999999999]),
49 U192::from_limbs([18446644073709551616, 18446744073709551615, 99999999999999]),
50 U192::from_limbs([18445744073709551616, 18446744073709551615, 999999999999999]),
51 U192::from_limbs([18436744073709551616, 18446744073709551615, 9999999999999999]),
52 U192::from_limbs([
53 18346744073709551616,
54 18446744073709551615,
55 99999999999999999,
56 ]),
57 U192::from_limbs([
58 17446744073709551616,
59 18446744073709551615,
60 999999999999999999,
61 ]),
62 U192::from_limbs([
63 8446744073709551616,
64 18446744073709551615,
65 9999999999999999999,
66 ]),
67 ];
68
69 &BOUNDS
70}
71
72pub fn find_divisor_decimals(num: &U192) -> u8 {
75 let bounds = get_power_bounds();
76
77 match bounds.binary_search(num) {
78 Ok(idx) | Err(idx) => idx as u8,
79 }
80}
81
82pub fn convert_to_u128_storage(mut num: U192, decimals: u8) -> Option<(u128, u8)> {
84 let divisor_decimals = find_divisor_decimals(&num);
85
86 if divisor_decimals > decimals {
87 return None;
88 }
89
90 num /= TEN.pow(U192::from(divisor_decimals));
91
92 Some((num.try_into().unwrap(), decimals - divisor_decimals))
93}
94
95#[repr(u8)]
97#[non_exhaustive]
98#[derive(num_enum::IntoPrimitive, num_enum::TryFromPrimitive)]
99pub enum PriceFlag {
100 Open,
102 LastUpdateDiffEnabled,
104 LastUpdateDiffSecs,
107 }
109
110#[repr(u8)]
112#[non_exhaustive]
113#[derive(num_enum::IntoPrimitive, num_enum::TryFromPrimitive)]
114pub enum OraclePriceFlag {
115 Synthetic,
117 Open,
119 }
121
122crate::flags!(OraclePriceFlag, MAX_ORACLE_PRICE_FLAG, u8);
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn test_bounds() {
130 let bounds = get_power_bounds();
131
132 assert_eq!(bounds.len(), 20);
133 assert_eq!(u128::try_from(bounds[0]).unwrap(), u128::MAX);
134 assert!(bounds[19].checked_mul(U192::from(10)).is_none());
135
136 assert_eq!(find_divisor_decimals(&U192::from(u128::MAX)), 0);
137 assert_eq!(find_divisor_decimals(&U192::MAX), 20);
138 }
139
140 #[test]
141 fn test_convert_to_u128_storage() {
142 assert_eq!(
143 convert_to_u128_storage(U192::from(u128::MAX), 18),
144 Some((u128::MAX, 18))
145 );
146
147 assert_eq!(
148 convert_to_u128_storage(U192::from(u128::MAX) + U192::from(1), 18),
149 Some((34028236692093846346337460743176821145, 17))
150 );
151
152 assert_eq!(
153 convert_to_u128_storage(U192::MAX, 20),
154 Some((62771017353866807638357894232076664161, 0))
155 );
156
157 assert_eq!(
158 convert_to_u128_storage(
159 U192::from(u128::MAX)
160 .checked_mul(U192::from(10).pow(U192::from(19)))
161 .unwrap()
162 - U192::from(11),
163 20
164 ),
165 Some((340282366920938463463374607431768211454, 1))
166 );
167 assert_eq!(
168 convert_to_u128_storage(
169 U192::from(u128::MAX)
170 .checked_mul(U192::from(10).pow(U192::from(19)))
171 .unwrap()
172 + U192::from(1),
173 20
174 ),
175 Some((34028236692093846346337460743176821145, 0))
176 );
177
178 assert_eq!(
179 convert_to_u128_storage(
180 U192::from(u128::MAX)
181 .checked_mul(U192::from(10).pow(U192::from(18)))
182 .unwrap(),
183 18
184 ),
185 Some((340282366920938463463374607431768211455, 0))
186 );
187 }
188}