1use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use serde_repr::*;
7use std::fmt;
8
9#[derive(Debug, Deserialize, Serialize)]
11pub enum Locale {
12 #[serde(rename = "de-DE")]
14 DeDe,
15 #[serde(rename = "en-US")]
17 EnUs,
18 #[serde(rename = "es-AR")]
20 EsAr,
21 #[serde(rename = "es-ES")]
23 EsEs,
24 #[serde(rename = "es-MX")]
26 EsMx,
27 #[serde(rename = "fr-FR")]
29 FrFr,
30 #[serde(rename = "kk-KZ")]
32 KkKz,
33 #[serde(rename = "id-ID")]
35 IdId,
36 #[serde(rename = "uk-UA")]
38 UkUa,
39 #[serde(rename = "ja-JP")]
41 JaJp,
42 #[serde(rename = "ru-RU")]
44 RuRu,
45 #[serde(rename = "th-TH")]
47 ThTh,
48 #[serde(rename = "pt-BR")]
50 PtBr,
51 #[serde(rename = "tr-TR")]
53 TrTr,
54 #[serde(rename = "vi-VN")]
56 ViVn,
57 #[serde(rename = "zh-TW")]
59 ZhTw,
60 #[serde(rename = "ar-SA")]
62 ArSa,
63 #[serde(rename = "hi-IN")]
65 HiIn,
66 #[serde(rename = "fil-PH")]
68 FilPh,
69}
70
71#[derive(Debug, Deserialize, Serialize)]
73pub enum AnnouncementType {
74 #[serde(rename = "new_crypto")]
76 NewCrypto,
77 #[serde(rename = "latest_bybit_news")]
79 LatestBybitNews,
80 #[serde(rename = "delistings")]
82 Delistings,
83 #[serde(rename = "latest_activities")]
85 LatestActivities,
86 #[serde(rename = "product_updates")]
88 ProductUpdates,
89 #[serde(rename = "maintenance_updates")]
91 MaintenanceUpdates,
92 #[serde(rename = "new_fiat_listings")]
94 NewFiatListings,
95 #[serde(rename = "other")]
97 Other,
98}
99
100#[derive(PartialEq, Eq, Hash, Debug, Deserialize, Serialize, Clone, Copy)]
103#[serde(rename_all = "lowercase")]
104pub enum Category {
105 Inverse,
107 Linear,
109 Option,
111 Spot,
113}
114
115impl fmt::Display for Category {
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 let value = match self {
118 Self::Inverse => "inverse",
119 Self::Linear => "linear",
120 Self::Option => "option",
121 Self::Spot => "spot",
122 };
123 write!(f, "{value}")
124 }
125}
126
127#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
129pub enum OrderStatus {
130 New,
133 PartiallyFilled,
135 Untriggered,
137 Rejected,
140 PartiallyFilledCanceled,
142 Filled,
144 Cancelled,
146 Triggered,
148 Deactivated,
150}
151
152impl OrderStatus {
153 pub fn is_open(&self) -> bool {
155 matches!(self, Self::New | Self::PartiallyFilled | Self::Untriggered)
156 }
157 pub fn is_closed(&self) -> bool {
159 matches!(
160 self,
161 Self::Rejected
162 | Self::PartiallyFilledCanceled
163 | Self::Filled
164 | Self::Cancelled
165 | Self::Triggered
166 | Self::Deactivated
167 )
168 }
169}
170
171#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
173pub enum TimeInForce {
174 GTC,
176 IOC,
178 FOK,
180 PostOnly,
182 RPI,
189}
190
191#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
193pub enum CreateType {
194 CreateByUser,
196 CreateByFutureSpread,
198 CreateByAdminClosing,
200 CreateBySettle,
202 CreateByStopOrder,
204 CreateByTakeProfit,
206 CreateByPartialTakeProfit,
208 CreateByStopLoss,
210 CreateByPartialStopLoss,
212 CreateByTrailingStop,
214 CreateByLiq,
216 #[serde(rename = "CreateByTakeOver_PassThrough")]
218 CreateByTakeOverPassThrough,
219 #[serde(rename = "CreateByAdl_PassThrough")]
221 CreateByAdlPassThrough,
222 #[serde(rename = "CreateByBlock_PassThrough")]
224 CreateByBlockPassThrough,
225 #[serde(rename = "CreateByBlockTradeMovePosition_PassThrough")]
227 CreateByBlockTradeMovePositionPassThrough,
228 CreateByClosing,
230 CreateByFGridBot,
232 CloseByFGridBot,
234 CreateByTWAP,
236 CreateByTVSignal,
238 CreateByMmRateClose,
240 CreateByMartingaleBot,
242 CloseByMartingaleBot,
244 CreateByIceBerg,
246 CreateByArbitrage,
248 CreateByDdh,
250}
251
252#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
254pub enum ExecType {
255 Trade,
257 AdlTrade,
259 Funding,
261 BustTrade,
263 Delivery,
265 Settle,
267 BlockTrade,
269 MovePosition,
271 FutureSpread,
273 UNKNOWN,
275}
276
277#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
279pub enum OrderType {
280 Market,
282 Limit,
284 UNKNOWN,
286}
287
288#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
290pub enum StopOrderType {
291 TakeProfit,
293 StopLoss,
295 TrailingStop,
297 Stop,
299 PartialTakeProfit,
301 PartialStopLoss,
303 #[serde(rename = "tpslOrder")]
305 TpslOrder,
306 OcoOrder,
308 MmRateClose,
310 BidirectionalTpslOrder,
312 UNKNOWN,
314}
315
316#[derive(Debug, PartialEq, Deserialize, Clone, Copy)]
318pub enum TickDirection {
319 PlusTick,
321 ZeroPlusTick,
323 MinusTick,
325 ZeroMinusTick,
327}
328
329#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
331pub enum Interval {
332 #[serde(rename = "1")]
334 Minute1,
335 #[serde(rename = "3")]
337 Minute3,
338 #[serde(rename = "5")]
340 Minute5,
341 #[serde(rename = "15")]
343 Minute15,
344 #[serde(rename = "30")]
346 Minute30,
347 #[serde(rename = "60")]
349 Hour1,
350 #[serde(rename = "120")]
352 Hour2,
353 #[serde(rename = "240")]
355 Hour4,
356 #[serde(rename = "360")]
358 Hour6,
359 #[serde(rename = "720")]
361 Hour12,
362 #[serde(rename = "D")]
364 Day1,
365 #[serde(rename = "W")]
367 Week1,
368 #[serde(rename = "M")]
370 Month1,
371}
372
373impl fmt::Display for Interval {
374 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
375 let value = match self {
376 Self::Minute1 => "1",
377 Self::Minute3 => "3",
378 Self::Minute5 => "5",
379 Self::Minute15 => "15",
380 Self::Minute30 => "30",
381 Self::Hour1 => "60",
382 Self::Hour2 => "120",
383 Self::Hour4 => "240",
384 Self::Hour6 => "360",
385 Self::Hour12 => "720",
386 Self::Day1 => "D",
387 Self::Week1 => "W",
388 Self::Month1 => "M",
389 };
390 write!(f, "{value}")
391 }
392}
393
394#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
396pub enum IntervalTime {
397 #[serde(rename = "5min")]
399 Minute5,
400 #[serde(rename = "15min")]
402 Minute15,
403 #[serde(rename = "30min")]
405 Minute30,
406 #[serde(rename = "1h")]
408 Hour1,
409 #[serde(rename = "4h")]
411 Hour4,
412 #[serde(rename = "1d")]
414 Day1,
415}
416
417#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Eq, Hash, Clone, Copy)]
419#[repr(u8)]
420pub enum PositionIdx {
421 OneWay = 0,
423 Buy = 1,
425 Sell = 2,
427}
428
429#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
431#[repr(u8)]
432pub enum PositionMode {
433 OneWay = 0,
435 Hedge = 3,
437}
438
439#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
441pub enum PositionStatus {
442 Normal,
444 Liq,
446 Adl,
448}
449
450#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
452pub enum RejectReason {
453 #[serde(rename = "EC_NoError")]
455 EcNoError,
456 #[serde(rename = "EC_Others")]
458 EcOthers,
459 #[serde(rename = "EC_UnknownMessageType")]
461 EcUnknownMessageType,
462 #[serde(rename = "EC_MissingClOrdID")]
464 EcMissingClOrdId,
465 #[serde(rename = "EC_MissingOrigClOrdID")]
467 EcMissingOrigClOrdId,
468 #[serde(rename = "EC_ClOrdIDOrigClOrdIDAreTheSame")]
470 EcClOrdIdorigClOrdIdareTheSame,
471 #[serde(rename = "EC_DuplicatedClOrdID")]
473 EcDuplicatedClOrdId,
474 #[serde(rename = "EC_OrigClOrdIDDoesNotExist")]
476 EcOrigClOrdIddoesNotExist,
477 #[serde(rename = "EC_TooLateToCancel")]
479 EcTooLateToCancel,
480 #[serde(rename = "EC_UnknownOrderType")]
482 EcUnknownOrderType,
483 #[serde(rename = "EC_UnknownSide")]
485 EcUnknownSide,
486 #[serde(rename = "EC_UnknownTimeInForce")]
488 EcUnknownTimeInForce,
489 #[serde(rename = "EC_WronglyRouted")]
491 EcWronglyRouted,
492 #[serde(rename = "EC_MarketOrderPriceIsNotZero")]
494 EcMarketOrderPriceIsNotZero,
495 #[serde(rename = "EC_LimitOrderInvalidPrice")]
497 EcLimitOrderInvalidPrice,
498 #[serde(rename = "EC_NoEnoughQtyToFill")]
500 EcNoEnoughQtyToFill,
501 #[serde(rename = "EC_NoImmediateQtyToFill")]
503 EcNoImmediateQtyToFill,
504 #[serde(rename = "EC_PerCancelRequest")]
506 EcPerCancelRequest,
507 #[serde(rename = "EC_MarketOrderCannotBePostOnly")]
509 EcMarketOrderCannotBePostOnly,
510 #[serde(rename = "EC_PostOnlyWillTakeLiquidity")]
512 EcPostOnlyWillTakeLiquidity,
513 #[serde(rename = "EC_CancelReplaceOrder")]
515 EcCancelReplaceOrder,
516 #[serde(rename = "EC_InvalidSymbolStatus")]
518 EcInvalidSymbolStatus,
519 #[serde(rename = "EC_CancelForNoFullFill")]
521 EcCancelForNoFullFill,
522 #[serde(rename = "EC_BySelfMatch")]
524 EcBySelfMatch,
525 #[serde(rename = "EC_InCallAuctionStatus")]
527 EcInCallAuctionStatus,
528 #[serde(rename = "EC_QtyCannotBeZero")]
530 EcQtyCannotBeZero,
531 #[serde(rename = "EC_MarketOrderNoSupportTIF")]
533 EcMarketOrderNoSupportTif,
534 #[serde(rename = "EC_ReachMaxTradeNum")]
536 EcReachMaxTradeNum,
537 #[serde(rename = "EC_InvalidPriceScale")]
539 EcInvalidPriceScale,
540 #[serde(rename = "EC_BitIndexInvalid")]
542 EcBitIndexInvalid,
543 #[serde(rename = "EC_StopBySelfMatch")]
545 EcStopBySelfMatch,
546 #[serde(rename = "EC_InvalidSmpType")]
548 EcInvalidSmpType,
549 #[serde(rename = "EC_CancelByMMP")]
551 EcCancelByMmp,
552 #[serde(rename = "EC_InvalidUserType")]
554 EcInvalidUserType,
555 #[serde(rename = "EC_InvalidMirrorOid")]
557 EcInvalidMirrorOid,
558 #[serde(rename = "EC_InvalidMirrorUid")]
560 EcInvalidMirrorUid,
561 #[serde(rename = "EC_EcInvalidQty")]
563 EcEcInvalidQty,
564 #[serde(rename = "EC_InvalidAmount")]
566 EcInvalidAmount,
567 #[serde(rename = "EC_LoadOrderCancel")]
569 EcLoadOrderCancel,
570 #[serde(rename = "EC_MarketQuoteNoSuppSell")]
572 EcMarketQuoteNoSuppSell,
573 #[serde(rename = "EC_DisorderOrderID")]
575 EcDisorderOrderId,
576 #[serde(rename = "EC_InvalidBaseValue")]
578 EcInvalidBaseValue,
579 #[serde(rename = "EC_LoadOrderCanMatch")]
581 EcLoadOrderCanMatch,
582 #[serde(rename = "EC_SecurityStatusFail")]
584 EcSecurityStatusFail,
585 #[serde(rename = "EC_ReachRiskPriceLimit")]
587 EcReachRiskPriceLimit,
588 #[serde(rename = "EC_OrderNotExist")]
590 EcOrderNotExist,
591 #[serde(rename = "EC_CancelByOrderValueZero")]
593 EcCancelByOrderValueZero,
594 #[serde(rename = "EC_CancelByMatchValueZero")]
596 EcCancelByMatchValueZero,
597 #[serde(rename = "EC_ReachMarketPriceLimit")]
599 EcReachMarketPriceLimit,
600}
601
602#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
604pub enum AccountType {
605 CONTRACT,
607 UNIFIED,
609 FUND,
611 SPOT,
613}
614
615impl AccountType {
616 pub fn is_uta_2(&self) -> bool {
618 matches!(self, Self::UNIFIED | Self::FUND)
619 }
620 pub fn is_uta_1(&self) -> bool {
622 matches!(self, Self::CONTRACT | Self::UNIFIED | Self::FUND)
623 }
624 pub fn is_classic(&self) -> bool {
626 matches!(self, Self::SPOT | Self::CONTRACT | Self::FUND)
627 }
628}
629
630#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
632pub enum TransferStatus {
633 SUCCESS,
635 PENDING,
637 FAILED,
639}
640
641#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
643pub enum DepositStatus {
644 #[serde(rename = "0")]
646 Unknown,
647 #[serde(rename = "1")]
649 ToBeConfirmed,
650 #[serde(rename = "2")]
652 Processing,
653 #[serde(rename = "3")]
655 Success,
656 #[serde(rename = "4")]
658 DepositFailed,
659 #[serde(rename = "10011")]
661 PendingToBeCreditedToFundingPool,
662 #[serde(rename = "10012")]
664 CreditedToFundingPoolSuccessfully,
665}
666
667#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
669pub enum WithdrawStatus {
670 SecurityCheck,
672 Pending,
674 #[serde(rename = "success")]
676 Success,
677 CancelByUser,
679 Reject,
681 Fail,
683 BlockchainConfirmed,
685 MoreInformationRequired,
687 Unknown,
689}
690
691#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
693pub enum TriggerBy {
694 LastPrice,
696 IndexPrice,
698 MarkPrice,
700 UNKNOWN,
702}
703
704#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
706pub enum CancelType {
707 CancelByUser,
709 CancelByReduceOnly,
711 CancelByPrepareLiq,
713 CancelAllBeforeLiq,
715 CancelByPrepareAdl,
717 CancelAllBeforeAdl,
719 CancelByAdmin,
721 CancelBySettle,
723 CancelByTpSlTsClear,
725 CancelBySmp,
727 CancelByDCP,
729 CancelByRebalance,
731
732 CancelByCannotAffordOrderCost,
735 CancelByPmTrialMmOverEquity,
737 CancelByAccountBlocking,
739 CancelByDelivery,
741 CancelByMmpTriggered,
743 CancelByCrossSelfMuch,
745 CancelByCrossReachMaxTradeNum,
747
748 UNKNOWN,
750}
751
752#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
754pub enum OptionPeriod {
755 #[serde(rename = "7")]
757 Day7,
758 #[serde(rename = "14")]
760 Day14,
761 #[serde(rename = "21")]
763 Day21,
764 #[serde(rename = "30")]
766 Day30,
767 #[serde(rename = "60")]
769 Day60,
770 #[serde(rename = "90")]
772 Day90,
773 #[serde(rename = "180")]
775 Day180,
776 #[serde(rename = "270")]
778 Day270,
779}
780
781#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
783pub enum DataRecordingPeriod {
784 #[serde(rename = "5min")]
786 Minute5,
787 #[serde(rename = "15min")]
789 Minute15,
790 #[serde(rename = "30min")]
792 Minute30,
793 #[serde(rename = "1h")]
795 Hour1,
796 #[serde(rename = "4h")]
798 Hour4,
799 #[serde(rename = "4d")]
801 Day4,
802}
803
804#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
806pub enum ContractType {
807 InversePerpetual,
809 LinearPerpetual,
811 LinearFutures,
813 InverseFutures,
815}
816
817#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
819pub enum Status {
820 PreLaunch,
822 Trading,
824 Delivering,
826 Closed,
828}
829
830#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
832#[serde(rename_all = "camelCase")]
833pub enum MarginTrading {
834 None,
836 Both,
838 UtaOnly,
840 NormalSpotOnly,
842}
843
844#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
846#[serde(rename_all = "camelCase")]
847pub enum CopyTrading {
848 None,
850 Both,
852 UtaOnly,
854 NormalOnly,
856}
857
858#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
860#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
861pub enum Type {
862 TransferIn,
864 TransferOut,
866 Trade,
868 Settlement,
871 Delivery,
873 Liquidation,
875 ADL,
877 Airdrop,
879 Bonus,
881 BonusRecollect,
883 FeeRefund,
885 Interest,
887 CurrencyBuy,
889 CurrencySell,
891 BorrowedAmountInsLoan,
893 PrincipleRepaymentInsLoan,
895 InterestRepaymentInsLoan,
897 AutoSoldCollateralInsLoan,
899 AutoBuyLiabilityInsLoan,
901 AutoPrincipleRepaymentInsLoan,
903 AutoInterestRepaymentInsLoan,
905 TransferInInsLoan,
907 TransferOutInsLoan,
909 SpotRepaymentSell,
911 SpotRepaymentBuy,
913 TokensSubscription,
915 TokensRedemption,
917 AutoDeduction,
919 FlexibleStakingSubscription,
921 FlexibleStakingRedemption,
923 FixedStakingSubscription,
925 PremarketTransferOut,
927 PremarketDeliverySellNewCoin,
929 PremarketDeliveryBuyNewCoin,
931 PremarketDeliveryPledgePaySeller,
933 PremarketDeliveryPledgeBack,
935 PremarketRollbackPledgeBack,
937 PremarketRollbackPledgePenaltyToBuyer,
939 CustodyNetworkFee,
941 CustodySettleFee,
943 CustodyLock,
945 CustodyUnlock,
947 CustodyUnlockRefund,
949 LoansBorrowFunds,
951 LoansPledgeAsset,
953 BonusTransferIn,
955 BonusTransferOut,
957 PefTransferIn,
959 PefTransferOut,
961 PefProfitShare,
963 #[serde(rename = "Others")]
965 Others,
966}
967
968impl Type {
969 pub fn is_uta(&self) -> bool {
971 matches!(
972 self,
973 Self::TransferIn
974 | Self::TransferOut
975 | Self::Trade
976 | Self::Settlement
977 | Self::Delivery
978 | Self::Liquidation
979 | Self::ADL
980 | Self::Airdrop
981 | Self::Bonus
982 | Self::BonusRecollect
983 | Self::FeeRefund
984 | Self::Interest
985 | Self::CurrencyBuy
986 | Self::CurrencySell
987 | Self::BorrowedAmountInsLoan
988 | Self::PrincipleRepaymentInsLoan
989 | Self::InterestRepaymentInsLoan
990 | Self::AutoSoldCollateralInsLoan
991 | Self::AutoBuyLiabilityInsLoan
992 | Self::AutoPrincipleRepaymentInsLoan
993 | Self::AutoInterestRepaymentInsLoan
994 | Self::TransferInInsLoan
995 | Self::TransferOutInsLoan
996 | Self::SpotRepaymentSell
997 | Self::SpotRepaymentBuy
998 | Self::TokensSubscription
999 | Self::TokensRedemption
1000 | Self::AutoDeduction
1001 | Self::FlexibleStakingSubscription
1002 | Self::FlexibleStakingRedemption
1003 | Self::FixedStakingSubscription
1004 | Self::PremarketTransferOut
1005 | Self::PremarketDeliverySellNewCoin
1006 | Self::PremarketDeliveryBuyNewCoin
1007 | Self::PremarketDeliveryPledgePaySeller
1008 | Self::PremarketDeliveryPledgeBack
1009 | Self::PremarketRollbackPledgeBack
1010 | Self::PremarketRollbackPledgePenaltyToBuyer
1011 | Self::CustodyNetworkFee
1012 | Self::CustodySettleFee
1013 | Self::CustodyLock
1014 | Self::CustodyUnlock
1015 | Self::CustodyUnlockRefund
1016 | Self::LoansBorrowFunds
1017 | Self::LoansPledgeAsset
1018 | Self::BonusTransferIn
1019 | Self::BonusTransferOut
1020 | Self::PefTransferIn
1021 | Self::PefTransferOut
1022 | Self::PefProfitShare
1023 )
1024 }
1025 pub fn is_contract(&self) -> bool {
1027 matches!(
1028 self,
1029 Self::TransferIn
1030 | Self::TransferOut
1031 | Self::Trade
1032 | Self::Settlement
1033 | Self::Delivery
1034 | Self::Liquidation
1035 | Self::ADL
1036 | Self::Airdrop
1037 | Self::Bonus
1038 | Self::BonusRecollect
1039 | Self::FeeRefund
1040 | Self::CurrencyBuy
1041 | Self::CurrencySell
1042 | Self::AutoDeduction
1043 | Self::Others
1044 )
1045 }
1046}
1047
1048#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1050#[repr(u8)]
1051pub enum UnifiedMarginStatus {
1052 ClassicAccount = 1,
1054 UnifiedTradingAccount1 = 3,
1056 UnifiedTradingAccount1Pro = 4,
1058 UnifiedTradingAccount2 = 5,
1060 UnifiedTradingAccount2Pro = 6,
1062}
1063
1064#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1066#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1067pub enum MarginMode {
1068 IsolatedMargin,
1070 RegularMargin,
1072 PortfolioMargin,
1074}
1075
1076#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1078pub enum SpotMarginMode {
1079 #[serde(rename = "0")]
1081 Disabled,
1082 #[serde(rename = "1")]
1084 Enabled,
1085}
1086
1087#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1089#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1090pub enum SpotHedgingStatus {
1091 On,
1093 Off,
1095}
1096
1097#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1099pub enum LtStatus {
1100 #[serde(rename = "1")]
1102 CanBePurchasedAndRedeemed,
1103 #[serde(rename = "2")]
1105 CanBePurchasedButNotRedeemed,
1106 #[serde(rename = "3")]
1108 CanBeRedeemedButNotPurchased,
1109 #[serde(rename = "4")]
1111 CannotBePurchasedNorRedeemed,
1112 #[serde(rename = "5")]
1114 AdjustingPosition,
1115}
1116
1117#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1119pub enum LtOrderStatus {
1120 #[serde(rename = "1")]
1122 Completed,
1123 #[serde(rename = "2")]
1125 InProgress,
1126 #[serde(rename = "3")]
1128 Failed,
1129}
1130
1131#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1133#[repr(u8)]
1134pub enum LtOrderType {
1135 Purchase = 1,
1137 Redemption = 2,
1139}
1140
1141#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1143pub enum ConvertAccountType {
1144 #[serde(rename = "eb_convert_uta")]
1146 Uta,
1147 #[serde(rename = "eb_convert_funding")]
1149 Funding,
1150 #[serde(rename = "eb_convert_inverse")]
1152 Inverse,
1153 #[serde(rename = "eb_convert_spot")]
1155 Spot,
1156 #[serde(rename = "eb_convert_contract")]
1158 Contract,
1159}
1160
1161#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1163pub enum VipLevel {
1164 #[serde(rename = "No VIP")]
1166 NoVIP,
1167 #[serde(rename = "VIP-1")]
1169 VIP1,
1170 #[serde(rename = "VIP-2")]
1172 VIP2,
1173 #[serde(rename = "VIP-3")]
1175 VIP3,
1176 #[serde(rename = "VIP-4")]
1178 VIP4,
1179 #[serde(rename = "VIP-5")]
1181 VIP5,
1182 #[serde(rename = "VIP-Supreme")]
1184 VIPSupreme,
1185 #[serde(rename = "PRO-1")]
1187 PRO1,
1188 #[serde(rename = "PRO-2")]
1190 PRO2,
1191 #[serde(rename = "PRO-3")]
1193 PRO3,
1194 #[serde(rename = "PRO-4")]
1196 PRO4,
1197 #[serde(rename = "PRO-5")]
1199 PRO5,
1200}
1201
1202#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1204#[repr(u8)]
1205pub enum AdlRankIndicator {
1206 Zero = 0,
1208 One = 1,
1210 Two = 2,
1212 Three = 3,
1214 Four = 4,
1216 Five = 5,
1218}
1219
1220#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1222pub enum SmpType {
1223 None,
1225 CancelMaker,
1227 CancelTaker,
1229 CancelBoth,
1231}
1232
1233#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1235#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1236pub enum ExtraFeeType {
1237 Unknown,
1239 Tax,
1241 Cfx,
1243 Wht,
1245 Gst,
1247 Vat,
1249}
1250
1251#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1253#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1254pub enum ExtraSubFeeType {
1255 Unknown,
1257 TaxPnn,
1259 TaxPph,
1261 CfxFiee,
1263 AutWithholdingTax,
1265 IndGst,
1267 AreVat,
1269}
1270
1271#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1273#[serde(rename_all = "lowercase")]
1274pub enum State {
1275 Scheduled,
1277 Ongoing,
1279 Completed,
1281 Canceled,
1283}
1284
1285#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1287#[repr(u8)]
1288pub enum ServiceTypes {
1289 TradingService = 1,
1291 TradingServiceViaHttpRequest = 2,
1293 TradingServiceViaWebsocket = 3,
1295 PrivateWebsocketStream = 4,
1297 MarketDataService = 5,
1299}
1300
1301#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1303#[repr(u8)]
1304pub enum Product {
1305 Futures = 1,
1307 Spot = 2,
1309 Option = 3,
1311 Spread = 4,
1313}
1314
1315#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1317#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1318pub enum DCPProduct {
1319 Spot,
1321 Derivatives,
1323 Option,
1325}
1326
1327#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1329#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1330pub enum UnifiedUpdateStatus {
1331 Fail,
1333 Process,
1335 Success,
1337}
1338
1339#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1341#[repr(u8)]
1342pub enum MaintainType {
1343 PlannedMaintenance = 1,
1345 TemporaryMaintenance = 2,
1347 Incident = 3,
1349}
1350
1351#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1353#[repr(u8)]
1354pub enum Env {
1355 Product = 1,
1357 ProductDemoService = 2,
1359}
1360
1361#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1363pub enum TpslMode {
1364 Full,
1366 Partial,
1368 UNKNOWN,
1370}
1371
1372#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1374pub enum OcoTriggerBy {
1375 #[serde(rename = "OcoTriggerByUnknown")]
1377 Unknown,
1378 #[serde(rename = "OcoTriggerByTp")]
1380 Tp,
1381 #[serde(rename = "OcoTriggerByBySl")]
1383 BySl,
1384}
1385
1386#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1388#[repr(u8)]
1389pub enum TriggerDirection {
1390 UNKNOWN = 0,
1392 Rise = 1,
1394 Fall = 2,
1396}
1397
1398#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1400pub enum CurAuctionPhase {
1401 NotStarted,
1403 Finished,
1407 CallAuction,
1413 CallAuctionNoCancel,
1419 CrossMatching,
1423 ContinuousTrading,
1427}
1428
1429#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1431pub enum PlaceType {
1432 #[serde(rename = "option")]
1434 Option,
1435 #[serde(rename = "iv")]
1437 Iv,
1438 #[serde(rename = "price")]
1440 Price,
1441}
1442
1443#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Hash, Clone, Copy)]
1445pub enum OptionType {
1446 Call,
1448 Put,
1450}
1451
1452#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1454pub enum Side {
1455 Buy,
1457 Sell,
1459}
1460impl Side {
1461 pub fn reverse(&self) -> Self {
1463 match self {
1464 Side::Buy => Self::Sell,
1465 Side::Sell => Self::Buy,
1466 }
1467 }
1468}
1469
1470#[derive(Debug, PartialEq, Clone, Copy)]
1472pub enum Pair {
1473 Base, Quote, }
1479
1480#[derive(Debug, Deserialize, PartialEq, Clone, Copy)]
1482pub enum SlippageToleranceType {
1483 TickSize,
1485 Percent,
1487 UNKNOWN,
1489}
1490
1491#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1493#[repr(u8)]
1494pub enum TradeMode {
1495 CrossMargin = 0,
1497 IsolatedMargin = 1,
1499}
1500
1501#[derive(Debug, Clone, PartialEq)]
1503pub enum Topic {
1504 Orderbook {
1506 symbol: String,
1508 depth: DepthLevel,
1510 },
1511 Trade(String),
1513 Ticker(String),
1515 Kline {
1517 symbol: String,
1519 interval: Interval,
1521 },
1522 AllLiquidation(String),
1524 Position(Category),
1526 PositionAllCategory,
1528 Execution(Category),
1530 ExecutionAllCategory,
1532 FastExecution(Category),
1534 FastExecutionAllCategory,
1536 Order(Category),
1538 OrderAllCategory,
1540 Wallet,
1542 Greek,
1544 Dcp(DcpFunction),
1546}
1547
1548impl fmt::Display for Topic {
1549 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1550 let value = match self {
1551 Self::Orderbook { symbol, depth } => format!("orderbook.{depth}.{symbol}"),
1552 Self::Trade(symbol) => format!("publicTrade.{symbol}"),
1553 Self::Ticker(symbol) => format!("tickers.{symbol}"),
1554 Self::Kline { symbol, interval } => format!("kline.{interval}.{symbol}"),
1555 Self::AllLiquidation(symbol) => format!("allLiquidation.{symbol}"),
1556 Self::Position(category) => format!("position.{category}"),
1557 Self::PositionAllCategory => "position".to_string(),
1558 Self::Execution(category) => format!("execution.{category}"),
1559 Self::ExecutionAllCategory => "execution".to_string(),
1560 Self::FastExecution(category) => format!("execution.fast.{category}"),
1561 Self::FastExecutionAllCategory => "execution.fast".to_string(),
1562 Self::Order(category) => format!("order.{category}"),
1563 Self::OrderAllCategory => "order".to_string(),
1564 Self::Wallet => "wallet".to_string(),
1565 Self::Greek => "greek".to_string(),
1566 Self::Dcp(function) => format!("dcp.{function}"),
1567 };
1568 write!(f, "{value}")
1569 }
1570}
1571
1572impl Serialize for Topic {
1573 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1574 where
1575 S: Serializer,
1576 {
1577 serializer.collect_str(self)
1578 }
1579}
1580
1581impl<'de> Deserialize<'de> for Topic {
1582 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1583 where
1584 D: Deserializer<'de>,
1585 {
1586 let s: std::borrow::Cow<'de, str> = Deserialize::deserialize(deserializer)?;
1587 let s = s.as_ref();
1588 if let Some((kind, args)) = s.split_once('.') {
1589 match kind {
1590 "orderbook" => {
1591 if let Some((depth, symbol)) = args.split_once('.') {
1592 let depth =
1593 serde_json::from_str(&format!("\"{depth}\"")).map_err(|err| {
1594 serde::de::Error::custom(format!(
1595 "DepthLevel: {depth}, error: {err}"
1596 ))
1597 })?;
1598 Ok(Self::Orderbook {
1599 depth,
1600 symbol: symbol.to_owned(),
1601 })
1602 } else {
1603 Err(serde::de::Error::custom("invalid stream format"))
1604 }
1605 }
1606 "publicTrade" => Ok(Self::Trade(args.to_owned())),
1607 "tickers" => Ok(Self::Ticker(args.to_owned())),
1608 "kline" => {
1609 if let Some((interval, symbol)) = args.split_once('.') {
1610 let interval = serde_json::from_str(&format!("\"{interval}\""))
1611 .map_err(|err| serde::de::Error::custom(format!("Interval: {err}")))?;
1612 Ok(Self::Kline {
1613 symbol: symbol.to_owned(),
1614 interval,
1615 })
1616 } else {
1617 Err(serde::de::Error::custom("invalid stream format"))
1618 }
1619 }
1620 "allLiquidation" => Ok(Self::AllLiquidation(args.to_owned())),
1621 "position" => {
1622 let category = serde_json::from_str(&format!("\"{args}\""))
1623 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1624 Ok(Self::Position(category))
1625 }
1626 "execution" => {
1627 if args == "fast" {
1628 Ok(Self::FastExecutionAllCategory)
1629 } else if let Some((fast, category)) = args.split_once('.') {
1630 let category = serde_json::from_str(&format!("\"{category}\""))
1631 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1632 if fast == "fast" {
1633 Ok(Self::FastExecution(category))
1634 } else {
1635 Ok(Self::Execution(category))
1636 }
1637 } else {
1638 let category = serde_json::from_str(&format!("\"{args}\""))
1639 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1640 Ok(Self::Execution(category))
1641 }
1642 }
1643 "order" => {
1644 let category = serde_json::from_str(&format!("\"{args}\""))
1645 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1646 Ok(Self::Order(category))
1647 }
1648 "dcp" => {
1649 let function = serde_json::from_str(&format!("\"{args}\""))
1650 .map_err(|err| serde::de::Error::custom(format!("DcpFunction: {err}")))?;
1651 Ok(Self::Dcp(function))
1652 }
1653 _ => Err(serde::de::Error::custom("invalid stream format")),
1654 }
1655 } else {
1656 match s {
1657 "position" => Ok(Self::PositionAllCategory),
1658 "execution" => Ok(Self::ExecutionAllCategory),
1659 "order" => Ok(Self::OrderAllCategory),
1660 "wallet" => Ok(Self::Wallet),
1661 "greek" => Ok(Self::Greek),
1662 _ => {
1663 let msg = String::from("invalid stream format");
1664 Err(serde::de::Error::custom(msg))
1665 }
1666 }
1667 }
1668 }
1669}
1670
1671#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1673#[serde(rename_all = "lowercase")]
1674pub enum DcpFunction {
1675 Future,
1677 Option,
1679 Spot,
1681}
1682
1683impl fmt::Display for DcpFunction {
1684 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1685 let value = match self {
1686 Self::Future => "future",
1687 Self::Option => "option",
1688 Self::Spot => "spot",
1689 };
1690 write!(f, "{value}")
1691 }
1692}
1693
1694#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1696pub enum DepthLevel {
1697 #[serde(rename = "1")]
1699 Level1,
1700 #[serde(rename = "25")]
1702 Level25,
1703 #[serde(rename = "50")]
1705 Level50,
1706 #[serde(rename = "100")]
1708 Level100,
1709 #[serde(rename = "200")]
1711 Level200,
1712 #[serde(rename = "500")]
1714 Level500,
1715 #[serde(rename = "1000")]
1717 Level1000,
1718}
1719
1720impl fmt::Display for DepthLevel {
1721 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1722 let value = match self {
1723 Self::Level1 => "1",
1724 Self::Level25 => "25",
1725 Self::Level50 => "50",
1726 Self::Level100 => "100",
1727 Self::Level200 => "200",
1728 Self::Level500 => "500",
1729 Self::Level1000 => "1000",
1730 };
1731 write!(f, "{value}")
1732 }
1733}
1734
1735pub fn spot_fee_currency(side: Side, is_maker_order: bool, maker_fee_rate: f64) -> Pair {
1739 if maker_fee_rate >= 0.0 {
1740 match side {
1741 Side::Buy => Pair::Base,
1742 Side::Sell => Pair::Quote,
1743 }
1744 } else if is_maker_order {
1745 match side {
1746 Side::Buy => Pair::Quote,
1747 Side::Sell => Pair::Base,
1748 }
1749 } else {
1750 match side {
1751 Side::Buy => Pair::Base,
1752 Side::Sell => Pair::Quote,
1753 }
1754 }
1755}
1756
1757#[cfg(test)]
1758mod tests {
1759 use crate::serde::deserialize_json;
1760
1761 use super::*;
1762
1763 #[test]
1764 fn serialize_category() {
1765 let cases = [
1766 (Category::Inverse, r#""inverse""#),
1767 (Category::Linear, r#""linear""#),
1768 (Category::Option, r#""option""#),
1769 (Category::Spot, r#""spot""#),
1770 ];
1771 cases.iter().for_each(|(category, expected)| {
1772 let json = serde_json::to_string(category).unwrap();
1773 assert_eq!(json, *expected);
1774 });
1775 }
1776
1777 #[test]
1778 fn deserialize_category() {
1779 let cases = [
1780 (r#""inverse""#, Category::Inverse),
1781 (r#""linear""#, Category::Linear),
1782 (r#""option""#, Category::Option),
1783 (r#""spot""#, Category::Spot),
1784 ];
1785 cases.iter().for_each(|(json, expected)| {
1786 let message: Category = deserialize_json(json).unwrap();
1787 assert_eq!(message, *expected);
1788 });
1789 }
1790
1791 #[test]
1792 fn serialize_interval() {
1793 let cases = vec![
1794 (Interval::Minute1, r#""1""#),
1795 (Interval::Minute3, r#""3""#),
1796 (Interval::Minute5, r#""5""#),
1797 (Interval::Minute15, r#""15""#),
1798 (Interval::Minute30, r#""30""#),
1799 (Interval::Hour1, r#""60""#),
1800 (Interval::Hour2, r#""120""#),
1801 (Interval::Hour4, r#""240""#),
1802 (Interval::Hour6, r#""360""#),
1803 (Interval::Hour12, r#""720""#),
1804 (Interval::Day1, r#""D""#),
1805 (Interval::Week1, r#""W""#),
1806 (Interval::Month1, r#""M""#),
1807 ];
1808 cases.iter().for_each(|(category, expected)| {
1809 let json = serde_json::to_string(category).unwrap();
1810 assert_eq!(json, *expected);
1811 });
1812 }
1813
1814 #[test]
1815 fn deserialize_interval() {
1816 let cases = vec![
1817 (r#""1""#, Interval::Minute1),
1818 (r#""3""#, Interval::Minute3),
1819 (r#""5""#, Interval::Minute5),
1820 (r#""15""#, Interval::Minute15),
1821 (r#""30""#, Interval::Minute30),
1822 (r#""60""#, Interval::Hour1),
1823 (r#""120""#, Interval::Hour2),
1824 (r#""240""#, Interval::Hour4),
1825 (r#""360""#, Interval::Hour6),
1826 (r#""720""#, Interval::Hour12),
1827 (r#""D""#, Interval::Day1),
1828 (r#""W""#, Interval::Week1),
1829 (r#""M""#, Interval::Month1),
1830 ];
1831 cases.iter().for_each(|(json, expected)| {
1832 let message: Interval = deserialize_json(json).unwrap();
1833 assert_eq!(message, *expected);
1834 });
1835 }
1836
1837 #[test]
1838 fn deserialize_topic_with_escaped_characters() {
1839 let topic: Topic = serde_json::from_str(r#""tickers.BTC\u0055SDT""#).unwrap();
1840
1841 assert_eq!(topic, Topic::Ticker(String::from("BTCUSDT")));
1842 }
1843
1844 #[test]
1845 fn serialize_topic() {
1846 let symbol = String::from("BTCUSDT");
1847 let cases = vec![
1848 (
1849 Topic::Orderbook {
1850 symbol: symbol.clone(),
1851 depth: DepthLevel::Level1,
1852 },
1853 r#""orderbook.1.BTCUSDT""#,
1854 ),
1855 (Topic::Trade(symbol.clone()), r#""publicTrade.BTCUSDT""#),
1856 (Topic::Ticker(symbol.clone()), r#""tickers.BTCUSDT""#),
1857 (
1858 Topic::Kline {
1859 symbol: symbol.clone(),
1860 interval: Interval::Minute1,
1861 },
1862 r#""kline.1.BTCUSDT""#,
1863 ),
1864 (
1865 Topic::AllLiquidation(symbol.clone()),
1866 r#""allLiquidation.BTCUSDT""#,
1867 ),
1868 (Topic::Position(Category::Linear), r#""position.linear""#),
1869 (Topic::PositionAllCategory, r#""position""#),
1870 (Topic::Execution(Category::Linear), r#""execution.linear""#),
1871 (Topic::ExecutionAllCategory, r#""execution""#),
1872 (
1873 Topic::FastExecution(Category::Linear),
1874 r#""execution.fast.linear""#,
1875 ),
1876 (Topic::FastExecutionAllCategory, r#""execution.fast""#),
1877 (Topic::Order(Category::Linear), r#""order.linear""#),
1878 (Topic::OrderAllCategory, r#""order""#),
1879 (Topic::Wallet, r#""wallet""#),
1880 (Topic::Greek, r#""greek""#),
1881 (Topic::Dcp(DcpFunction::Future), r#""dcp.future""#),
1882 ];
1883 cases.iter().for_each(|(category, expected)| {
1884 let json = serde_json::to_string(category).unwrap();
1885 assert_eq!(*expected, json);
1886 });
1887 }
1888
1889 #[test]
1890 fn deserialize_topic() {
1891 let symbol = String::from("BTCUSDT");
1892 let cases = vec![
1893 (
1894 r#""orderbook.1.BTCUSDT""#,
1895 Topic::Orderbook {
1896 symbol: symbol.clone(),
1897 depth: DepthLevel::Level1,
1898 },
1899 ),
1900 (r#""publicTrade.BTCUSDT""#, Topic::Trade(symbol.clone())),
1901 (r#""tickers.BTCUSDT""#, Topic::Ticker(symbol.clone())),
1902 (
1903 r#""kline.1.BTCUSDT""#,
1904 Topic::Kline {
1905 symbol: symbol.clone(),
1906 interval: Interval::Minute1,
1907 },
1908 ),
1909 (
1910 r#""allLiquidation.BTCUSDT""#,
1911 Topic::AllLiquidation(symbol.clone()),
1912 ),
1913 (r#""position.linear""#, Topic::Position(Category::Linear)),
1914 (r#""position""#, Topic::PositionAllCategory),
1915 (r#""execution.linear""#, Topic::Execution(Category::Linear)),
1916 (r#""execution""#, Topic::ExecutionAllCategory),
1917 (
1918 r#""execution.fast.linear""#,
1919 Topic::FastExecution(Category::Linear),
1920 ),
1921 (r#""execution.fast""#, Topic::FastExecutionAllCategory),
1922 (r#""order.linear""#, Topic::Order(Category::Linear)),
1923 (r#""order""#, Topic::OrderAllCategory),
1924 (r#""wallet""#, Topic::Wallet),
1925 (r#""greek""#, Topic::Greek),
1926 (r#""dcp.future""#, Topic::Dcp(DcpFunction::Future)),
1927 ];
1928 cases.iter().for_each(|(json, expected)| {
1929 let message = deserialize_json(json).unwrap();
1930 assert_eq!(*expected, message);
1931 });
1932 }
1933}