use serde::ser::SerializeTuple;
use serde::{Deserialize, Serialize};
use crate::{RequestId, WSError};
pub type ClientOrderId = u64;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum MessageType {
#[serde(rename = "s")]
Snapshot,
#[serde(rename = "u")]
Update,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct DataMessage {
pub channel: String,
pub symbol: String,
pub ts: u64,
#[serde(rename = "mt")]
pub msg_type: MessageType,
pub data: serde_json::Value,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct StatusMessage {
#[serde(rename = "E")]
pub event_time: u64,
pub status: String,
pub client_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct PongMessage {
pub id: Option<RequestId>,
#[serde(rename = "E")]
pub event_time: u64,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ErrorMessage {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<RequestId>,
#[serde(rename = "E")]
pub event_time: u64,
pub error: WSError,
}
#[derive(Clone, Debug)]
pub struct PriceLevel(pub String, pub String);
impl Serialize for PriceLevel {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut tuple = serializer.serialize_tuple(2)?;
tuple.serialize_element(&self.0)?;
tuple.serialize_element(&self.1)?;
tuple.end()
}
}
impl<'de> Deserialize<'de> for PriceLevel {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let (price, qty) = <(String, String)>::deserialize(deserializer)?;
Ok(PriceLevel(price, qty))
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DepthUpdate {
#[serde(rename = "e")]
pub event_type: String,
#[serde(rename = "E")]
pub event_time: u64,
#[serde(rename = "T")]
pub transaction_time: u64,
#[serde(rename = "s")]
pub symbol: String,
#[serde(rename = "U")]
pub first_update_id: u64,
#[serde(rename = "u")]
pub last_update_id: u64,
#[serde(rename = "pu")]
pub prev_update_id: u64,
#[serde(rename = "b")]
pub bids: Vec<PriceLevel>,
#[serde(rename = "a")]
pub asks: Vec<PriceLevel>,
#[serde(rename = "mt")]
pub msg_type: MessageType,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct AggTradeMessage {
#[serde(rename = "e")]
pub event_type: String,
#[serde(rename = "E")]
pub event_time: u64,
#[serde(rename = "s")]
pub symbol: String,
#[serde(rename = "a")]
pub agg_trade_id: u64,
#[serde(rename = "p")]
pub price: String,
#[serde(rename = "q")]
pub quantity: String,
#[serde(rename = "f")]
pub first_trade_id: u64,
#[serde(rename = "l")]
pub last_trade_id: u64,
#[serde(rename = "T")]
pub trade_time: u64,
#[serde(rename = "m")]
pub is_buyer_maker: bool,
#[serde(rename = "th")]
pub tx_hash: String,
#[serde(rename = "ua")]
pub user_address: String,
#[serde(rename = "oi")]
pub order_id: u64,
#[serde(rename = "mk")]
pub is_maker: bool,
#[serde(rename = "ff")]
pub is_full_fill: bool,
#[serde(rename = "lq")]
pub is_liquidation: bool,
#[serde(rename = "fe")]
pub fee: String,
#[serde(rename = "nf")]
pub net_fee: String,
#[serde(rename = "fa")]
pub fee_asset: String,
#[serde(rename = "co", skip_serializing_if = "Option::is_none")]
pub client_order_id: Option<ClientOrderId>,
#[serde(rename = "sd")]
pub side: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BookTickerMessage {
#[serde(rename = "e")]
pub event_type: String,
#[serde(rename = "u")]
pub update_id: u64,
#[serde(rename = "E")]
pub event_time: u64,
#[serde(rename = "T")]
pub transaction_time: u64,
#[serde(rename = "s")]
pub symbol: String,
#[serde(rename = "b")]
pub best_bid_price: String,
#[serde(rename = "B")]
pub best_bid_qty: String,
#[serde(rename = "a")]
pub best_ask_price: String,
#[serde(rename = "A")]
pub best_ask_qty: String,
#[serde(rename = "mt")]
pub msg_type: MessageType,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ForceOrderMessage {
#[serde(rename = "e")]
pub event_type: String,
#[serde(rename = "E")]
pub event_time: u64,
#[serde(rename = "o")]
pub order: ForceOrderDetails,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ForceOrderDetails {
#[serde(rename = "s")]
pub symbol: String,
#[serde(rename = "S")]
pub side: String,
#[serde(rename = "o")]
pub order_type: String,
#[serde(rename = "f")]
pub time_in_force: String,
#[serde(rename = "q", skip_serializing_if = "Option::is_none")]
pub quantity: Option<String>,
#[serde(rename = "z", skip_serializing_if = "Option::is_none")]
pub filled_qty: Option<String>,
#[serde(rename = "p")]
pub price: String,
#[serde(rename = "ap")]
pub avg_price: String,
#[serde(rename = "X")]
pub status: String,
#[serde(rename = "l")]
pub last_filled_qty: String,
#[serde(rename = "T")]
pub trade_time: u64,
#[serde(rename = "th")]
pub tx_hash: String,
#[serde(rename = "ua")]
pub user_address: String,
#[serde(rename = "oi")]
pub order_id: u64,
#[serde(rename = "ti")]
pub trade_id: u64,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct MarkPriceMessage {
#[serde(rename = "e")]
pub event_type: String,
#[serde(rename = "E")]
pub event_time: u64,
#[serde(rename = "s")]
pub symbol: String,
#[serde(rename = "p")]
pub mark_price: String,
#[serde(rename = "i")]
pub index_price: String,
#[serde(rename = "P", skip_serializing_if = "Option::is_none")]
pub estimated_settle_price: Option<String>,
#[serde(rename = "r")]
pub funding_rate: String,
#[serde(rename = "T", skip_serializing_if = "Option::is_none")]
pub next_funding_time: Option<u64>,
#[serde(rename = "th", skip_serializing_if = "Option::is_none")]
pub tx_hash: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct OrderUpdateMessage {
#[serde(rename = "e")]
pub event_type: String,
#[serde(rename = "E")]
pub event_time: u64,
#[serde(rename = "o")]
pub order: OrderUpdateData,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct OrderUpdateCommon {
#[serde(rename = "s")]
pub symbol: String,
#[serde(rename = "i")]
pub order_id: u64,
#[serde(rename = "co", skip_serializing_if = "Option::is_none")]
pub client_order_id: Option<ClientOrderId>,
#[serde(rename = "X")]
pub status: String,
#[serde(rename = "x")]
pub execution_type: String,
#[serde(rename = "T")]
pub transaction_time: u64,
#[serde(rename = "th")]
pub tx_hash: String,
#[serde(rename = "ua")]
pub user_address: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PlaceOrderData {
#[serde(flatten)]
pub common: OrderUpdateCommon,
#[serde(rename = "S")]
pub side: String,
#[serde(rename = "o")]
pub order_type: String,
#[serde(rename = "f")]
pub time_in_force: String,
#[serde(rename = "p")]
pub price: String,
#[serde(rename = "q")]
pub quantity: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct CancelOrderData {
#[serde(flatten)]
pub common: OrderUpdateCommon,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct TradeFillData {
#[serde(flatten)]
pub common: OrderUpdateCommon,
#[serde(rename = "S")]
pub side: String,
#[serde(rename = "p", skip_serializing_if = "Option::is_none")]
pub price: Option<String>,
#[serde(rename = "q", skip_serializing_if = "Option::is_none")]
pub quantity: Option<String>,
#[serde(rename = "l")]
pub last_filled_qty: String,
#[serde(rename = "L")]
pub last_filled_price: String,
#[serde(rename = "n")]
pub commission: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(untagged)]
pub enum OrderUpdateData {
TradeFill(TradeFillData),
PlaceOrder(PlaceOrderData),
Cancel(CancelOrderData),
}