acta_maker_sdk/types/
decimal.rs1use rust_decimal::Decimal;
4
5use super::PRICE_SCALE;
6use super::ids::{Decimals, Price, Quantity, Strike};
7
8const PRICE_DECIMALS: u32 = 9;
9
10fn scaled(value: u64) -> Decimal {
11 Decimal::from_i128_with_scale(i128::from(value), PRICE_DECIMALS)
12}
13
14fn floor_atoms(value: Decimal, multiplier: Decimal) -> Option<u64> {
16 let atoms = value.checked_mul(multiplier)?.floor();
17 u64::try_from(atoms).ok()
18}
19
20impl Strike {
21 #[must_use]
22 pub fn to_decimal(self) -> Decimal {
23 scaled(self.value())
24 }
25}
26
27impl Price {
28 #[must_use]
29 pub fn to_decimal(self) -> Decimal {
30 scaled(self.value())
31 }
32
33 #[must_use]
35 pub fn from_decimal_floor(value: Decimal) -> Option<Self> {
36 floor_atoms(value, Decimal::from(PRICE_SCALE)).map(Self::new)
37 }
38}
39
40impl Quantity {
41 #[must_use]
43 pub fn to_decimal(self, decimals: Decimals) -> Option<Decimal> {
44 let scale = u32::from(decimals.value());
45 (scale <= Decimal::MAX_SCALE)
46 .then(|| Decimal::from_i128_with_scale(i128::from(self.value()), scale))
47 }
48
49 #[must_use]
51 pub fn from_decimal_floor(units: Decimal, decimals: Decimals) -> Option<Self> {
52 let power = 10i128.checked_pow(u32::from(decimals.value()))?;
53 let multiplier = Decimal::try_from_i128_with_scale(power, 0).ok()?;
54 floor_atoms(units, multiplier).map(Self::new)
55 }
56}
57
58#[cfg(test)]
59#[path = "decimal_tests.rs"]
60mod tests;