polyoxide_clob/ws/
market.rs1use rust_decimal::Decimal;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct OrderSummary {
11 #[serde(with = "rust_decimal::serde::str")]
13 pub price: Decimal,
14 #[serde(with = "rust_decimal::serde::str")]
16 pub size: Decimal,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct BookMessage {
22 pub event_type: String,
24 pub asset_id: String,
26 pub market: String,
28 pub timestamp: String,
30 pub hash: String,
32 pub bids: Vec<OrderSummary>,
34 pub asks: Vec<OrderSummary>,
36 pub last_trade_price: Option<String>,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct PriceChange {
43 pub asset_id: String,
45 #[serde(with = "rust_decimal::serde::str")]
47 pub price: Decimal,
48 #[serde(with = "rust_decimal::serde::str")]
50 pub size: Decimal,
51 pub side: String,
53 pub hash: String,
55 #[serde(default, with = "rust_decimal::serde::str_option")]
57 pub best_bid: Option<Decimal>,
58 #[serde(default, with = "rust_decimal::serde::str_option")]
60 pub best_ask: Option<Decimal>,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct PriceChangeMessage {
66 pub event_type: String,
68 pub market: String,
70 pub price_changes: Vec<PriceChange>,
72 pub timestamp: String,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct TickSizeChangeMessage {
79 pub event_type: String,
81 pub asset_id: String,
83 pub market: String,
85 pub old_tick_size: String,
87 pub new_tick_size: String,
89 pub side: String,
91 pub timestamp: String,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct LastTradePriceMessage {
98 pub event_type: String,
100 pub asset_id: String,
102 pub market: String,
104 #[serde(with = "rust_decimal::serde::str")]
106 pub price: Decimal,
107 pub side: String,
109 #[serde(with = "rust_decimal::serde::str")]
111 pub size: Decimal,
112 pub fee_rate_bps: Option<String>,
114 pub timestamp: String,
116}
117
118#[derive(Debug, Clone, Serialize)]
120#[serde(untagged)]
121pub enum MarketMessage {
122 Book(BookMessage),
124 PriceChange(PriceChangeMessage),
126 TickSizeChange(TickSizeChangeMessage),
128 LastTradePrice(LastTradePriceMessage),
130}
131
132impl MarketMessage {
133 pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
135 if json.starts_with('[') {
137 let books: Vec<BookMessage> = serde_json::from_str(json)?;
138 if let Some(book) = books.into_iter().next() {
139 return Ok(MarketMessage::Book(book));
140 }
141 return Err(serde::de::Error::custom("Empty book array"));
142 }
143
144 #[derive(Deserialize)]
145 struct RawMessage {
146 event_type: String,
147 }
148
149 let raw: RawMessage = serde_json::from_str(json)?;
150 match raw.event_type.as_str() {
151 "book" => Ok(MarketMessage::Book(serde_json::from_str(json)?)),
152 "price_change" => Ok(MarketMessage::PriceChange(serde_json::from_str(json)?)),
153 "tick_size_change" => Ok(MarketMessage::TickSizeChange(serde_json::from_str(json)?)),
154 "last_trade_price" => Ok(MarketMessage::LastTradePrice(serde_json::from_str(json)?)),
155 _ => Err(serde::de::Error::custom(format!(
156 "Unknown market event type: {}",
157 raw.event_type
158 ))),
159 }
160 }
161}