use crate::markets::perps::meta::PerpAsset;
use crate::trade::MarginMode;
use crate::utils::Dec;
use crate::utils::{Grid, MINIMUM_ORDER_VALUE, PERP_PRICE_PLACES};
const BOTH: [MarginMode; 2] = [MarginMode::Cross, MarginMode::Isolated];
const ISOLATED: [MarginMode; 1] = [MarginMode::Isolated];
const THOUSAND: Dec = Dec::from_int(1000);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Rules {
pub grid: Grid,
pub size_step: Dec,
pub min_value: Dec,
pub max_leverage: u32,
pub isolated_only: bool,
}
impl Rules {
#[must_use]
pub fn of(perp: &PerpAsset) -> Option<Rules> {
PERP_PRICE_PLACES.checked_sub(perp.sz_decimals)?;
Some(Rules {
grid: perp.grid(),
size_step: Dec::new(1, perp.sz_decimals)?,
min_value: MINIMUM_ORDER_VALUE,
max_leverage: perp.max_leverage,
isolated_only: !perp.allows_cross(),
})
}
#[must_use]
pub const fn margin_modes(&self) -> &'static [MarginMode] {
match self.isolated_only {
true => &ISOLATED,
false => &BOTH,
}
}
}
#[must_use]
pub fn underlying(coin: &str) -> (&str, Dec) {
let bare = coin.split_once(':').map_or(coin, |(_, symbol)| symbol);
match bare.strip_prefix('k') {
Some(rest) if rest.starts_with(|first: char| first.is_ascii_uppercase()) => (rest, THOUSAND),
_ => (bare, Dec::ONE),
}
}