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)]
125#[expect(
126 clippy::large_enum_variant,
127 reason = "Commands are ephemeral and immediately consumed"
128)]
129pub enum ExecHandlerCommand {
130 SetClient(WebSocketClient),
132 Disconnect,
134 InitializeInstruments(Vec<BinanceFuturesInstrument>),
136 UpdateInstrument(BinanceFuturesInstrument),
138 Subscribe { streams: Vec<String> },
140 RegisterOrder {
142 client_order_id: ClientOrderId,
143 trader_id: TraderId,
144 strategy_id: StrategyId,
145 instrument_id: InstrumentId,
146 },
147 RegisterCancel {
149 client_order_id: ClientOrderId,
150 trader_id: TraderId,
151 strategy_id: StrategyId,
152 instrument_id: InstrumentId,
153 venue_order_id: Option<VenueOrderId>,
154 },
155 RegisterModify {
157 client_order_id: ClientOrderId,
158 trader_id: TraderId,
159 strategy_id: StrategyId,
160 instrument_id: InstrumentId,
161 venue_order_id: Option<VenueOrderId>,
162 },
163}
164
165#[derive(Debug, Clone, Deserialize)]
167pub struct BinanceFuturesAggTradeMsg {
168 #[serde(rename = "e")]
170 pub event_type: String,
171 #[serde(rename = "E")]
173 pub event_time: i64,
174 #[serde(rename = "s")]
176 pub symbol: Ustr,
177 #[serde(rename = "a")]
179 pub agg_trade_id: u64,
180 #[serde(rename = "p")]
182 pub price: String,
183 #[serde(rename = "q")]
185 pub quantity: String,
186 #[serde(rename = "f")]
188 pub first_trade_id: u64,
189 #[serde(rename = "l")]
191 pub last_trade_id: u64,
192 #[serde(rename = "T")]
194 pub trade_time: i64,
195 #[serde(rename = "m")]
197 pub is_buyer_maker: bool,
198}
199
200#[derive(Debug, Clone, Deserialize)]
202pub struct BinanceFuturesTradeMsg {
203 #[serde(rename = "e")]
205 pub event_type: String,
206 #[serde(rename = "E")]
208 pub event_time: i64,
209 #[serde(rename = "s")]
211 pub symbol: Ustr,
212 #[serde(rename = "t")]
214 pub trade_id: u64,
215 #[serde(rename = "p")]
217 pub price: String,
218 #[serde(rename = "q")]
220 pub quantity: String,
221 #[serde(rename = "T")]
223 pub trade_time: i64,
224 #[serde(rename = "m")]
226 pub is_buyer_maker: bool,
227}
228
229#[derive(Debug, Clone, Deserialize)]
231pub struct BinanceFuturesDepthUpdateMsg {
232 #[serde(rename = "e")]
234 pub event_type: String,
235 #[serde(rename = "E")]
237 pub event_time: i64,
238 #[serde(rename = "T")]
240 pub transaction_time: i64,
241 #[serde(rename = "s")]
243 pub symbol: Ustr,
244 #[serde(rename = "U")]
246 pub first_update_id: u64,
247 #[serde(rename = "u")]
249 pub final_update_id: u64,
250 #[serde(rename = "pu")]
252 pub prev_final_update_id: u64,
253 #[serde(rename = "b")]
255 pub bids: Vec<[String; 2]>,
256 #[serde(rename = "a")]
258 pub asks: Vec<[String; 2]>,
259}
260
261#[derive(Debug, Clone, Deserialize)]
263pub struct BinanceFuturesMarkPriceMsg {
264 #[serde(rename = "e")]
266 pub event_type: String,
267 #[serde(rename = "E")]
269 pub event_time: i64,
270 #[serde(rename = "s")]
272 pub symbol: Ustr,
273 #[serde(rename = "p")]
275 pub mark_price: String,
276 #[serde(rename = "ap", default)]
278 pub mark_price_moving_avg: Option<String>,
279 #[serde(rename = "i")]
281 pub index_price: String,
282 #[serde(rename = "P")]
284 pub estimated_settle_price: String,
285 #[serde(rename = "r")]
287 pub funding_rate: String,
288 #[serde(rename = "T")]
290 pub next_funding_time: i64,
291}
292
293#[derive(Debug, Clone, Deserialize)]
295pub struct BinanceFuturesBookTickerMsg {
296 #[serde(rename = "e")]
298 pub event_type: String,
299 #[serde(rename = "u")]
301 pub update_id: u64,
302 #[serde(rename = "E")]
304 pub event_time: i64,
305 #[serde(rename = "T")]
307 pub transaction_time: i64,
308 #[serde(rename = "s")]
310 pub symbol: Ustr,
311 #[serde(rename = "b")]
313 pub best_bid_price: String,
314 #[serde(rename = "B")]
316 pub best_bid_qty: String,
317 #[serde(rename = "a")]
319 pub best_ask_price: String,
320 #[serde(rename = "A")]
322 pub best_ask_qty: String,
323}
324
325#[derive(Debug, Clone, Deserialize)]
327pub struct BinanceFuturesKlineMsg {
328 #[serde(rename = "e")]
330 pub event_type: String,
331 #[serde(rename = "E")]
333 pub event_time: i64,
334 #[serde(rename = "s")]
336 pub symbol: Ustr,
337 #[serde(rename = "k")]
339 pub kline: BinanceFuturesKlineData,
340}
341
342#[derive(Debug, Clone, Deserialize)]
344pub struct BinanceFuturesKlineData {
345 #[serde(rename = "t")]
347 pub start_time: i64,
348 #[serde(rename = "T")]
350 pub close_time: i64,
351 #[serde(rename = "s")]
353 pub symbol: Ustr,
354 #[serde(rename = "i")]
356 pub interval: BinanceKlineInterval,
357 #[serde(rename = "f")]
359 pub first_trade_id: i64,
360 #[serde(rename = "L")]
362 pub last_trade_id: i64,
363 #[serde(rename = "o")]
365 pub open: String,
366 #[serde(rename = "c")]
368 pub close: String,
369 #[serde(rename = "h")]
371 pub high: String,
372 #[serde(rename = "l")]
374 pub low: String,
375 #[serde(rename = "v")]
377 pub volume: String,
378 #[serde(rename = "n")]
380 pub num_trades: i64,
381 #[serde(rename = "x")]
383 pub is_closed: bool,
384 #[serde(rename = "q")]
386 pub quote_volume: String,
387 #[serde(rename = "V")]
389 pub taker_buy_volume: String,
390 #[serde(rename = "Q")]
392 pub taker_buy_quote_volume: String,
393}
394
395#[derive(Debug, Clone, Deserialize)]
397pub struct BinanceFuturesLiquidationMsg {
398 #[serde(rename = "e")]
400 pub event_type: String,
401 #[serde(rename = "E")]
403 pub event_time: i64,
404 #[serde(rename = "o")]
406 pub order: BinanceFuturesLiquidationOrder,
407}
408
409#[derive(Debug, Clone, Deserialize)]
411pub struct BinanceFuturesLiquidationOrder {
412 #[serde(rename = "s")]
414 pub symbol: Ustr,
415 #[serde(rename = "S")]
417 pub side: BinanceSide,
418 #[serde(rename = "o")]
420 pub order_type: BinanceFuturesOrderType,
421 #[serde(rename = "f")]
423 pub time_in_force: BinanceTimeInForce,
424 #[serde(rename = "q")]
426 pub original_qty: String,
427 #[serde(rename = "p")]
429 pub price: String,
430 #[serde(rename = "ap")]
432 pub average_price: String,
433 #[serde(rename = "X")]
435 pub status: BinanceOrderStatus,
436 #[serde(rename = "l")]
438 pub last_filled_qty: String,
439 #[serde(rename = "z")]
441 pub accumulated_qty: String,
442 #[serde(rename = "T")]
444 pub trade_time: i64,
445}
446
447#[derive(Debug, Clone, Deserialize)]
449pub struct BinanceFuturesTickerMsg {
450 #[serde(rename = "e")]
452 pub event_type: String,
453 #[serde(rename = "E")]
455 pub event_time: i64,
456 #[serde(rename = "s")]
458 pub symbol: Ustr,
459 #[serde(rename = "p")]
461 pub price_change: String,
462 #[serde(rename = "P")]
464 pub price_change_percent: String,
465 #[serde(rename = "w")]
467 pub weighted_avg_price: String,
468 #[serde(rename = "c")]
470 pub last_price: String,
471 #[serde(rename = "Q")]
473 pub last_qty: String,
474 #[serde(rename = "o")]
476 pub open_price: String,
477 #[serde(rename = "h")]
479 pub high_price: String,
480 #[serde(rename = "l")]
482 pub low_price: String,
483 #[serde(rename = "v")]
485 pub volume: String,
486 #[serde(rename = "q")]
488 pub quote_volume: String,
489 #[serde(rename = "O")]
491 pub open_time: i64,
492 #[serde(rename = "C")]
494 pub close_time: i64,
495 #[serde(rename = "F")]
497 pub first_trade_id: i64,
498 #[serde(rename = "L")]
500 pub last_trade_id: i64,
501 #[serde(rename = "n")]
503 pub num_trades: i64,
504}
505
506#[derive(Debug, Clone, Serialize)]
508pub struct BinanceFuturesWsSubscribeRequest {
509 pub method: BinanceWsMethod,
511 pub params: Vec<String>,
513 pub id: u64,
515}
516
517#[derive(Debug, Clone, Deserialize)]
519pub struct BinanceFuturesWsSubscribeResponse {
520 pub result: Option<serde_json::Value>,
522 pub id: u64,
524}
525
526#[derive(Debug, Clone, Deserialize)]
528pub struct BinanceFuturesWsErrorResponse {
529 pub code: i64,
531 pub msg: String,
533 pub id: Option<u64>,
535}
536
537#[derive(Debug, Clone, Deserialize)]
539pub struct BinanceFuturesAccountUpdateMsg {
540 #[serde(rename = "e")]
542 pub event_type: String,
543 #[serde(rename = "E")]
545 pub event_time: i64,
546 #[serde(rename = "T")]
548 pub transaction_time: i64,
549 #[serde(rename = "a")]
551 pub account: AccountUpdateData,
552}
553
554#[derive(Debug, Clone, Deserialize)]
556pub struct AccountUpdateData {
557 #[serde(rename = "m")]
559 pub reason: AccountUpdateReason,
560 #[serde(rename = "B", default)]
562 pub balances: Vec<BalanceUpdate>,
563 #[serde(rename = "P", default)]
565 pub positions: Vec<PositionUpdate>,
566}
567
568#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
570#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
571pub enum AccountUpdateReason {
572 Deposit,
573 Withdraw,
574 Order,
575 FundingFee,
576 WithdrawReject,
577 Adjustment,
578 InsuranceClear,
579 AdminDeposit,
580 AdminWithdraw,
581 MarginTransfer,
582 MarginTypeChange,
583 AssetTransfer,
584 OptionsPremiumFee,
585 OptionsSettleProfit,
586 AutoExchange,
587 Adl,
588 CoinSwapDeposit,
589 CoinSwapWithdraw,
590 #[serde(other)]
591 Unknown,
592}
593
594#[derive(Debug, Clone, Deserialize)]
596pub struct BalanceUpdate {
597 #[serde(rename = "a")]
599 pub asset: Ustr,
600 #[serde(rename = "wb", deserialize_with = "deserialize_decimal_from_str")]
602 pub wallet_balance: Decimal,
603 #[serde(rename = "cw", deserialize_with = "deserialize_decimal_from_str")]
605 pub cross_wallet_balance: Decimal,
606 #[serde(
608 rename = "bc",
609 default,
610 deserialize_with = "deserialize_optional_decimal_from_str"
611 )]
612 pub balance_change: Option<Decimal>,
613}
614
615#[derive(Debug, Clone, Deserialize)]
617pub struct PositionUpdate {
618 #[serde(rename = "s")]
620 pub symbol: Ustr,
621 #[serde(rename = "pa")]
623 pub position_amount: String,
624 #[serde(rename = "ep")]
626 pub entry_price: String,
627 #[serde(rename = "bep", default)]
629 pub break_even_price: Option<String>,
630 #[serde(rename = "cr")]
632 pub accumulated_realized: String,
633 #[serde(rename = "up")]
635 pub unrealized_pnl: String,
636 #[serde(rename = "mt")]
638 pub margin_type: BinanceMarginType,
639 #[serde(rename = "iw")]
641 pub isolated_wallet: String,
642 #[serde(rename = "ps")]
644 pub position_side: BinancePositionSide,
645}
646
647#[derive(Debug, Clone, Deserialize)]
649pub struct BinanceFuturesOrderUpdateMsg {
650 #[serde(rename = "e")]
652 pub event_type: String,
653 #[serde(rename = "E")]
655 pub event_time: i64,
656 #[serde(rename = "T")]
658 pub transaction_time: i64,
659 #[serde(rename = "o")]
661 pub order: OrderUpdateData,
662}
663
664#[derive(Debug, Clone, Deserialize)]
666pub struct OrderUpdateData {
667 #[serde(rename = "s")]
669 pub symbol: Ustr,
670 #[serde(rename = "c")]
672 pub client_order_id: String,
673 #[serde(rename = "S")]
675 pub side: BinanceSide,
676 #[serde(rename = "o")]
678 pub order_type: BinanceFuturesOrderType,
679 #[serde(rename = "f")]
681 pub time_in_force: BinanceTimeInForce,
682 #[serde(rename = "q")]
684 pub original_qty: String,
685 #[serde(rename = "p")]
687 pub original_price: String,
688 #[serde(rename = "ap")]
690 pub average_price: String,
691 #[serde(rename = "sp")]
693 pub stop_price: String,
694 #[serde(rename = "x")]
696 pub execution_type: BinanceExecutionType,
697 #[serde(rename = "X")]
699 pub order_status: BinanceOrderStatus,
700 #[serde(rename = "i")]
702 pub order_id: i64,
703 #[serde(rename = "l")]
705 pub last_filled_qty: String,
706 #[serde(rename = "z")]
708 pub cumulative_filled_qty: String,
709 #[serde(rename = "L")]
711 pub last_filled_price: String,
712 #[serde(rename = "N", default)]
714 pub commission_asset: Option<Ustr>,
715 #[serde(rename = "n", default)]
717 pub commission: Option<String>,
718 #[serde(rename = "T")]
720 pub trade_time: i64,
721 #[serde(rename = "t")]
723 pub trade_id: i64,
724 #[serde(rename = "b", default)]
726 pub bids_notional: Option<String>,
727 #[serde(rename = "a", default)]
729 pub asks_notional: Option<String>,
730 #[serde(rename = "m")]
732 pub is_maker: bool,
733 #[serde(rename = "R")]
735 pub is_reduce_only: bool,
736 #[serde(rename = "wt")]
738 pub working_type: BinanceWorkingType,
739 #[serde(rename = "ot")]
741 pub original_order_type: BinanceFuturesOrderType,
742 #[serde(rename = "ps")]
744 pub position_side: BinancePositionSide,
745 #[serde(rename = "cp", default)]
747 pub close_position: Option<bool>,
748 #[serde(rename = "AP", default)]
750 pub activation_price: Option<String>,
751 #[serde(rename = "cr", default)]
753 pub callback_rate: Option<String>,
754 #[serde(rename = "pP", default)]
756 pub price_protect: Option<bool>,
757 #[serde(rename = "rp")]
759 pub realized_profit: String,
760 #[serde(rename = "V", default)]
762 pub stp_mode: Option<BinanceSelfTradePreventionMode>,
763 #[serde(rename = "pm", default)]
765 pub price_match: Option<BinancePriceMatch>,
766 #[serde(rename = "gtd", default)]
768 pub good_till_date: Option<i64>,
769}
770
771impl OrderUpdateData {
772 #[must_use]
774 pub fn is_liquidation(&self) -> bool {
775 self.client_order_id.starts_with("autoclose-")
776 }
777
778 #[must_use]
780 pub fn is_adl(&self) -> bool {
781 self.client_order_id.starts_with("adl_autoclose")
782 }
783
784 #[must_use]
790 pub fn is_settlement(&self) -> bool {
791 self.client_order_id.starts_with("settlement_autoclose-")
792 || self.client_order_id.starts_with("delivery_autoclose-")
793 }
794
795 #[must_use]
797 pub fn is_exchange_generated(&self) -> bool {
798 self.is_liquidation() || self.is_adl() || self.is_settlement()
799 }
800}
801
802#[derive(Debug, Clone, Deserialize)]
809pub struct BinanceFuturesTradeLiteMsg {
810 #[serde(rename = "e")]
812 pub event_type: String,
813 #[serde(rename = "E")]
815 pub event_time: i64,
816 #[serde(rename = "T")]
818 pub transaction_time: i64,
819 #[serde(rename = "s")]
821 pub symbol: Ustr,
822 #[serde(rename = "c")]
824 pub client_order_id: String,
825 #[serde(rename = "S")]
827 pub side: BinanceSide,
828 #[serde(rename = "q")]
830 pub original_qty: String,
831 #[serde(rename = "p")]
833 pub original_price: String,
834 #[serde(rename = "i")]
836 pub order_id: i64,
837 #[serde(rename = "l")]
839 pub last_filled_qty: String,
840 #[serde(rename = "L")]
842 pub last_filled_price: String,
843 #[serde(rename = "t")]
845 pub trade_id: i64,
846 #[serde(rename = "m")]
848 pub is_maker: bool,
849}
850
851#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
853#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
854pub enum BinanceExecutionType {
855 New,
857 Canceled,
859 Calculated,
861 Expired,
863 Trade,
865 Amendment,
867 #[serde(other)]
869 Unknown,
870}
871
872#[derive(Debug, Clone, Deserialize)]
874pub struct BinanceFuturesMarginCallMsg {
875 #[serde(rename = "e")]
877 pub event_type: String,
878 #[serde(rename = "E")]
880 pub event_time: i64,
881 #[serde(rename = "cw")]
883 pub cross_wallet_balance: String,
884 #[serde(rename = "p")]
886 pub positions: Vec<MarginCallPosition>,
887}
888
889#[derive(Debug, Clone, Deserialize)]
891pub struct MarginCallPosition {
892 #[serde(rename = "s")]
894 pub symbol: Ustr,
895 #[serde(rename = "ps")]
897 pub position_side: BinancePositionSide,
898 #[serde(rename = "pa")]
900 pub position_amount: String,
901 #[serde(rename = "mt")]
903 pub margin_type: BinanceMarginType,
904 #[serde(rename = "iw")]
906 pub isolated_wallet: String,
907 #[serde(rename = "mp")]
909 pub mark_price: String,
910 #[serde(rename = "up")]
912 pub unrealized_pnl: String,
913 #[serde(rename = "mm")]
915 pub maintenance_margin: String,
916}
917
918#[derive(Debug, Clone, Deserialize)]
920pub struct BinanceFuturesAccountConfigMsg {
921 #[serde(rename = "e")]
923 pub event_type: String,
924 #[serde(rename = "E")]
926 pub event_time: i64,
927 #[serde(rename = "T")]
929 pub transaction_time: i64,
930 #[serde(rename = "ac", default)]
932 pub leverage_config: Option<LeverageConfig>,
933 #[serde(rename = "ai", default)]
935 pub asset_index: Option<AssetIndexConfig>,
936}
937
938#[derive(Debug, Clone, Deserialize)]
940pub struct LeverageConfig {
941 #[serde(rename = "s")]
943 pub symbol: Ustr,
944 #[serde(rename = "l")]
946 pub leverage: u32,
947}
948
949#[derive(Debug, Clone, Deserialize)]
951pub struct AssetIndexConfig {
952 #[serde(rename = "s")]
954 pub symbol: Ustr,
955}
956
957#[derive(Debug, Clone, Deserialize)]
967pub struct BinanceFuturesAlgoUpdateMsg {
968 #[serde(rename = "e")]
970 pub event_type: String,
971 #[serde(rename = "E")]
973 pub event_time: i64,
974 #[serde(rename = "T")]
976 pub transaction_time: i64,
977 #[serde(rename = "o", alias = "ao")]
979 pub algo_order: AlgoOrderUpdateData,
980}
981
982#[derive(Debug, Clone, Deserialize)]
984pub struct AlgoOrderUpdateData {
985 #[serde(rename = "caid")]
987 pub client_algo_id: String,
988 #[serde(rename = "aid")]
990 pub algo_id: i64,
991 #[serde(rename = "at")]
993 pub algo_type: BinanceAlgoType,
994 #[serde(rename = "o")]
996 pub order_type: BinanceFuturesOrderType,
997 #[serde(rename = "s")]
999 pub symbol: Ustr,
1000 #[serde(rename = "S")]
1002 pub side: BinanceSide,
1003 #[serde(rename = "ps")]
1005 pub position_side: BinancePositionSide,
1006 #[serde(rename = "f")]
1008 pub time_in_force: BinanceTimeInForce,
1009 #[serde(rename = "q")]
1011 pub quantity: String,
1012 #[serde(rename = "X")]
1014 pub algo_status: BinanceAlgoStatus,
1015 #[serde(rename = "tp")]
1017 pub trigger_price: String,
1018 #[serde(rename = "p")]
1020 pub price: String,
1021 #[serde(rename = "wt")]
1023 pub working_type: BinanceWorkingType,
1024 #[serde(rename = "pm", default)]
1026 pub price_match: Option<BinancePriceMatch>,
1027 #[serde(rename = "cp", default)]
1029 pub close_position: Option<bool>,
1030 #[serde(rename = "pP", default)]
1032 pub price_protect: Option<bool>,
1033 #[serde(rename = "R", default)]
1035 pub reduce_only: Option<bool>,
1036 #[serde(rename = "tt", default)]
1038 pub trigger_time: Option<i64>,
1039 #[serde(rename = "gtd", default)]
1041 pub good_till_date: Option<i64>,
1042 #[serde(rename = "ai", default)]
1044 pub actual_order_id: Option<String>,
1045 #[serde(rename = "ap", default)]
1047 pub avg_price: Option<String>,
1048 #[serde(rename = "aq", default)]
1050 pub executed_qty: Option<String>,
1051 #[serde(rename = "act", default)]
1053 pub actual_order_type: Option<String>,
1054 #[serde(rename = "cr", default)]
1056 pub callback_rate: Option<String>,
1057 #[serde(rename = "V", default)]
1059 pub stp_mode: Option<BinanceSelfTradePreventionMode>,
1060}
1061
1062#[derive(Debug, Clone, Deserialize)]
1064pub struct BinanceFuturesListenKeyExpiredMsg {
1065 #[serde(rename = "e")]
1067 pub event_type: String,
1068 #[serde(rename = "E")]
1070 pub event_time: i64,
1071}
1072
1073#[cfg(test)]
1074mod tests {
1075 use rstest::rstest;
1076
1077 use super::*;
1078
1079 #[rstest]
1080 fn test_account_update_reason_adl_deserializes() {
1081 let value: AccountUpdateReason = serde_json::from_str("\"ADL\"").unwrap();
1082 assert_eq!(value, AccountUpdateReason::Adl);
1083 }
1084
1085 #[rstest]
1086 fn test_account_update_reason_unknown_fallback() {
1087 let value: AccountUpdateReason = serde_json::from_str("\"SOMETHING_NEW\"").unwrap();
1088 assert_eq!(value, AccountUpdateReason::Unknown);
1089 }
1090}