1use serde::{Deserialize, Serialize};
2use serde_json::{from_value, Value};
3use crate::errors::{Error, Result};
4
5#[derive(Deserialize, Clone)]
6pub struct Empty {}
7
8#[derive(Serialize, Deserialize, Clone)]
9#[serde(rename_all = "camelCase")]
10pub struct ServerTime {
11 pub server_time: u64,
12}
13
14#[derive(Debug, Serialize, Deserialize, Clone)]
15#[serde(rename_all = "camelCase")]
16pub struct ExchangeInformation {
17 pub timezone: String,
18 pub server_time: u64,
19 pub rate_limits: Vec<RateLimit>,
20 pub symbols: Vec<Symbol>,
21}
22
23#[derive(Debug, Serialize, Deserialize, Clone)]
24#[serde(rename_all = "camelCase")]
25pub struct RateLimit {
26 pub rate_limit_type: String,
27 pub interval: String,
28 pub interval_num: u16,
29 pub limit: u64,
30}
31
32#[derive(Debug, Serialize, Deserialize, Clone)]
33#[serde(rename_all = "camelCase")]
34pub struct Symbol {
35 pub symbol: String,
36 pub status: String,
37 pub base_asset: String,
38 pub base_asset_precision: u64,
39 pub quote_asset: String,
40 pub quote_precision: u64,
41 pub order_types: Vec<String>,
42 pub iceberg_allowed: bool,
43 pub is_spot_trading_allowed: bool,
44 pub is_margin_trading_allowed: bool,
45 pub filters: Vec<Filters>,
46}
47
48#[derive(Debug, Serialize, Deserialize, Clone)]
49#[serde(tag = "filterType")]
50pub enum Filters {
51 #[serde(rename = "PRICE_FILTER")]
52 #[serde(rename_all = "camelCase")]
53 PriceFilter {
54 min_price: String,
55 max_price: String,
56 tick_size: String,
57 },
58 #[serde(rename = "PERCENT_PRICE")]
59 #[serde(rename_all = "camelCase")]
60 PercentPrice {
61 multiplier_up: String,
62 multiplier_down: String,
63 avg_price_mins: Option<f64>,
64 },
65 #[serde(rename = "PERCENT_PRICE_BY_SIDE")]
66 #[serde(rename_all = "camelCase")]
67 PercentPriceBySide {
68 bid_multiplier_up: String,
69 bid_multiplier_down: String,
70 ask_multiplier_up: String,
71 ask_multiplier_down: String,
72 avg_price_mins: Option<f64>,
73 },
74 #[serde(rename = "LOT_SIZE")]
75 #[serde(rename_all = "camelCase")]
76 LotSize {
77 min_qty: String,
78 max_qty: String,
79 step_size: String,
80 },
81 #[serde(rename = "MIN_NOTIONAL")]
82 #[serde(rename_all = "camelCase")]
83 MinNotional {
84 notional: Option<String>,
85 min_notional: Option<String>,
86 apply_to_market: Option<bool>,
87 avg_price_mins: Option<f64>,
88 },
89 #[serde(rename = "NOTIONAL")]
90 #[serde(rename_all = "camelCase")]
91 Notional {
92 notional: Option<String>,
93 min_notional: Option<String>,
94 apply_to_market: Option<bool>,
95 avg_price_mins: Option<f64>,
96 },
97 #[serde(rename = "ICEBERG_PARTS")]
98 #[serde(rename_all = "camelCase")]
99 IcebergParts { limit: Option<u16> },
100 #[serde(rename = "MAX_NUM_ORDERS")]
101 #[serde(rename_all = "camelCase")]
102 MaxNumOrders { max_num_orders: Option<u16> },
103 #[serde(rename = "MAX_NUM_ALGO_ORDERS")]
104 #[serde(rename_all = "camelCase")]
105 MaxNumAlgoOrders { max_num_algo_orders: Option<u16> },
106 #[serde(rename = "MAX_NUM_ICEBERG_ORDERS")]
107 #[serde(rename_all = "camelCase")]
108 MaxNumIcebergOrders { max_num_iceberg_orders: u16 },
109 #[serde(rename = "MAX_POSITION")]
110 #[serde(rename_all = "camelCase")]
111 MaxPosition { max_position: String },
112 #[serde(rename = "MARKET_LOT_SIZE")]
113 #[serde(rename_all = "camelCase")]
114 MarketLotSize {
115 min_qty: String,
116 max_qty: String,
117 step_size: String,
118 },
119 #[serde(rename = "TRAILING_DELTA")]
120 #[serde(rename_all = "camelCase")]
121 TrailingData {
122 min_trailing_above_delta: Option<u16>,
123 max_trailing_above_delta: Option<u16>,
124 min_trailing_below_delta: Option<u16>,
125 max_trailing_below_delta: Option<u16>,
126 },
127}
128
129#[derive(Debug, Serialize, Deserialize, Clone)]
130#[serde(rename_all = "camelCase")]
131pub struct AccountInformation {
132 pub maker_commission: f32,
133 pub taker_commission: f32,
134 pub buyer_commission: f32,
135 pub seller_commission: f32,
136 pub can_trade: bool,
137 pub can_withdraw: bool,
138 pub can_deposit: bool,
139 pub balances: Vec<Balance>,
140}
141
142#[derive(Debug, Serialize, Deserialize, Clone)]
143#[serde(rename_all = "camelCase")]
144pub struct Balance {
145 pub asset: String,
146 pub free: String,
147 pub locked: String,
148}
149
150#[derive(Debug, Serialize, Deserialize, Clone)]
151#[serde(rename_all = "camelCase")]
152pub struct Order {
153 pub symbol: String,
154 pub order_id: u64,
155 pub order_list_id: i64,
156 pub client_order_id: String,
157 #[serde(with = "string_or_float")]
158 pub price: f64,
159 pub orig_qty: String,
160 pub executed_qty: String,
161 pub cummulative_quote_qty: String,
162 pub status: String,
163 pub time_in_force: String,
164 #[serde(rename = "type")]
165 pub type_name: String,
166 pub side: String,
167 #[serde(with = "string_or_float")]
168 pub stop_price: f64,
169 pub iceberg_qty: String,
170 pub time: u64,
171 pub update_time: u64,
172 pub is_working: bool,
173 pub orig_quote_order_qty: String,
174}
175
176#[derive(Debug, Serialize, Deserialize, Clone)]
177#[serde(rename_all = "camelCase")]
178pub struct OrderCanceled {
179 pub symbol: String,
180 pub orig_client_order_id: Option<String>,
181 pub order_id: Option<u64>,
182 pub client_order_id: Option<String>,
183}
184#[derive(Debug, Serialize, Deserialize, Clone)]
185#[serde(rename_all = "camelCase")]
186pub enum SpotFuturesTransferType {
187 SpotToUsdtFutures = 1,
188 UsdtFuturesToSpot = 2,
189 SpotToCoinFutures = 3,
190 CoinFuturesToSpot = 4,
191}
192
193#[derive(Debug, Serialize, Deserialize, Clone)]
194#[serde(rename_all = "camelCase")]
195pub struct TransactionId {
196 pub tran_id: u64,
197}
198
199#[derive(Debug, Serialize, Deserialize, Clone)]
200#[serde(rename_all = "camelCase")]
201pub struct Transaction {
202 pub symbol: String,
203 pub order_id: u64,
204 pub order_list_id: Option<i64>,
205 pub client_order_id: String,
206 pub transact_time: u64,
207 #[serde(with = "string_or_float")]
208 pub price: f64,
209 #[serde(with = "string_or_float")]
210 pub orig_qty: f64,
211 #[serde(with = "string_or_float")]
212 pub executed_qty: f64,
213 #[serde(with = "string_or_float")]
214 pub cummulative_quote_qty: f64,
215 #[serde(with = "string_or_float", default = "default_stop_price")]
216 pub stop_price: f64,
217 pub status: String,
218 pub time_in_force: String,
219 #[serde(rename = "type")]
220 pub type_name: String,
221 pub side: String,
222 pub fills: Option<Vec<FillInfo>>,
223}
224
225fn default_stop_price() -> f64 {
226 0.0
227}
228
229#[derive(Debug, Serialize, Deserialize, Clone)]
230#[serde(rename_all = "camelCase")]
231pub struct FillInfo {
232 #[serde(with = "string_or_float")]
233 pub price: f64,
234 #[serde(with = "string_or_float")]
235 pub qty: f64,
236 #[serde(with = "string_or_float")]
237 pub commission: f64,
238 pub commission_asset: String,
239 pub trade_id: Option<u64>,
240}
241#[derive(Debug, Serialize, Deserialize, Clone)]
246#[serde(rename_all = "camelCase")]
247pub struct TestResponse {}
248
249#[derive(Debug, Serialize, Deserialize, Clone)]
250#[serde(rename_all = "camelCase")]
251pub struct OrderBook {
252 pub last_update_id: u64,
253 pub bids: Vec<Bids>,
254 pub asks: Vec<Asks>,
255}
256
257#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)]
258pub struct Bids {
259 #[serde(with = "string_or_float")]
260 pub price: f64,
261 #[serde(with = "string_or_float")]
262 pub qty: f64,
263}
264
265impl Bids {
266 pub fn new(price: f64, qty: f64) -> Bids {
267 Bids { price, qty }
268 }
269}
270
271#[derive(Debug, Serialize, Deserialize, Clone)]
272pub struct Asks {
273 #[serde(with = "string_or_float")]
274 pub price: f64,
275 #[serde(with = "string_or_float")]
276 pub qty: f64,
277}
278
279#[derive(Debug, Serialize, Deserialize, Clone)]
280#[serde(rename_all = "camelCase")]
281pub struct UserDataStream {
282 pub listen_key: String,
283}
284
285#[derive(Debug, Serialize, Deserialize, Clone)]
286pub struct Success {}
287
288#[derive(Debug, Serialize, Deserialize, Clone)]
289#[serde(rename_all = "camelCase")]
290#[serde(untagged)]
291pub enum Prices {
292 AllPrices(Vec<SymbolPrice>),
293}
294
295#[derive(Debug, Serialize, Deserialize, Clone)]
296pub struct SymbolPrice {
297 pub symbol: String,
298 #[serde(with = "string_or_float")]
299 pub price: f64,
300}
301
302#[derive(Debug, Serialize, Deserialize, Clone)]
303pub struct AveragePrice {
304 pub mins: u64,
305 #[serde(with = "string_or_float")]
306 pub price: f64,
307}
308
309#[derive(Debug, Serialize, Deserialize, Clone)]
310#[serde(rename_all = "camelCase")]
311#[serde(untagged)]
312pub enum BookTickers {
313 AllBookTickers(Vec<Tickers>),
314}
315
316#[derive(Debug, Serialize, Deserialize, Clone)]
317pub enum KlineSummaries {
318 AllKlineSummaries(Vec<KlineSummary>),
319}
320
321#[derive(Debug, Serialize, Deserialize, Clone)]
322#[serde(rename_all = "camelCase")]
323pub struct Tickers {
324 pub symbol: String,
325 #[serde(with = "string_or_float")]
326 pub bid_price: f64,
327 #[serde(with = "string_or_float")]
328 pub bid_qty: f64,
329 #[serde(with = "string_or_float")]
330 pub ask_price: f64,
331 #[serde(with = "string_or_float")]
332 pub ask_qty: f64,
333}
334
335#[derive(Debug, Serialize, Deserialize, Clone)]
336#[serde(rename_all = "camelCase")]
337pub struct TradeHistory {
338 pub id: u64,
339 #[serde(with = "string_or_float")]
340 pub price: f64,
341 #[serde(with = "string_or_float")]
342 pub qty: f64,
343 pub commission: String,
344 pub commission_asset: String,
345 pub time: u64,
346 pub is_buyer: bool,
347 pub is_maker: bool,
348 pub is_best_match: bool,
349}
350
351#[derive(Debug, Serialize, Deserialize, Clone)]
352#[serde(rename_all = "camelCase")]
353pub struct PriceStats {
354 pub symbol: String,
355 pub price_change: String,
356 pub price_change_percent: String,
357 pub weighted_avg_price: String,
358 #[serde(with = "string_or_float")]
359 pub prev_close_price: f64,
360 #[serde(with = "string_or_float")]
361 pub last_price: f64,
362 #[serde(with = "string_or_float")]
363 pub bid_price: f64,
364 #[serde(with = "string_or_float")]
365 pub ask_price: f64,
366 #[serde(with = "string_or_float")]
367 pub open_price: f64,
368 #[serde(with = "string_or_float")]
369 pub high_price: f64,
370 #[serde(with = "string_or_float")]
371 pub low_price: f64,
372 #[serde(with = "string_or_float")]
373 pub volume: f64,
374 pub open_time: u64,
375 pub close_time: u64,
376 pub first_id: i64,
377 pub last_id: i64,
378 pub count: u64,
379}
380
381#[derive(Debug, Serialize, Deserialize, Clone)]
382pub struct AggTrade {
383 #[serde(rename = "T")]
384 pub time: u64,
385 #[serde(rename = "a")]
386 pub agg_id: u64,
387 #[serde(rename = "f")]
388 pub first_id: u64,
389 #[serde(rename = "l")]
390 pub last_id: u64,
391 #[serde(rename = "m")]
392 pub maker: bool,
393 #[serde(rename = "M")]
394 pub best_match: bool,
395 #[serde(rename = "p", with = "string_or_float")]
396 pub price: f64,
397 #[serde(rename = "q", with = "string_or_float")]
398 pub qty: f64,
399}
400
401#[derive(Debug, Serialize, Deserialize, Clone)]
402#[serde(rename_all = "camelCase")]
403pub struct UserDataStreamExpiredEvent {
404 #[serde(rename = "e")]
405 pub event_type: String,
406
407 #[serde(rename = "E")]
408 pub event_time: u64,
409}
410
411#[derive(Debug, Serialize, Deserialize, Clone)]
412#[serde(rename_all = "camelCase")]
413pub struct AccountUpdateEvent {
414 #[serde(rename = "e")]
415 pub event_type: String,
416
417 #[serde(rename = "E")]
418 pub event_time: u64,
419
420 #[serde(rename = "a")]
421 pub data: AccountUpdateDataEvent,
422}
423
424#[derive(Debug, Serialize, Deserialize, Clone)]
425#[serde(rename_all = "camelCase")]
426pub struct AccountUpdateDataEvent {
427 #[serde(rename = "m")]
428 pub reason: String,
429
430 #[serde(rename = "B")]
431 pub balances: Vec<EventBalance>,
432
433 #[serde(rename = "P")]
434 pub positions: Vec<EventPosition>,
435}
436
437#[derive(Debug, Serialize, Deserialize, Clone)]
438#[serde(rename_all = "camelCase")]
439pub struct EventBalance {
440 #[serde(rename = "a")]
441 pub asset: String,
442 #[serde(rename = "wb")]
443 pub wallet_balance: String,
444 #[serde(rename = "cw")]
445 pub cross_wallet_balance: String,
446 #[serde(rename = "bc")]
447 pub balance_change: String, }
449
450#[derive(Debug, Serialize, Deserialize, Clone)]
451#[serde(rename_all = "camelCase")]
452pub struct EventPosition {
453 #[serde(rename = "s")]
454 pub symbol: String,
455 #[serde(rename = "pa")]
456 pub position_amount: String,
457 #[serde(rename = "ep")]
458 pub entry_price: String,
459 #[serde(rename = "cr")]
460 pub accumulated_realized: String, #[serde(rename = "up")]
462 pub unrealized_pnl: String,
463 #[serde(rename = "mt")]
464 pub margin_type: String,
465 #[serde(rename = "iw")]
466 pub isolated_wallet: String,
467 #[serde(rename = "ps")]
468 pub position_side: String,
469}
470
471#[derive(Debug, Serialize, Deserialize, Clone)]
472#[serde(rename_all = "camelCase")]
473pub struct BalanceUpdateEvent {
474 #[serde(rename = "B")]
475 pub balance: Vec<EventBalance>,
476
477 #[serde(rename = "e")]
478 pub event_type: String,
479
480 #[serde(rename = "E")]
481 pub event_time: u64,
482
483 #[serde(rename = "u")]
484 pub last_account_update_time: u64,
485}
486
487#[derive(Debug, Serialize, Deserialize, Clone)]
488#[serde(rename_all = "camelCase")]
489pub struct OrderTradeEvent {
490 #[serde(rename = "e")]
491 pub event_type: String,
492
493 #[serde(rename = "E")]
494 pub event_time: u64,
495
496 #[serde(rename = "s")]
497 pub symbol: String,
498
499 #[serde(rename = "c")]
500 pub new_client_order_id: String,
501
502 #[serde(rename = "S")]
503 pub side: String,
504
505 #[serde(rename = "o")]
506 pub order_type: String,
507
508 #[serde(rename = "f")]
509 pub time_in_force: String,
510
511 #[serde(rename = "q")]
512 pub qty: String,
513
514 #[serde(rename = "p")]
515 pub price: String,
516
517 #[serde(skip, rename = "P")]
518 pub p_ignore: String,
519
520 #[serde(skip, rename = "F")]
521 pub f_ignore: String,
522
523 #[serde(skip)]
524 pub g: i32,
525
526 #[serde(skip, rename = "C")]
527 pub c_ignore: Option<String>,
528
529 #[serde(rename = "x")]
530 pub execution_type: String,
531
532 #[serde(rename = "X")]
533 pub order_status: String,
534
535 #[serde(rename = "r")]
536 pub order_reject_reason: String,
537
538 #[serde(rename = "i")]
539 pub order_id: u64,
540
541 #[serde(rename = "l")]
542 pub qty_last_filled_trade: String,
543
544 #[serde(rename = "z")]
545 pub accumulated_qty_filled_trades: String,
546
547 #[serde(rename = "L")]
548 pub price_last_filled_trade: String,
549
550 #[serde(rename = "n")]
551 pub commission: String,
552
553 #[serde(skip, rename = "N")]
554 pub asset_commisioned: Option<String>,
555
556 #[serde(rename = "T")]
557 pub trade_order_time: u64,
558
559 #[serde(rename = "t")]
560 pub trade_id: i64,
561
562 #[serde(skip, rename = "I")]
563 pub i_ignore: u64,
564
565 #[serde(skip)]
566 pub w: bool,
567
568 #[serde(rename = "m")]
569 pub is_buyer_maker: bool,
570
571 #[serde(skip, rename = "M")]
572 pub m_ignore: bool,
573}
574
575#[derive(Debug, Serialize, Deserialize, Clone)]
583#[serde(rename_all = "camelCase")]
584pub struct AggrTradesEvent {
585 #[serde(rename = "e")]
586 pub event_type: String,
587
588 #[serde(rename = "E")]
589 pub event_time: u64,
590
591 #[serde(rename = "s")]
592 pub symbol: String,
593
594 #[serde(rename = "a")]
595 pub aggregated_trade_id: u64,
596
597 #[serde(rename = "p")]
598 pub price: String,
599
600 #[serde(rename = "q")]
601 pub qty: String,
602
603 #[serde(rename = "f")]
604 pub first_break_trade_id: u64,
605
606 #[serde(rename = "l")]
607 pub last_break_trade_id: u64,
608
609 #[serde(rename = "T")]
610 pub trade_order_time: u64,
611
612 #[serde(rename = "m")]
613 pub is_buyer_maker: bool,
614
615 #[serde(skip, rename = "M")]
616 pub m_ignore: bool,
617}
618
619#[derive(Debug, Serialize, Deserialize, Clone)]
627#[serde(rename_all = "camelCase")]
628pub struct TradeEvent {
629 #[serde(rename = "e")]
630 pub event_type: String,
631
632 #[serde(rename = "E")]
633 pub event_time: u64,
634
635 #[serde(rename = "s")]
636 pub symbol: String,
637
638 #[serde(rename = "t")]
639 pub trade_id: u64,
640
641 #[serde(rename = "p")]
642 pub price: String,
643
644 #[serde(rename = "q")]
645 pub qty: String,
646
647 #[serde(rename = "b")]
648 pub buyer_order_id: u64,
649
650 #[serde(rename = "a")]
651 pub seller_order_id: u64,
652
653 #[serde(rename = "T")]
654 pub trade_order_time: u64,
655
656 #[serde(rename = "m")]
657 pub is_buyer_maker: bool,
658
659 #[serde(skip, rename = "M")]
660 pub m_ignore: bool,
661}
662
663#[derive(Debug, Serialize, Deserialize, Clone)]
664#[serde(rename_all = "camelCase")]
665pub struct IndexPriceEvent {
666 #[serde(rename = "e")]
667 pub event_type: String,
668
669 #[serde(rename = "E")]
670 pub event_time: u64,
671
672 #[serde(rename = "i")]
673 pub pair: String,
674
675 #[serde(rename = "p")]
676 pub price: String,
677}
678#[derive(Debug, Serialize, Deserialize, Clone)]
681#[serde(rename_all = "camelCase")]
682pub struct MarkPriceEvent {
683 #[serde(rename = "E")]
684 pub event_time: u64,
685
686 #[serde(rename = "P")]
687 pub estimate_settle_price: String,
688
689 #[serde(rename = "T")]
690 pub next_funding_time: u64,
691
692 #[serde(rename = "e")]
693 pub event_type: String,
694
695 #[serde(rename = "i")]
696 pub index_price: Option<String>,
697
698 #[serde(rename = "p")]
699 pub mark_price: String,
700
701 #[serde(rename = "r")]
702 pub funding_rate: String,
703
704 #[serde(rename = "s")]
705 pub symbol: String,
706}
707
708#[derive(Debug, Serialize, Deserialize, Clone)]
712#[serde(rename_all = "camelCase")]
713pub struct LiquidationEvent {
714 #[serde(rename = "e")]
715 pub event_type: String,
716
717 #[serde(rename = "E")]
718 pub event_time: u64,
719
720 #[serde(rename = "o")]
721 pub liquidation_order: LiquidationOrder,
722}
723
724#[derive(Debug, Serialize, Deserialize, Clone)]
725#[serde(rename_all = "camelCase")]
726pub struct LiquidationOrder {
727 #[serde(rename = "s")]
728 pub symbol: String,
729
730 #[serde(rename = "S")]
731 pub side: String,
732
733 #[serde(rename = "o")]
734 pub order_type: String,
735
736 #[serde(rename = "f")]
737 pub time_in_force: String,
738
739 #[serde(rename = "q")]
740 pub original_quantity: String,
741
742 #[serde(rename = "p")]
743 pub price: String,
744
745 #[serde(rename = "ap")]
746 pub average_price: String,
747
748 #[serde(rename = "X")]
749 pub order_status: String,
750
751 #[serde(rename = "l")]
752 pub order_last_filled_quantity: String,
753
754 #[serde(rename = "z")]
755 pub order_filled_accumulated_quantity: String,
756
757 #[serde(rename = "T")]
758 pub order_trade_time: u64,
759}
760
761#[derive(Debug, Serialize, Deserialize, Clone)]
762#[serde(rename_all = "camelCase")]
763pub struct BookTickerEvent {
764 #[serde(rename = "u")]
765 pub update_id: u64,
766
767 #[serde(rename = "s")]
768 pub symbol: String,
769
770 #[serde(rename = "b")]
771 pub best_bid: String,
772
773 #[serde(rename = "B")]
774 pub best_bid_qty: String,
775
776 #[serde(rename = "a")]
777 pub best_ask: String,
778
779 #[serde(rename = "A")]
780 pub best_ask_qty: String,
781}
782
783#[derive(Debug, Serialize, Deserialize, Clone)]
784#[serde(rename_all = "camelCase")]
785pub struct DayTickerEvent {
786 #[serde(rename = "e")]
787 pub event_type: String,
788
789 #[serde(rename = "E")]
790 pub event_time: u64,
791
792 #[serde(rename = "s")]
793 pub symbol: String,
794
795 #[serde(rename = "p")]
796 pub price_change: String,
797
798 #[serde(rename = "P")]
799 pub price_change_percent: String,
800
801 #[serde(rename = "w")]
802 pub average_price: String,
803
804 #[serde(rename = "x")]
805 pub prev_close: String,
806
807 #[serde(rename = "c")]
808 pub current_close: String,
809
810 #[serde(rename = "Q")]
811 pub current_close_qty: String,
812
813 #[serde(rename = "b")]
814 pub best_bid: String,
815
816 #[serde(rename = "B")]
817 pub best_bid_qty: String,
818
819 #[serde(rename = "a")]
820 pub best_ask: String,
821
822 #[serde(rename = "A")]
823 pub best_ask_qty: String,
824
825 #[serde(rename = "o")]
826 pub open: String,
827
828 #[serde(rename = "h")]
829 pub high: String,
830
831 #[serde(rename = "l")]
832 pub low: String,
833
834 #[serde(rename = "v")]
835 pub volume: String,
836
837 #[serde(rename = "q")]
838 pub quote_volume: String,
839
840 #[serde(rename = "O")]
841 pub open_time: u64,
842
843 #[serde(rename = "C")]
844 pub close_time: u64,
845
846 #[serde(rename = "F")]
847 pub first_trade_id: i64,
848
849 #[serde(rename = "L")]
850 pub last_trade_id: i64,
851
852 #[serde(rename = "n")]
853 pub num_trades: u64,
854}
855
856#[derive(Debug, Serialize, Deserialize, Clone)]
857#[serde(rename_all = "camelCase")]
858pub struct WindowTickerEvent {
859 #[serde(rename = "e")]
860 pub event_type: String,
861
862 #[serde(rename = "E")]
863 pub event_time: u64,
864
865 #[serde(rename = "s")]
866 pub symbol: String,
867
868 #[serde(rename = "p")]
869 pub price_change: String,
870
871 #[serde(rename = "P")]
872 pub price_change_percent: String,
873
874 #[serde(rename = "o")]
875 pub open: String,
876
877 #[serde(rename = "h")]
878 pub high: String,
879
880 #[serde(rename = "l")]
881 pub low: String,
882
883 #[serde(rename = "c")]
884 pub current_close: String,
885
886 #[serde(rename = "w")]
887 pub average_price: String,
888
889 #[serde(rename = "v")]
890 pub volume: String,
891
892 #[serde(rename = "q")]
893 pub quote_volume: String,
894
895 #[serde(rename = "O")]
896 pub open_time: u64,
897
898 #[serde(rename = "C")]
899 pub close_time: u64,
900
901 #[serde(rename = "F")]
902 pub first_trade_id: i64,
903
904 #[serde(rename = "L")]
905 pub last_trade_id: i64,
906
907 #[serde(rename = "n")]
908 pub num_trades: u64,
909}
910
911#[derive(Debug, Serialize, Deserialize, Clone)]
912#[serde(rename_all = "camelCase")]
913pub struct MiniTickerEvent {
914 #[serde(rename = "e")]
915 pub event_type: String,
916
917 #[serde(rename = "E")]
918 pub event_time: u64,
919
920 #[serde(rename = "s")]
921 pub symbol: String,
922
923 #[serde(rename = "c")]
924 pub close: String,
925
926 #[serde(rename = "o")]
927 pub open: String,
928
929 #[serde(rename = "h")]
930 pub high: String,
931
932 #[serde(rename = "l")]
933 pub low: String,
934
935 #[serde(rename = "v")]
936 pub volume: String,
937
938 #[serde(rename = "q")]
939 pub quote_volume: String,
940}
941
942#[derive(Debug, Serialize, Deserialize, Clone)]
943#[serde(rename_all = "camelCase")]
944pub struct KlineEvent {
945 #[serde(rename = "e")]
946 pub event_type: String,
947
948 #[serde(rename = "E")]
949 pub event_time: u64,
950
951 #[serde(rename = "s")]
952 pub symbol: String,
953
954 #[serde(rename = "k")]
955 pub kline: Kline,
956}
957
958#[derive(Debug, Serialize, Deserialize, Clone)]
961#[serde(rename_all = "camelCase")]
962pub struct ContinuousKlineEvent {
963 #[serde(rename = "e")]
964 pub event_type: String,
965
966 #[serde(rename = "E")]
967 pub event_time: u64,
968
969 #[serde(rename = "ps")]
970 pub pair: String,
971
972 #[serde(rename = "ct")]
973 pub contract_type: String,
974
975 #[serde(rename = "k")]
976 pub kline: ContinuousKline,
977}
978
979#[derive(Debug, Serialize, Deserialize, Clone)]
982#[serde(rename_all = "camelCase")]
983pub struct IndexKlineEvent {
984 #[serde(rename = "e")]
985 pub event_type: String,
986
987 #[serde(rename = "E")]
988 pub event_time: u64,
989
990 #[serde(rename = "ps")]
991 pub pair: String,
992
993 #[serde(rename = "k")]
994 pub kline: IndexKline,
995}
996
997#[derive(Debug, Serialize, Deserialize, Clone)]
998pub struct KlineSummary {
999 pub open_time: i64,
1000
1001 pub open: String,
1002
1003 pub high: String,
1004
1005 pub low: String,
1006
1007 pub close: String,
1008
1009 pub volume: String,
1010
1011 pub close_time: i64,
1012
1013 pub quote_asset_volume: String,
1014
1015 pub number_of_trades: i64,
1016
1017 pub taker_buy_base_asset_volume: String,
1018
1019 pub taker_buy_quote_asset_volume: String,
1020}
1021
1022fn get_value(row: &[Value], index: usize, name: &'static str) -> Result<Value> {
1023 Ok(row
1024 .get(index)
1025 .ok_or_else(|| Error::KlineValueMissingError { index, name })?
1026 .clone())
1027}
1028
1029impl TryFrom<&Vec<Value>> for KlineSummary {
1030 type Error = Error;
1031
1032 fn try_from(row: &Vec<Value>) -> Result<Self> {
1033 Ok(Self {
1034 open_time: from_value(get_value(row, 0, "open_time")?)?,
1035 open: from_value(get_value(row, 1, "open")?)?,
1036 high: from_value(get_value(row, 2, "high")?)?,
1037 low: from_value(get_value(row, 3, "low")?)?,
1038 close: from_value(get_value(row, 4, "close")?)?,
1039 volume: from_value(get_value(row, 5, "volume")?)?,
1040 close_time: from_value(get_value(row, 6, "close_time")?)?,
1041 quote_asset_volume: from_value(get_value(row, 7, "quote_asset_volume")?)?,
1042 number_of_trades: from_value(get_value(row, 8, "number_of_trades")?)?,
1043 taker_buy_base_asset_volume: from_value(get_value(
1044 row,
1045 9,
1046 "taker_buy_base_asset_volume",
1047 )?)?,
1048 taker_buy_quote_asset_volume: from_value(get_value(
1049 row,
1050 10,
1051 "taker_buy_quote_asset_volume",
1052 )?)?,
1053 })
1054 }
1055}
1056
1057#[derive(Debug, Serialize, Deserialize, Clone)]
1058#[serde(rename_all = "camelCase")]
1059pub struct Kline {
1060 #[serde(rename = "t")]
1061 pub open_time: i64,
1062
1063 #[serde(rename = "T")]
1064 pub close_time: i64,
1065
1066 #[serde(rename = "s")]
1067 pub symbol: String,
1068
1069 #[serde(rename = "i")]
1070 pub interval: String,
1071
1072 #[serde(rename = "f")]
1073 pub first_trade_id: i64,
1074
1075 #[serde(rename = "L")]
1076 pub last_trade_id: i64,
1077
1078 #[serde(rename = "o")]
1079 pub open: String,
1080
1081 #[serde(rename = "c")]
1082 pub close: String,
1083
1084 #[serde(rename = "h")]
1085 pub high: String,
1086
1087 #[serde(rename = "l")]
1088 pub low: String,
1089
1090 #[serde(rename = "v")]
1091 pub volume: String,
1092
1093 #[serde(rename = "n")]
1094 pub number_of_trades: i64,
1095
1096 #[serde(rename = "x")]
1097 pub is_final_bar: bool,
1098
1099 #[serde(rename = "q")]
1100 pub quote_asset_volume: String,
1101
1102 #[serde(rename = "V")]
1103 pub taker_buy_base_asset_volume: String,
1104
1105 #[serde(rename = "Q")]
1106 pub taker_buy_quote_asset_volume: String,
1107
1108 #[serde(skip, rename = "B")]
1109 pub ignore_me: String,
1110}
1111
1112#[derive(Debug, Serialize, Deserialize, Clone)]
1113#[serde(rename_all = "camelCase")]
1114pub struct ContinuousKline {
1115 #[serde(rename = "t")]
1116 pub start_time: i64,
1117
1118 #[serde(rename = "T")]
1119 pub end_time: i64,
1120
1121 #[serde(rename = "i")]
1122 pub interval: String,
1123
1124 #[serde(rename = "f")]
1125 pub first_trade_id: i64,
1126
1127 #[serde(rename = "L")]
1128 pub last_trade_id: i64,
1129
1130 #[serde(rename = "o")]
1131 pub open: String,
1132
1133 #[serde(rename = "c")]
1134 pub close: String,
1135
1136 #[serde(rename = "h")]
1137 pub high: String,
1138
1139 #[serde(rename = "l")]
1140 pub low: String,
1141
1142 #[serde(rename = "v")]
1143 pub volume: String,
1144
1145 #[serde(rename = "n")]
1146 pub number_of_trades: i64,
1147
1148 #[serde(rename = "x")]
1149 pub is_final_bar: bool,
1150
1151 #[serde(rename = "q")]
1152 pub quote_volume: String,
1153
1154 #[serde(rename = "V")]
1155 pub active_buy_volume: String,
1156
1157 #[serde(rename = "Q")]
1158 pub active_volume_buy_quote: String,
1159
1160 #[serde(skip, rename = "B")]
1161 pub ignore_me: String,
1162}
1163
1164#[derive(Debug, Serialize, Deserialize, Clone)]
1166#[serde(rename_all = "camelCase")]
1167pub struct IndexKline {
1168 #[serde(rename = "t")]
1169 pub start_time: i64,
1170
1171 #[serde(rename = "T")]
1172 pub end_time: i64,
1173
1174 #[serde(skip, rename = "s")]
1175 pub ignore_me: String,
1176
1177 #[serde(rename = "i")]
1178 pub interval: String,
1179
1180 #[serde(rename = "f")]
1181 pub first_trade_id: i64,
1182
1183 #[serde(rename = "L")]
1184 pub last_trade_id: i64,
1185
1186 #[serde(rename = "o")]
1187 pub open: String,
1188
1189 #[serde(rename = "c")]
1190 pub close: String,
1191
1192 #[serde(rename = "h")]
1193 pub high: String,
1194
1195 #[serde(rename = "l")]
1196 pub low: String,
1197
1198 #[serde(rename = "v")]
1199 pub volume: String,
1200
1201 #[serde(rename = "n")]
1202 pub number_of_trades: i64,
1203
1204 #[serde(rename = "x")]
1205 pub is_final_bar: bool,
1206
1207 #[serde(skip, rename = "q")]
1208 pub ignore_me2: String,
1209
1210 #[serde(skip, rename = "V")]
1211 pub ignore_me3: String,
1212
1213 #[serde(skip, rename = "Q")]
1214 pub ignore_me4: String,
1215
1216 #[serde(skip, rename = "B")]
1217 pub ignore_me5: String,
1218}
1219
1220#[derive(Debug, Serialize, Deserialize, Clone)]
1221#[serde(rename_all = "camelCase")]
1222pub struct DepthOrderBookEvent {
1223 #[serde(rename = "e")]
1224 pub event_type: String,
1225
1226 #[serde(rename = "E")]
1227 pub event_time: u64,
1228
1229 #[serde(rename = "s")]
1230 pub symbol: String,
1231
1232 #[serde(rename = "U")]
1233 pub first_update_id: u64,
1234
1235 #[serde(rename = "u")]
1236 pub final_update_id: u64,
1237
1238 #[serde(rename = "pu")]
1239 #[serde(default)]
1240 pub previous_final_update_id: Option<u64>,
1241
1242 #[serde(rename = "b")]
1243 pub bids: Vec<Bids>,
1244
1245 #[serde(rename = "a")]
1246 pub asks: Vec<Asks>,
1247}
1248
1249#[derive(Debug, Serialize, Deserialize, Clone)]
1251#[serde(rename_all = "camelCase")]
1252pub struct CoinInfo {
1253 pub coin: String,
1254 pub deposit_all_enable: bool,
1255 #[serde(with = "string_or_float")]
1256 pub free: f64,
1257 #[serde(with = "string_or_float")]
1258 pub freeze: f64,
1259 #[serde(with = "string_or_float")]
1260 pub ipoable: f64,
1261 #[serde(with = "string_or_float")]
1262 pub ipoing: f64,
1263 pub is_legal_money: bool,
1264 #[serde(with = "string_or_float")]
1265 pub locked: f64,
1266 pub name: String,
1267 pub network_list: Vec<Network>,
1268 #[serde(with = "string_or_float")]
1269 pub storage: f64,
1270 pub trading: bool,
1271 pub withdraw_all_enable: bool,
1272 #[serde(with = "string_or_float")]
1273 pub withdrawing: f64,
1274}
1275
1276#[derive(Debug, Serialize, Deserialize, Clone)]
1278#[serde(rename_all = "camelCase")]
1279pub struct Network {
1280 pub address_regex: String,
1281 pub coin: String,
1282 pub deposit_desc: Option<String>,
1284 pub deposit_enable: bool,
1285 pub is_default: bool,
1286 pub memo_regex: String,
1287 pub min_confirm: u32,
1289 pub name: String,
1290 pub network: String,
1291 pub reset_address_status: bool,
1292 pub special_tips: Option<String>,
1293 pub un_lock_confirm: u32,
1295 pub withdraw_desc: Option<String>,
1297 pub withdraw_enable: bool,
1298 #[serde(with = "string_or_float")]
1299 pub withdraw_fee: f64,
1300 #[serde(with = "string_or_float")]
1301 pub withdraw_min: f64,
1302 pub withdraw_integer_multiple: Option<String>,
1305}
1306
1307#[derive(Debug, Serialize, Deserialize, Clone)]
1308#[serde(rename_all = "camelCase")]
1309pub struct AssetDetail {
1310 #[serde(with = "string_or_float")]
1311 pub min_withdraw_amount: f64,
1312 pub deposit_status: bool,
1314 #[serde(with = "string_or_float")]
1315 pub withdraw_fee: f64,
1316 pub withdraw_status: bool,
1318 pub deposit_tip: Option<String>,
1320}
1321
1322#[derive(Debug, Serialize, Deserialize, Clone)]
1323pub struct DepositAddress {
1324 pub address: String,
1325 pub coin: String,
1326 pub tag: String,
1327 pub url: String,
1328}
1329
1330pub(crate) mod string_or_float {
1331 use std::fmt;
1332
1333 use serde::{de, Serializer, Deserialize, Deserializer};
1334
1335 pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
1336 where
1337 T: fmt::Display,
1338 S: Serializer,
1339 {
1340 serializer.collect_str(value)
1341 }
1342
1343 pub fn deserialize<'de, D>(deserializer: D) -> Result<f64, D::Error>
1344 where
1345 D: Deserializer<'de>,
1346 {
1347 #[derive(Deserialize)]
1348 #[serde(untagged)]
1349 enum StringOrFloat {
1350 String(String),
1351 Float(f64),
1352 }
1353
1354 match StringOrFloat::deserialize(deserializer)? {
1355 StringOrFloat::String(s) => {
1356 if s == "INF" {
1357 Ok(f64::INFINITY)
1358 } else {
1359 s.parse().map_err(de::Error::custom)
1360 }
1361 }
1362 StringOrFloat::Float(i) => Ok(i),
1363 }
1364 }
1365}
1366
1367pub(crate) mod string_or_float_opt {
1368 use std::fmt;
1369
1370 use serde::{Serializer, Deserialize, Deserializer};
1371
1372 pub fn serialize<T, S>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
1373 where
1374 T: fmt::Display,
1375 S: Serializer,
1376 {
1377 match value {
1378 Some(v) => crate::model::string_or_float::serialize(v, serializer),
1379 None => serializer.serialize_none(),
1380 }
1381 }
1382
1383 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<f64>, D::Error>
1384 where
1385 D: Deserializer<'de>,
1386 {
1387 #[derive(Deserialize)]
1388 #[serde(untagged)]
1389 enum StringOrFloat {
1390 String(()),
1391 Float(()),
1392 }
1393
1394 Ok(Some(crate::model::string_or_float::deserialize(
1395 deserializer,
1396 )?))
1397 }
1398}
1399
1400pub(crate) mod string_or_bool {
1401 use std::fmt;
1402
1403 use serde::{de, Serializer, Deserialize, Deserializer};
1404
1405 pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
1406 where
1407 T: fmt::Display,
1408 S: Serializer,
1409 {
1410 serializer.collect_str(value)
1411 }
1412
1413 pub fn deserialize<'de, D>(deserializer: D) -> Result<bool, D::Error>
1414 where
1415 D: Deserializer<'de>,
1416 {
1417 #[derive(Deserialize)]
1418 #[serde(untagged)]
1419 enum StringOrFloat {
1420 String(String),
1421 Bool(bool),
1422 }
1423
1424 match StringOrFloat::deserialize(deserializer)? {
1425 StringOrFloat::String(s) => s.parse().map_err(de::Error::custom),
1426 StringOrFloat::Bool(i) => Ok(i),
1427 }
1428 }
1429}
1430
1431#[test]
1432fn test_account_update_event() {
1433 let json = r#"
1434 {
1435 "e": "ACCOUNT_UPDATE",
1436 "E": 1564745798939,
1437 "T": 1564745798938,
1438 "a": {
1439 "m": "ORDER",
1440 "B": [
1441 {
1442 "a": "USDT",
1443 "wb": "122624.12345678",
1444 "cw": "100.12345678",
1445 "bc": "50.12345678"
1446 },
1447 {
1448 "a": "BUSD",
1449 "wb": "1.00000000",
1450 "cw": "0.00000000",
1451 "bc": "-49.12345678"
1452 }
1453 ],
1454 "P": [
1455 {
1456 "s": "BTCUSDT",
1457 "pa": "0",
1458 "ep": "0.00000",
1459 "cr": "200",
1460 "up": "0",
1461 "mt": "isolated",
1462 "iw": "0.00000000",
1463 "ps": "BOTH"
1464 },
1465 {
1466 "s": "BTCUSDT",
1467 "pa": "20",
1468 "ep": "6563.66500",
1469 "cr": "0",
1470 "up": "2850.21200",
1471 "mt": "isolated",
1472 "iw": "13200.70726908",
1473 "ps": "LONG"
1474 },
1475 {
1476 "s": "BTCUSDT",
1477 "pa": "-10",
1478 "ep": "6563.86000",
1479 "cr": "-45.04000000",
1480 "up": "-1423.15600",
1481 "mt": "isolated",
1482 "iw": "6570.42511771",
1483 "ps": "SHORT"
1484 }
1485 ]
1486 }
1487}
1488 "#;
1489
1490 let res = r#"AccountUpdateEvent { event_type: "ACCOUNT_UPDATE", event_time: 1564745798939, data: AccountUpdateDataEvent { reason: "ORDER", balances: [EventBalance { asset: "USDT", wallet_balance: "122624.12345678", cross_wallet_balance: "100.12345678", balance_change: "50.12345678" }, EventBalance { asset: "BUSD", wallet_balance: "1.00000000", cross_wallet_balance: "0.00000000", balance_change: "-49.12345678" }], positions: [EventPosition { symbol: "BTCUSDT", position_amount: "0", entry_price: "0.00000", accumulated_realized: "200", unrealized_pnl: "0", margin_type: "isolated", isolated_wallet: "0.00000000", position_side: "BOTH" }, EventPosition { symbol: "BTCUSDT", position_amount: "20", entry_price: "6563.66500", accumulated_realized: "0", unrealized_pnl: "2850.21200", margin_type: "isolated", isolated_wallet: "13200.70726908", position_side: "LONG" }, EventPosition { symbol: "BTCUSDT", position_amount: "-10", entry_price: "6563.86000", accumulated_realized: "-45.04000000", unrealized_pnl: "-1423.15600", margin_type: "isolated", isolated_wallet: "6570.42511771", position_side: "SHORT" }] } }"#;
1491 let v: AccountUpdateEvent = serde_json::from_str(json).unwrap();
1492 assert_eq!(format!("{:?}", v), res);
1493 }