o2-primitives 0.1.12

Core trading primitives for the Fuel O2 exchange
Documentation
//! Core trading primitives for the Fuel O2 exchange.
//!
//! This crate contains pure types with minimal dependencies,
//! suitable for sharing across the entire O2 stack.

use std::{
    fmt::Display,
    str::FromStr,
};

pub type Price = u64;

/// Determines how the order should be matched in the order book.
#[derive(
    Default, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, Clone, Copy, Hash,
)]
pub enum OrderType {
    Limit(Price, u128),
    #[default]
    Spot,
    FillOrKill,
    PostOnly,
    Market,
    BoundedMarket {
        max_price: Price,
        min_price: Price,
    },
}

impl OrderType {
    pub fn is_market_order(&self) -> bool {
        matches!(self, OrderType::Market | OrderType::BoundedMarket { .. })
    }
}

#[derive(
    Default, Debug, serde::Serialize, serde::Deserialize, Clone, Copy, PartialEq, Eq, Hash,
)]
pub enum Side {
    #[default]
    Sell,
    Buy,
}

impl Display for Side {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Side::Sell => write!(f, "sell"),
            Side::Buy => write!(f, "buy"),
        }
    }
}

impl FromStr for Side {
    type Err = anyhow::Error;

    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        match s {
            "sell" => Ok(Side::Sell),
            "buy" => Ok(Side::Buy),
            s => Err(anyhow::anyhow!("Invalid side: {}", s)),
        }
    }
}

impl<T: AsRef<str>> From<T> for Side {
    fn from(s: T) -> Self {
        if s.as_ref() == "sell" {
            Side::Sell
        } else {
            Side::Buy
        }
    }
}

impl From<Side> for String {
    fn from(s: Side) -> Self {
        if s == Side::Sell {
            "sell".to_string()
        } else {
            "buy".to_string()
        }
    }
}