1use crate::portfolio::{Action, Side};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Deserialize)]
6pub struct MessageEnvelope {
7 #[serde(rename = "type")]
8 pub msg_type: String,
9 pub sid: Option<i32>,
10 pub seq: Option<i64>,
11 pub id: Option<i32>,
12 pub msg: Option<serde_json::Value>,
13}
14
15#[derive(Debug)]
17pub enum WebSocketMessage {
18 Subscribed(SubscribedMsg),
20 Ok(OkMsg),
21 Error(ErrorMsg),
22
23 OrderbookSnapshot(OrderbookSnapshotMsg),
25 OrderbookDelta(OrderbookDeltaMsg),
26
27 Ticker(TickerMsg),
29 Trade(TradeMsg),
30
31 Fill(FillMsg),
33 MarketPosition(MarketPositionMsg),
34
35 MarketLifecycle(MarketLifecycleMsg),
37 EventLifecycle(EventLifecycleMsg),
38
39 MultivariateLookup(MultivariateLookupMsg),
41
42 RfqCreated(RfqCreatedMsg),
44 QuoteCreated(QuoteCreatedMsg),
45 QuoteAccepted(QuoteAcceptedMsg),
46
47 Unknown(serde_json::Value),
49}
50
51#[derive(Debug, Deserialize, Serialize)]
54pub struct SubscribedMsg {
55 pub channel: String,
56 pub sid: i32,
57}
58
59#[derive(Debug, Deserialize, Serialize)]
60pub struct OkMsg {
61 pub sid: i32,
62 pub seq: i64,
63}
64
65#[derive(Debug, Deserialize, Serialize)]
66pub struct ErrorMsg {
67 pub code: i32,
68 pub msg: String,
69}
70
71#[derive(Debug, Deserialize, Serialize)]
74pub struct OrderbookSnapshotMsg {
75 pub market_ticker: String,
76 pub yes: Vec<Vec<i32>>,
77 pub yes_dollars: Vec<Vec<String>>,
78 pub no: Vec<Vec<i32>>,
79 pub no_dollars: Vec<Vec<String>>,
80}
81
82#[derive(Debug, Deserialize, Serialize)]
83pub struct OrderbookDeltaMsg {
84 pub market_ticker: String,
85 pub price: i32,
86 pub price_dollars: String,
87 pub delta: i32,
88 pub side: String, }
90
91#[derive(Debug, Deserialize, Serialize)]
94pub struct TickerMsg {
95 pub market_ticker: String,
96 pub price: Option<i32>,
97 pub yes_bid: Option<i32>,
98 pub yes_ask: Option<i32>,
99 pub price_dollars: Option<String>,
100 pub volume: Option<i64>,
101 pub open_interest: Option<i64>,
102 pub ts: Option<i64>,
103}
104
105#[derive(Debug, Deserialize, Serialize)]
106pub struct TradeMsg {
107 pub market_ticker: String,
108 pub yes_price: i32,
109 pub no_price: i32,
110 pub count: i32,
111 pub taker_side: String,
112 pub ts: i64,
113}
114
115#[derive(Debug, Deserialize, Serialize)]
118pub struct FillMsg {
119 pub trade_id: String,
120 pub order_id: String,
121 pub market_ticker: String,
122 pub side: Side,
123 pub action: Action,
124 pub count: i32,
125 pub post_position: i32,
126}
127
128#[derive(Debug, Deserialize, Serialize)]
129pub struct MarketPositionMsg {
130 pub market_ticker: String,
131 pub position: i32,
132 pub position_cost: i64,
134 pub realized_pnl: i64,
136 pub fees_paid: i64,
138}
139
140#[derive(Debug, Deserialize, Serialize)]
143pub struct MarketLifecycleMsg {
144 pub market_ticker: String,
145 pub event_type: MarketLifecycleEvent,
146 pub open_ts: Option<i64>,
147 pub close_ts: Option<i64>,
148}
149
150#[derive(Debug, Deserialize, Serialize, Clone, Copy)]
151#[serde(rename_all = "lowercase")]
152pub enum MarketLifecycleEvent {
153 Created,
154 Activated,
155 Deactivated,
156 CloseDateUpdated,
157 Determined,
158 Settled,
159}
160
161#[derive(Debug, Deserialize, Serialize)]
162pub struct EventLifecycleMsg {
163 pub event_ticker: String,
164 pub title: String,
165}
166
167#[derive(Debug, Deserialize, Serialize)]
170pub struct MultivariateLookupMsg {
171 pub collection_ticker: String,
172 pub market_ticker: String,
173 pub selected_markets: Vec<SelectedMarket>,
174}
175
176#[derive(Debug, Deserialize, Serialize)]
177pub struct SelectedMarket {
178 pub market_ticker: String,
179 pub side: String,
180}
181
182#[derive(Debug, Deserialize, Serialize)]
185pub struct RfqCreatedMsg {
186 pub id: String,
187 pub market_ticker: String,
188 pub contracts: i32,
189}
190
191#[derive(Debug, Deserialize, Serialize)]
192pub struct QuoteCreatedMsg {
193 pub quote_id: String,
194 pub rfq_id: String,
195 pub yes_bid: i32,
196 pub no_bid: i32,
197}
198
199#[derive(Debug, Deserialize, Serialize)]
200pub struct QuoteAcceptedMsg {
201 pub quote_id: String,
202 pub accepted_side: String,
203}
204
205impl WebSocketMessage {
208 pub fn parse(text: &str) -> Result<Self, serde_json::Error> {
210 let envelope: MessageEnvelope = serde_json::from_str(text)?;
211
212 match envelope.msg_type.as_str() {
213 "subscribed" => {
214 let msg: SubscribedMsg = serde_json::from_value(envelope.msg.unwrap_or_default())?;
215 Ok(WebSocketMessage::Subscribed(msg))
216 }
217 "ok" => Ok(WebSocketMessage::Ok(OkMsg {
218 sid: envelope.sid.unwrap_or(0),
219 seq: envelope.seq.unwrap_or(0),
220 })),
221 "error" => {
222 let msg: ErrorMsg = serde_json::from_value(envelope.msg.unwrap_or_default())?;
223 Ok(WebSocketMessage::Error(msg))
224 }
225 "orderbook_snapshot" => {
226 let msg: OrderbookSnapshotMsg =
227 serde_json::from_value(envelope.msg.unwrap_or_default())?;
228 Ok(WebSocketMessage::OrderbookSnapshot(msg))
229 }
230 "orderbook_delta" => {
231 let msg: OrderbookDeltaMsg =
232 serde_json::from_value(envelope.msg.unwrap_or_default())?;
233 Ok(WebSocketMessage::OrderbookDelta(msg))
234 }
235 "ticker" => {
236 let msg: TickerMsg = serde_json::from_value(envelope.msg.unwrap_or_default())?;
237 Ok(WebSocketMessage::Ticker(msg))
238 }
239 "trade" => {
240 let msg: TradeMsg = serde_json::from_value(envelope.msg.unwrap_or_default())?;
241 Ok(WebSocketMessage::Trade(msg))
242 }
243 "fill" => {
244 let msg: FillMsg = serde_json::from_value(envelope.msg.unwrap_or_default())?;
245 Ok(WebSocketMessage::Fill(msg))
246 }
247 "market_position" => {
248 let msg: MarketPositionMsg =
249 serde_json::from_value(envelope.msg.unwrap_or_default())?;
250 Ok(WebSocketMessage::MarketPosition(msg))
251 }
252 "market_lifecycle_v2" => {
253 let msg: MarketLifecycleMsg =
254 serde_json::from_value(envelope.msg.unwrap_or_default())?;
255 Ok(WebSocketMessage::MarketLifecycle(msg))
256 }
257 "event_lifecycle" => {
258 let msg: EventLifecycleMsg =
259 serde_json::from_value(envelope.msg.unwrap_or_default())?;
260 Ok(WebSocketMessage::EventLifecycle(msg))
261 }
262 "multivariate_lookup" => {
263 let msg: MultivariateLookupMsg =
264 serde_json::from_value(envelope.msg.unwrap_or_default())?;
265 Ok(WebSocketMessage::MultivariateLookup(msg))
266 }
267 "rfq_created" => {
268 let msg: RfqCreatedMsg = serde_json::from_value(envelope.msg.unwrap_or_default())?;
269 Ok(WebSocketMessage::RfqCreated(msg))
270 }
271 "quote_created" => {
272 let msg: QuoteCreatedMsg =
273 serde_json::from_value(envelope.msg.unwrap_or_default())?;
274 Ok(WebSocketMessage::QuoteCreated(msg))
275 }
276 "quote_accepted" => {
277 let msg: QuoteAcceptedMsg =
278 serde_json::from_value(envelope.msg.unwrap_or_default())?;
279 Ok(WebSocketMessage::QuoteAccepted(msg))
280 }
281 _ => Ok(WebSocketMessage::Unknown(serde_json::json!({
282 "type": envelope.msg_type,
283 "msg": envelope.msg
284 }))),
285 }
286 }
287}