use std::collections::HashMap;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
use std::pin::Pin;
use futures_core::Stream;
pub type BoxStream<T> = Pin<Box<dyn Stream<Item = T> + Send + 'static>>;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Status {
Success,
InProgress,
Completed,
Failed,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Side {
Bid,
Ask,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum OrderSide {
Buy,
Sell,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum OrderStatus {
Placed,
PartiallyFilled,
Filled,
Cancelled,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum MarketType {
Spot,
Future,
Perpetual,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum OrderType {
Market,
Limit,
TakeProfit,
StopLoss,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum TimeInForce {
Gtc,
Ioc,
Fok,
Alo,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum VolumeDenomination {
Base,
Quote,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum AssetClass {
Crypto,
Stablecoin,
Fiat,
}
#[derive(Debug, Clone)]
pub struct L2Update {
pub symbol: String,
pub price: Decimal,
pub volume: Decimal,
pub side: Side,
pub sequence: i64,
}
#[derive(Debug, Clone)]
pub struct L2Level {
pub price: Decimal,
pub volume: Decimal,
}
#[derive(Debug, Clone)]
pub struct L2Snapshot {
pub symbol: String,
pub bids: Vec<L2Level>,
pub asks: Vec<L2Level>,
pub sequence: i64,
}
#[derive(Debug, Clone)]
pub struct Liquidation {
pub symbol: String,
pub side: OrderSide,
pub liquidated_user: String,
pub notional_position: Decimal,
pub account_value: Decimal,
}
#[derive(Debug, Clone)]
pub struct AssetContext {
pub symbol: String,
pub open_interest: Decimal,
pub funding_rate: Decimal,
pub mark_price: Decimal,
pub day_volume: Decimal,
pub mid_price: Option<Decimal>,
pub oracle_price: Option<Decimal>,
pub premium: Option<Decimal>,
pub prev_day_price: Option<Decimal>,
pub sz_decimals: i32,
}
#[derive(Debug, Clone)]
pub struct PredictedFunding {
pub symbol: String,
pub venue: String,
pub funding_rate: Decimal,
pub next_funding_time_ms: i64,
}
#[derive(Debug, Clone)]
pub struct Fill {
pub symbol: String,
pub price: Decimal,
pub volume: Decimal,
pub side: OrderSide,
pub timestamp_ms: i64,
pub trade_id: i64,
}
#[derive(Debug, Clone)]
pub struct Position {
pub symbol: String,
pub side: OrderSide,
pub size: Decimal,
pub entry_price: Decimal,
}
#[derive(Debug, Clone)]
pub struct OpenOrder {
pub order_id: i64,
pub symbol: String,
pub side: OrderSide,
pub price: Decimal,
pub quantity: Decimal,
pub filled_quantity: Decimal,
pub order_type: Option<OrderType>,
pub trigger_price: Option<Decimal>,
pub reduce_only: bool,
}
#[derive(Debug, Clone)]
pub struct OrderPlacement {
pub order_id: i64,
pub symbol: String,
pub side: OrderSide,
pub price: Decimal,
pub quantity: Decimal,
pub timestamp_ms: i64,
pub cloid: Option<String>,
pub order_type: OrderType,
pub trigger_price: Option<Decimal>,
pub reduce_only: bool,
}
#[derive(Debug, Clone)]
pub struct UserFill {
pub order_id: i64,
pub symbol: String,
pub side: OrderSide,
pub price: Decimal,
pub quantity: Decimal,
pub fee_usd: Decimal,
pub timestamp_ms: i64,
pub cloid: Option<String>,
}
#[derive(Debug, Clone)]
pub struct OrderUpdate {
pub order_id: i64,
pub symbol: String,
pub status: OrderStatus,
pub side: Option<OrderSide>,
pub price: Option<Decimal>,
pub quantity: Option<Decimal>,
pub remaining_quantity: Option<Decimal>,
pub timestamp_ms: i64,
pub cloid: Option<String>,
}
#[derive(Debug, Clone)]
pub struct FundingPayment {
pub symbol: String,
pub amount_usd: Decimal,
pub timestamp_ms: i64,
}
#[derive(Debug, Clone)]
pub struct Deposit {
pub asset: String,
pub amount_usd: Decimal,
pub timestamp_ms: i64,
}
#[derive(Debug, Clone)]
pub struct Withdrawal {
pub asset: String,
pub amount_usd: Decimal,
pub timestamp_ms: i64,
}
#[derive(Debug, Clone)]
pub struct AccountBalance {
pub token: String,
pub equity: Decimal,
pub free: Decimal,
pub safe: Option<Decimal>,
pub usable: Decimal,
pub hold: Decimal,
pub margin_used: Option<Decimal>,
pub maintenance: Option<Decimal>,
}
#[derive(Debug, Clone)]
pub struct UserRateLimit {
pub cumulative_volume: Decimal,
pub requests_used: i64,
pub requests_cap: i64,
pub requests_surplus: i64,
}
#[allow(async_fn_in_trait)]
#[allow(clippy::too_many_arguments)]
pub trait TestServer {
async fn ping(&self) -> Result<bool, String>;
async fn get_server_time(&self) -> Result<i64, String>;
}
#[allow(async_fn_in_trait)]
#[allow(clippy::too_many_arguments)]
pub trait GetMarketData {
async fn get_symbol(&self) -> Result<Vec<String>, String>;
async fn get_price(&self, symbol: String) -> Result<Decimal, String>;
async fn get_open_interest(&self, symbol: String) -> Result<Decimal, String>;
async fn get_asset_context(&self, symbol: String) -> Result<AssetContext, String>;
async fn get_all_asset_contexts(&self) -> Result<Vec<AssetContext>, String>;
async fn get_sz_decimals(&self, symbol: String) -> Result<i32, String>;
async fn get_all_sz_decimals(&self) -> Result<HashMap<String, i32>, String>;
async fn get_predicted_fundings(&self) -> Result<Vec<PredictedFunding>, String>;
async fn get_l2_orderbook(&self, symbol: String) -> Result<L2Snapshot, String>;
}
#[allow(async_fn_in_trait)]
#[allow(clippy::too_many_arguments)]
pub trait ManageOrder {
async fn place_order(&self, symbol: String, side: OrderSide, price: Decimal, volume: Decimal, order_type: OrderType, time_in_force: TimeInForce, trigger_price: Option<Decimal>, reduce_only: bool, cloid: Option<String>) -> Result<OrderPlacement, String>;
async fn change_order_by_cloid(&self, cloid: i64, price: Decimal, volume: Decimal) -> Result<i64, String>;
async fn cancel_order_by_cloid(&self, cloid: String) -> Result<(), String>;
async fn cancel_all_order(&self) -> Result<bool, String>;
}
#[allow(async_fn_in_trait)]
#[allow(clippy::too_many_arguments)]
pub trait SubscribeMarketData {
fn subscribe_l2_update(&self, symbol: String) -> BoxStream<Result<L2Update, String>>;
fn subscribe_l2_snapshot(&self, symbol: String) -> BoxStream<Result<L2Snapshot, String>>;
fn subscribe_fill(&self, symbol: String) -> BoxStream<Result<Fill, String>>;
fn subscribe_asset_context(&self, symbol: String) -> BoxStream<Result<AssetContext, String>>;
fn subscribe_liquidation(&self, user: String) -> BoxStream<Result<Liquidation, String>>;
async fn unsubscribe_all(&self) -> ();
}
#[allow(async_fn_in_trait)]
#[allow(clippy::too_many_arguments)]
pub trait GetAccountSnapshot {
async fn get_positions(&self) -> Result<Vec<Position>, String>;
async fn get_open_orders(&self) -> Result<Vec<OpenOrder>, String>;
async fn get_balance(&self) -> Result<Vec<AccountBalance>, String>;
async fn get_user_rate_limit(&self) -> Result<UserRateLimit, String>;
}
#[allow(async_fn_in_trait)]
#[allow(clippy::too_many_arguments)]
pub trait SubscribeUserEvents {
fn subscribe_user_fills(&self) -> BoxStream<Result<UserFill, String>>;
fn subscribe_order_updates(&self) -> BoxStream<Result<OrderUpdate, String>>;
fn subscribe_funding_payments(&self) -> BoxStream<Result<FundingPayment, String>>;
fn subscribe_deposits(&self) -> BoxStream<Result<Deposit, String>>;
fn subscribe_withdrawals(&self) -> BoxStream<Result<Withdrawal, String>>;
fn subscribe_spot_balance(&self) -> BoxStream<Result<Vec<AccountBalance>, String>>;
fn subscribe_spot_balance_with_address(&self, address: String) -> BoxStream<Result<Vec<AccountBalance>, String>>;
async fn unsubscribe_user_events(&self) -> ();
}
#[allow(async_fn_in_trait)]
#[allow(clippy::too_many_arguments)]
pub trait SubscribeMarketDataOps {
async fn unsubscribe_market_data(&self, symbol: String) -> ();
}