lighter-rust 0.2.0

A comprehensive Rust SDK for the Lighter trading platform with async/await, WebSocket support, and Ethereum wallet integration
#![allow(clippy::too_many_arguments)]
use crate::{
    apis::{self, configuration::Configuration},
    config::LighterConfig,
    models::{
        order::{TimeInForce, Type as OrderType},
        ExchangeStats, ExportData, OrderBookDetails, OrderBookOrders, OrderBooks, Orders, Trades,
    },
    Result,
};

#[derive(Debug, Clone, strum::Display)]
#[strum(serialize_all = "snake_case")]
pub enum ExportType {
    Funding,
    Trade,
}

#[derive(Debug, Clone, strum::Display)]
#[strum(serialize_all = "snake_case")]
pub enum TradesSortBy {
    BlockHeight,
    Timestamp,
    TradeId,
}

#[derive(Debug, Clone, strum::Display)]
#[strum(serialize_all = "snake_case")]
pub enum TradesSortDir {
    Desc,
}

#[allow(clippy::enum_variant_names)]
#[derive(Debug, Clone)]
#[repr(u8)]
pub enum GroupingType {
    OneTriggersOther = 1,
    OneCancelsOther = 2,
    OneTriggersAndOneCancelsOther = 3,
}

impl From<crate::models::order::Type> for u8 {
    fn from(val: crate::models::order::Type) -> Self {
        match val {
            OrderType::Limit => 0,
            OrderType::Market => 1,
            OrderType::StopLoss => 2,
            OrderType::StopLossLimit => 3,
            OrderType::TakeProfit => 4,
            OrderType::TakeProfitLimit => 5,
            OrderType::Twap => 6,
            OrderType::TwapSub => 7,
            OrderType::Liquidation => 8,
        }
    }
}

impl From<crate::models::order::TimeInForce> for u8 {
    fn from(val: crate::models::order::TimeInForce) -> Self {
        match val {
            TimeInForce::ImmediateOrCancel => 0,
            TimeInForce::GoodTillTime => 1,
            TimeInForce::PostOnly => 2,
            TimeInForce::Unknown => 3,
        }
    }
}

#[derive(Debug)]
pub struct OrderApi {
    config: apis::configuration::Configuration,
}

impl OrderApi {
    pub fn new(config: &LighterConfig) -> Result<Self> {
        Ok(Self {
            config: Configuration::try_from(config)?,
        })
    }

    /// Get account active orders. `auth` can be generated using the SDK.
    pub async fn account_active_orders(
        &self,
        account_index: i64,
        market_id: i32,
        authorization: Option<&str>,
        auth: Option<&str>,
    ) -> Result<Orders> {
        let resp = apis::order_api::account_active_orders(
            &self.config,
            account_index,
            market_id,
            authorization,
            auth,
        )
        .await
        .inspect_err(|e| tracing::error!("unable to call `account_active_orders`: {e}"))?;

        Ok(resp)
    }

    /// Get account inactive orders
    pub async fn account_inactive_orders(
        &self,
        account_index: i64,
        limit: i64,
        authorization: Option<&str>,
        auth: Option<&str>,
        market_id: Option<i32>,
        ask_filter: Option<i32>,
        between_timestamps: Option<&str>,
        cursor: Option<&str>,
    ) -> Result<Orders> {
        let resp = apis::order_api::account_inactive_orders(
            &self.config,
            account_index,
            limit,
            authorization,
            auth,
            market_id,
            ask_filter,
            between_timestamps,
            cursor,
        )
        .await
        .inspect_err(|e| tracing::error!("unable to call `account_inactive_orders`: {e}"))?;

        Ok(resp)
    }

    /// Get exchange stats
    pub async fn exchange_stats(&self) -> Result<ExchangeStats> {
        let resp = apis::order_api::exchange_stats(&self.config)
            .await
            .inspect_err(|e| tracing::error!("unable to call `exchange_stats`: {e}"))?;

        Ok(resp)
    }

    /// Export data
    pub async fn export(
        &self,
        export_type: ExportType,
        authorization: Option<&str>,
        auth: Option<&str>,
        account_index: Option<i64>,
        market_id: Option<i32>,
    ) -> Result<ExportData> {
        let resp = apis::order_api::export(
            &self.config,
            &export_type.to_string(),
            authorization,
            auth,
            account_index,
            market_id,
        )
        .await
        .inspect_err(|e| tracing::error!("unable to call `export`: {e}"))?;

        Ok(resp)
    }

    /// Get order books metadata
    pub async fn order_book_details(&self, market_id: Option<i32>) -> Result<OrderBookDetails> {
        let resp = apis::order_api::order_book_details(&self.config, market_id)
            .await
            .inspect_err(|e| tracing::error!("unable to call `order_book_details`: {e}"))?;

        Ok(resp)
    }

    /// Get order book orders
    pub async fn order_book_orders(&self, market_id: i32, limit: i64) -> Result<OrderBookOrders> {
        let resp = apis::order_api::order_book_orders(&self.config, market_id, limit)
            .await
            .inspect_err(|e| tracing::error!("unable to call `order_book_orders`: {e}"))?;

        Ok(resp)
    }

    /// Get order books metadata.<hr>**Response Description:**<br><br>1) **Taker and maker fees** are in percentage.<br>2) **Min base amount:** The amount of base token that can be traded in a single order.<br>3) **Min quote amount:** The amount of quote token that can be traded in a single order.<br>4) **Supported size decimals:** The number of decimal places that can be used for the size of the order.<br>5) **Supported price decimals:** The number of decimal places that can be used for the price of the order.<br>6) **Supported quote decimals:** Size Decimals + Quote Decimals.
    pub async fn order_books(&self, market_id: Option<i32>) -> Result<OrderBooks> {
        let resp = apis::order_api::order_books(&self.config, market_id)
            .await
            .inspect_err(|e| tracing::error!("unable to call `order_books`: {e}"))?;

        Ok(resp)
    }

    /// Get recent trades
    pub async fn recent_trades(&self, market_id: i32, limit: i64) -> Result<Trades> {
        let resp = apis::order_api::recent_trades(&self.config, market_id, limit)
            .await
            .inspect_err(|e| tracing::error!("unable to call `recent_trades`: {e}"))?;

        Ok(resp)
    }

    /// Get trades
    pub async fn trades(
        &self,
        sort_by: TradesSortBy,
        limit: i64,
        authorization: Option<&str>,
        auth: Option<&str>,
        market_id: Option<i32>,
        account_index: Option<i64>,
        order_index: Option<i64>,
        sort_dir: Option<TradesSortDir>,
        cursor: Option<&str>,
        from: Option<i64>,
        ask_filter: Option<i32>,
    ) -> Result<Trades> {
        let resp = apis::order_api::trades(
            &self.config,
            &sort_by.to_string(),
            limit,
            authorization,
            auth,
            market_id,
            account_index,
            order_index,
            sort_dir.map(|v| v.to_string()).as_deref(),
            cursor,
            from,
            ask_filter,
        )
        .await
        .inspect_err(|e| tracing::error!("unable to call `trades`: {e}"))?;

        Ok(resp)
    }
}