1use nautilus_core::serialization::{
24 deserialize_decimal_from_str, deserialize_optional_decimal_from_str,
25};
26use nautilus_model::identifiers::{
27 ClientOrderId, InstrumentId, StrategyId, TraderId, VenueOrderId,
28};
29use nautilus_network::websocket::WebSocketClient;
30use rust_decimal::Decimal;
31use serde::{Deserialize, Serialize};
32use ustr::Ustr;
33
34use crate::{
35 common::enums::{
36 BinanceAlgoStatus, BinanceAlgoType, BinanceFuturesOrderType, BinanceKlineInterval,
37 BinanceMarginType, BinanceOrderStatus, BinancePositionSide, BinancePriceMatch,
38 BinanceSelfTradePreventionMode, BinanceSide, BinanceTimeInForce, BinanceWorkingType,
39 BinanceWsMethod,
40 },
41 futures::http::BinanceFuturesInstrument,
42};
43
44#[derive(Debug, Clone)]
50pub enum BinanceFuturesWsStreamsMessage {
51 AggTrade(BinanceFuturesAggTradeMsg),
53 Trade(BinanceFuturesTradeMsg),
55 BookTicker(BinanceFuturesBookTickerMsg),
57 DepthUpdate(BinanceFuturesDepthUpdateMsg),
59 MarkPrice(BinanceFuturesMarkPriceMsg),
61 Kline(BinanceFuturesKlineMsg),
63 ForceOrder(BinanceFuturesLiquidationMsg),
65 Ticker(BinanceFuturesTickerMsg),
67 AccountUpdate(BinanceFuturesAccountUpdateMsg),
69 OrderUpdate(Box<BinanceFuturesOrderUpdateMsg>),
71 TradeLite(Box<BinanceFuturesTradeLiteMsg>),
73 AlgoUpdate(Box<BinanceFuturesAlgoUpdateMsg>),
75 MarginCall(BinanceFuturesMarginCallMsg),
77 AccountConfigUpdate(BinanceFuturesAccountConfigMsg),
79 ListenKeyExpired,
81 Error(BinanceFuturesWsErrorMsg),
83 Reconnected(Vec<u64>),
86 Unsubscribed {
89 streams: Vec<String>,
91 correlation: Option<u64>,
93 },
94}
95
96#[derive(Debug, Clone)]
98pub struct BinanceFuturesWsErrorMsg {
99 pub code: i64,
101 pub msg: String,
103}
104
105#[derive(Debug)]
107pub enum BinanceFuturesWsStreamsCommand {
108 SetClient(WebSocketClient),
110 Disconnect,
112 Subscribe { streams: Vec<String> },
114 Unsubscribe {
116 streams: Vec<String>,
118 correlation: Option<u64>,
120 },
121}
122
123#[derive(Debug)]
125pub enum ExecHandlerCommand {
126 SetClient(WebSocketClient),
128 Disconnect,
130 InitializeInstruments(Vec<BinanceFuturesInstrument>),
132 UpdateInstrument(BinanceFuturesInstrument),
134 Subscribe { streams: Vec<String> },
136 RegisterOrder {
138 client_order_id: ClientOrderId,
139 trader_id: TraderId,
140 strategy_id: StrategyId,
141 instrument_id: InstrumentId,
142 },
143 RegisterCancel {
145 client_order_id: ClientOrderId,
146 trader_id: TraderId,
147 strategy_id: StrategyId,
148 instrument_id: InstrumentId,
149 venue_order_id: Option<VenueOrderId>,
150 },
151 RegisterModify {
153 client_order_id: ClientOrderId,
154 trader_id: TraderId,
155 strategy_id: StrategyId,
156 instrument_id: InstrumentId,
157 venue_order_id: Option<VenueOrderId>,
158 },
159}
160
161#[derive(Debug, Clone, Deserialize)]
163pub struct BinanceFuturesAggTradeMsg {
164 #[serde(rename = "e")]
166 pub event_type: String,
167 #[serde(rename = "E")]
169 pub event_time: i64,
170 #[serde(rename = "s")]
172 pub symbol: Ustr,
173 #[serde(rename = "a")]
175 pub agg_trade_id: u64,
176 #[serde(rename = "p")]
178 pub price: String,
179 #[serde(rename = "q")]
181 pub quantity: String,
182 #[serde(rename = "f")]
184 pub first_trade_id: u64,
185 #[serde(rename = "l")]
187 pub last_trade_id: u64,
188 #[serde(rename = "T")]
190 pub trade_time: i64,
191 #[serde(rename = "m")]
193 pub is_buyer_maker: bool,
194}
195
196#[derive(Debug, Clone, Deserialize)]
198pub struct BinanceFuturesTradeMsg {
199 #[serde(rename = "e")]
201 pub event_type: String,
202 #[serde(rename = "E")]
204 pub event_time: i64,
205 #[serde(rename = "s")]
207 pub symbol: Ustr,
208 #[serde(rename = "t")]
210 pub trade_id: u64,
211 #[serde(rename = "p")]
213 pub price: String,
214 #[serde(rename = "q")]
216 pub quantity: String,
217 #[serde(rename = "T")]
219 pub trade_time: i64,
220 #[serde(rename = "m")]
222 pub is_buyer_maker: bool,
223}
224
225#[derive(Debug, Clone, Deserialize)]
227pub struct BinanceFuturesDepthUpdateMsg {
228 #[serde(rename = "e")]
230 pub event_type: String,
231 #[serde(rename = "E")]
233 pub event_time: i64,
234 #[serde(rename = "T")]
236 pub transaction_time: i64,
237 #[serde(rename = "s")]
239 pub symbol: Ustr,
240 #[serde(rename = "U")]
242 pub first_update_id: u64,
243 #[serde(rename = "u")]
245 pub final_update_id: u64,
246 #[serde(rename = "pu")]
248 pub prev_final_update_id: u64,
249 #[serde(rename = "b")]
251 pub bids: Vec<[String; 2]>,
252 #[serde(rename = "a")]
254 pub asks: Vec<[String; 2]>,
255}
256
257#[derive(Debug, Clone, Deserialize)]
259pub struct BinanceFuturesMarkPriceMsg {
260 #[serde(rename = "e")]
262 pub event_type: String,
263 #[serde(rename = "E")]
265 pub event_time: i64,
266 #[serde(rename = "s")]
268 pub symbol: Ustr,
269 #[serde(rename = "p")]
271 pub mark_price: String,
272 #[serde(rename = "ap", default)]
274 pub mark_price_moving_avg: Option<String>,
275 #[serde(rename = "i")]
277 pub index_price: String,
278 #[serde(rename = "P")]
280 pub estimated_settle_price: String,
281 #[serde(rename = "r")]
283 pub funding_rate: String,
284 #[serde(rename = "T")]
286 pub next_funding_time: i64,
287}
288
289#[derive(Debug, Clone, Deserialize)]
291pub struct BinanceFuturesBookTickerMsg {
292 #[serde(rename = "e")]
294 pub event_type: String,
295 #[serde(rename = "u")]
297 pub update_id: u64,
298 #[serde(rename = "E")]
300 pub event_time: i64,
301 #[serde(rename = "T")]
303 pub transaction_time: i64,
304 #[serde(rename = "s")]
306 pub symbol: Ustr,
307 #[serde(rename = "b")]
309 pub best_bid_price: String,
310 #[serde(rename = "B")]
312 pub best_bid_qty: String,
313 #[serde(rename = "a")]
315 pub best_ask_price: String,
316 #[serde(rename = "A")]
318 pub best_ask_qty: String,
319}
320
321#[derive(Debug, Clone, Deserialize)]
323pub struct BinanceFuturesKlineMsg {
324 #[serde(rename = "e")]
326 pub event_type: String,
327 #[serde(rename = "E")]
329 pub event_time: i64,
330 #[serde(rename = "s")]
332 pub symbol: Ustr,
333 #[serde(rename = "k")]
335 pub kline: BinanceFuturesKlineData,
336}
337
338#[derive(Debug, Clone, Deserialize)]
340pub struct BinanceFuturesKlineData {
341 #[serde(rename = "t")]
343 pub start_time: i64,
344 #[serde(rename = "T")]
346 pub close_time: i64,
347 #[serde(rename = "s")]
349 pub symbol: Ustr,
350 #[serde(rename = "i")]
352 pub interval: BinanceKlineInterval,
353 #[serde(rename = "f")]
355 pub first_trade_id: i64,
356 #[serde(rename = "L")]
358 pub last_trade_id: i64,
359 #[serde(rename = "o")]
361 pub open: String,
362 #[serde(rename = "c")]
364 pub close: String,
365 #[serde(rename = "h")]
367 pub high: String,
368 #[serde(rename = "l")]
370 pub low: String,
371 #[serde(rename = "v")]
373 pub volume: String,
374 #[serde(rename = "n")]
376 pub num_trades: i64,
377 #[serde(rename = "x")]
379 pub is_closed: bool,
380 #[serde(rename = "q")]
382 pub quote_volume: String,
383 #[serde(rename = "V")]
385 pub taker_buy_volume: String,
386 #[serde(rename = "Q")]
388 pub taker_buy_quote_volume: String,
389}
390
391#[derive(Debug, Clone, Deserialize)]
393pub struct BinanceFuturesLiquidationMsg {
394 #[serde(rename = "e")]
396 pub event_type: String,
397 #[serde(rename = "E")]
399 pub event_time: i64,
400 #[serde(rename = "o")]
402 pub order: BinanceFuturesLiquidationOrder,
403}
404
405#[derive(Debug, Clone, Deserialize)]
407pub struct BinanceFuturesLiquidationOrder {
408 #[serde(rename = "s")]
410 pub symbol: Ustr,
411 #[serde(rename = "S")]
413 pub side: BinanceSide,
414 #[serde(rename = "o")]
416 pub order_type: BinanceFuturesOrderType,
417 #[serde(rename = "f")]
419 pub time_in_force: BinanceTimeInForce,
420 #[serde(rename = "q")]
422 pub original_qty: String,
423 #[serde(rename = "p")]
425 pub price: String,
426 #[serde(rename = "ap")]
428 pub average_price: String,
429 #[serde(rename = "X")]
431 pub status: BinanceOrderStatus,
432 #[serde(rename = "l")]
434 pub last_filled_qty: String,
435 #[serde(rename = "z")]
437 pub accumulated_qty: String,
438 #[serde(rename = "T")]
440 pub trade_time: i64,
441}
442
443#[derive(Debug, Clone, Deserialize)]
445pub struct BinanceFuturesTickerMsg {
446 #[serde(rename = "e")]
448 pub event_type: String,
449 #[serde(rename = "E")]
451 pub event_time: i64,
452 #[serde(rename = "s")]
454 pub symbol: Ustr,
455 #[serde(rename = "p")]
457 pub price_change: String,
458 #[serde(rename = "P")]
460 pub price_change_percent: String,
461 #[serde(rename = "w")]
463 pub weighted_avg_price: String,
464 #[serde(rename = "c")]
466 pub last_price: String,
467 #[serde(rename = "Q")]
469 pub last_qty: String,
470 #[serde(rename = "o")]
472 pub open_price: String,
473 #[serde(rename = "h")]
475 pub high_price: String,
476 #[serde(rename = "l")]
478 pub low_price: String,
479 #[serde(rename = "v")]
481 pub volume: String,
482 #[serde(rename = "q")]
484 pub quote_volume: String,
485 #[serde(rename = "O")]
487 pub open_time: i64,
488 #[serde(rename = "C")]
490 pub close_time: i64,
491 #[serde(rename = "F")]
493 pub first_trade_id: i64,
494 #[serde(rename = "L")]
496 pub last_trade_id: i64,
497 #[serde(rename = "n")]
499 pub num_trades: i64,
500}
501
502#[derive(Debug, Clone, Serialize)]
504pub struct BinanceFuturesWsSubscribeRequest {
505 pub method: BinanceWsMethod,
507 pub params: Vec<String>,
509 pub id: u64,
511}
512
513#[derive(Debug, Clone, Deserialize)]
515pub struct BinanceFuturesWsSubscribeResponse {
516 pub result: Option<serde_json::Value>,
518 pub id: u64,
520}
521
522#[derive(Debug, Clone, Deserialize)]
524pub struct BinanceFuturesWsErrorResponse {
525 pub code: i64,
527 pub msg: String,
529 pub id: Option<u64>,
531}
532
533#[derive(Debug, Clone, Deserialize)]
535pub struct BinanceFuturesAccountUpdateMsg {
536 #[serde(rename = "e")]
538 pub event_type: String,
539 #[serde(rename = "E")]
541 pub event_time: i64,
542 #[serde(rename = "T")]
544 pub transaction_time: i64,
545 #[serde(rename = "a")]
547 pub account: AccountUpdateData,
548}
549
550#[derive(Debug, Clone, Deserialize)]
552pub struct AccountUpdateData {
553 #[serde(rename = "m")]
555 pub reason: AccountUpdateReason,
556 #[serde(rename = "B", default)]
558 pub balances: Vec<BalanceUpdate>,
559 #[serde(rename = "P", default)]
561 pub positions: Vec<PositionUpdate>,
562}
563
564#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
566#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
567pub enum AccountUpdateReason {
568 Deposit,
569 Withdraw,
570 Order,
571 FundingFee,
572 WithdrawReject,
573 Adjustment,
574 InsuranceClear,
575 AdminDeposit,
576 AdminWithdraw,
577 MarginTransfer,
578 MarginTypeChange,
579 AssetTransfer,
580 OptionsPremiumFee,
581 OptionsSettleProfit,
582 AutoExchange,
583 Adl,
584 CoinSwapDeposit,
585 CoinSwapWithdraw,
586 #[serde(other)]
587 Unknown,
588}
589
590#[derive(Debug, Clone, Deserialize)]
592pub struct BalanceUpdate {
593 #[serde(rename = "a")]
595 pub asset: Ustr,
596 #[serde(rename = "wb", deserialize_with = "deserialize_decimal_from_str")]
598 pub wallet_balance: Decimal,
599 #[serde(rename = "cw", deserialize_with = "deserialize_decimal_from_str")]
601 pub cross_wallet_balance: Decimal,
602 #[serde(
604 rename = "bc",
605 default,
606 deserialize_with = "deserialize_optional_decimal_from_str"
607 )]
608 pub balance_change: Option<Decimal>,
609}
610
611#[derive(Debug, Clone, Deserialize)]
613pub struct PositionUpdate {
614 #[serde(rename = "s")]
616 pub symbol: Ustr,
617 #[serde(rename = "pa")]
619 pub position_amount: String,
620 #[serde(rename = "ep")]
622 pub entry_price: String,
623 #[serde(rename = "bep", default)]
625 pub break_even_price: Option<String>,
626 #[serde(rename = "cr")]
628 pub accumulated_realized: String,
629 #[serde(rename = "up")]
631 pub unrealized_pnl: String,
632 #[serde(rename = "mt")]
634 pub margin_type: BinanceMarginType,
635 #[serde(rename = "iw")]
637 pub isolated_wallet: String,
638 #[serde(rename = "ps")]
640 pub position_side: BinancePositionSide,
641}
642
643#[derive(Debug, Clone, Deserialize)]
645pub struct BinanceFuturesOrderUpdateMsg {
646 #[serde(rename = "e")]
648 pub event_type: String,
649 #[serde(rename = "E")]
651 pub event_time: i64,
652 #[serde(rename = "T")]
654 pub transaction_time: i64,
655 #[serde(rename = "o")]
657 pub order: OrderUpdateData,
658}
659
660#[derive(Debug, Clone, Deserialize)]
662pub struct OrderUpdateData {
663 #[serde(rename = "s")]
665 pub symbol: Ustr,
666 #[serde(rename = "c")]
668 pub client_order_id: String,
669 #[serde(rename = "S")]
671 pub side: BinanceSide,
672 #[serde(rename = "o")]
674 pub order_type: BinanceFuturesOrderType,
675 #[serde(rename = "f")]
677 pub time_in_force: BinanceTimeInForce,
678 #[serde(rename = "q")]
680 pub original_qty: String,
681 #[serde(rename = "p")]
683 pub original_price: String,
684 #[serde(rename = "ap")]
686 pub average_price: String,
687 #[serde(rename = "sp")]
689 pub stop_price: String,
690 #[serde(rename = "x")]
692 pub execution_type: BinanceExecutionType,
693 #[serde(rename = "X")]
695 pub order_status: BinanceOrderStatus,
696 #[serde(rename = "i")]
698 pub order_id: i64,
699 #[serde(rename = "l")]
701 pub last_filled_qty: String,
702 #[serde(rename = "z")]
704 pub cumulative_filled_qty: String,
705 #[serde(rename = "L")]
707 pub last_filled_price: String,
708 #[serde(rename = "N", default)]
710 pub commission_asset: Option<Ustr>,
711 #[serde(rename = "n", default)]
713 pub commission: Option<String>,
714 #[serde(rename = "T")]
716 pub trade_time: i64,
717 #[serde(rename = "t")]
719 pub trade_id: i64,
720 #[serde(rename = "b", default)]
722 pub bids_notional: Option<String>,
723 #[serde(rename = "a", default)]
725 pub asks_notional: Option<String>,
726 #[serde(rename = "m")]
728 pub is_maker: bool,
729 #[serde(rename = "R")]
731 pub is_reduce_only: bool,
732 #[serde(rename = "wt")]
734 pub working_type: BinanceWorkingType,
735 #[serde(rename = "ot")]
737 pub original_order_type: BinanceFuturesOrderType,
738 #[serde(rename = "ps")]
740 pub position_side: BinancePositionSide,
741 #[serde(rename = "cp", default)]
743 pub close_position: Option<bool>,
744 #[serde(rename = "AP", default)]
746 pub activation_price: Option<String>,
747 #[serde(rename = "cr", default)]
749 pub callback_rate: Option<String>,
750 #[serde(rename = "pP", default)]
752 pub price_protect: Option<bool>,
753 #[serde(rename = "rp")]
755 pub realized_profit: String,
756 #[serde(rename = "V", default)]
758 pub stp_mode: Option<BinanceSelfTradePreventionMode>,
759 #[serde(rename = "pm", default)]
761 pub price_match: Option<BinancePriceMatch>,
762 #[serde(rename = "gtd", default)]
764 pub good_till_date: Option<i64>,
765}
766
767impl OrderUpdateData {
768 #[must_use]
770 pub fn is_liquidation(&self) -> bool {
771 self.client_order_id.starts_with("autoclose-")
772 }
773
774 #[must_use]
776 pub fn is_adl(&self) -> bool {
777 self.client_order_id.starts_with("adl_autoclose")
778 }
779
780 #[must_use]
786 pub fn is_settlement(&self) -> bool {
787 self.client_order_id.starts_with("settlement_autoclose-")
788 || self.client_order_id.starts_with("delivery_autoclose-")
789 }
790
791 #[must_use]
793 pub fn is_exchange_generated(&self) -> bool {
794 self.is_liquidation() || self.is_adl() || self.is_settlement()
795 }
796}
797
798#[derive(Debug, Clone, Deserialize)]
805pub struct BinanceFuturesTradeLiteMsg {
806 #[serde(rename = "e")]
808 pub event_type: String,
809 #[serde(rename = "E")]
811 pub event_time: i64,
812 #[serde(rename = "T")]
814 pub transaction_time: i64,
815 #[serde(rename = "s")]
817 pub symbol: Ustr,
818 #[serde(rename = "c")]
820 pub client_order_id: String,
821 #[serde(rename = "S")]
823 pub side: BinanceSide,
824 #[serde(rename = "q")]
826 pub original_qty: String,
827 #[serde(rename = "p")]
829 pub original_price: String,
830 #[serde(rename = "i")]
832 pub order_id: i64,
833 #[serde(rename = "l")]
835 pub last_filled_qty: String,
836 #[serde(rename = "L")]
838 pub last_filled_price: String,
839 #[serde(rename = "t")]
841 pub trade_id: i64,
842 #[serde(rename = "m")]
844 pub is_maker: bool,
845}
846
847#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
849#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
850pub enum BinanceExecutionType {
851 New,
853 Canceled,
855 Calculated,
857 Expired,
859 Trade,
861 Amendment,
863 #[serde(other)]
865 Unknown,
866}
867
868#[derive(Debug, Clone, Deserialize)]
870pub struct BinanceFuturesMarginCallMsg {
871 #[serde(rename = "e")]
873 pub event_type: String,
874 #[serde(rename = "E")]
876 pub event_time: i64,
877 #[serde(rename = "cw")]
879 pub cross_wallet_balance: String,
880 #[serde(rename = "p")]
882 pub positions: Vec<MarginCallPosition>,
883}
884
885#[derive(Debug, Clone, Deserialize)]
887pub struct MarginCallPosition {
888 #[serde(rename = "s")]
890 pub symbol: Ustr,
891 #[serde(rename = "ps")]
893 pub position_side: BinancePositionSide,
894 #[serde(rename = "pa")]
896 pub position_amount: String,
897 #[serde(rename = "mt")]
899 pub margin_type: BinanceMarginType,
900 #[serde(rename = "iw")]
902 pub isolated_wallet: String,
903 #[serde(rename = "mp")]
905 pub mark_price: String,
906 #[serde(rename = "up")]
908 pub unrealized_pnl: String,
909 #[serde(rename = "mm")]
911 pub maintenance_margin: String,
912}
913
914#[derive(Debug, Clone, Deserialize)]
916pub struct BinanceFuturesAccountConfigMsg {
917 #[serde(rename = "e")]
919 pub event_type: String,
920 #[serde(rename = "E")]
922 pub event_time: i64,
923 #[serde(rename = "T")]
925 pub transaction_time: i64,
926 #[serde(rename = "ac", default)]
928 pub leverage_config: Option<LeverageConfig>,
929 #[serde(rename = "ai", default)]
931 pub asset_index: Option<AssetIndexConfig>,
932}
933
934#[derive(Debug, Clone, Deserialize)]
936pub struct LeverageConfig {
937 #[serde(rename = "s")]
939 pub symbol: Ustr,
940 #[serde(rename = "l")]
942 pub leverage: u32,
943}
944
945#[derive(Debug, Clone, Deserialize)]
947pub struct AssetIndexConfig {
948 #[serde(rename = "s")]
950 pub symbol: Ustr,
951}
952
953#[derive(Debug, Clone, Deserialize)]
963pub struct BinanceFuturesAlgoUpdateMsg {
964 #[serde(rename = "e")]
966 pub event_type: String,
967 #[serde(rename = "E")]
969 pub event_time: i64,
970 #[serde(rename = "T")]
972 pub transaction_time: i64,
973 #[serde(rename = "o", alias = "ao")]
975 pub algo_order: AlgoOrderUpdateData,
976}
977
978#[derive(Debug, Clone, Deserialize)]
980pub struct AlgoOrderUpdateData {
981 #[serde(rename = "caid")]
983 pub client_algo_id: String,
984 #[serde(rename = "aid")]
986 pub algo_id: i64,
987 #[serde(rename = "at")]
989 pub algo_type: BinanceAlgoType,
990 #[serde(rename = "o")]
992 pub order_type: BinanceFuturesOrderType,
993 #[serde(rename = "s")]
995 pub symbol: Ustr,
996 #[serde(rename = "S")]
998 pub side: BinanceSide,
999 #[serde(rename = "ps")]
1001 pub position_side: BinancePositionSide,
1002 #[serde(rename = "f")]
1004 pub time_in_force: BinanceTimeInForce,
1005 #[serde(rename = "q")]
1007 pub quantity: String,
1008 #[serde(rename = "X")]
1010 pub algo_status: BinanceAlgoStatus,
1011 #[serde(rename = "tp")]
1013 pub trigger_price: String,
1014 #[serde(rename = "p")]
1016 pub price: String,
1017 #[serde(rename = "wt")]
1019 pub working_type: BinanceWorkingType,
1020 #[serde(rename = "pm", default)]
1022 pub price_match: Option<BinancePriceMatch>,
1023 #[serde(rename = "cp", default)]
1025 pub close_position: Option<bool>,
1026 #[serde(rename = "pP", default)]
1028 pub price_protect: Option<bool>,
1029 #[serde(rename = "R", default)]
1031 pub reduce_only: Option<bool>,
1032 #[serde(rename = "tt", default)]
1034 pub trigger_time: Option<i64>,
1035 #[serde(rename = "gtd", default)]
1037 pub good_till_date: Option<i64>,
1038 #[serde(rename = "ai", default)]
1040 pub actual_order_id: Option<String>,
1041 #[serde(rename = "ap", default)]
1043 pub avg_price: Option<String>,
1044 #[serde(rename = "aq", default)]
1046 pub executed_qty: Option<String>,
1047 #[serde(rename = "act", default)]
1049 pub actual_order_type: Option<String>,
1050 #[serde(rename = "cr", default)]
1052 pub callback_rate: Option<String>,
1053 #[serde(rename = "V", default)]
1055 pub stp_mode: Option<BinanceSelfTradePreventionMode>,
1056}
1057
1058#[derive(Debug, Clone, Deserialize)]
1060pub struct BinanceFuturesListenKeyExpiredMsg {
1061 #[serde(rename = "e")]
1063 pub event_type: String,
1064 #[serde(rename = "E")]
1066 pub event_time: i64,
1067}
1068
1069#[cfg(test)]
1070mod tests {
1071 use rstest::rstest;
1072
1073 use super::*;
1074
1075 #[rstest]
1076 fn test_account_update_reason_adl_deserializes() {
1077 let value: AccountUpdateReason = serde_json::from_str("\"ADL\"").unwrap();
1078 assert_eq!(value, AccountUpdateReason::Adl);
1079 }
1080
1081 #[rstest]
1082 fn test_account_update_reason_unknown_fallback() {
1083 let value: AccountUpdateReason = serde_json::from_str("\"SOMETHING_NEW\"").unwrap();
1084 assert_eq!(value, AccountUpdateReason::Unknown);
1085 }
1086}