converter/
lib.rs

1//! Saber swap math helpers for $CASH
2#![deny(missing_docs)]
3#![deny(rustdoc::all)]
4#![allow(rustdoc::missing_doc_code_examples)]
5#![deny(clippy::integer_arithmetic)]
6
7use std::cmp::Ordering;
8
9/// Number of decimals of $CASH.
10pub const CASH_DECIMALS: u8 = 6;
11
12pub use stable_swap_math::price::SaberSwap;
13
14/// A Saber swap and number of decimals.
15#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
16pub struct CashSwap {
17    /// Decimals of the LP mint.
18    /// This is used for $CASH conversion.
19    pub lp_mint_decimals: u8,
20    /// Saber.
21    pub saber: SaberSwap,
22}
23
24impl CashSwap {
25    /// Calculates the virtual price of the given amount of pool tokens.
26    pub fn calculate_cash_for_pool_tokens(&self, pool_token_amount: u64) -> Option<u64> {
27        self.scale_lp_to_cash_decimals(
28            self.saber
29                .calculate_virtual_price_of_pool_tokens(pool_token_amount)?,
30        )
31    }
32
33    /// Calculates the virtual price of the given amount of pool tokens.
34    pub fn calculate_pool_tokens_for_cash(&self, cash_amount: u64) -> Option<u64> {
35        self.saber
36            .calculate_pool_tokens_from_virtual_amount(self.scale_cash_to_lp_decimals(cash_amount)?)
37    }
38
39    fn scale_lp_to_cash_decimals(&self, amount: u64) -> Option<u64> {
40        match CASH_DECIMALS.cmp(&self.lp_mint_decimals) {
41            Ordering::Equal => amount.into(),
42            Ordering::Less => amount.checked_mul(
43                10u64.checked_pow(self.lp_mint_decimals.checked_sub(CASH_DECIMALS)?.into())?,
44            ),
45            Ordering::Greater => amount.checked_div(
46                10u64.checked_pow(CASH_DECIMALS.checked_sub(self.lp_mint_decimals)?.into())?,
47            ),
48        }
49    }
50
51    fn scale_cash_to_lp_decimals(&self, amount: u64) -> Option<u64> {
52        match CASH_DECIMALS.cmp(&self.lp_mint_decimals) {
53            Ordering::Equal => amount.into(),
54            Ordering::Less => amount.checked_div(
55                10u64.checked_pow(self.lp_mint_decimals.checked_sub(CASH_DECIMALS)?.into())?,
56            ),
57            Ordering::Greater => amount.checked_mul(
58                10u64.checked_pow(CASH_DECIMALS.checked_sub(self.lp_mint_decimals)?.into())?,
59            ),
60        }
61    }
62}