1use super::StreamTopic;
2use crate::client::Product;
3use serde::Deserialize;
4
5#[derive(Debug, Clone, Copy)]
6pub struct AggTradeStream<'a> {
7 pub symbol: &'a str,
8}
9
10#[derive(Debug, Clone, Deserialize)]
11pub struct AggTradeEvent {
12 #[serde(rename = "E")]
13 pub event_time: usize,
14 #[serde(rename = "s")]
15 pub symbol: String,
16 #[serde(rename = "a")]
17 pub id: usize,
18 #[serde(rename = "p")]
19 pub price: String,
20 #[serde(rename = "q")]
21 pub qty: String,
22 #[serde(rename = "f")]
23 pub first_trade_id: usize,
24 #[serde(rename = "l")]
25 pub last_trade_id: usize,
26 #[serde(rename = "T")]
27 pub trade_time: usize,
28 #[serde(rename = "m")]
29 pub buyer_is_maker: bool,
30}
31
32impl<'a> StreamTopic for AggTradeStream<'a> {
33 const PRODUCT: Product = Product::UsdMFutures;
34 fn endpoint(&self) -> String {
35 format!("/ws/{}@aggTrade", self.symbol.to_lowercase())
36 }
37 type Event = AggTradeEvent;
38}
39
40#[derive(Debug, Clone, Copy)]
41pub struct BookTickerStream<'a> {
42 pub symbol: &'a str,
43}
44
45#[derive(Debug, Clone, Deserialize)]
46pub struct BookTickerEvent {
47 #[serde(rename = "u")]
48 pub order_book_update_id: usize,
49 #[serde(rename = "E")]
50 pub event_time: usize,
51 #[serde(rename = "T")]
52 pub transaction_time: usize,
53 #[serde(rename = "s")]
54 pub symbol: String,
55 #[serde(rename = "b")]
56 pub best_bid_price: String,
57 #[serde(rename = "B")]
58 pub best_bid_qty: String,
59 #[serde(rename = "a")]
60 pub best_ask_price: String,
61 #[serde(rename = "A")]
62 pub best_ask_qty: String,
63}
64
65impl<'a> StreamTopic for BookTickerStream<'a> {
66 const PRODUCT: Product = Product::UsdMFutures;
67 fn endpoint(&self) -> String {
68 format!("/ws/{}@bookTicker", self.symbol.to_lowercase())
69 }
70 type Event = BookTickerEvent;
71}
72
73#[derive(Debug, Clone, Deserialize)]
74pub struct DiffDepthEvent {
75 #[serde(rename = "E")]
76 pub event_time: usize,
77 #[serde(rename = "T")]
78 pub transaction_time: usize,
79 #[serde(rename = "s")]
80 pub symbol: String,
81 #[serde(rename = "U")]
82 pub first_update_id: usize,
83 #[serde(rename = "u")]
84 pub final_update_id: usize,
85 #[serde(rename = "pu")]
86 pub last_event_final_update_id: usize,
87 #[serde(rename = "b")]
88 pub bid_updates: Vec<BookLevelUpdate>,
89 #[serde(rename = "a")]
90 pub ask_updates: Vec<BookLevelUpdate>,
91}
92
93#[derive(Debug, Clone, Deserialize)]
94pub struct BookLevelUpdate {
95 pub price: String,
96 pub qty: String,
97}
98
99#[derive(Debug, Clone, Copy)]
100pub struct DiffDepthStream<'a> {
101 pub symbol: &'a str,
102}
103
104impl<'a> StreamTopic for DiffDepthStream<'a> {
105 const PRODUCT: Product = Product::UsdMFutures;
106 fn endpoint(&self) -> String {
107 format!("/ws/{}@depth@100ms", self.symbol.to_lowercase())
108 }
109 type Event = DiffDepthEvent;
110}
111
112#[derive(Debug, Clone, Copy)]
113pub struct UserStream<'a> {
114 pub listen_key: &'a str,
115}
116
117#[derive(Debug, Clone, Deserialize)]
118pub struct PositionMarginCall {
119 #[serde(rename = "s")]
120 pub symbol: String,
121 #[serde(rename = "ps")]
122 pub position_side: String,
123 #[serde(rename = "pa")]
124 pub position_amount: String,
125 #[serde(rename = "mt")]
126 pub margin_type: String,
127 #[serde(rename = "iw")]
128 pub isolated_wallet: Option<String>,
129 #[serde(rename = "mp")]
130 pub mark_price: String,
131 #[serde(rename = "up")]
132 pub unrealized_pnl: String,
133 #[serde(rename = "mm")]
134 pub required_maintenance_margin: String,
135}
136
137#[derive(Debug, Clone, Deserialize)]
138pub struct MarginCallEvent {
139 #[serde(rename = "E")]
140 pub event_time: usize,
141 #[serde(rename = "cw")]
142 pub cross_wallet_balance: Option<String>,
143 #[serde(rename = "p")]
144 pub positions: Vec<PositionMarginCall>,
145}
146
147#[derive(Debug, Clone, Deserialize)]
148pub struct BalancePositionUpdateEvent {
149 #[serde(rename = "E")]
150 pub event_time: usize,
151 #[serde(rename = "T")]
152 pub transaction_time: usize,
153 #[serde(rename = "a")]
154 pub balance_position_update: BalancePositionUpdate,
155}
156
157#[derive(Debug, Clone, Deserialize)]
158pub struct BalancePositionUpdate {
159 #[serde(rename = "m")]
160 pub reason: String,
161 #[serde(rename = "B")]
162 pub balance_updates: Vec<BalanceUpdate>,
163 #[serde(rename = "P")]
164 pub position_updates: Vec<PositionUpdate>,
165}
166
167#[derive(Debug, Clone, Deserialize)]
168pub struct BalanceUpdate {
169 #[serde(rename = "a")]
170 pub asset: String,
171 #[serde(rename = "wb")]
172 pub wallet_balance: String,
173 #[serde(rename = "cw")]
174 pub cross_wallet_balance: String,
175 #[serde(rename = "bc")]
176 pub balance_change: String,
177}
178
179#[derive(Debug, Clone, Deserialize)]
180pub struct PositionUpdate {
181 #[serde(rename = "s")]
182 pub symbol: String,
183 #[serde(rename = "pa")]
184 pub position_amount: String,
185 #[serde(rename = "ep")]
186 pub entry_price: String,
187 #[serde(rename = "bep")]
188 pub breakeven_price: String,
189 #[serde(rename = "cr")]
190 pub realized_pnl: String,
191 #[serde(rename = "up")]
192 pub unrealized_pnl: String,
193 #[serde(rename = "mt")]
194 pub margin_type: String,
195 #[serde(rename = "iw")]
196 pub isolated_wallet: Option<String>,
197 #[serde(rename = "ps")]
198 pub position_side: String,
199}
200
201#[derive(Debug, Clone, Deserialize)]
202pub struct OrderUpdateEvent {
203 #[serde(rename = "E")]
204 pub event_time: usize,
205 #[serde(rename = "T")]
206 pub transaction_time: usize,
207 #[serde(rename = "o")]
208 pub order_update: OrderUpdate,
209}
210
211#[derive(Debug, Clone, Deserialize)]
212pub struct OrderUpdate {
213 #[serde(rename = "s")]
214 pub symbol: String,
215 #[serde(rename = "c")]
216 pub client_order_id: String,
217 #[serde(rename = "S")]
218 pub side: String,
219 #[serde(rename = "o")]
220 pub order_type: String,
221 #[serde(rename = "f")]
222 pub time_in_force: String,
223 #[serde(rename = "q")]
224 pub orig_qty: String,
225 #[serde(rename = "p")]
226 pub orig_price: String,
227 #[serde(rename = "ap")]
228 pub average_price: String,
229 #[serde(rename = "sp")]
230 pub stop_price: String,
231 #[serde(rename = "x")]
232 pub current_order_execution_type: String,
233 #[serde(rename = "X")]
234 pub current_order_status: String,
235 #[serde(rename = "i")]
236 pub order_id: usize,
237 #[serde(rename = "l")]
238 pub last_filled_qty: String,
239 #[serde(rename = "z")]
240 pub cummulative_filled_qty: String,
241 #[serde(rename = "L")]
242 pub last_fill_price: String,
243 #[serde(rename = "N")]
244 pub commission_asset: Option<String>,
245 #[serde(rename = "n")]
246 pub commission_amount: Option<String>,
247 #[serde(rename = "T")]
248 pub order_trade_time: usize,
249 #[serde(rename = "t")]
250 pub order_trade_id: usize,
251 #[serde(rename = "b")]
252 pub bid_notional: String,
253 #[serde(rename = "a")]
254 pub ask_notional: String,
255 #[serde(rename = "m")]
256 pub is_trade_maker: bool,
257 #[serde(rename = "R")]
258 pub is_reduce_only: bool,
259 #[serde(rename = "wt")]
260 pub stop_price_working_type: String,
261 #[serde(rename = "ot")]
262 pub orig_order_type: String,
263 #[serde(rename = "ps")]
264 pub position_side: String,
265 #[serde(rename = "cp")]
266 pub close_position: bool,
267 #[serde(rename = "AP")]
268 pub activation_price: Option<String>,
269 #[serde(rename = "cr")]
270 pub callback_rate: Option<String>,
271 #[serde(rename = "pP")]
272 pub price_protection: bool,
273 #[serde(rename = "rp")]
274 pub trade_realized_profit: String,
275 #[serde(rename = "V")]
276 pub self_trade_prevention_mode: String,
277 #[serde(rename = "gtd")]
278 pub good_till_date: usize,
279}
280
281#[derive(Debug, Clone, Deserialize)]
282pub struct AccountConfigurationUpdateEvent {
283 #[serde(rename = "E")]
284 pub event_time: usize,
285 #[serde(rename = "T")]
286 pub transaction_time: usize,
287 #[serde(rename = "ac")]
288 pub leverage: Option<LeverageUpdate>,
289 #[serde(rename = "ai")]
290 pub multi_asset_mode: Option<MultiAssetModeUpdate>,
291}
292
293#[derive(Debug, Clone, Deserialize)]
294pub struct LeverageUpdate {
295 #[serde(rename = "s")]
296 pub symbol: String,
297 #[serde(rename = "l")]
298 pub leverage: usize,
299}
300
301#[derive(Debug, Clone, Deserialize)]
302pub struct MultiAssetModeUpdate {
303 #[serde(rename = "j")]
304 pub multi_asset_mode: bool,
305}
306
307#[derive(Debug, Clone, Deserialize)]
308pub struct ConditionalOrderTriggerRejectEvent {
309 #[serde(rename = "E")]
310 pub event_time: usize,
311 #[serde(rename = "T")]
312 pub transaction_time: usize,
313 #[serde(rename = "or")]
314 pub conditional_order_trigger_reject: ConditionalOrderTriggerReject,
315}
316
317#[derive(Debug, Clone, Deserialize)]
318pub struct ConditionalOrderTriggerReject {
319 #[serde(rename = "s")]
320 pub symbol: String,
321 #[serde(rename = "i")]
322 pub order_id: usize,
323}
324
325#[derive(Debug, Clone, Deserialize)]
326pub struct ListenKeyExpiredEvent {
327 #[serde(rename = "E")]
328 pub event_time: usize,
329 #[serde(rename = "listenKey")]
330 pub listen_key: String,
331}
332
333#[derive(Debug, Clone, Deserialize)]
334#[serde(tag = "e")]
335#[allow(clippy::large_enum_variant)]
336pub enum UserStreamEvent {
337 #[serde(rename = "MARGIN_CALL")]
338 MarginCall(MarginCallEvent),
339 #[serde(rename = "ACCOUNT_UPDATE")]
340 BalancePositionUpdate(BalancePositionUpdateEvent),
341 #[serde(rename = "ORDER_TRADE_UPDATE")]
342 OrderUpdate(OrderUpdateEvent),
343 #[serde(rename = "ACCOUNT_CONFIG_UPDATE")]
344 AccountConfigurationUpdate(AccountConfigurationUpdateEvent),
345 #[serde(rename = "CONDITIONAL_ORDER_TRIGGER_REJECT")]
346 ConditionalOrderTriggerReject(ConditionalOrderTriggerRejectEvent),
347 #[serde(rename = "listenKeyExpired")]
348 ListenKeyExpired(ListenKeyExpiredEvent),
349}
350
351impl<'a> StreamTopic for UserStream<'a> {
352 const PRODUCT: Product = Product::UsdMFutures;
353 fn endpoint(&self) -> String {
354 format!("/ws/{}", self.listen_key)
355 }
356 type Event = UserStreamEvent;
357}