1use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use serde_repr::*;
7use std::fmt;
8
9#[derive(Debug, Deserialize, Serialize)]
10pub enum Locale {
11 #[serde(rename = "de-DE")]
12 DeDe,
13 #[serde(rename = "en-US")]
14 EnUs,
15 #[serde(rename = "es-AR")]
16 EsAr,
17 #[serde(rename = "es-ES")]
18 EsEs,
19 #[serde(rename = "es-MX")]
20 EsMx,
21 #[serde(rename = "fr-FR")]
22 FrFr,
23 #[serde(rename = "kk-KZ")]
24 KkKz,
25 #[serde(rename = "id-ID")]
26 IdId,
27 #[serde(rename = "uk-UA")]
28 UkUa,
29 #[serde(rename = "ja-JP")]
30 JaJp,
31 #[serde(rename = "ru-RU")]
32 RuRu,
33 #[serde(rename = "th-TH")]
34 ThTh,
35 #[serde(rename = "pt-BR")]
36 PtBr,
37 #[serde(rename = "tr-TR")]
38 TrTr,
39 #[serde(rename = "vi-VN")]
40 ViVn,
41 #[serde(rename = "zh-TW")]
42 ZhTw,
43 #[serde(rename = "ar-SA")]
44 ArSa,
45 #[serde(rename = "hi-IN")]
46 HiIn,
47 #[serde(rename = "fil-PH")]
48 FilPh,
49}
50
51#[derive(Debug, Deserialize, Serialize)]
52pub enum AnnouncementType {
53 #[serde(rename = "new_crypto")]
54 NewCrypto,
55 #[serde(rename = "latest_bybit_news")]
56 LatestBybitNews,
57 #[serde(rename = "delistings")]
58 Delistings,
59 #[serde(rename = "latest_activities")]
60 LatestActivities,
61 #[serde(rename = "product_updates")]
62 ProductUpdates,
63 #[serde(rename = "maintenance_updates")]
64 MaintenanceUpdates,
65 #[serde(rename = "new_fiat_listings")]
66 NewFiatListings,
67 #[serde(rename = "other")]
68 Other,
69}
70
71#[derive(PartialEq, Eq, Hash, Debug, Deserialize, Serialize, Clone, Copy)]
74#[serde(rename_all = "lowercase")]
75pub enum Category {
76 Inverse,
78 Linear,
80 Option,
81 Spot,
82}
83
84impl fmt::Display for Category {
85 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 let value = match self {
87 Self::Inverse => "inverse",
88 Self::Linear => "linear",
89 Self::Option => "option",
90 Self::Spot => "spot",
91 };
92 write!(f, "{value}")
93 }
94}
95
96#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
97pub enum OrderStatus {
98 New,
101 PartiallyFilled,
102 Untriggered,
104 Rejected,
106 PartiallyFilledCanceled,
108 Filled,
109 Cancelled,
111 Triggered,
113 Deactivated,
115}
116
117impl OrderStatus {
118 pub fn is_open(&self) -> bool {
119 matches!(self, Self::New | Self::PartiallyFilled | Self::Untriggered)
120 }
121 pub fn is_closed(&self) -> bool {
122 matches!(
123 self,
124 Self::Rejected
125 | Self::PartiallyFilledCanceled
126 | Self::Filled
127 | Self::Cancelled
128 | Self::Triggered
129 | Self::Deactivated
130 )
131 }
132}
133
134#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
135pub enum TimeInForce {
136 GTC,
138 IOC,
140 FOK,
142 PostOnly,
143 RPI,
150}
151
152#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
153pub enum CreateType {
154 CreateByUser,
155 CreateByFutureSpread,
157 CreateByAdminClosing,
158 CreateBySettle,
160 CreateByStopOrder,
162 CreateByTakeProfit,
164 CreateByPartialTakeProfit,
166 CreateByStopLoss,
168 CreateByPartialStopLoss,
170 CreateByTrailingStop,
172 CreateByLiq,
174 #[serde(rename = "CreateByTakeOver_PassThrough")]
176 CreateByTakeOverPassThrough,
177 #[serde(rename = "CreateByAdl_PassThrough")]
179 CreateByAdlPassThrough,
180 #[serde(rename = "CreateByBlock_PassThrough")]
182 CreateByBlockPassThrough,
183 #[serde(rename = "CreateByBlockTradeMovePosition_PassThrough")]
185 CreateByBlockTradeMovePositionPassThrough,
186 CreateByClosing,
188 CreateByFGridBot,
190 CloseByFGridBot,
192 CreateByTWAP,
194 CreateByTVSignal,
196 CreateByMmRateClose,
198 CreateByMartingaleBot,
200 CloseByMartingaleBot,
202 CreateByIceBerg,
204 CreateByArbitrage,
206 CreateByDdh,
208}
209
210#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
211pub enum ExecType {
212 Trade,
213 AdlTrade,
215 Funding,
217 BustTrade,
219 Delivery,
221 Settle,
223 BlockTrade,
224 MovePosition,
225 FutureSpread,
227 UNKNOWN,
229}
230
231#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
232pub enum OrderType {
233 Market,
234 Limit,
235 UNKNOWN,
237}
238
239#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
240pub enum StopOrderType {
241 TakeProfit,
242 StopLoss,
243 TrailingStop,
244 Stop,
245 PartialTakeProfit,
246 PartialStopLoss,
247 #[serde(rename = "tpslOrder")]
249 TpslOrder,
250 OcoOrder,
252 MmRateClose,
254 BidirectionalTpslOrder,
256 UNKNOWN,
257}
258
259#[derive(Debug, PartialEq, Deserialize, Clone, Copy)]
260pub enum TickDirection {
261 PlusTick,
263 ZeroPlusTick,
265 MinusTick,
267 ZeroMinusTick,
269}
270
271#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
272pub enum Interval {
273 #[serde(rename = "1")]
274 Minute1,
275 #[serde(rename = "3")]
276 Minute3,
277 #[serde(rename = "5")]
278 Minute5,
279 #[serde(rename = "15")]
280 Minute15,
281 #[serde(rename = "30")]
282 Minute30,
283 #[serde(rename = "60")]
284 Hour1,
285 #[serde(rename = "120")]
286 Hour2,
287 #[serde(rename = "240")]
288 Hour4,
289 #[serde(rename = "360")]
290 Hour6,
291 #[serde(rename = "720")]
292 Hour12,
293 #[serde(rename = "D")]
294 Day1,
295 #[serde(rename = "W")]
296 Week1,
297 #[serde(rename = "M")]
298 Month1,
299}
300
301impl fmt::Display for Interval {
302 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
303 let value = match self {
304 Self::Minute1 => "1",
305 Self::Minute3 => "3",
306 Self::Minute5 => "5",
307 Self::Minute15 => "15",
308 Self::Minute30 => "30",
309 Self::Hour1 => "60",
310 Self::Hour2 => "120",
311 Self::Hour4 => "240",
312 Self::Hour6 => "360",
313 Self::Hour12 => "720",
314 Self::Day1 => "D",
315 Self::Week1 => "W",
316 Self::Month1 => "M",
317 };
318 write!(f, "{value}")
319 }
320}
321
322#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
323pub enum IntervalTime {
324 #[serde(rename = "5min")]
325 Minute5,
326 #[serde(rename = "15min")]
327 Minute15,
328 #[serde(rename = "30min")]
329 Minute30,
330 #[serde(rename = "1h")]
331 Hour1,
332 #[serde(rename = "4h")]
333 Hour4,
334 #[serde(rename = "1d")]
335 Day1,
336}
337
338#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Eq, Hash, Clone, Copy)]
339#[repr(u8)]
340pub enum PositionIdx {
341 OneWay = 0,
343 Buy = 1,
345 Sell = 2,
347}
348
349#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
350#[repr(u8)]
351pub enum PositionMode {
352 OneWay = 0,
354 Hedge = 3,
356}
357
358#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
359pub enum PositionStatus {
360 Normal,
361 Liq,
363 Adl,
365}
366
367#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
368pub enum RejectReason {
369 #[serde(rename = "EC_NoError")]
370 EcNoError,
371 #[serde(rename = "EC_Others")]
372 EcOthers,
373 #[serde(rename = "EC_UnknownMessageType")]
374 EcUnknownMessageType,
375 #[serde(rename = "EC_MissingClOrdID")]
376 EcMissingClOrdId,
377 #[serde(rename = "EC_MissingOrigClOrdID")]
378 EcMissingOrigClOrdId,
379 #[serde(rename = "EC_ClOrdIDOrigClOrdIDAreTheSame")]
380 EcClOrdIdorigClOrdIdareTheSame,
381 #[serde(rename = "EC_DuplicatedClOrdID")]
382 EcDuplicatedClOrdId,
383 #[serde(rename = "EC_OrigClOrdIDDoesNotExist")]
384 EcOrigClOrdIddoesNotExist,
385 #[serde(rename = "EC_TooLateToCancel")]
386 EcTooLateToCancel,
387 #[serde(rename = "EC_UnknownOrderType")]
388 EcUnknownOrderType,
389 #[serde(rename = "EC_UnknownSide")]
390 EcUnknownSide,
391 #[serde(rename = "EC_UnknownTimeInForce")]
392 EcUnknownTimeInForce,
393 #[serde(rename = "EC_WronglyRouted")]
394 EcWronglyRouted,
395 #[serde(rename = "EC_MarketOrderPriceIsNotZero")]
396 EcMarketOrderPriceIsNotZero,
397 #[serde(rename = "EC_LimitOrderInvalidPrice")]
398 EcLimitOrderInvalidPrice,
399 #[serde(rename = "EC_NoEnoughQtyToFill")]
400 EcNoEnoughQtyToFill,
401 #[serde(rename = "EC_NoImmediateQtyToFill")]
402 EcNoImmediateQtyToFill,
403 #[serde(rename = "EC_PerCancelRequest")]
404 EcPerCancelRequest,
405 #[serde(rename = "EC_MarketOrderCannotBePostOnly")]
406 EcMarketOrderCannotBePostOnly,
407 #[serde(rename = "EC_PostOnlyWillTakeLiquidity")]
408 EcPostOnlyWillTakeLiquidity,
409 #[serde(rename = "EC_CancelReplaceOrder")]
410 EcCancelReplaceOrder,
411 #[serde(rename = "EC_InvalidSymbolStatus")]
412 EcInvalidSymbolStatus,
413 #[serde(rename = "EC_CancelForNoFullFill")]
414 EcCancelForNoFullFill,
415 #[serde(rename = "EC_BySelfMatch")]
416 EcBySelfMatch,
417 #[serde(rename = "EC_InCallAuctionStatus")]
419 EcInCallAuctionStatus,
420 #[serde(rename = "EC_QtyCannotBeZero")]
421 EcQtyCannotBeZero,
422 #[serde(rename = "EC_MarketOrderNoSupportTIF")]
423 EcMarketOrderNoSupportTif,
424 #[serde(rename = "EC_ReachMaxTradeNum")]
425 EcReachMaxTradeNum,
426 #[serde(rename = "EC_InvalidPriceScale")]
427 EcInvalidPriceScale,
428 #[serde(rename = "EC_BitIndexInvalid")]
429 EcBitIndexInvalid,
430 #[serde(rename = "EC_StopBySelfMatch")]
431 EcStopBySelfMatch,
432 #[serde(rename = "EC_InvalidSmpType")]
433 EcInvalidSmpType,
434 #[serde(rename = "EC_CancelByMMP")]
435 EcCancelByMmp,
436 #[serde(rename = "EC_InvalidUserType")]
437 EcInvalidUserType,
438 #[serde(rename = "EC_InvalidMirrorOid")]
439 EcInvalidMirrorOid,
440 #[serde(rename = "EC_InvalidMirrorUid")]
441 EcInvalidMirrorUid,
442 #[serde(rename = "EC_EcInvalidQty")]
443 EcEcInvalidQty,
444 #[serde(rename = "EC_InvalidAmount")]
445 EcInvalidAmount,
446 #[serde(rename = "EC_LoadOrderCancel")]
447 EcLoadOrderCancel,
448 #[serde(rename = "EC_MarketQuoteNoSuppSell")]
449 EcMarketQuoteNoSuppSell,
450 #[serde(rename = "EC_DisorderOrderID")]
451 EcDisorderOrderId,
452 #[serde(rename = "EC_InvalidBaseValue")]
453 EcInvalidBaseValue,
454 #[serde(rename = "EC_LoadOrderCanMatch")]
455 EcLoadOrderCanMatch,
456 #[serde(rename = "EC_SecurityStatusFail")]
457 EcSecurityStatusFail,
458 #[serde(rename = "EC_ReachRiskPriceLimit")]
459 EcReachRiskPriceLimit,
460 #[serde(rename = "EC_OrderNotExist")]
461 EcOrderNotExist,
462 #[serde(rename = "EC_CancelByOrderValueZero")]
463 EcCancelByOrderValueZero,
464 #[serde(rename = "EC_CancelByMatchValueZero")]
465 EcCancelByMatchValueZero,
466 #[serde(rename = "EC_ReachMarketPriceLimit")]
467 EcReachMarketPriceLimit,
468}
469
470#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
471pub enum AccountType {
472 CONTRACT,
474 UNIFIED,
476 FUND,
478 SPOT,
480}
481
482impl AccountType {
483 pub fn is_uta_2(&self) -> bool {
484 matches!(self, Self::UNIFIED | Self::FUND)
485 }
486 pub fn is_uta_1(&self) -> bool {
487 matches!(self, Self::CONTRACT | Self::UNIFIED | Self::FUND)
488 }
489 pub fn is_classic(&self) -> bool {
490 matches!(self, Self::SPOT | Self::CONTRACT | Self::FUND)
491 }
492}
493
494#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
495pub enum TransferStatus {
496 SUCCESS,
497 PENDING,
498 FAILED,
499}
500
501#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
502pub enum DepositStatus {
503 #[serde(rename = "0")]
504 Unknown,
505 #[serde(rename = "1")]
506 ToBeConfirmed,
507 #[serde(rename = "2")]
508 Processing,
509 #[serde(rename = "3")]
511 Success,
512 #[serde(rename = "4")]
513 DepositFailed,
514 #[serde(rename = "10011")]
515 PendingToBeCreditedToFundingPool,
516 #[serde(rename = "10012")]
517 CreditedToFundingPoolSuccessfully,
518}
519
520#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
521pub enum WithdrawStatus {
522 SecurityCheck,
523 Pending,
524 #[serde(rename = "success")]
525 Success,
526 CancelByUser,
527 Reject,
528 Fail,
529 BlockchainConfirmed,
530 MoreInformationRequired,
531 Unknown,
533}
534
535#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
536pub enum TriggerBy {
537 LastPrice,
538 IndexPrice,
539 MarkPrice,
540 UNKNOWN,
541}
542
543#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
544pub enum CancelType {
545 CancelByUser,
546 CancelByReduceOnly,
548 CancelByPrepareLiq,
550 CancelAllBeforeLiq,
552 CancelByPrepareAdl,
554 CancelAllBeforeAdl,
556 CancelByAdmin,
557 CancelBySettle,
559 CancelByTpSlTsClear,
561 CancelBySmp,
563 CancelByDCP,
565 CancelByRebalance,
567
568 CancelByCannotAffordOrderCost,
570 CancelByPmTrialMmOverEquity,
571 CancelByAccountBlocking,
572 CancelByDelivery,
573 CancelByMmpTriggered,
574 CancelByCrossSelfMuch,
575 CancelByCrossReachMaxTradeNum,
576
577 UNKNOWN,
579}
580
581#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
582pub enum OptionPeriod {
583 #[serde(rename = "7")]
584 Day7,
585 #[serde(rename = "14")]
586 Day14,
587 #[serde(rename = "21")]
588 Day21,
589 #[serde(rename = "30")]
590 Day30,
591 #[serde(rename = "60")]
592 Day60,
593 #[serde(rename = "90")]
594 Day90,
595 #[serde(rename = "180")]
596 Day180,
597 #[serde(rename = "270")]
598 Day270,
599}
600
601#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
602pub enum DataRecordingPeriod {
603 #[serde(rename = "5min")]
604 Minute5,
605 #[serde(rename = "15min")]
606 Minute15,
607 #[serde(rename = "30min")]
608 Minute30,
609 #[serde(rename = "1h")]
610 Hour1,
611 #[serde(rename = "4h")]
612 Hour4,
613 #[serde(rename = "4d")]
614 Day4,
615}
616
617#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
618pub enum ContractType {
619 InversePerpetual,
620 LinearPerpetual,
621 LinearFutures,
623 InverseFutures,
624}
625
626#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
627pub enum Status {
628 PreLaunch,
629 Trading,
630 Delivering,
631 Closed,
632}
633
634#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
635#[serde(rename_all = "camelCase")]
636pub enum MarginTrading {
637 None,
639 Both,
641 UtaOnly,
643 NormalSpotOnly,
645}
646
647#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
648#[serde(rename_all = "camelCase")]
649pub enum CopyTrading {
650 None,
652 Both,
654 UtaOnly,
656 NormalOnly,
658}
659
660#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
661#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
662pub enum Type {
663 TransferIn,
665 TransferOut,
667 Trade,
668 Settlement,
671 Delivery,
673 Liquidation,
675 ADL,
677 Airdrop,
678 Bonus,
680 BonusRecollect,
682 FeeRefund,
684 Interest,
686 CurrencyBuy,
688 CurrencySell,
690 BorrowedAmountInsLoan,
691 PrincipleRepaymentInsLoan,
692 InterestRepaymentInsLoan,
693 AutoSoldCollateralInsLoan,
695 AutoBuyLiabilityInsLoan,
697 AutoPrincipleRepaymentInsLoan,
698 AutoInterestRepaymentInsLoan,
699 TransferInInsLoan,
701 TransferOutInsLoan,
703 SpotRepaymentSell,
705 SpotRepaymentBuy,
707 TokensSubscription,
709 TokensRedemption,
711 AutoDeduction,
713 FlexibleStakingSubscription,
715 FlexibleStakingRedemption,
717 FixedStakingSubscription,
719 PremarketTransferOut,
720 PremarketDeliverySellNewCoin,
721 PremarketDeliveryBuyNewCoin,
722 PremarketDeliveryPledgePaySeller,
723 PremarketDeliveryPledgeBack,
724 PremarketRollbackPledgeBack,
725 PremarketRollbackPledgePenaltyToBuyer,
726 CustodyNetworkFee,
728 CustodySettleFee,
730 CustodyLock,
732 CustodyUnlock,
734 CustodyUnlockRefund,
736 LoansBorrowFunds,
738 LoansPledgeAsset,
740 BonusTransferIn,
741 BonusTransferOut,
742 PefTransferIn,
743 PefTransferOut,
744 PefProfitShare,
745 #[serde(rename = "Others")]
746 Others,
747}
748
749impl Type {
750 pub fn is_uta(&self) -> bool {
751 matches!(
752 self,
753 Self::TransferIn
754 | Self::TransferOut
755 | Self::Trade
756 | Self::Settlement
757 | Self::Delivery
758 | Self::Liquidation
759 | Self::ADL
760 | Self::Airdrop
761 | Self::Bonus
762 | Self::BonusRecollect
763 | Self::FeeRefund
764 | Self::Interest
765 | Self::CurrencyBuy
766 | Self::CurrencySell
767 | Self::BorrowedAmountInsLoan
768 | Self::PrincipleRepaymentInsLoan
769 | Self::InterestRepaymentInsLoan
770 | Self::AutoSoldCollateralInsLoan
771 | Self::AutoBuyLiabilityInsLoan
772 | Self::AutoPrincipleRepaymentInsLoan
773 | Self::AutoInterestRepaymentInsLoan
774 | Self::TransferInInsLoan
775 | Self::TransferOutInsLoan
776 | Self::SpotRepaymentSell
777 | Self::SpotRepaymentBuy
778 | Self::TokensSubscription
779 | Self::TokensRedemption
780 | Self::AutoDeduction
781 | Self::FlexibleStakingSubscription
782 | Self::FlexibleStakingRedemption
783 | Self::FixedStakingSubscription
784 | Self::PremarketTransferOut
785 | Self::PremarketDeliverySellNewCoin
786 | Self::PremarketDeliveryBuyNewCoin
787 | Self::PremarketDeliveryPledgePaySeller
788 | Self::PremarketDeliveryPledgeBack
789 | Self::PremarketRollbackPledgeBack
790 | Self::PremarketRollbackPledgePenaltyToBuyer
791 | Self::CustodyNetworkFee
792 | Self::CustodySettleFee
793 | Self::CustodyLock
794 | Self::CustodyUnlock
795 | Self::CustodyUnlockRefund
796 | Self::LoansBorrowFunds
797 | Self::LoansPledgeAsset
798 | Self::BonusTransferIn
799 | Self::BonusTransferOut
800 | Self::PefTransferIn
801 | Self::PefTransferOut
802 | Self::PefProfitShare
803 )
804 }
805 pub fn is_contract(&self) -> bool {
806 matches!(
807 self,
808 Self::TransferIn
809 | Self::TransferOut
810 | Self::Trade
811 | Self::Settlement
812 | Self::Delivery
813 | Self::Liquidation
814 | Self::ADL
815 | Self::Airdrop
816 | Self::Bonus
817 | Self::BonusRecollect
818 | Self::FeeRefund
819 | Self::CurrencyBuy
820 | Self::CurrencySell
821 | Self::AutoDeduction
822 | Self::Others
823 )
824 }
825}
826
827#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
828#[repr(u8)]
829pub enum UnifiedMarginStatus {
830 ClassicAccount = 1,
831 UnifiedTradingAccount1 = 3,
833 UnifiedTradingAccount1Pro = 4,
835 UnifiedTradingAccount2 = 5,
837 UnifiedTradingAccount2Pro = 6,
839}
840
841#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
842#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
843pub enum MarginMode {
844 IsolatedMargin,
845 RegularMargin,
846 PortfolioMargin,
847}
848
849#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
851pub enum SpotMarginMode {
852 #[serde(rename = "0")]
853 Disabled,
854 #[serde(rename = "1")]
855 Enabled,
856}
857
858#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
859#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
860pub enum SpotHedgingStatus {
861 On,
862 Off,
863}
864
865#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
866pub enum LtStatus {
867 #[serde(rename = "1")]
869 CanBePurchasedAndRedeemed,
870 #[serde(rename = "2")]
872 CanBePurchasedButNotRedeemed,
873 #[serde(rename = "3")]
875 CanBeRedeemedButNotPurchased,
876 #[serde(rename = "4")]
878 CannotBePurchasedNorRedeemed,
879 #[serde(rename = "5")]
881 AdjustingPosition,
882}
883
884#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
886pub enum LtOrderStatus {
887 #[serde(rename = "1")]
888 Completed,
889 #[serde(rename = "2")]
890 InProgress,
891 #[serde(rename = "3")]
892 Failed,
893}
894
895#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
897#[repr(u8)]
898pub enum LtOrderType {
899 Purchase = 1,
900 Redemption = 2,
901}
902
903#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
904pub enum ConvertAccountType {
905 #[serde(rename = "eb_convert_uta")]
907 Uta,
908 #[serde(rename = "eb_convert_funding")]
910 Funding,
911 #[serde(rename = "eb_convert_inverse")]
913 Inverse,
914 #[serde(rename = "eb_convert_spot")]
916 Spot,
917 #[serde(rename = "eb_convert_contract")]
919 Contract,
920}
921
922#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
923pub enum VipLevel {
924 #[serde(rename = "No VIP")]
925 NoVIP,
926 #[serde(rename = "VIP-1")]
927 VIP1,
928 #[serde(rename = "VIP-2")]
929 VIP2,
930 #[serde(rename = "VIP-3")]
931 VIP3,
932 #[serde(rename = "VIP-4")]
933 VIP4,
934 #[serde(rename = "VIP-5")]
935 VIP5,
936 #[serde(rename = "VIP-Supreme")]
937 VIPSupreme,
938 #[serde(rename = "PRO-1")]
939 PRO1,
940 #[serde(rename = "PRO-2")]
941 PRO2,
942 #[serde(rename = "PRO-3")]
943 PRO3,
944 #[serde(rename = "PRO-4")]
945 PRO4,
946 #[serde(rename = "PRO-5")]
947 PRO5,
948}
949
950#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
951#[repr(u8)]
952pub enum AdlRankIndicator {
953 Zero = 0,
955 One = 1,
956 Two = 2,
957 Three = 3,
958 Four = 4,
959 Five = 5,
960}
961
962#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
963pub enum SmpType {
964 None,
966 CancelMaker,
967 CancelTaker,
968 CancelBoth,
969}
970
971#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
972#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
973pub enum ExtraFeeType {
974 Unknown,
975 Tax,
977 Cfx,
979 Wht,
981 Gst,
983 Vat,
985}
986
987#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
988#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
989pub enum ExtraSubFeeType {
990 Unknown,
991 TaxPnn,
993 TaxPph,
995 CfxFiee,
997 AutWithholdingTax,
999 IndGst,
1001 AreVat,
1003}
1004
1005#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1006#[serde(rename_all = "lowercase")]
1007pub enum State {
1008 Scheduled,
1009 Ongoing,
1010 Completed,
1011 Canceled,
1012}
1013
1014#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1015#[repr(u8)]
1016pub enum ServiceTypes {
1017 TradingService = 1,
1019 TradingServiceViaHttpRequest = 2,
1021 TradingServiceViaWebsocket = 3,
1023 PrivateWebsocketStream = 4,
1025 MarketDataService = 5,
1027}
1028
1029#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1030#[repr(u8)]
1031pub enum Product {
1032 Futures = 1,
1033 Spot = 2,
1034 Option = 3,
1035 Spread = 4,
1036}
1037
1038#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1039#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1040pub enum DCPProduct {
1041 Spot,
1042 Derivatives,
1043 Option,
1044}
1045
1046#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1048#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1049pub enum UnifiedUpdateStatus {
1050 Fail,
1051 Process,
1052 Success,
1053}
1054
1055#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1056#[repr(u8)]
1057pub enum MaintainType {
1058 PlannedMaintenance = 1,
1059 TemporaryMaintenance = 2,
1060 Incident = 3,
1061}
1062
1063#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1064#[repr(u8)]
1065pub enum Env {
1066 Product = 1,
1067 ProductDemoService = 2,
1068}
1069
1070#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1071pub enum TpslMode {
1072 Full,
1073 Partial,
1074 UNKNOWN,
1075}
1076
1077#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1078pub enum OcoTriggerBy {
1079 #[serde(rename = "OcoTriggerByUnknown")]
1080 Unknown,
1081 #[serde(rename = "OcoTriggerByTp")]
1082 Tp,
1083 #[serde(rename = "OcoTriggerByBySl")]
1084 BySl,
1085}
1086
1087#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1088#[repr(u8)]
1089pub enum TriggerDirection {
1090 UNKNOWN = 0,
1091 Rise = 1,
1092 Fall = 2,
1093}
1094
1095#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1096pub enum CurAuctionPhase {
1097 NotStarted,
1099 Finished,
1103 CallAuction,
1109 CallAuctionNoCancel,
1115 CrossMatching,
1119 ContinuousTrading,
1123}
1124
1125#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1126pub enum PlaceType {
1127 #[serde(rename = "option")]
1128 Option,
1129 #[serde(rename = "iv")]
1130 Iv,
1131 #[serde(rename = "price")]
1132 Price,
1133}
1134
1135#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1136pub enum Side {
1137 Buy,
1138 Sell,
1139}
1140impl Side {
1141 pub fn reverse(&self) -> Self {
1142 match self {
1143 Side::Buy => Self::Sell,
1144 Side::Sell => Self::Buy,
1145 }
1146 }
1147}
1148
1149#[derive(Debug, PartialEq, Clone, Copy)]
1150pub enum Pair {
1151 Base, Quote, }
1155
1156#[derive(Debug, Deserialize, PartialEq, Clone, Copy)]
1157pub enum SlippageToleranceType {
1158 TickSize,
1159 Percent,
1160 UNKNOWN,
1162}
1163
1164#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1165#[repr(u8)]
1166pub enum TradeMode {
1167 CrossMargin = 0,
1168 IsolatedMargin = 1,
1169}
1170
1171#[derive(Debug, Clone, PartialEq)]
1172pub enum Topic {
1173 Orderbook {
1174 symbol: String,
1175 depth: DepthLevel,
1176 },
1177 Trade(String),
1178 Ticker(String),
1179 Kline {
1180 symbol: String,
1181 interval: Interval,
1182 },
1183 AllLiquidation(String),
1184 Position(Category),
1185 PositionAllCategory,
1186 Execution(Category),
1187 ExecutionAllCategory,
1188 FastExecution(Category),
1189 FastExecutionAllCategory,
1190 Order(Category),
1191 OrderAllCategory,
1192 Wallet,
1193 Greek,
1195 Dcp(DcpFunction),
1196}
1197
1198impl fmt::Display for Topic {
1199 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1200 let value = match self {
1201 Self::Orderbook { symbol, depth } => format!("orderbook.{depth}.{symbol}"),
1202 Self::Trade(symbol) => format!("publicTrade.{symbol}"),
1203 Self::Ticker(symbol) => format!("tickers.{symbol}"),
1204 Self::Kline { symbol, interval } => format!("kline.{interval}.{symbol}"),
1205 Self::AllLiquidation(symbol) => format!("allLiquidation.{symbol}"),
1206 Self::Position(category) => format!("position.{category}"),
1207 Self::PositionAllCategory => "position".to_string(),
1208 Self::Execution(category) => format!("execution.{category}"),
1209 Self::ExecutionAllCategory => "execution".to_string(),
1210 Self::FastExecution(category) => format!("execution.fast.{category}"),
1211 Self::FastExecutionAllCategory => "execution.fast".to_string(),
1212 Self::Order(category) => format!("order.{category}"),
1213 Self::OrderAllCategory => "order".to_string(),
1214 Self::Wallet => "wallet".to_string(),
1215 Self::Greek => "greek".to_string(),
1216 Self::Dcp(function) => format!("dcp.{function}"),
1217 };
1218 write!(f, "{value}")
1219 }
1220}
1221
1222impl Serialize for Topic {
1223 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1224 where
1225 S: Serializer,
1226 {
1227 serializer.collect_str(self)
1228 }
1229}
1230
1231impl<'de> Deserialize<'de> for Topic {
1232 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1233 where
1234 D: Deserializer<'de>,
1235 {
1236 let s: std::borrow::Cow<'de, str> = Deserialize::deserialize(deserializer)?;
1237 let s = s.as_ref();
1238 if let Some((kind, args)) = s.split_once('.') {
1239 match kind {
1240 "orderbook" => {
1241 if let Some((depth, symbol)) = args.split_once('.') {
1242 let depth =
1243 serde_json::from_str(&format!("\"{depth}\"")).map_err(|err| {
1244 serde::de::Error::custom(format!(
1245 "DepthLevel: {depth}, error: {err}"
1246 ))
1247 })?;
1248 Ok(Self::Orderbook {
1249 depth,
1250 symbol: symbol.to_owned(),
1251 })
1252 } else {
1253 Err(serde::de::Error::custom("invalid stream format"))
1254 }
1255 }
1256 "publicTrade" => Ok(Self::Trade(args.to_owned())),
1257 "tickers" => Ok(Self::Ticker(args.to_owned())),
1258 "kline" => {
1259 if let Some((interval, symbol)) = args.split_once('.') {
1260 let interval = serde_json::from_str(&format!("\"{interval}\""))
1261 .map_err(|err| serde::de::Error::custom(format!("Interval: {err}")))?;
1262 Ok(Self::Kline {
1263 symbol: symbol.to_owned(),
1264 interval,
1265 })
1266 } else {
1267 Err(serde::de::Error::custom("invalid stream format"))
1268 }
1269 }
1270 "allLiquidation" => Ok(Self::AllLiquidation(args.to_owned())),
1271 "position" => {
1272 let category = serde_json::from_str(&format!("\"{args}\""))
1273 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1274 Ok(Self::Position(category))
1275 }
1276 "execution" => {
1277 if args == "fast" {
1278 Ok(Self::FastExecutionAllCategory)
1279 } else if let Some((fast, category)) = args.split_once('.') {
1280 let category = serde_json::from_str(&format!("\"{category}\""))
1281 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1282 if fast == "fast" {
1283 Ok(Self::FastExecution(category))
1284 } else {
1285 Ok(Self::Execution(category))
1286 }
1287 } else {
1288 let category = serde_json::from_str(&format!("\"{args}\""))
1289 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1290 Ok(Self::Execution(category))
1291 }
1292 }
1293 "order" => {
1294 let category = serde_json::from_str(&format!("\"{args}\""))
1295 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1296 Ok(Self::Order(category))
1297 }
1298 "dcp" => {
1299 let function = serde_json::from_str(&format!("\"{args}\""))
1300 .map_err(|err| serde::de::Error::custom(format!("DcpFunction: {err}")))?;
1301 Ok(Self::Dcp(function))
1302 }
1303 _ => Err(serde::de::Error::custom("invalid stream format")),
1304 }
1305 } else {
1306 match s {
1307 "position" => Ok(Self::PositionAllCategory),
1308 "execution" => Ok(Self::ExecutionAllCategory),
1309 "order" => Ok(Self::OrderAllCategory),
1310 "wallet" => Ok(Self::Wallet),
1311 "greek" => Ok(Self::Greek),
1312 _ => {
1313 let msg = String::from("invalid stream format");
1314 Err(serde::de::Error::custom(msg))
1315 }
1316 }
1317 }
1318 }
1319}
1320
1321#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1322#[serde(rename_all = "lowercase")]
1323pub enum DcpFunction {
1324 Future,
1325 Option,
1326 Spot,
1327}
1328
1329impl fmt::Display for DcpFunction {
1330 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1331 let value = match self {
1332 Self::Future => "future",
1333 Self::Option => "option",
1334 Self::Spot => "spot",
1335 };
1336 write!(f, "{value}")
1337 }
1338}
1339
1340#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1341pub enum DepthLevel {
1342 #[serde(rename = "1")]
1343 Level1,
1344 #[serde(rename = "25")]
1345 Level25,
1346 #[serde(rename = "50")]
1347 Level50,
1348 #[serde(rename = "100")]
1349 Level100,
1350 #[serde(rename = "200")]
1351 Level200,
1352 #[serde(rename = "500")]
1354 Level500,
1355 #[serde(rename = "1000")]
1357 Level1000,
1358}
1359
1360impl fmt::Display for DepthLevel {
1361 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1362 let value = match self {
1363 Self::Level1 => "1",
1364 Self::Level25 => "25",
1365 Self::Level50 => "50",
1366 Self::Level100 => "100",
1367 Self::Level200 => "200",
1368 Self::Level500 => "500",
1369 Self::Level1000 => "1000",
1370 };
1371 write!(f, "{value}")
1372 }
1373}
1374
1375pub fn spot_fee_currency(side: Side, is_maker_order: bool, maker_fee_rate: f64) -> Pair {
1376 if maker_fee_rate >= 0.0 {
1377 match side {
1378 Side::Buy => Pair::Base,
1379 Side::Sell => Pair::Quote,
1380 }
1381 } else if is_maker_order {
1382 match side {
1383 Side::Buy => Pair::Quote,
1384 Side::Sell => Pair::Base,
1385 }
1386 } else {
1387 match side {
1388 Side::Buy => Pair::Base,
1389 Side::Sell => Pair::Quote,
1390 }
1391 }
1392}
1393
1394#[cfg(test)]
1395mod tests {
1396 use crate::serde::deserialize_json;
1397
1398 use super::*;
1399
1400 #[test]
1401 fn serialize_category() {
1402 let cases = [
1403 (Category::Inverse, r#""inverse""#),
1404 (Category::Linear, r#""linear""#),
1405 (Category::Option, r#""option""#),
1406 (Category::Spot, r#""spot""#),
1407 ];
1408 cases.iter().for_each(|(category, expected)| {
1409 let json = serde_json::to_string(category).unwrap();
1410 assert_eq!(json, *expected);
1411 });
1412 }
1413
1414 #[test]
1415 fn deserialize_category() {
1416 let cases = [
1417 (r#""inverse""#, Category::Inverse),
1418 (r#""linear""#, Category::Linear),
1419 (r#""option""#, Category::Option),
1420 (r#""spot""#, Category::Spot),
1421 ];
1422 cases.iter().for_each(|(json, expected)| {
1423 let message: Category = deserialize_json(json).unwrap();
1424 assert_eq!(message, *expected);
1425 });
1426 }
1427
1428 #[test]
1429 fn serialize_interval() {
1430 let cases = vec![
1431 (Interval::Minute1, r#""1""#),
1432 (Interval::Minute3, r#""3""#),
1433 (Interval::Minute5, r#""5""#),
1434 (Interval::Minute15, r#""15""#),
1435 (Interval::Minute30, r#""30""#),
1436 (Interval::Hour1, r#""60""#),
1437 (Interval::Hour2, r#""120""#),
1438 (Interval::Hour4, r#""240""#),
1439 (Interval::Hour6, r#""360""#),
1440 (Interval::Hour12, r#""720""#),
1441 (Interval::Day1, r#""D""#),
1442 (Interval::Week1, r#""W""#),
1443 (Interval::Month1, r#""M""#),
1444 ];
1445 cases.iter().for_each(|(category, expected)| {
1446 let json = serde_json::to_string(category).unwrap();
1447 assert_eq!(json, *expected);
1448 });
1449 }
1450
1451 #[test]
1452 fn deserialize_interval() {
1453 let cases = vec![
1454 (r#""1""#, Interval::Minute1),
1455 (r#""3""#, Interval::Minute3),
1456 (r#""5""#, Interval::Minute5),
1457 (r#""15""#, Interval::Minute15),
1458 (r#""30""#, Interval::Minute30),
1459 (r#""60""#, Interval::Hour1),
1460 (r#""120""#, Interval::Hour2),
1461 (r#""240""#, Interval::Hour4),
1462 (r#""360""#, Interval::Hour6),
1463 (r#""720""#, Interval::Hour12),
1464 (r#""D""#, Interval::Day1),
1465 (r#""W""#, Interval::Week1),
1466 (r#""M""#, Interval::Month1),
1467 ];
1468 cases.iter().for_each(|(json, expected)| {
1469 let message: Interval = deserialize_json(json).unwrap();
1470 assert_eq!(message, *expected);
1471 });
1472 }
1473
1474 #[test]
1475 fn deserialize_topic_with_escaped_characters() {
1476 let topic: Topic = serde_json::from_str(r#""tickers.BTC\u0055SDT""#).unwrap();
1477
1478 assert_eq!(topic, Topic::Ticker(String::from("BTCUSDT")));
1479 }
1480
1481 #[test]
1482 fn serialize_topic() {
1483 let symbol = String::from("BTCUSDT");
1484 let cases = vec![
1485 (
1486 Topic::Orderbook {
1487 symbol: symbol.clone(),
1488 depth: DepthLevel::Level1,
1489 },
1490 r#""orderbook.1.BTCUSDT""#,
1491 ),
1492 (Topic::Trade(symbol.clone()), r#""publicTrade.BTCUSDT""#),
1493 (Topic::Ticker(symbol.clone()), r#""tickers.BTCUSDT""#),
1494 (
1495 Topic::Kline {
1496 symbol: symbol.clone(),
1497 interval: Interval::Minute1,
1498 },
1499 r#""kline.1.BTCUSDT""#,
1500 ),
1501 (
1502 Topic::AllLiquidation(symbol.clone()),
1503 r#""allLiquidation.BTCUSDT""#,
1504 ),
1505 (Topic::Position(Category::Linear), r#""position.linear""#),
1506 (Topic::PositionAllCategory, r#""position""#),
1507 (Topic::Execution(Category::Linear), r#""execution.linear""#),
1508 (Topic::ExecutionAllCategory, r#""execution""#),
1509 (
1510 Topic::FastExecution(Category::Linear),
1511 r#""execution.fast.linear""#,
1512 ),
1513 (Topic::FastExecutionAllCategory, r#""execution.fast""#),
1514 (Topic::Order(Category::Linear), r#""order.linear""#),
1515 (Topic::OrderAllCategory, r#""order""#),
1516 (Topic::Wallet, r#""wallet""#),
1517 (Topic::Greek, r#""greek""#),
1518 (Topic::Dcp(DcpFunction::Future), r#""dcp.future""#),
1519 ];
1520 cases.iter().for_each(|(category, expected)| {
1521 let json = serde_json::to_string(category).unwrap();
1522 assert_eq!(*expected, json);
1523 });
1524 }
1525
1526 #[test]
1527 fn deserialize_topic() {
1528 let symbol = String::from("BTCUSDT");
1529 let cases = vec![
1530 (
1531 r#""orderbook.1.BTCUSDT""#,
1532 Topic::Orderbook {
1533 symbol: symbol.clone(),
1534 depth: DepthLevel::Level1,
1535 },
1536 ),
1537 (r#""publicTrade.BTCUSDT""#, Topic::Trade(symbol.clone())),
1538 (r#""tickers.BTCUSDT""#, Topic::Ticker(symbol.clone())),
1539 (
1540 r#""kline.1.BTCUSDT""#,
1541 Topic::Kline {
1542 symbol: symbol.clone(),
1543 interval: Interval::Minute1,
1544 },
1545 ),
1546 (
1547 r#""allLiquidation.BTCUSDT""#,
1548 Topic::AllLiquidation(symbol.clone()),
1549 ),
1550 (r#""position.linear""#, Topic::Position(Category::Linear)),
1551 (r#""position""#, Topic::PositionAllCategory),
1552 (r#""execution.linear""#, Topic::Execution(Category::Linear)),
1553 (r#""execution""#, Topic::ExecutionAllCategory),
1554 (
1555 r#""execution.fast.linear""#,
1556 Topic::FastExecution(Category::Linear),
1557 ),
1558 (r#""execution.fast""#, Topic::FastExecutionAllCategory),
1559 (r#""order.linear""#, Topic::Order(Category::Linear)),
1560 (r#""order""#, Topic::OrderAllCategory),
1561 (r#""wallet""#, Topic::Wallet),
1562 (r#""greek""#, Topic::Greek),
1563 (r#""dcp.future""#, Topic::Dcp(DcpFunction::Future)),
1564 ];
1565 cases.iter().for_each(|(json, expected)| {
1566 let message = deserialize_json(json).unwrap();
1567 assert_eq!(*expected, message);
1568 });
1569 }
1570}