crypto_exc_all 0.1.1

Unified cryptocurrency exchange SDK facade
Documentation
use crate::adapters::ExchangeClient;
use crate::error::Result;
use crate::exchange::ExchangeId;
use crate::instrument::Instrument;
use crate::margin::MarginMode;
use serde::{Deserialize, Serialize};
use serde_json::Value;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Balance {
    pub exchange: ExchangeId,
    pub asset: String,
    pub total: String,
    pub available: String,
    pub frozen: Option<String>,
    pub raw: Value,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SetLeverageRequest {
    pub instrument: Instrument,
    pub leverage: String,
    pub margin_mode: Option<MarginMode>,
    pub margin_coin: Option<String>,
    pub position_side: Option<String>,
}

impl SetLeverageRequest {
    pub fn new(instrument: Instrument, leverage: impl Into<String>) -> Self {
        Self {
            instrument,
            leverage: leverage.into(),
            margin_mode: None,
            margin_coin: None,
            position_side: None,
        }
    }

    pub fn with_margin_mode(mut self, value: impl Into<MarginMode>) -> Self {
        self.margin_mode = Some(value.into());
        self
    }

    pub fn with_margin_coin(mut self, value: impl Into<String>) -> Self {
        self.margin_coin = Some(value.into());
        self
    }

    pub fn with_position_side(mut self, value: impl Into<String>) -> Self {
        self.position_side = Some(value.into());
        self
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct LeverageSetting {
    pub exchange: ExchangeId,
    pub instrument: Instrument,
    pub exchange_symbol: String,
    pub leverage: String,
    pub margin_mode: Option<String>,
    pub margin_coin: Option<String>,
    pub position_side: Option<String>,
    pub raw: Value,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub struct AccountCapabilities {
    pub set_leverage: bool,
    pub set_position_mode: bool,
    pub set_symbol_margin_mode: bool,
    pub order_level_margin_mode: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SetSymbolMarginModeRequest {
    pub instrument: Instrument,
    pub mode: MarginMode,
    pub product_type: Option<String>,
    pub margin_coin: Option<String>,
}

impl SetSymbolMarginModeRequest {
    pub fn new(instrument: Instrument, mode: MarginMode) -> Self {
        Self {
            instrument,
            mode,
            product_type: None,
            margin_coin: None,
        }
    }

    pub fn with_product_type(mut self, value: impl Into<String>) -> Self {
        self.product_type = Some(value.into());
        self
    }

    pub fn with_margin_coin(mut self, value: impl Into<String>) -> Self {
        self.margin_coin = Some(value.into());
        self
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct SymbolMarginModeSetting {
    pub exchange: ExchangeId,
    pub instrument: Instrument,
    pub exchange_symbol: String,
    pub mode: MarginMode,
    pub raw_mode: Option<String>,
    pub product_type: Option<String>,
    pub margin_coin: Option<String>,
    pub raw: Value,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum MarginModeApplyMethod {
    SymbolConfiguration,
    OrderLevel,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct EnsureOrderMarginModeRequest {
    pub instrument: Instrument,
    pub mode: MarginMode,
    pub product_type: Option<String>,
    pub margin_coin: Option<String>,
}

impl EnsureOrderMarginModeRequest {
    pub fn new(instrument: Instrument, mode: MarginMode) -> Self {
        Self {
            instrument,
            mode,
            product_type: None,
            margin_coin: None,
        }
    }

    pub fn with_product_type(mut self, value: impl Into<String>) -> Self {
        self.product_type = Some(value.into());
        self
    }

    pub fn with_margin_coin(mut self, value: impl Into<String>) -> Self {
        self.margin_coin = Some(value.into());
        self
    }

    pub(crate) fn into_set_symbol_request(self) -> SetSymbolMarginModeRequest {
        SetSymbolMarginModeRequest {
            instrument: self.instrument,
            mode: self.mode,
            product_type: self.product_type,
            margin_coin: self.margin_coin,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct EnsureOrderMarginModeResult {
    pub exchange: ExchangeId,
    pub instrument: Instrument,
    pub exchange_symbol: String,
    pub mode: MarginMode,
    pub apply_method: MarginModeApplyMethod,
    pub raw_mode: Option<String>,
    pub product_type: Option<String>,
    pub margin_coin: Option<String>,
    pub raw: Value,
}

impl EnsureOrderMarginModeResult {
    pub(crate) fn from_symbol_setting(setting: SymbolMarginModeSetting) -> Self {
        Self {
            exchange: setting.exchange,
            instrument: setting.instrument,
            exchange_symbol: setting.exchange_symbol,
            mode: setting.mode,
            apply_method: MarginModeApplyMethod::SymbolConfiguration,
            raw_mode: setting.raw_mode,
            product_type: setting.product_type,
            margin_coin: setting.margin_coin,
            raw: setting.raw,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct PrepareOrderSettingsRequest {
    pub instrument: Instrument,
    pub margin_mode: Option<MarginMode>,
    pub leverage: Option<String>,
    pub position_mode: Option<PositionMode>,
    pub product_type: Option<String>,
    pub margin_coin: Option<String>,
    pub position_side: Option<String>,
}

impl PrepareOrderSettingsRequest {
    pub fn new(instrument: Instrument) -> Self {
        Self {
            instrument,
            margin_mode: None,
            leverage: None,
            position_mode: None,
            product_type: None,
            margin_coin: None,
            position_side: None,
        }
    }

    pub fn with_margin_mode(mut self, value: impl Into<MarginMode>) -> Self {
        self.margin_mode = Some(value.into());
        self
    }

    pub fn with_leverage(mut self, value: impl Into<String>) -> Self {
        self.leverage = Some(value.into());
        self
    }

    pub fn with_position_mode(mut self, value: PositionMode) -> Self {
        self.position_mode = Some(value);
        self
    }

    pub fn with_product_type(mut self, value: impl Into<String>) -> Self {
        self.product_type = Some(value.into());
        self
    }

    pub fn with_margin_coin(mut self, value: impl Into<String>) -> Self {
        self.margin_coin = Some(value.into());
        self
    }

    pub fn with_position_side(mut self, value: impl Into<String>) -> Self {
        self.position_side = Some(value.into());
        self
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PrepareOrderSettingsResult {
    pub exchange: ExchangeId,
    pub instrument: Instrument,
    pub exchange_symbol: String,
    pub position_mode: Option<PositionModeSetting>,
    pub margin_mode: Option<EnsureOrderMarginModeResult>,
    pub leverage: Option<LeverageSetting>,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum PositionMode {
    OneWay,
    Hedge,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SetPositionModeRequest {
    pub mode: PositionMode,
    pub product_type: Option<String>,
}

impl SetPositionModeRequest {
    pub fn new(mode: PositionMode) -> Self {
        Self {
            mode,
            product_type: None,
        }
    }

    pub fn with_product_type(mut self, value: impl Into<String>) -> Self {
        self.product_type = Some(value.into());
        self
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PositionModeSetting {
    pub exchange: ExchangeId,
    pub mode: PositionMode,
    pub raw_mode: Option<String>,
    pub product_type: Option<String>,
    pub raw: Value,
}

pub struct AccountFacade<'a> {
    pub(crate) client: &'a ExchangeClient,
}

impl<'a> AccountFacade<'a> {
    pub(crate) fn new(client: &'a ExchangeClient) -> Self {
        Self { client }
    }

    pub async fn balances(&self) -> Result<Vec<Balance>> {
        self.client.balances().await
    }

    pub async fn set_leverage(&self, request: SetLeverageRequest) -> Result<LeverageSetting> {
        self.client.set_leverage(request).await
    }

    pub fn capabilities(&self) -> AccountCapabilities {
        self.client.account_capabilities()
    }

    pub async fn set_position_mode(
        &self,
        request: SetPositionModeRequest,
    ) -> Result<PositionModeSetting> {
        self.client.set_position_mode(request).await
    }

    pub async fn set_symbol_margin_mode(
        &self,
        request: SetSymbolMarginModeRequest,
    ) -> Result<SymbolMarginModeSetting> {
        self.client.set_symbol_margin_mode(request).await
    }

    pub async fn ensure_order_margin_mode(
        &self,
        request: EnsureOrderMarginModeRequest,
    ) -> Result<EnsureOrderMarginModeResult> {
        self.client.ensure_order_margin_mode(request).await
    }

    pub async fn prepare_order_settings(
        &self,
        request: PrepareOrderSettingsRequest,
    ) -> Result<PrepareOrderSettingsResult> {
        self.client.prepare_order_settings(request).await
    }
}