use anchor_lang::prelude::*;
use fix::prelude::*;
use fix::typenum::Integer;
use serde::{Deserialize, Serialize};
use crate::error::CoreError::{SlippageArithmetic, SlippageExceeded};
#[derive(Debug, AnchorSerialize, AnchorDeserialize, Serialize, Deserialize)]
pub struct SlippageConfig {
pub expected_token_out: UFixValue64,
pub slippage_tolerance: UFixValue64,
}
impl SlippageConfig {
#[must_use]
pub fn new<Exp: Integer>(
expected_token_out: UFix64<Exp>,
slippage_tolerance: UFix64<N4>,
) -> SlippageConfig {
SlippageConfig {
expected_token_out: expected_token_out.into(),
slippage_tolerance: slippage_tolerance.into(),
}
}
pub fn expected_token_out<Exp: Integer>(&self) -> Result<UFix64<Exp>> {
self.expected_token_out.try_into()
}
pub fn slippage_tolerance(&self) -> Result<UFix64<N4>> {
self.slippage_tolerance.try_into()
}
pub fn validate_token_out<Exp: Integer>(
&self,
token_out: UFix64<Exp>,
) -> Result<()> {
let expected = self.expected_token_out()?;
let tolerance = self.slippage_tolerance()?;
let tolerable_amount = UFix64::<N4>::one()
.checked_sub(&tolerance)
.and_then(|factor| expected.mul_div_floor(factor, UFix64::one()))
.ok_or(SlippageArithmetic)?;
if token_out >= tolerable_amount {
Ok(())
} else {
Err(SlippageExceeded.into())
}
}
}