use crate::utils::sign::BadTx;
use crate::utils::{BadUnits, Dec};
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum TradeError {
#[error("{field}: {error}")]
Units { field: &'static str, error: BadUnits },
#[error("{0} needs a positive price")]
NoPrice(&'static str),
#[error("{0} basis points of slippage is more than the 1000 allowed")]
Slippage(u32),
#[error("the worst price {worst} is more than 10% from the reference {reference}")]
TooFar { worst: Dec, reference: Dec },
#[error("{what} is between {least_ms} and {most_ms} ms ahead; {at} is not (now {now})")]
Expiry { field: &'static str, what: &'static str, at: u64, now: u64, least_ms: u64, most_ms: u64 },
#[error("{0}")]
NotFor(&'static str),
#[error("{size} is below the market's least size {least}")]
BelowLeastSize { size: Dec, least: Dec },
#[error("{value} is below the market's least order value {least}")]
BelowLeastValue { value: Dec, least: Dec },
#[error("leverage is 1x or more")]
NoLeverage,
#[error("the most leverage on this market is {most}x, not {asked}x")]
Leverage { asked: u16, most: u16 },
#[error("this market trades isolated margin only")]
IsolatedOnly,
#[error(transparent)]
Bad(#[from] BadTx),
}
impl TradeError {
#[must_use]
pub const fn field(&self) -> &'static str {
match self {
TradeError::Units { field, .. } => field,
TradeError::NoPrice(_) | TradeError::Slippage(_) | TradeError::TooFar { .. } => "Price",
TradeError::Expiry { field, .. } => field,
TradeError::NotFor(_) => "Type",
TradeError::BelowLeastSize { .. } | TradeError::BelowLeastValue { .. } => "BaseAmount",
TradeError::NoLeverage | TradeError::Leverage { .. } => "InitialMarginFraction",
TradeError::IsolatedOnly => "MarginMode",
TradeError::Bad(bad) => bad.field,
}
}
}
impl From<TradeError> for BadTx {
fn from(error: TradeError) -> BadTx {
match error {
TradeError::Bad(bad) => bad,
other => BadTx::new(other.field(), other.to_string()),
}
}
}
pub(crate) fn units<T>(field: &'static str, converted: Result<T, BadUnits>) -> Result<T, TradeError> {
converted.map_err(|error| TradeError::Units { field, error })
}