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, 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)]
850#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
851pub enum SpotHedgingStatus {
852 On,
853 Off,
854}
855
856#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
857pub enum LtStatus {
858 #[serde(rename = "1")]
860 CanBePurchasedAndRedeemed,
861 #[serde(rename = "2")]
863 CanBePurchasedButNotRedeemed,
864 #[serde(rename = "3")]
866 CanBeRedeemedButNotPurchased,
867 #[serde(rename = "4")]
869 CannotBePurchasedNorRedeemed,
870 #[serde(rename = "5")]
872 AdjustingPosition,
873}
874
875#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
876pub enum ConvertAccountType {
877 #[serde(rename = "eb_convert_uta")]
879 Uta,
880 #[serde(rename = "eb_convert_funding")]
882 Funding,
883 #[serde(rename = "eb_convert_inverse")]
885 Inverse,
886 #[serde(rename = "eb_convert_spot")]
888 Spot,
889 #[serde(rename = "eb_convert_contract")]
891 Contract,
892}
893
894#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
895pub enum VipLevel {
896 #[serde(rename = "No VIP")]
897 NoVIP,
898 #[serde(rename = "VIP-1")]
899 VIP1,
900 #[serde(rename = "VIP-2")]
901 VIP2,
902 #[serde(rename = "VIP-3")]
903 VIP3,
904 #[serde(rename = "VIP-4")]
905 VIP4,
906 #[serde(rename = "VIP-5")]
907 VIP5,
908 #[serde(rename = "VIP-Supreme")]
909 VIPSupreme,
910 #[serde(rename = "PRO-1")]
911 PRO1,
912 #[serde(rename = "PRO-2")]
913 PRO2,
914 #[serde(rename = "PRO-3")]
915 PRO3,
916 #[serde(rename = "PRO-4")]
917 PRO4,
918 #[serde(rename = "PRO-5")]
919 PRO5,
920}
921
922#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
923#[repr(u8)]
924pub enum AdlRankIndicator {
925 Zero = 0,
927 One = 1,
928 Two = 2,
929 Three = 3,
930 Four = 4,
931 Five = 5,
932}
933
934#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
935pub enum SmpType {
936 None,
938 CancelMaker,
939 CancelTaker,
940 CancelBoth,
941}
942
943#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
944#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
945pub enum ExtraFeeType {
946 Unknown,
947 Tax,
949 Cfx,
951 Wht,
953 Gst,
955 Vat,
957}
958
959#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
960#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
961pub enum ExtraSubFeeType {
962 Unknown,
963 TaxPnn,
965 TaxPph,
967 CfxFiee,
969 AutWithholdingTax,
971 IndGst,
973 AreVat,
975}
976
977#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
978#[serde(rename_all = "lowercase")]
979pub enum State {
980 Scheduled,
981 Ongoing,
982 Completed,
983 Canceled,
984}
985
986#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
987#[repr(u8)]
988pub enum ServiceTypes {
989 TradingService = 1,
991 TradingServiceViaHttpRequest = 2,
993 TradingServiceViaWebsocket = 3,
995 PrivateWebsocketStream = 4,
997 MarketDataService = 5,
999}
1000
1001#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1002#[repr(u8)]
1003pub enum Product {
1004 Futures = 1,
1005 Spot = 2,
1006 Option = 3,
1007 Spread = 4,
1008}
1009
1010#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1011#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1012pub enum DCPProduct {
1013 Spot,
1014 Derivatives,
1015 Option,
1016}
1017
1018#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1019#[repr(u8)]
1020pub enum MaintainType {
1021 PlannedMaintenance = 1,
1022 TemporaryMaintenance = 2,
1023 Incident = 3,
1024}
1025
1026#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1027#[repr(u8)]
1028pub enum Env {
1029 Product = 1,
1030 ProductDemoService = 2,
1031}
1032
1033#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1034pub enum TpslMode {
1035 Full,
1036 Partial,
1037 UNKNOWN,
1038}
1039
1040#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1041pub enum OcoTriggerBy {
1042 #[serde(rename = "OcoTriggerByUnknown")]
1043 Unknown,
1044 #[serde(rename = "OcoTriggerByTp")]
1045 Tp,
1046 #[serde(rename = "OcoTriggerByBySl")]
1047 BySl,
1048}
1049
1050#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1051#[repr(u8)]
1052pub enum TriggerDirection {
1053 UNKNOWN = 0,
1054 Rise = 1,
1055 Fall = 2,
1056}
1057
1058#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1059pub enum CurAuctionPhase {
1060 NotStarted,
1062 Finished,
1066 CallAuction,
1072 CallAuctionNoCancel,
1078 CrossMatching,
1082 ContinuousTrading,
1086}
1087
1088#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1089pub enum PlaceType {
1090 #[serde(rename = "option")]
1091 Option,
1092 #[serde(rename = "iv")]
1093 Iv,
1094 #[serde(rename = "price")]
1095 Price,
1096}
1097
1098#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1099pub enum Side {
1100 Buy,
1101 Sell,
1102}
1103impl Side {
1104 pub fn reverse(&self) -> Self {
1105 match self {
1106 Side::Buy => Self::Sell,
1107 Side::Sell => Self::Buy,
1108 }
1109 }
1110}
1111
1112#[derive(Debug, PartialEq, Clone, Copy)]
1113pub enum Pair {
1114 Base, Quote, }
1118
1119#[derive(Debug, Deserialize, PartialEq, Clone, Copy)]
1120pub enum SlippageToleranceType {
1121 TickSize,
1122 Percent,
1123 UNKNOWN,
1125}
1126
1127#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1128#[repr(u8)]
1129pub enum TradeMode {
1130 CrossMargin = 0,
1131 IsolatedMargin = 1,
1132}
1133
1134#[derive(Debug, Clone, PartialEq)]
1135pub enum Topic {
1136 Orderbook {
1137 symbol: String,
1138 depth: DepthLevel,
1139 },
1140 Trade(String),
1141 Ticker(String),
1142 Kline {
1143 symbol: String,
1144 interval: Interval,
1145 },
1146 AllLiquidation(String),
1147 Position(Category),
1148 PositionAllCategory,
1149 Execution(Category),
1150 ExecutionAllCategory,
1151 FastExecution(Category),
1152 FastExecutionAllCategory,
1153 Order(Category),
1154 OrderAllCategory,
1155 Wallet,
1156 Greek,
1158 Dcp(DcpFunction),
1159}
1160
1161impl fmt::Display for Topic {
1162 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1163 let value = match self {
1164 Self::Orderbook { symbol, depth } => format!("orderbook.{depth}.{symbol}"),
1165 Self::Trade(symbol) => format!("publicTrade.{symbol}"),
1166 Self::Ticker(symbol) => format!("tickers.{symbol}"),
1167 Self::Kline { symbol, interval } => format!("kline.{interval}.{symbol}"),
1168 Self::AllLiquidation(symbol) => format!("allLiquidation.{symbol}"),
1169 Self::Position(category) => format!("position.{category}"),
1170 Self::PositionAllCategory => "position".to_string(),
1171 Self::Execution(category) => format!("execution.{category}"),
1172 Self::ExecutionAllCategory => "execution".to_string(),
1173 Self::FastExecution(category) => format!("execution.fast.{category}"),
1174 Self::FastExecutionAllCategory => "execution.fast".to_string(),
1175 Self::Order(category) => format!("order.{category}"),
1176 Self::OrderAllCategory => "order".to_string(),
1177 Self::Wallet => "wallet".to_string(),
1178 Self::Greek => "greek".to_string(),
1179 Self::Dcp(function) => format!("dcp.{function}"),
1180 };
1181 write!(f, "{value}")
1182 }
1183}
1184
1185impl Serialize for Topic {
1186 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1187 where
1188 S: Serializer,
1189 {
1190 let s = match self {
1191 Self::Orderbook { symbol, depth } => format!("orderbook.{depth}.{symbol}"),
1192 Self::Trade(symbol) => format!("publicTrade.{symbol}"),
1193 Self::Ticker(symbol) => format!("tickers.{symbol}"),
1194 Self::Kline { symbol, interval } => format!("kline.{interval}.{symbol}"),
1195 Self::AllLiquidation(symbol) => format!("allLiquidation.{symbol}"),
1196 Self::Position(category) => format!("position.{category}"),
1197 Self::PositionAllCategory => "position".to_string(),
1198 Self::Execution(category) => format!("execution.{category}"),
1199 Self::ExecutionAllCategory => "execution".to_string(),
1200 Self::FastExecution(category) => format!("execution.fast.{category}"),
1201 Self::FastExecutionAllCategory => "execution.fast".to_string(),
1202 Self::Order(category) => format!("order.{category}"),
1203 Self::OrderAllCategory => "order".to_string(),
1204 Self::Wallet => "wallet".to_string(),
1205 Self::Greek => "greek".to_string(),
1206 Self::Dcp(function) => format!("dcp.{function}"),
1207 };
1208 serializer.serialize_str(&s)
1209 }
1210}
1211
1212impl<'de> Deserialize<'de> for Topic {
1213 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1214 where
1215 D: Deserializer<'de>,
1216 {
1217 let s: &str = Deserialize::deserialize(deserializer)?;
1218 if let Some((kind, args)) = s.split_once('.') {
1219 match kind {
1220 "orderbook" => {
1221 if let Some((depth, symbol)) = args.split_once('.') {
1222 let depth =
1223 serde_json::from_str(&format!("\"{depth}\"")).map_err(|err| {
1224 serde::de::Error::custom(format!(
1225 "DepthLevel: {depth}, error: {err}"
1226 ))
1227 })?;
1228 Ok(Self::Orderbook {
1229 depth,
1230 symbol: symbol.to_owned(),
1231 })
1232 } else {
1233 Err(serde::de::Error::custom("invalid stream format"))
1234 }
1235 }
1236 "publicTrade" => Ok(Self::Trade(args.to_owned())),
1237 "tickers" => Ok(Self::Ticker(args.to_owned())),
1238 "kline" => {
1239 if let Some((interval, symbol)) = args.split_once('.') {
1240 let interval = serde_json::from_str(&format!("\"{interval}\""))
1241 .map_err(|err| serde::de::Error::custom(format!("Interval: {err}")))?;
1242 Ok(Self::Kline {
1243 symbol: symbol.to_owned(),
1244 interval,
1245 })
1246 } else {
1247 Err(serde::de::Error::custom("invalid stream format"))
1248 }
1249 }
1250 "allLiquidation" => Ok(Self::AllLiquidation(args.to_owned())),
1251 "position" => {
1252 let category = serde_json::from_str(&format!("\"{args}\""))
1253 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1254 Ok(Self::Position(category))
1255 }
1256 "execution" => {
1257 if args == "fast" {
1258 Ok(Self::FastExecutionAllCategory)
1259 } else if let Some((fast, category)) = args.split_once('.') {
1260 let category = serde_json::from_str(&format!("\"{category}\""))
1261 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1262 if fast == "fast" {
1263 Ok(Self::FastExecution(category))
1264 } else {
1265 Ok(Self::Execution(category))
1266 }
1267 } else {
1268 let category = serde_json::from_str(&format!("\"{args}\""))
1269 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1270 Ok(Self::Execution(category))
1271 }
1272 }
1273 "order" => {
1274 let category = serde_json::from_str(&format!("\"{args}\""))
1275 .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1276 Ok(Self::Order(category))
1277 }
1278 "dcp" => {
1279 let function = serde_json::from_str(&format!("\"{args}\""))
1280 .map_err(|err| serde::de::Error::custom(format!("DcpFunction: {err}")))?;
1281 Ok(Self::Dcp(function))
1282 }
1283 _ => Err(serde::de::Error::custom("invalid stream format")),
1284 }
1285 } else {
1286 match s {
1287 "position" => Ok(Self::PositionAllCategory),
1288 "execution" => Ok(Self::ExecutionAllCategory),
1289 "order" => Ok(Self::OrderAllCategory),
1290 "wallet" => Ok(Self::Wallet),
1291 "greek" => Ok(Self::Greek),
1292 _ => {
1293 let msg = String::from("invalid stream format");
1294 Err(serde::de::Error::custom(msg))
1295 }
1296 }
1297 }
1298 }
1299}
1300
1301#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1302#[serde(rename_all = "lowercase")]
1303pub enum DcpFunction {
1304 Future,
1305 Option,
1306 Spot,
1307}
1308
1309impl fmt::Display for DcpFunction {
1310 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1311 let value = match self {
1312 Self::Future => "future",
1313 Self::Option => "option",
1314 Self::Spot => "spot",
1315 };
1316 write!(f, "{value}")
1317 }
1318}
1319
1320#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1321pub enum DepthLevel {
1322 #[serde(rename = "1")]
1323 Level1,
1324 #[serde(rename = "25")]
1325 Level25,
1326 #[serde(rename = "50")]
1327 Level50,
1328 #[serde(rename = "100")]
1329 Level100,
1330 #[serde(rename = "200")]
1331 Level200,
1332 #[serde(rename = "500")]
1333 Level500,
1334}
1335
1336impl fmt::Display for DepthLevel {
1337 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1338 let value = match self {
1339 Self::Level1 => "1",
1340 Self::Level25 => "25",
1341 Self::Level50 => "50",
1342 Self::Level100 => "100",
1343 Self::Level200 => "200",
1344 Self::Level500 => "500",
1345 };
1346 write!(f, "{value}")
1347 }
1348}
1349
1350pub fn spot_fee_currency(side: Side, is_maker_order: bool, maker_fee_rate: f64) -> Pair {
1351 if maker_fee_rate >= 0.0 {
1352 match side {
1353 Side::Buy => Pair::Base,
1354 Side::Sell => Pair::Quote,
1355 }
1356 } else if is_maker_order {
1357 match side {
1358 Side::Buy => Pair::Quote,
1359 Side::Sell => Pair::Base,
1360 }
1361 } else {
1362 match side {
1363 Side::Buy => Pair::Base,
1364 Side::Sell => Pair::Quote,
1365 }
1366 }
1367}
1368
1369#[cfg(test)]
1370mod tests {
1371 use crate::serde::deserialize_json;
1372
1373 use super::*;
1374
1375 #[test]
1376 fn serialize_category() {
1377 let cases = vec![
1378 (Category::Inverse, r#""inverse""#),
1379 (Category::Linear, r#""linear""#),
1380 (Category::Option, r#""option""#),
1381 (Category::Spot, r#""spot""#),
1382 ];
1383 cases.iter().for_each(|(category, expected)| {
1384 let json = serde_json::to_string(category).unwrap();
1385 assert_eq!(json, *expected);
1386 });
1387 }
1388
1389 #[test]
1390 fn deserialize_category() {
1391 let cases = vec![
1392 (r#""inverse""#, Category::Inverse),
1393 (r#""linear""#, Category::Linear),
1394 (r#""option""#, Category::Option),
1395 (r#""spot""#, Category::Spot),
1396 ];
1397 cases.iter().for_each(|(json, expected)| {
1398 let message: Category = deserialize_json(json).unwrap();
1399 assert_eq!(message, *expected);
1400 });
1401 }
1402
1403 #[test]
1404 fn serialize_interval() {
1405 let cases = vec![
1406 (Interval::Minute1, r#""1""#),
1407 (Interval::Minute3, r#""3""#),
1408 (Interval::Minute5, r#""5""#),
1409 (Interval::Minute15, r#""15""#),
1410 (Interval::Minute30, r#""30""#),
1411 (Interval::Hour1, r#""60""#),
1412 (Interval::Hour2, r#""120""#),
1413 (Interval::Hour4, r#""240""#),
1414 (Interval::Hour6, r#""360""#),
1415 (Interval::Hour12, r#""720""#),
1416 (Interval::Day1, r#""D""#),
1417 (Interval::Week1, r#""W""#),
1418 (Interval::Month1, r#""M""#),
1419 ];
1420 cases.iter().for_each(|(category, expected)| {
1421 let json = serde_json::to_string(category).unwrap();
1422 assert_eq!(json, *expected);
1423 });
1424 }
1425
1426 #[test]
1427 fn deserialize_interval() {
1428 let cases = vec![
1429 (r#""1""#, Interval::Minute1),
1430 (r#""3""#, Interval::Minute3),
1431 (r#""5""#, Interval::Minute5),
1432 (r#""15""#, Interval::Minute15),
1433 (r#""30""#, Interval::Minute30),
1434 (r#""60""#, Interval::Hour1),
1435 (r#""120""#, Interval::Hour2),
1436 (r#""240""#, Interval::Hour4),
1437 (r#""360""#, Interval::Hour6),
1438 (r#""720""#, Interval::Hour12),
1439 (r#""D""#, Interval::Day1),
1440 (r#""W""#, Interval::Week1),
1441 (r#""M""#, Interval::Month1),
1442 ];
1443 cases.iter().for_each(|(json, expected)| {
1444 let message: Interval = deserialize_json(json).unwrap();
1445 assert_eq!(message, *expected);
1446 });
1447 }
1448
1449 #[test]
1450 fn serialize_topic() {
1451 let symbol = String::from("BTCUSDT");
1452 let cases = vec![
1453 (
1454 Topic::Orderbook {
1455 symbol: symbol.clone(),
1456 depth: DepthLevel::Level1,
1457 },
1458 r#""orderbook.1.BTCUSDT""#,
1459 ),
1460 (Topic::Trade(symbol.clone()), r#""publicTrade.BTCUSDT""#),
1461 (Topic::Ticker(symbol.clone()), r#""tickers.BTCUSDT""#),
1462 (
1463 Topic::Kline {
1464 symbol: symbol.clone(),
1465 interval: Interval::Minute1,
1466 },
1467 r#""kline.1.BTCUSDT""#,
1468 ),
1469 (
1470 Topic::AllLiquidation(symbol.clone()),
1471 r#""allLiquidation.BTCUSDT""#,
1472 ),
1473 (Topic::Position(Category::Linear), r#""position.linear""#),
1474 (Topic::PositionAllCategory, r#""position""#),
1475 (Topic::Execution(Category::Linear), r#""execution.linear""#),
1476 (Topic::ExecutionAllCategory, r#""execution""#),
1477 (
1478 Topic::FastExecution(Category::Linear),
1479 r#""execution.fast.linear""#,
1480 ),
1481 (Topic::FastExecutionAllCategory, r#""execution.fast""#),
1482 (Topic::Order(Category::Linear), r#""order.linear""#),
1483 (Topic::OrderAllCategory, r#""order""#),
1484 (Topic::Wallet, r#""wallet""#),
1485 (Topic::Greek, r#""greek""#),
1486 (Topic::Dcp(DcpFunction::Future), r#""dcp.future""#),
1487 ];
1488 cases.iter().for_each(|(category, expected)| {
1489 let json = serde_json::to_string(category).unwrap();
1490 assert_eq!(*expected, json);
1491 });
1492 }
1493
1494 #[test]
1495 fn deserialize_topic() {
1496 let symbol = String::from("BTCUSDT");
1497 let cases = vec![
1498 (
1499 r#""orderbook.1.BTCUSDT""#,
1500 Topic::Orderbook {
1501 symbol: symbol.clone(),
1502 depth: DepthLevel::Level1,
1503 },
1504 ),
1505 (r#""publicTrade.BTCUSDT""#, Topic::Trade(symbol.clone())),
1506 (r#""tickers.BTCUSDT""#, Topic::Ticker(symbol.clone())),
1507 (
1508 r#""kline.1.BTCUSDT""#,
1509 Topic::Kline {
1510 symbol: symbol.clone(),
1511 interval: Interval::Minute1,
1512 },
1513 ),
1514 (
1515 r#""allLiquidation.BTCUSDT""#,
1516 Topic::AllLiquidation(symbol.clone()),
1517 ),
1518 (r#""position.linear""#, Topic::Position(Category::Linear)),
1519 (r#""position""#, Topic::PositionAllCategory),
1520 (r#""execution.linear""#, Topic::Execution(Category::Linear)),
1521 (r#""execution""#, Topic::ExecutionAllCategory),
1522 (
1523 r#""execution.fast.linear""#,
1524 Topic::FastExecution(Category::Linear),
1525 ),
1526 (r#""execution.fast""#, Topic::FastExecutionAllCategory),
1527 (r#""order.linear""#, Topic::Order(Category::Linear)),
1528 (r#""order""#, Topic::OrderAllCategory),
1529 (r#""wallet""#, Topic::Wallet),
1530 (r#""greek""#, Topic::Greek),
1531 (r#""dcp.future""#, Topic::Dcp(DcpFunction::Future)),
1532 ];
1533 cases.iter().for_each(|(json, expected)| {
1534 let message = deserialize_json(json).unwrap();
1535 assert_eq!(*expected, message);
1536 });
1537 }
1538}