1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
8#[serde(rename_all = "lowercase")]
9pub enum WebSocketMessageType {
10 Subscribe,
12
13 Unsubscribe,
15
16 Ping,
18
19 Pong,
21
22 Heartbeat,
24
25 #[serde(rename = "systemStatus")]
27 SystemStatus,
28
29 #[serde(rename = "subscriptionStatus")]
31 SubscriptionStatus,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
36#[serde(rename_all = "lowercase")]
37pub enum WebSocketSubscriptionType {
38 Ticker,
40
41 OHLC,
43
44 Trade,
46
47 Spread,
49
50 Book,
52
53 #[serde(rename = "*")]
55 All,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct WebSocketSubscription {
61 pub name: WebSocketSubscriptionType,
63
64 #[serde(skip_serializing_if = "Option::is_none")]
66 pub interval: Option<u32>,
67
68 #[serde(skip_serializing_if = "Option::is_none")]
70 pub depth: Option<u32>,
71}
72
73#[derive(Debug, Clone, Serialize)]
75pub struct WebSocketSubscriptionRequest {
76 pub event: WebSocketMessageType,
78
79 pub subscription: WebSocketSubscription,
81
82 #[serde(skip_serializing_if = "Option::is_none")]
84 pub pair: Option<Vec<String>>,
85}
86
87impl WebSocketSubscriptionRequest {
88 pub fn new() -> Self {
90 Self {
91 event: WebSocketMessageType::Subscribe,
92 subscription: WebSocketSubscription {
93 name: WebSocketSubscriptionType::Ticker,
94 interval: None,
95 depth: None,
96 },
97 pair: None,
98 }
99 }
100
101 pub fn new_with_type(subscription_type: WebSocketSubscriptionType) -> Self {
103 Self {
104 event: WebSocketMessageType::Subscribe,
105 subscription: WebSocketSubscription {
106 name: subscription_type,
107 interval: None,
108 depth: None,
109 },
110 pair: None,
111 }
112 }
113
114 pub fn with_pairs(mut self, pairs: Vec<String>) -> Self {
116 self.pair = Some(pairs);
117 self
118 }
119
120 pub fn add_pair<S: Into<String>>(mut self, pair: S) -> Self {
122 if let Some(pairs) = self.pair.as_mut() {
123 pairs.push(pair.into());
124 } else {
125 self.pair = Some(vec![pair.into()]);
126 }
127 self
128 }
129
130 pub fn with_interval(mut self, interval: u32) -> Self {
132 self.subscription.interval = Some(interval);
133 self
134 }
135
136 pub fn with_depth(mut self, depth: u32) -> Self {
138 self.subscription.depth = Some(depth);
139 self
140 }
141
142 pub fn add_subscription<S: AsRef<str>>(mut self, name: S) -> Self {
144 let name_str = name.as_ref();
145 self.subscription.name = match name_str {
146 "ticker" => WebSocketSubscriptionType::Ticker,
147 "ohlc" => WebSocketSubscriptionType::OHLC,
148 "trade" => WebSocketSubscriptionType::Trade,
149 "spread" => WebSocketSubscriptionType::Spread,
150 "book" => WebSocketSubscriptionType::Book,
151 _ => WebSocketSubscriptionType::Ticker, };
153 self
154 }
155}
156
157#[derive(Debug, Clone, Serialize)]
159pub struct WebSocketUnsubscriptionRequest {
160 pub event: WebSocketMessageType,
162
163 pub subscription: WebSocketSubscription,
165
166 #[serde(skip_serializing_if = "Option::is_none")]
168 pub pair: Option<Vec<String>>,
169}
170
171impl WebSocketUnsubscriptionRequest {
172 pub fn new(subscription_type: WebSocketSubscriptionType) -> Self {
174 Self {
175 event: WebSocketMessageType::Unsubscribe,
176 subscription: WebSocketSubscription {
177 name: subscription_type,
178 interval: None,
179 depth: None,
180 },
181 pair: None,
182 }
183 }
184
185 pub fn with_pairs(mut self, pairs: Vec<String>) -> Self {
187 self.pair = Some(pairs);
188 self
189 }
190
191 pub fn with_interval(mut self, interval: u32) -> Self {
193 self.subscription.interval = Some(interval);
194 self
195 }
196
197 pub fn with_depth(mut self, depth: u32) -> Self {
199 self.subscription.depth = Some(depth);
200 self
201 }
202}
203
204#[derive(Debug, Clone, Deserialize)]
206#[serde(untagged)]
207pub enum WebSocketMessage {
208 SystemStatus {
210 event: String,
212
213 #[serde(rename = "connectionID")]
215 connection_id: u64,
216
217 status: String,
219
220 version: String,
222 },
223
224 SubscriptionStatus {
226 #[serde(rename = "channelID")]
228 channel_id: Option<u64>,
229
230 #[serde(rename = "channelName")]
232 channel_name: Option<String>,
233
234 event: String,
236
237 pair: Option<String>,
239
240 status: String,
242
243 subscription: WebSocketSubscription,
245 },
246
247 Heartbeat {
249 #[serde(rename = "event")]
251 event_type: WebSocketMessageType,
252 },
253
254 Ping {
256 #[serde(rename = "event")]
258 event_type: WebSocketMessageType,
259
260 #[serde(rename = "reqid")]
262 req_id: Option<u64>,
263 },
264
265 Pong {
267 #[serde(rename = "event")]
269 event_type: WebSocketMessageType,
270
271 #[serde(rename = "reqid")]
273 req_id: Option<u64>,
274 },
275
276 Error {
278 event: String,
280
281 #[serde(rename = "errorMessage")]
283 error_message: String,
284
285 status: String,
287
288 subscription: Option<WebSocketSubscription>,
290
291 pair: Option<String>,
293 },
294
295 DataArray(Vec<Value>),
297
298 Generic(Value),
300}