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, 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, 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 let s = match self {
1228 Self::Orderbook { symbol, depth } => format!("orderbook.{depth}.{symbol}"),
1229 Self::Trade(symbol) => format!("publicTrade.{symbol}"),
1230 Self::Ticker(symbol) => format!("tickers.{symbol}"),
1231 Self::Kline { symbol, interval } => format!("kline.{interval}.{symbol}"),
1232 Self::AllLiquidation(symbol) => format!("allLiquidation.{symbol}"),
1233 Self::Position(category) => format!("position.{category}"),
1234 Self::PositionAllCategory => "position".to_string(),
1235 Self::Execution(category) => format!("execution.{category}"),
1236 Self::ExecutionAllCategory => "execution".to_string(),
1237 Self::FastExecution(category) => format!("execution.fast.{category}"),
1238 Self::FastExecutionAllCategory => "execution.fast".to_string(),
1239 Self::Order(category) => format!("order.{category}"),
1240 Self::OrderAllCategory => "order".to_string(),
1241 Self::Wallet => "wallet".to_string(),
1242 Self::Greek => "greek".to_string(),
1243 Self::Dcp(function) => format!("dcp.{function}"),
1244 };
1245 serializer.serialize_str(&s)
1246 }
1247}
1248
1249impl<'de> Deserialize<'de> for Topic {
1250 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1251 where
1252 D: Deserializer<'de>,
1253 {
1254 let s: &str = Deserialize::deserialize(deserializer)?;
1255 if let Some((kind, args)) = s.split_once('.') {
1256 match kind {
1257 "orderbook" => {
1258 if let Some((depth, symbol)) = args.split_once('.') {
1259 let depth =
1260 serde_json::from_str(&format!("\"{depth}\"")).map_err(|err| {
1261 serde::de::Error::custom(format!(
1262 "DepthLevel: {depth}, error: {err}"
1263 ))
1264 })?;
1265 Ok(Self::Orderbook {
1266 depth,
1267 symbol: symbol.to_owned(),
1268 })
1269 } else {
1270 Err(serde::de::Error::custom("invalid stream format"))
1271 }
1272 }
1273 "publicTrade" => Ok(Self::Trade(args.to_owned())),
1274 "tickers" => Ok(Self::Ticker(args.to_owned())),
1275 "kline" => {
1276 if let Some((interval, symbol)) = args.split_once('.') {
1277 let interval = serde_json::from_str(&format!("\"{interval}\""))
1278 .map_err(|err| serde::de::Error::custom(format!("Interval: {err}")))?;
1279 Ok(Self::Kline {
1280 symbol: symbol.to_owned(),
1281 interval,
1282 })
1283 } else {
1284 Err(serde::de::Error::custom("invalid stream format"))
1285 }
1286 }
1287 "allLiquidation" => Ok(Self::AllLiquidation(args.to_owned())),
1288 "position" => {
1289 let category = serde_json::from_str(&format!("\"{args}\""))
1290 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1291 Ok(Self::Position(category))
1292 }
1293 "execution" => {
1294 if args == "fast" {
1295 Ok(Self::FastExecutionAllCategory)
1296 } else if let Some((fast, category)) = args.split_once('.') {
1297 let category = serde_json::from_str(&format!("\"{category}\""))
1298 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1299 if fast == "fast" {
1300 Ok(Self::FastExecution(category))
1301 } else {
1302 Ok(Self::Execution(category))
1303 }
1304 } else {
1305 let category = serde_json::from_str(&format!("\"{args}\""))
1306 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1307 Ok(Self::Execution(category))
1308 }
1309 }
1310 "order" => {
1311 let category = serde_json::from_str(&format!("\"{args}\""))
1312 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1313 Ok(Self::Order(category))
1314 }
1315 "dcp" => {
1316 let function = serde_json::from_str(&format!("\"{args}\""))
1317 .map_err(|err| serde::de::Error::custom(format!("DcpFunction: {err}")))?;
1318 Ok(Self::Dcp(function))
1319 }
1320 _ => Err(serde::de::Error::custom("invalid stream format")),
1321 }
1322 } else {
1323 match s {
1324 "position" => Ok(Self::PositionAllCategory),
1325 "execution" => Ok(Self::ExecutionAllCategory),
1326 "order" => Ok(Self::OrderAllCategory),
1327 "wallet" => Ok(Self::Wallet),
1328 "greek" => Ok(Self::Greek),
1329 _ => {
1330 let msg = String::from("invalid stream format");
1331 Err(serde::de::Error::custom(msg))
1332 }
1333 }
1334 }
1335 }
1336}
1337
1338#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1339#[serde(rename_all = "lowercase")]
1340pub enum DcpFunction {
1341 Future,
1342 Option,
1343 Spot,
1344}
1345
1346impl fmt::Display for DcpFunction {
1347 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1348 let value = match self {
1349 Self::Future => "future",
1350 Self::Option => "option",
1351 Self::Spot => "spot",
1352 };
1353 write!(f, "{value}")
1354 }
1355}
1356
1357#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1358pub enum DepthLevel {
1359 #[serde(rename = "1")]
1360 Level1,
1361 #[serde(rename = "25")]
1362 Level25,
1363 #[serde(rename = "50")]
1364 Level50,
1365 #[serde(rename = "100")]
1366 Level100,
1367 #[serde(rename = "200")]
1368 Level200,
1369 #[serde(rename = "500")]
1371 Level500,
1372 #[serde(rename = "1000")]
1374 Level1000,
1375}
1376
1377impl fmt::Display for DepthLevel {
1378 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1379 let value = match self {
1380 Self::Level1 => "1",
1381 Self::Level25 => "25",
1382 Self::Level50 => "50",
1383 Self::Level100 => "100",
1384 Self::Level200 => "200",
1385 Self::Level500 => "500",
1386 Self::Level1000 => "1000",
1387 };
1388 write!(f, "{value}")
1389 }
1390}
1391
1392pub fn spot_fee_currency(side: Side, is_maker_order: bool, maker_fee_rate: f64) -> Pair {
1393 if maker_fee_rate >= 0.0 {
1394 match side {
1395 Side::Buy => Pair::Base,
1396 Side::Sell => Pair::Quote,
1397 }
1398 } else if is_maker_order {
1399 match side {
1400 Side::Buy => Pair::Quote,
1401 Side::Sell => Pair::Base,
1402 }
1403 } else {
1404 match side {
1405 Side::Buy => Pair::Base,
1406 Side::Sell => Pair::Quote,
1407 }
1408 }
1409}
1410
1411#[cfg(test)]
1412mod tests {
1413 use crate::serde::deserialize_json;
1414
1415 use super::*;
1416
1417 #[test]
1418 fn serialize_category() {
1419 let cases = vec![
1420 (Category::Inverse, r#""inverse""#),
1421 (Category::Linear, r#""linear""#),
1422 (Category::Option, r#""option""#),
1423 (Category::Spot, r#""spot""#),
1424 ];
1425 cases.iter().for_each(|(category, expected)| {
1426 let json = serde_json::to_string(category).unwrap();
1427 assert_eq!(json, *expected);
1428 });
1429 }
1430
1431 #[test]
1432 fn deserialize_category() {
1433 let cases = vec![
1434 (r#""inverse""#, Category::Inverse),
1435 (r#""linear""#, Category::Linear),
1436 (r#""option""#, Category::Option),
1437 (r#""spot""#, Category::Spot),
1438 ];
1439 cases.iter().for_each(|(json, expected)| {
1440 let message: Category = deserialize_json(json).unwrap();
1441 assert_eq!(message, *expected);
1442 });
1443 }
1444
1445 #[test]
1446 fn serialize_interval() {
1447 let cases = vec![
1448 (Interval::Minute1, r#""1""#),
1449 (Interval::Minute3, r#""3""#),
1450 (Interval::Minute5, r#""5""#),
1451 (Interval::Minute15, r#""15""#),
1452 (Interval::Minute30, r#""30""#),
1453 (Interval::Hour1, r#""60""#),
1454 (Interval::Hour2, r#""120""#),
1455 (Interval::Hour4, r#""240""#),
1456 (Interval::Hour6, r#""360""#),
1457 (Interval::Hour12, r#""720""#),
1458 (Interval::Day1, r#""D""#),
1459 (Interval::Week1, r#""W""#),
1460 (Interval::Month1, r#""M""#),
1461 ];
1462 cases.iter().for_each(|(category, expected)| {
1463 let json = serde_json::to_string(category).unwrap();
1464 assert_eq!(json, *expected);
1465 });
1466 }
1467
1468 #[test]
1469 fn deserialize_interval() {
1470 let cases = vec![
1471 (r#""1""#, Interval::Minute1),
1472 (r#""3""#, Interval::Minute3),
1473 (r#""5""#, Interval::Minute5),
1474 (r#""15""#, Interval::Minute15),
1475 (r#""30""#, Interval::Minute30),
1476 (r#""60""#, Interval::Hour1),
1477 (r#""120""#, Interval::Hour2),
1478 (r#""240""#, Interval::Hour4),
1479 (r#""360""#, Interval::Hour6),
1480 (r#""720""#, Interval::Hour12),
1481 (r#""D""#, Interval::Day1),
1482 (r#""W""#, Interval::Week1),
1483 (r#""M""#, Interval::Month1),
1484 ];
1485 cases.iter().for_each(|(json, expected)| {
1486 let message: Interval = deserialize_json(json).unwrap();
1487 assert_eq!(message, *expected);
1488 });
1489 }
1490
1491 #[test]
1492 fn serialize_topic() {
1493 let symbol = String::from("BTCUSDT");
1494 let cases = vec![
1495 (
1496 Topic::Orderbook {
1497 symbol: symbol.clone(),
1498 depth: DepthLevel::Level1,
1499 },
1500 r#""orderbook.1.BTCUSDT""#,
1501 ),
1502 (Topic::Trade(symbol.clone()), r#""publicTrade.BTCUSDT""#),
1503 (Topic::Ticker(symbol.clone()), r#""tickers.BTCUSDT""#),
1504 (
1505 Topic::Kline {
1506 symbol: symbol.clone(),
1507 interval: Interval::Minute1,
1508 },
1509 r#""kline.1.BTCUSDT""#,
1510 ),
1511 (
1512 Topic::AllLiquidation(symbol.clone()),
1513 r#""allLiquidation.BTCUSDT""#,
1514 ),
1515 (Topic::Position(Category::Linear), r#""position.linear""#),
1516 (Topic::PositionAllCategory, r#""position""#),
1517 (Topic::Execution(Category::Linear), r#""execution.linear""#),
1518 (Topic::ExecutionAllCategory, r#""execution""#),
1519 (
1520 Topic::FastExecution(Category::Linear),
1521 r#""execution.fast.linear""#,
1522 ),
1523 (Topic::FastExecutionAllCategory, r#""execution.fast""#),
1524 (Topic::Order(Category::Linear), r#""order.linear""#),
1525 (Topic::OrderAllCategory, r#""order""#),
1526 (Topic::Wallet, r#""wallet""#),
1527 (Topic::Greek, r#""greek""#),
1528 (Topic::Dcp(DcpFunction::Future), r#""dcp.future""#),
1529 ];
1530 cases.iter().for_each(|(category, expected)| {
1531 let json = serde_json::to_string(category).unwrap();
1532 assert_eq!(*expected, json);
1533 });
1534 }
1535
1536 #[test]
1537 fn deserialize_topic() {
1538 let symbol = String::from("BTCUSDT");
1539 let cases = vec![
1540 (
1541 r#""orderbook.1.BTCUSDT""#,
1542 Topic::Orderbook {
1543 symbol: symbol.clone(),
1544 depth: DepthLevel::Level1,
1545 },
1546 ),
1547 (r#""publicTrade.BTCUSDT""#, Topic::Trade(symbol.clone())),
1548 (r#""tickers.BTCUSDT""#, Topic::Ticker(symbol.clone())),
1549 (
1550 r#""kline.1.BTCUSDT""#,
1551 Topic::Kline {
1552 symbol: symbol.clone(),
1553 interval: Interval::Minute1,
1554 },
1555 ),
1556 (
1557 r#""allLiquidation.BTCUSDT""#,
1558 Topic::AllLiquidation(symbol.clone()),
1559 ),
1560 (r#""position.linear""#, Topic::Position(Category::Linear)),
1561 (r#""position""#, Topic::PositionAllCategory),
1562 (r#""execution.linear""#, Topic::Execution(Category::Linear)),
1563 (r#""execution""#, Topic::ExecutionAllCategory),
1564 (
1565 r#""execution.fast.linear""#,
1566 Topic::FastExecution(Category::Linear),
1567 ),
1568 (r#""execution.fast""#, Topic::FastExecutionAllCategory),
1569 (r#""order.linear""#, Topic::Order(Category::Linear)),
1570 (r#""order""#, Topic::OrderAllCategory),
1571 (r#""wallet""#, Topic::Wallet),
1572 (r#""greek""#, Topic::Greek),
1573 (r#""dcp.future""#, Topic::Dcp(DcpFunction::Future)),
1574 ];
1575 cases.iter().for_each(|(json, expected)| {
1576 let message = deserialize_json(json).unwrap();
1577 assert_eq!(*expected, message);
1578 });
1579 }
1580}