polyte_clob/ws/
market.rs

1//! Market channel message types.
2//!
3//! The market channel provides real-time order book and price updates.
4
5use serde::{Deserialize, Serialize};
6
7/// Order summary in the order book
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct OrderSummary {
10    /// Price level
11    pub price: String,
12    /// Size at this price level
13    pub size: String,
14}
15
16/// Book message - full order book snapshot
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct BookMessage {
19    /// Event type (always "book")
20    pub event_type: String,
21    /// Asset ID (token ID)
22    pub asset_id: String,
23    /// Market condition ID
24    pub market: String,
25    /// Timestamp in milliseconds (as string)
26    pub timestamp: String,
27    /// Order book hash
28    pub hash: String,
29    /// Buy orders (bids)
30    pub bids: Vec<OrderSummary>,
31    /// Sell orders (asks)
32    pub asks: Vec<OrderSummary>,
33    /// Last trade price
34    pub last_trade_price: Option<String>,
35}
36
37/// Price change entry
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct PriceChange {
40    /// Asset ID (token ID)
41    pub asset_id: String,
42    /// Price level
43    pub price: String,
44    /// Size at this price level
45    pub size: String,
46    /// Order side (BUY or SELL)
47    pub side: String,
48    /// Order book hash
49    pub hash: String,
50    /// Best bid price
51    pub best_bid: Option<String>,
52    /// Best ask price
53    pub best_ask: Option<String>,
54}
55
56/// Price change message - incremental order book update
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct PriceChangeMessage {
59    /// Event type (always "price_change")
60    pub event_type: String,
61    /// Market condition ID
62    pub market: String,
63    /// List of price changes
64    pub price_changes: Vec<PriceChange>,
65    /// Timestamp in milliseconds (as string)
66    pub timestamp: String,
67}
68
69/// Tick size change message
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct TickSizeChangeMessage {
72    /// Event type (always "tick_size_change")
73    pub event_type: String,
74    /// Asset ID (token ID)
75    pub asset_id: String,
76    /// Market condition ID
77    pub market: String,
78    /// Old tick size
79    pub old_tick_size: String,
80    /// New tick size
81    pub new_tick_size: String,
82    /// Side (BUY or SELL)
83    pub side: String,
84    /// Timestamp in milliseconds (as string)
85    pub timestamp: String,
86}
87
88/// Last trade price message
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct LastTradePriceMessage {
91    /// Event type (always "last_trade_price")
92    pub event_type: String,
93    /// Asset ID (token ID)
94    pub asset_id: String,
95    /// Market condition ID
96    pub market: String,
97    /// Trade price
98    pub price: String,
99    /// Trade side (BUY or SELL)
100    pub side: String,
101    /// Trade size
102    pub size: String,
103    /// Fee rate
104    pub fee_rate_bps: Option<String>,
105    /// Timestamp in milliseconds (as string)
106    pub timestamp: String,
107}
108
109/// Market channel message types
110#[derive(Debug, Clone, Serialize)]
111#[serde(untagged)]
112pub enum MarketMessage {
113    /// Full order book snapshot
114    Book(BookMessage),
115    /// Incremental price change
116    PriceChange(PriceChangeMessage),
117    /// Tick size change
118    TickSizeChange(TickSizeChangeMessage),
119    /// Last trade price
120    LastTradePrice(LastTradePriceMessage),
121}
122
123impl MarketMessage {
124    /// Parse a market channel message from JSON
125    pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
126        // Book messages come as an array with a single element
127        if json.starts_with('[') {
128            let books: Vec<BookMessage> = serde_json::from_str(json)?;
129            if let Some(book) = books.into_iter().next() {
130                return Ok(MarketMessage::Book(book));
131            }
132            return Err(serde::de::Error::custom("Empty book array"));
133        }
134
135        #[derive(Deserialize)]
136        struct RawMessage {
137            event_type: String,
138        }
139
140        let raw: RawMessage = serde_json::from_str(json)?;
141        match raw.event_type.as_str() {
142            "book" => Ok(MarketMessage::Book(serde_json::from_str(json)?)),
143            "price_change" => Ok(MarketMessage::PriceChange(serde_json::from_str(json)?)),
144            "tick_size_change" => Ok(MarketMessage::TickSizeChange(serde_json::from_str(json)?)),
145            "last_trade_price" => Ok(MarketMessage::LastTradePrice(serde_json::from_str(json)?)),
146            _ => Err(serde::de::Error::custom(format!(
147                "Unknown market event type: {}",
148                raw.event_type
149            ))),
150        }
151    }
152}