1use serde::{Deserialize, Serialize};
24use strum::{AsRefStr, Display, EnumIter, EnumString};
25
26#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
29#[serde(rename_all = "lowercase")]
30#[cfg_attr(
31 feature = "python",
32 pyo3::pyclass(
33 module = "nautilus_trader.adapters.derive",
34 eq,
35 eq_int,
36 frozen,
37 from_py_object,
38 rename_all = "SCREAMING_SNAKE_CASE"
39 )
40)]
41#[cfg_attr(
42 feature = "python",
43 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.derive")
44)]
45pub enum DeriveEnvironment {
46 #[default]
48 Mainnet,
49 Testnet,
51}
52
53impl DeriveEnvironment {
54 #[must_use]
55 pub const fn is_testnet(self) -> bool {
56 matches!(self, Self::Testnet)
57 }
58}
59
60#[derive(
64 Debug,
65 Clone,
66 Copy,
67 PartialEq,
68 Eq,
69 Hash,
70 Serialize,
71 Deserialize,
72 Display,
73 EnumString,
74 AsRefStr,
75 EnumIter,
76)]
77#[serde(rename_all = "lowercase")]
78#[strum(serialize_all = "lowercase")]
79pub enum DeriveInstrumentType {
80 Erc20,
82 Option,
84 Perp,
86 #[serde(other)]
88 Unknown,
89}
90
91#[derive(
96 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, EnumIter,
97)]
98#[serde(rename_all = "lowercase")]
99#[strum(serialize_all = "lowercase")]
100pub enum DeriveAssetType {
101 Erc20,
103 Option,
105 Perp,
107 #[serde(other)]
109 Unknown,
110}
111
112#[derive(
114 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
115)]
116#[serde(rename_all = "lowercase")]
117#[strum(serialize_all = "lowercase")]
118pub enum DeriveOrderSide {
119 Buy,
120 Sell,
121}
122
123#[derive(
125 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
126)]
127#[serde(rename_all = "lowercase")]
128#[strum(serialize_all = "lowercase")]
129pub enum DeriveOrderType {
130 Limit,
131 Market,
132 #[serde(other)]
134 Unknown,
135}
136
137#[derive(
139 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
140)]
141#[serde(rename_all = "lowercase")]
142#[strum(serialize_all = "lowercase")]
143pub enum DeriveTriggerType {
144 Stoploss,
146 Takeprofit,
148 #[serde(other)]
150 Unknown,
151}
152
153#[derive(
155 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
156)]
157#[serde(rename_all = "lowercase")]
158#[strum(serialize_all = "lowercase")]
159pub enum DeriveTriggerPriceType {
160 Mark,
162 Index,
164 #[serde(other)]
166 Unknown,
167}
168
169#[derive(
172 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
173)]
174#[serde(rename_all = "snake_case")]
175#[strum(serialize_all = "snake_case")]
176pub enum DeriveOrderStatus {
177 Open,
179 Filled,
181 Rejected,
183 Cancelled,
185 Expired,
187 Untriggered,
189 AlgoActive,
191 #[serde(other)]
193 Unknown,
194}
195
196#[derive(
198 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
199)]
200#[serde(rename_all = "snake_case")]
201#[strum(serialize_all = "snake_case")]
202pub enum DeriveTimeInForce {
203 Gtc,
205 PostOnly,
207 Fok,
209 Ioc,
211 #[serde(other)]
213 Unknown,
214}
215
216#[derive(
218 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
219)]
220pub enum DeriveOptionKind {
221 #[serde(rename = "C")]
223 #[strum(serialize = "C")]
224 Call,
225 #[serde(rename = "P")]
227 #[strum(serialize = "P")]
228 Put,
229}
230
231#[derive(
237 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
238)]
239pub enum DeriveOrderCancelReason {
240 #[serde(rename = "")]
242 #[strum(serialize = "")]
243 Empty,
244 #[serde(rename = "user_request")]
246 #[strum(serialize = "user_request")]
247 UserRequest,
248 #[serde(rename = "mmp_trigger")]
250 #[strum(serialize = "mmp_trigger")]
251 MmpTrigger,
252 #[serde(rename = "insufficient_margin")]
254 #[strum(serialize = "insufficient_margin")]
255 InsufficientMargin,
256 #[serde(rename = "signed_max_fee_too_low")]
258 #[strum(serialize = "signed_max_fee_too_low")]
259 SignedMaxFeeTooLow,
260 #[serde(rename = "cancel_on_disconnect")]
262 #[strum(serialize = "cancel_on_disconnect")]
263 CancelOnDisconnect,
264 #[serde(rename = "ioc_or_market_partial_fill")]
266 #[strum(serialize = "ioc_or_market_partial_fill")]
267 IocOrMarketPartialFill,
268 #[serde(rename = "session_key_deregistered")]
270 #[strum(serialize = "session_key_deregistered")]
271 SessionKeyDeregistered,
272 #[serde(rename = "subaccount_withdrawn")]
274 #[strum(serialize = "subaccount_withdrawn")]
275 SubaccountWithdrawn,
276 #[serde(rename = "compliance")]
278 #[strum(serialize = "compliance")]
279 Compliance,
280 #[serde(rename = "trigger_failed")]
282 #[strum(serialize = "trigger_failed")]
283 TriggerFailed,
284 #[serde(rename = "validation_failed")]
286 #[strum(serialize = "validation_failed")]
287 ValidationFailed,
288 #[serde(rename = "algo_completed")]
290 #[strum(serialize = "algo_completed")]
291 AlgoCompleted,
292 #[serde(rename = "Post only order cannot cross the market")]
294 #[strum(serialize = "Post only order cannot cross the market")]
295 PostOnlyCrossMarket,
296 #[serde(rename = "unknown", other)]
299 #[strum(serialize = "unknown")]
300 Unknown,
301}
302
303#[derive(
307 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
308)]
309pub enum DeriveRfqCancelReason {
310 #[serde(rename = "")]
312 #[strum(serialize = "")]
313 Empty,
314 #[serde(rename = "user_request")]
316 #[strum(serialize = "user_request")]
317 UserRequest,
318 #[serde(rename = "insufficient_margin")]
320 #[strum(serialize = "insufficient_margin")]
321 InsufficientMargin,
322 #[serde(rename = "signed_max_fee_too_low")]
324 #[strum(serialize = "signed_max_fee_too_low")]
325 SignedMaxFeeTooLow,
326 #[serde(rename = "mmp_trigger")]
328 #[strum(serialize = "mmp_trigger")]
329 MmpTrigger,
330 #[serde(rename = "cancel_on_disconnect")]
332 #[strum(serialize = "cancel_on_disconnect")]
333 CancelOnDisconnect,
334 #[serde(rename = "session_key_deregistered")]
336 #[strum(serialize = "session_key_deregistered")]
337 SessionKeyDeregistered,
338 #[serde(rename = "subaccount_withdrawn")]
340 #[strum(serialize = "subaccount_withdrawn")]
341 SubaccountWithdrawn,
342 #[serde(rename = "rfq_no_longer_open")]
344 #[strum(serialize = "rfq_no_longer_open")]
345 RfqNoLongerOpen,
346 #[serde(rename = "compliance")]
348 #[strum(serialize = "compliance")]
349 Compliance,
350}
351
352#[derive(
354 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
355)]
356#[serde(rename_all = "lowercase")]
357#[strum(serialize_all = "lowercase")]
358pub enum DeriveLiquidityRole {
359 Maker,
361 Taker,
363 #[serde(other)]
365 Unknown,
366}
367
368#[derive(
371 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
372)]
373pub enum DeriveMarginType {
374 #[serde(rename = "SM")]
376 #[strum(serialize = "SM")]
377 Sm,
378 #[serde(rename = "PM")]
380 #[strum(serialize = "PM")]
381 Pm,
382 #[serde(rename = "PM2")]
384 #[strum(serialize = "PM2")]
385 Pm2,
386 #[serde(rename = "unknown", other)]
388 #[strum(serialize = "unknown")]
389 Unknown,
390}
391
392#[derive(
394 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
395)]
396#[serde(rename_all = "lowercase")]
397#[strum(serialize_all = "lowercase")]
398pub enum DeriveAuctionType {
399 Solvent,
401 Insolvent,
403}
404
405#[derive(
407 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
408)]
409#[serde(rename_all = "lowercase")]
410#[strum(serialize_all = "lowercase")]
411pub enum DeriveAuctionState {
412 Ongoing,
414 Ended,
416}
417
418#[derive(
421 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
422)]
423#[serde(rename_all = "lowercase")]
424#[strum(serialize_all = "lowercase")]
425pub enum DeriveNotificationStatus {
426 Unseen,
428 Seen,
430 Hidden,
432}
433
434#[derive(
438 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
439)]
440#[serde(rename_all = "lowercase")]
441#[strum(serialize_all = "lowercase")]
442pub enum DeriveNotificationType {
443 Deposit,
445 Withdraw,
447 Transfer,
449 Trade,
451 Settlement,
453 Liquidation,
455 Types,
457}
458
459#[derive(
462 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
463)]
464#[serde(rename_all = "snake_case")]
465#[strum(serialize_all = "snake_case")]
466pub enum DeriveBalanceUpdateType {
467 Trade,
469 AssetDeposit,
471 AssetWithdrawal,
473 Transfer,
475 SubaccountDeposit,
477 SubaccountWithdrawal,
479 Liquidation,
481 OnchainDriftFix,
483 PerpSettlement,
485 OptionSettlement,
487 InterestAccrual,
489 OnchainRevert,
491 DoubleRevert,
493}
494
495#[derive(
497 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
498)]
499#[serde(rename_all = "lowercase")]
500#[strum(serialize_all = "lowercase")]
501pub enum DeriveComplianceStatus {
502 Enabled,
504 Disabled,
506}
507
508#[derive(
511 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
512)]
513pub enum DeriveOrderbookDepth {
514 #[serde(rename = "1")]
516 #[strum(serialize = "1")]
517 D1,
518 #[serde(rename = "10")]
520 #[strum(serialize = "10")]
521 D10,
522 #[serde(rename = "20")]
524 #[strum(serialize = "20")]
525 D20,
526 #[serde(rename = "100")]
528 #[strum(serialize = "100")]
529 D100,
530}
531
532#[derive(
534 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
535)]
536pub enum DeriveOrderbookGroup {
537 #[serde(rename = "1")]
539 #[strum(serialize = "1")]
540 G1,
541 #[serde(rename = "10")]
543 #[strum(serialize = "10")]
544 G10,
545 #[serde(rename = "100")]
547 #[strum(serialize = "100")]
548 G100,
549}
550
551#[derive(
554 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumString, AsRefStr,
555)]
556pub enum DeriveTickerInterval {
557 #[serde(rename = "100")]
559 #[strum(serialize = "100")]
560 Ms100,
561 #[serde(rename = "1000")]
563 #[strum(serialize = "1000")]
564 Ms1000,
565}
566
567#[cfg(test)]
568mod tests {
569 use std::str::FromStr;
570
571 use rstest::rstest;
572
573 use super::*;
574
575 #[rstest]
576 fn test_environment_default_is_mainnet() {
577 assert_eq!(DeriveEnvironment::default(), DeriveEnvironment::Mainnet);
578 assert!(!DeriveEnvironment::default().is_testnet());
579 assert!(DeriveEnvironment::Testnet.is_testnet());
580 }
581
582 #[rstest]
583 #[case(DeriveInstrumentType::Erc20, "erc20")]
584 #[case(DeriveInstrumentType::Option, "option")]
585 #[case(DeriveInstrumentType::Perp, "perp")]
586 #[case(DeriveInstrumentType::Unknown, "unknown")]
587 fn test_instrument_type_display(#[case] variant: DeriveInstrumentType, #[case] expected: &str) {
588 assert_eq!(variant.to_string(), expected);
589 }
590
591 #[rstest]
592 #[case(DeriveTimeInForce::Gtc, "gtc")]
593 #[case(DeriveTimeInForce::PostOnly, "post_only")]
594 #[case(DeriveTimeInForce::Fok, "fok")]
595 #[case(DeriveTimeInForce::Ioc, "ioc")]
596 #[case(DeriveTimeInForce::Unknown, "unknown")]
597 fn test_time_in_force_wire_strings(#[case] variant: DeriveTimeInForce, #[case] expected: &str) {
598 assert_eq!(variant.to_string(), expected);
599 assert_eq!(DeriveTimeInForce::from_str(expected).unwrap(), variant);
600 assert_eq!(
601 serde_json::to_string(&variant).unwrap(),
602 format!("\"{expected}\""),
603 );
604 }
605
606 #[rstest]
607 fn test_option_kind_serialization_uses_single_letter() {
608 assert_eq!(DeriveOptionKind::Call.to_string(), "C");
609 assert_eq!(DeriveOptionKind::Put.to_string(), "P");
610 assert_eq!(
611 DeriveOptionKind::from_str("C").unwrap(),
612 DeriveOptionKind::Call
613 );
614 assert_eq!(
615 DeriveOptionKind::from_str("P").unwrap(),
616 DeriveOptionKind::Put
617 );
618 }
619
620 #[rstest]
621 #[case(DeriveAssetType::Erc20, "erc20")]
622 #[case(DeriveAssetType::Option, "option")]
623 #[case(DeriveAssetType::Perp, "perp")]
624 #[case(DeriveAssetType::Unknown, "unknown")]
625 fn test_asset_type_wire_strings(#[case] variant: DeriveAssetType, #[case] expected: &str) {
626 assert_eq!(variant.to_string(), expected);
627 assert_eq!(DeriveAssetType::from_str(expected).unwrap(), variant);
628 }
629
630 #[rstest]
631 #[case(DeriveOrderSide::Buy, "buy")]
632 #[case(DeriveOrderSide::Sell, "sell")]
633 fn test_order_side_wire_strings(#[case] variant: DeriveOrderSide, #[case] expected: &str) {
634 assert_eq!(variant.to_string(), expected);
635 assert_eq!(
636 serde_json::from_str::<DeriveOrderSide>(&format!("\"{expected}\"")).unwrap(),
637 variant
638 );
639 }
640
641 #[rstest]
642 #[case(DeriveOrderType::Limit, "limit")]
643 #[case(DeriveOrderType::Market, "market")]
644 #[case(DeriveOrderType::Unknown, "unknown")]
645 fn test_order_type_wire_strings(#[case] variant: DeriveOrderType, #[case] expected: &str) {
646 assert_eq!(variant.to_string(), expected);
647 assert_eq!(DeriveOrderType::from_str(expected).unwrap(), variant);
648 }
649
650 #[rstest]
651 #[case(DeriveTriggerType::Stoploss, "stoploss")]
652 #[case(DeriveTriggerType::Takeprofit, "takeprofit")]
653 #[case(DeriveTriggerType::Unknown, "unknown")]
654 fn test_trigger_type_wire_strings(#[case] variant: DeriveTriggerType, #[case] expected: &str) {
655 assert_eq!(variant.to_string(), expected);
656 assert_eq!(DeriveTriggerType::from_str(expected).unwrap(), variant);
657 }
658
659 #[rstest]
660 #[case(DeriveTriggerPriceType::Mark, "mark")]
661 #[case(DeriveTriggerPriceType::Index, "index")]
662 #[case(DeriveTriggerPriceType::Unknown, "unknown")]
663 fn test_trigger_price_type_wire_strings(
664 #[case] variant: DeriveTriggerPriceType,
665 #[case] expected: &str,
666 ) {
667 assert_eq!(variant.to_string(), expected);
668 assert_eq!(DeriveTriggerPriceType::from_str(expected).unwrap(), variant);
669 }
670
671 #[rstest]
672 #[case(DeriveOrderStatus::Open, "open")]
673 #[case(DeriveOrderStatus::Filled, "filled")]
674 #[case(DeriveOrderStatus::Rejected, "rejected")]
675 #[case(DeriveOrderStatus::Cancelled, "cancelled")]
676 #[case(DeriveOrderStatus::Expired, "expired")]
677 #[case(DeriveOrderStatus::Untriggered, "untriggered")]
678 #[case(DeriveOrderStatus::AlgoActive, "algo_active")]
679 fn test_order_status_wire_strings(#[case] variant: DeriveOrderStatus, #[case] expected: &str) {
680 assert_eq!(variant.to_string(), expected);
681 assert_eq!(DeriveOrderStatus::from_str(expected).unwrap(), variant);
682 }
683
684 #[rstest]
685 #[case(DeriveOrderCancelReason::Empty, "")]
686 #[case(DeriveOrderCancelReason::UserRequest, "user_request")]
687 #[case(DeriveOrderCancelReason::MmpTrigger, "mmp_trigger")]
688 #[case(DeriveOrderCancelReason::InsufficientMargin, "insufficient_margin")]
689 #[case(DeriveOrderCancelReason::SignedMaxFeeTooLow, "signed_max_fee_too_low")]
690 #[case(DeriveOrderCancelReason::CancelOnDisconnect, "cancel_on_disconnect")]
691 #[case(
692 DeriveOrderCancelReason::IocOrMarketPartialFill,
693 "ioc_or_market_partial_fill"
694 )]
695 #[case(
696 DeriveOrderCancelReason::SessionKeyDeregistered,
697 "session_key_deregistered"
698 )]
699 #[case(DeriveOrderCancelReason::SubaccountWithdrawn, "subaccount_withdrawn")]
700 #[case(DeriveOrderCancelReason::Compliance, "compliance")]
701 #[case(DeriveOrderCancelReason::TriggerFailed, "trigger_failed")]
702 #[case(DeriveOrderCancelReason::ValidationFailed, "validation_failed")]
703 #[case(DeriveOrderCancelReason::AlgoCompleted, "algo_completed")]
704 #[case(
705 DeriveOrderCancelReason::PostOnlyCrossMarket,
706 "Post only order cannot cross the market"
707 )]
708 #[case(DeriveOrderCancelReason::Unknown, "unknown")]
709 fn test_order_cancel_reason_wire_strings(
710 #[case] variant: DeriveOrderCancelReason,
711 #[case] expected: &str,
712 ) {
713 assert_eq!(variant.to_string(), expected);
714 assert_eq!(
715 serde_json::from_str::<DeriveOrderCancelReason>(&format!("\"{expected}\"")).unwrap(),
716 variant
717 );
718 }
719
720 #[rstest]
721 #[case(DeriveRfqCancelReason::Empty, "")]
722 #[case(DeriveRfqCancelReason::UserRequest, "user_request")]
723 #[case(DeriveRfqCancelReason::InsufficientMargin, "insufficient_margin")]
724 #[case(DeriveRfqCancelReason::SignedMaxFeeTooLow, "signed_max_fee_too_low")]
725 #[case(DeriveRfqCancelReason::MmpTrigger, "mmp_trigger")]
726 #[case(DeriveRfqCancelReason::CancelOnDisconnect, "cancel_on_disconnect")]
727 #[case(
728 DeriveRfqCancelReason::SessionKeyDeregistered,
729 "session_key_deregistered"
730 )]
731 #[case(DeriveRfqCancelReason::SubaccountWithdrawn, "subaccount_withdrawn")]
732 #[case(DeriveRfqCancelReason::RfqNoLongerOpen, "rfq_no_longer_open")]
733 #[case(DeriveRfqCancelReason::Compliance, "compliance")]
734 fn test_rfq_cancel_reason_wire_strings(
735 #[case] variant: DeriveRfqCancelReason,
736 #[case] expected: &str,
737 ) {
738 assert_eq!(variant.to_string(), expected);
739 assert_eq!(
740 serde_json::from_str::<DeriveRfqCancelReason>(&format!("\"{expected}\"")).unwrap(),
741 variant
742 );
743 }
744
745 #[rstest]
746 fn test_response_enums_decode_unknown_wire_strings_leniently() {
747 assert_eq!(
748 serde_json::from_str::<DeriveInstrumentType>("\"structured\"").unwrap(),
749 DeriveInstrumentType::Unknown,
750 );
751 assert_eq!(
752 serde_json::from_str::<DeriveAssetType>("\"structured\"").unwrap(),
753 DeriveAssetType::Unknown,
754 );
755 assert_eq!(
756 serde_json::from_str::<DeriveOrderType>("\"twap\"").unwrap(),
757 DeriveOrderType::Unknown,
758 );
759 assert_eq!(
760 serde_json::from_str::<DeriveTriggerType>("\"trailing_stop\"").unwrap(),
761 DeriveTriggerType::Unknown,
762 );
763 assert_eq!(
764 serde_json::from_str::<DeriveTriggerPriceType>("\"last\"").unwrap(),
765 DeriveTriggerPriceType::Unknown,
766 );
767 assert_eq!(
768 serde_json::from_str::<DeriveTimeInForce>("\"day\"").unwrap(),
769 DeriveTimeInForce::Unknown,
770 );
771 assert_eq!(
772 serde_json::from_str::<DeriveOrderCancelReason>("\"Trigger worker restarted\"")
773 .unwrap(),
774 DeriveOrderCancelReason::Unknown,
775 );
776 assert_eq!(
777 serde_json::from_str::<DeriveLiquidityRole>("\"auction\"").unwrap(),
778 DeriveLiquidityRole::Unknown,
779 );
780 assert_eq!(
781 serde_json::from_str::<DeriveMarginType>("\"PM3\"").unwrap(),
782 DeriveMarginType::Unknown,
783 );
784 }
785
786 #[rstest]
787 fn test_order_cancel_reason_empty_string_round_trips() {
788 let json = serde_json::to_string(&DeriveOrderCancelReason::Empty).unwrap();
789 assert_eq!(json, "\"\"");
790 let parsed: DeriveOrderCancelReason = serde_json::from_str("\"\"").unwrap();
791 assert_eq!(parsed, DeriveOrderCancelReason::Empty);
792 }
793
794 #[rstest]
795 #[case(DeriveLiquidityRole::Maker, "maker")]
796 #[case(DeriveLiquidityRole::Taker, "taker")]
797 #[case(DeriveLiquidityRole::Unknown, "unknown")]
798 fn test_liquidity_role_wire_strings(
799 #[case] variant: DeriveLiquidityRole,
800 #[case] expected: &str,
801 ) {
802 assert_eq!(variant.to_string(), expected);
803 assert_eq!(DeriveLiquidityRole::from_str(expected).unwrap(), variant);
804 }
805
806 #[rstest]
807 #[case(DeriveMarginType::Sm, "SM")]
808 #[case(DeriveMarginType::Pm, "PM")]
809 #[case(DeriveMarginType::Pm2, "PM2")]
810 #[case(DeriveMarginType::Unknown, "unknown")]
811 fn test_margin_type_wire_strings(#[case] variant: DeriveMarginType, #[case] expected: &str) {
812 assert_eq!(variant.to_string(), expected);
813 assert_eq!(DeriveMarginType::from_str(expected).unwrap(), variant);
814 }
815
816 #[rstest]
817 #[case(DeriveAuctionType::Solvent, "solvent")]
818 #[case(DeriveAuctionType::Insolvent, "insolvent")]
819 fn test_auction_type_wire_strings(#[case] variant: DeriveAuctionType, #[case] expected: &str) {
820 assert_eq!(variant.to_string(), expected);
821 assert_eq!(DeriveAuctionType::from_str(expected).unwrap(), variant);
822 }
823
824 #[rstest]
825 #[case(DeriveAuctionState::Ongoing, "ongoing")]
826 #[case(DeriveAuctionState::Ended, "ended")]
827 fn test_auction_state_wire_strings(
828 #[case] variant: DeriveAuctionState,
829 #[case] expected: &str,
830 ) {
831 assert_eq!(variant.to_string(), expected);
832 assert_eq!(DeriveAuctionState::from_str(expected).unwrap(), variant);
833 }
834
835 #[rstest]
836 #[case(DeriveNotificationStatus::Unseen, "unseen")]
837 #[case(DeriveNotificationStatus::Seen, "seen")]
838 #[case(DeriveNotificationStatus::Hidden, "hidden")]
839 fn test_notification_status_wire_strings(
840 #[case] variant: DeriveNotificationStatus,
841 #[case] expected: &str,
842 ) {
843 assert_eq!(variant.to_string(), expected);
844 assert_eq!(
845 DeriveNotificationStatus::from_str(expected).unwrap(),
846 variant
847 );
848 }
849
850 #[rstest]
851 #[case(DeriveNotificationType::Deposit, "deposit")]
852 #[case(DeriveNotificationType::Withdraw, "withdraw")]
853 #[case(DeriveNotificationType::Transfer, "transfer")]
854 #[case(DeriveNotificationType::Trade, "trade")]
855 #[case(DeriveNotificationType::Settlement, "settlement")]
856 #[case(DeriveNotificationType::Liquidation, "liquidation")]
857 #[case(DeriveNotificationType::Types, "types")]
858 fn test_notification_type_wire_strings(
859 #[case] variant: DeriveNotificationType,
860 #[case] expected: &str,
861 ) {
862 assert_eq!(variant.to_string(), expected);
863 assert_eq!(DeriveNotificationType::from_str(expected).unwrap(), variant);
864 }
865
866 #[rstest]
867 #[case(DeriveBalanceUpdateType::Trade, "trade")]
868 #[case(DeriveBalanceUpdateType::AssetDeposit, "asset_deposit")]
869 #[case(DeriveBalanceUpdateType::AssetWithdrawal, "asset_withdrawal")]
870 #[case(DeriveBalanceUpdateType::Transfer, "transfer")]
871 #[case(DeriveBalanceUpdateType::SubaccountDeposit, "subaccount_deposit")]
872 #[case(DeriveBalanceUpdateType::SubaccountWithdrawal, "subaccount_withdrawal")]
873 #[case(DeriveBalanceUpdateType::Liquidation, "liquidation")]
874 #[case(DeriveBalanceUpdateType::OnchainDriftFix, "onchain_drift_fix")]
875 #[case(DeriveBalanceUpdateType::PerpSettlement, "perp_settlement")]
876 #[case(DeriveBalanceUpdateType::OptionSettlement, "option_settlement")]
877 #[case(DeriveBalanceUpdateType::InterestAccrual, "interest_accrual")]
878 #[case(DeriveBalanceUpdateType::OnchainRevert, "onchain_revert")]
879 #[case(DeriveBalanceUpdateType::DoubleRevert, "double_revert")]
880 fn test_balance_update_type_wire_strings(
881 #[case] variant: DeriveBalanceUpdateType,
882 #[case] expected: &str,
883 ) {
884 assert_eq!(variant.to_string(), expected);
885 assert_eq!(
886 DeriveBalanceUpdateType::from_str(expected).unwrap(),
887 variant
888 );
889 }
890
891 #[rstest]
892 #[case(DeriveComplianceStatus::Enabled, "enabled")]
893 #[case(DeriveComplianceStatus::Disabled, "disabled")]
894 fn test_compliance_status_wire_strings(
895 #[case] variant: DeriveComplianceStatus,
896 #[case] expected: &str,
897 ) {
898 assert_eq!(variant.to_string(), expected);
899 assert_eq!(DeriveComplianceStatus::from_str(expected).unwrap(), variant);
900 }
901
902 #[rstest]
903 #[case(DeriveOrderbookDepth::D1, "1")]
904 #[case(DeriveOrderbookDepth::D10, "10")]
905 #[case(DeriveOrderbookDepth::D20, "20")]
906 #[case(DeriveOrderbookDepth::D100, "100")]
907 fn test_orderbook_depth_wire_strings(
908 #[case] variant: DeriveOrderbookDepth,
909 #[case] expected: &str,
910 ) {
911 assert_eq!(variant.to_string(), expected);
912 assert_eq!(DeriveOrderbookDepth::from_str(expected).unwrap(), variant);
913 }
914
915 #[rstest]
916 #[case(DeriveOrderbookGroup::G1, "1")]
917 #[case(DeriveOrderbookGroup::G10, "10")]
918 #[case(DeriveOrderbookGroup::G100, "100")]
919 fn test_orderbook_group_wire_strings(
920 #[case] variant: DeriveOrderbookGroup,
921 #[case] expected: &str,
922 ) {
923 assert_eq!(variant.to_string(), expected);
924 assert_eq!(DeriveOrderbookGroup::from_str(expected).unwrap(), variant);
925 }
926
927 #[rstest]
928 #[case(DeriveTickerInterval::Ms100, "100")]
929 #[case(DeriveTickerInterval::Ms1000, "1000")]
930 fn test_ticker_interval_wire_strings(
931 #[case] variant: DeriveTickerInterval,
932 #[case] expected: &str,
933 ) {
934 assert_eq!(variant.to_string(), expected);
935 assert_eq!(DeriveTickerInterval::from_str(expected).unwrap(), variant);
936 }
937}