Skip to main content

binance_sdk/spot/websocket_api/apis/
trade_api.rs

1/*
2 * Spot WebSocket API
3 *
4 * Access market data, manage accounts, and trade on Binance Spot.
5 *
6 * The version of the OpenAPI document: 1.0.0
7 *
8 *
9 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
10 * https://openapi-generator.tech
11 * Do not edit the class manually.
12 */
13
14#![allow(unused_imports)]
15use anyhow::Context;
16use async_trait::async_trait;
17use derive_builder::Builder;
18use rust_decimal::prelude::*;
19use serde::{Deserialize, Serialize};
20use serde_json::Value;
21use std::{collections::BTreeMap, sync::Arc};
22
23use crate::common::{
24    errors::WebsocketError,
25    models::{ParamBuildError, WebsocketApiResponse},
26    utils::remove_empty_value,
27    websocket::{WebsocketApi, WebsocketMessageSendOptions},
28};
29use crate::spot::websocket_api::models;
30
31#[async_trait]
32pub trait TradeApi: Send + Sync {
33    async fn open_orders_cancel_all(
34        &self,
35        params: OpenOrdersCancelAllParams,
36    ) -> anyhow::Result<WebsocketApiResponse<Vec<models::OpenOrdersCancelAllResponseResultInner>>>;
37    async fn order_amend_keep_priority(
38        &self,
39        params: OrderAmendKeepPriorityParams,
40    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderAmendKeepPriorityResponseResult>>>;
41    async fn order_cancel(
42        &self,
43        params: OrderCancelParams,
44    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderCancelResponseResult>>>;
45    async fn order_cancel_replace(
46        &self,
47        params: OrderCancelReplaceParams,
48    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderCancelReplaceResponseResult>>>;
49    async fn order_list_cancel(
50        &self,
51        params: OrderListCancelParams,
52    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListCancelResponseResult>>>;
53    async fn order_list_place(
54        &self,
55        params: OrderListPlaceParams,
56    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceResponseResult>>>;
57    async fn order_list_place_oco(
58        &self,
59        params: OrderListPlaceOcoParams,
60    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOcoResponseResult>>>;
61    async fn order_list_place_opo(
62        &self,
63        params: OrderListPlaceOpoParams,
64    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOpoResponseResult>>>;
65    async fn order_list_place_opoco(
66        &self,
67        params: OrderListPlaceOpocoParams,
68    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOpocoResponseResult>>>;
69    async fn order_list_place_oto(
70        &self,
71        params: OrderListPlaceOtoParams,
72    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOtoResponseResult>>>;
73    async fn order_list_place_otoco(
74        &self,
75        params: OrderListPlaceOtocoParams,
76    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOtocoResponseResult>>>;
77    async fn order_place(
78        &self,
79        params: OrderPlaceParams,
80    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderPlaceResponseResult>>>;
81    async fn order_test(
82        &self,
83        params: OrderTestParams,
84    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderTestResponseResult>>>;
85    async fn sor_order_place(
86        &self,
87        params: SorOrderPlaceParams,
88    ) -> anyhow::Result<WebsocketApiResponse<Vec<models::SorOrderPlaceResponseResultInner>>>;
89    async fn sor_order_test(
90        &self,
91        params: SorOrderTestParams,
92    ) -> anyhow::Result<WebsocketApiResponse<Box<models::SorOrderTestResponseResult>>>;
93}
94
95#[derive(Clone)]
96pub struct TradeApiClient {
97    websocket_api_base: Arc<WebsocketApi>,
98}
99
100impl TradeApiClient {
101    pub fn new(websocket_api_base: Arc<WebsocketApi>) -> Self {
102        Self { websocket_api_base }
103    }
104}
105
106#[allow(non_camel_case_types)]
107#[derive(Debug, Clone, Serialize, Deserialize)]
108pub enum OrderCancelCancelRestrictionsEnum {
109    #[serde(rename = "ONLY_NEW")]
110    OnlyNew,
111    #[serde(rename = "ONLY_PARTIALLY_FILLED")]
112    OnlyPartiallyFilled,
113}
114
115impl OrderCancelCancelRestrictionsEnum {
116    #[must_use]
117    pub fn as_str(&self) -> &'static str {
118        match self {
119            Self::OnlyNew => "ONLY_NEW",
120            Self::OnlyPartiallyFilled => "ONLY_PARTIALLY_FILLED",
121        }
122    }
123}
124
125impl std::str::FromStr for OrderCancelCancelRestrictionsEnum {
126    type Err = Box<dyn std::error::Error + Send + Sync>;
127
128    fn from_str(s: &str) -> Result<Self, Self::Err> {
129        match s {
130            "ONLY_NEW" => Ok(Self::OnlyNew),
131            "ONLY_PARTIALLY_FILLED" => Ok(Self::OnlyPartiallyFilled),
132            other => Err(format!("invalid OrderCancelCancelRestrictionsEnum: {}", other).into()),
133        }
134    }
135}
136
137#[allow(non_camel_case_types)]
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub enum OrderCancelReplaceCancelReplaceModeEnum {
140    #[serde(rename = "STOP_ON_FAILURE")]
141    StopOnFailure,
142    #[serde(rename = "ALLOW_FAILURE")]
143    AllowFailure,
144}
145
146impl OrderCancelReplaceCancelReplaceModeEnum {
147    #[must_use]
148    pub fn as_str(&self) -> &'static str {
149        match self {
150            Self::StopOnFailure => "STOP_ON_FAILURE",
151            Self::AllowFailure => "ALLOW_FAILURE",
152        }
153    }
154}
155
156impl std::str::FromStr for OrderCancelReplaceCancelReplaceModeEnum {
157    type Err = Box<dyn std::error::Error + Send + Sync>;
158
159    fn from_str(s: &str) -> Result<Self, Self::Err> {
160        match s {
161            "STOP_ON_FAILURE" => Ok(Self::StopOnFailure),
162            "ALLOW_FAILURE" => Ok(Self::AllowFailure),
163            other => {
164                Err(format!("invalid OrderCancelReplaceCancelReplaceModeEnum: {}", other).into())
165            }
166        }
167    }
168}
169
170#[allow(non_camel_case_types)]
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub enum OrderCancelReplaceSideEnum {
173    #[serde(rename = "BUY")]
174    Buy,
175    #[serde(rename = "SELL")]
176    Sell,
177}
178
179impl OrderCancelReplaceSideEnum {
180    #[must_use]
181    pub fn as_str(&self) -> &'static str {
182        match self {
183            Self::Buy => "BUY",
184            Self::Sell => "SELL",
185        }
186    }
187}
188
189impl std::str::FromStr for OrderCancelReplaceSideEnum {
190    type Err = Box<dyn std::error::Error + Send + Sync>;
191
192    fn from_str(s: &str) -> Result<Self, Self::Err> {
193        match s {
194            "BUY" => Ok(Self::Buy),
195            "SELL" => Ok(Self::Sell),
196            other => Err(format!("invalid OrderCancelReplaceSideEnum: {}", other).into()),
197        }
198    }
199}
200
201#[allow(non_camel_case_types)]
202#[derive(Debug, Clone, Serialize, Deserialize)]
203pub enum OrderCancelReplaceTypeEnum {
204    #[serde(rename = "MARKET")]
205    Market,
206    #[serde(rename = "LIMIT")]
207    Limit,
208    #[serde(rename = "STOP_LOSS")]
209    StopLoss,
210    #[serde(rename = "STOP_LOSS_LIMIT")]
211    StopLossLimit,
212    #[serde(rename = "TAKE_PROFIT")]
213    TakeProfit,
214    #[serde(rename = "TAKE_PROFIT_LIMIT")]
215    TakeProfitLimit,
216    #[serde(rename = "LIMIT_MAKER")]
217    LimitMaker,
218}
219
220impl OrderCancelReplaceTypeEnum {
221    #[must_use]
222    pub fn as_str(&self) -> &'static str {
223        match self {
224            Self::Market => "MARKET",
225            Self::Limit => "LIMIT",
226            Self::StopLoss => "STOP_LOSS",
227            Self::StopLossLimit => "STOP_LOSS_LIMIT",
228            Self::TakeProfit => "TAKE_PROFIT",
229            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
230            Self::LimitMaker => "LIMIT_MAKER",
231        }
232    }
233}
234
235impl std::str::FromStr for OrderCancelReplaceTypeEnum {
236    type Err = Box<dyn std::error::Error + Send + Sync>;
237
238    fn from_str(s: &str) -> Result<Self, Self::Err> {
239        match s {
240            "MARKET" => Ok(Self::Market),
241            "LIMIT" => Ok(Self::Limit),
242            "STOP_LOSS" => Ok(Self::StopLoss),
243            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
244            "TAKE_PROFIT" => Ok(Self::TakeProfit),
245            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
246            "LIMIT_MAKER" => Ok(Self::LimitMaker),
247            other => Err(format!("invalid OrderCancelReplaceTypeEnum: {}", other).into()),
248        }
249    }
250}
251
252#[allow(non_camel_case_types)]
253#[derive(Debug, Clone, Serialize, Deserialize)]
254pub enum OrderCancelReplaceTimeInForceEnum {
255    #[serde(rename = "GTC")]
256    Gtc,
257    #[serde(rename = "IOC")]
258    Ioc,
259    #[serde(rename = "FOK")]
260    Fok,
261}
262
263impl OrderCancelReplaceTimeInForceEnum {
264    #[must_use]
265    pub fn as_str(&self) -> &'static str {
266        match self {
267            Self::Gtc => "GTC",
268            Self::Ioc => "IOC",
269            Self::Fok => "FOK",
270        }
271    }
272}
273
274impl std::str::FromStr for OrderCancelReplaceTimeInForceEnum {
275    type Err = Box<dyn std::error::Error + Send + Sync>;
276
277    fn from_str(s: &str) -> Result<Self, Self::Err> {
278        match s {
279            "GTC" => Ok(Self::Gtc),
280            "IOC" => Ok(Self::Ioc),
281            "FOK" => Ok(Self::Fok),
282            other => Err(format!("invalid OrderCancelReplaceTimeInForceEnum: {}", other).into()),
283        }
284    }
285}
286
287#[allow(non_camel_case_types)]
288#[derive(Debug, Clone, Serialize, Deserialize)]
289pub enum OrderCancelReplaceNewOrderRespTypeEnum {
290    #[serde(rename = "ACK")]
291    Ack,
292    #[serde(rename = "RESULT")]
293    Result,
294    #[serde(rename = "FULL")]
295    Full,
296}
297
298impl OrderCancelReplaceNewOrderRespTypeEnum {
299    #[must_use]
300    pub fn as_str(&self) -> &'static str {
301        match self {
302            Self::Ack => "ACK",
303            Self::Result => "RESULT",
304            Self::Full => "FULL",
305        }
306    }
307}
308
309impl std::str::FromStr for OrderCancelReplaceNewOrderRespTypeEnum {
310    type Err = Box<dyn std::error::Error + Send + Sync>;
311
312    fn from_str(s: &str) -> Result<Self, Self::Err> {
313        match s {
314            "ACK" => Ok(Self::Ack),
315            "RESULT" => Ok(Self::Result),
316            "FULL" => Ok(Self::Full),
317            other => {
318                Err(format!("invalid OrderCancelReplaceNewOrderRespTypeEnum: {}", other).into())
319            }
320        }
321    }
322}
323
324#[allow(non_camel_case_types)]
325#[derive(Debug, Clone, Serialize, Deserialize)]
326pub enum OrderCancelReplaceSelfTradePreventionModeEnum {
327    #[serde(rename = "NONE")]
328    None,
329    #[serde(rename = "EXPIRE_TAKER")]
330    ExpireTaker,
331    #[serde(rename = "EXPIRE_MAKER")]
332    ExpireMaker,
333    #[serde(rename = "EXPIRE_BOTH")]
334    ExpireBoth,
335    #[serde(rename = "DECREMENT")]
336    Decrement,
337    #[serde(rename = "TRANSFER")]
338    Transfer,
339}
340
341impl OrderCancelReplaceSelfTradePreventionModeEnum {
342    #[must_use]
343    pub fn as_str(&self) -> &'static str {
344        match self {
345            Self::None => "NONE",
346            Self::ExpireTaker => "EXPIRE_TAKER",
347            Self::ExpireMaker => "EXPIRE_MAKER",
348            Self::ExpireBoth => "EXPIRE_BOTH",
349            Self::Decrement => "DECREMENT",
350            Self::Transfer => "TRANSFER",
351        }
352    }
353}
354
355impl std::str::FromStr for OrderCancelReplaceSelfTradePreventionModeEnum {
356    type Err = Box<dyn std::error::Error + Send + Sync>;
357
358    fn from_str(s: &str) -> Result<Self, Self::Err> {
359        match s {
360            "NONE" => Ok(Self::None),
361            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
362            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
363            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
364            "DECREMENT" => Ok(Self::Decrement),
365            "TRANSFER" => Ok(Self::Transfer),
366            other => Err(format!(
367                "invalid OrderCancelReplaceSelfTradePreventionModeEnum: {}",
368                other
369            )
370            .into()),
371        }
372    }
373}
374
375#[allow(non_camel_case_types)]
376#[derive(Debug, Clone, Serialize, Deserialize)]
377pub enum OrderCancelReplaceCancelRestrictionsEnum {
378    #[serde(rename = "ONLY_NEW")]
379    OnlyNew,
380    #[serde(rename = "ONLY_PARTIALLY_FILLED")]
381    OnlyPartiallyFilled,
382}
383
384impl OrderCancelReplaceCancelRestrictionsEnum {
385    #[must_use]
386    pub fn as_str(&self) -> &'static str {
387        match self {
388            Self::OnlyNew => "ONLY_NEW",
389            Self::OnlyPartiallyFilled => "ONLY_PARTIALLY_FILLED",
390        }
391    }
392}
393
394impl std::str::FromStr for OrderCancelReplaceCancelRestrictionsEnum {
395    type Err = Box<dyn std::error::Error + Send + Sync>;
396
397    fn from_str(s: &str) -> Result<Self, Self::Err> {
398        match s {
399            "ONLY_NEW" => Ok(Self::OnlyNew),
400            "ONLY_PARTIALLY_FILLED" => Ok(Self::OnlyPartiallyFilled),
401            other => Err(format!(
402                "invalid OrderCancelReplaceCancelRestrictionsEnum: {}",
403                other
404            )
405            .into()),
406        }
407    }
408}
409
410#[allow(non_camel_case_types)]
411#[derive(Debug, Clone, Serialize, Deserialize)]
412pub enum OrderCancelReplaceOrderRateLimitExceededModeEnum {
413    #[serde(rename = "DO_NOTHING")]
414    DoNothing,
415    #[serde(rename = "CANCEL_ONLY")]
416    CancelOnly,
417}
418
419impl OrderCancelReplaceOrderRateLimitExceededModeEnum {
420    #[must_use]
421    pub fn as_str(&self) -> &'static str {
422        match self {
423            Self::DoNothing => "DO_NOTHING",
424            Self::CancelOnly => "CANCEL_ONLY",
425        }
426    }
427}
428
429impl std::str::FromStr for OrderCancelReplaceOrderRateLimitExceededModeEnum {
430    type Err = Box<dyn std::error::Error + Send + Sync>;
431
432    fn from_str(s: &str) -> Result<Self, Self::Err> {
433        match s {
434            "DO_NOTHING" => Ok(Self::DoNothing),
435            "CANCEL_ONLY" => Ok(Self::CancelOnly),
436            other => Err(format!(
437                "invalid OrderCancelReplaceOrderRateLimitExceededModeEnum: {}",
438                other
439            )
440            .into()),
441        }
442    }
443}
444
445#[allow(non_camel_case_types)]
446#[derive(Debug, Clone, Serialize, Deserialize)]
447pub enum OrderCancelReplacePegPriceTypeEnum {
448    #[serde(rename = "PRIMARY_PEG")]
449    PrimaryPeg,
450    #[serde(rename = "MARKET_PEG")]
451    MarketPeg,
452}
453
454impl OrderCancelReplacePegPriceTypeEnum {
455    #[must_use]
456    pub fn as_str(&self) -> &'static str {
457        match self {
458            Self::PrimaryPeg => "PRIMARY_PEG",
459            Self::MarketPeg => "MARKET_PEG",
460        }
461    }
462}
463
464impl std::str::FromStr for OrderCancelReplacePegPriceTypeEnum {
465    type Err = Box<dyn std::error::Error + Send + Sync>;
466
467    fn from_str(s: &str) -> Result<Self, Self::Err> {
468        match s {
469            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
470            "MARKET_PEG" => Ok(Self::MarketPeg),
471            other => Err(format!("invalid OrderCancelReplacePegPriceTypeEnum: {}", other).into()),
472        }
473    }
474}
475
476#[allow(non_camel_case_types)]
477#[derive(Debug, Clone, Serialize, Deserialize)]
478pub enum OrderCancelReplacePegOffsetTypeEnum {
479    #[serde(rename = "PRICE_LEVEL")]
480    PriceLevel,
481}
482
483impl OrderCancelReplacePegOffsetTypeEnum {
484    #[must_use]
485    pub fn as_str(&self) -> &'static str {
486        match self {
487            Self::PriceLevel => "PRICE_LEVEL",
488        }
489    }
490}
491
492impl std::str::FromStr for OrderCancelReplacePegOffsetTypeEnum {
493    type Err = Box<dyn std::error::Error + Send + Sync>;
494
495    fn from_str(s: &str) -> Result<Self, Self::Err> {
496        match s {
497            "PRICE_LEVEL" => Ok(Self::PriceLevel),
498            other => Err(format!("invalid OrderCancelReplacePegOffsetTypeEnum: {}", other).into()),
499        }
500    }
501}
502
503#[allow(non_camel_case_types)]
504#[derive(Debug, Clone, Serialize, Deserialize)]
505pub enum OrderListPlaceSideEnum {
506    #[serde(rename = "BUY")]
507    Buy,
508    #[serde(rename = "SELL")]
509    Sell,
510}
511
512impl OrderListPlaceSideEnum {
513    #[must_use]
514    pub fn as_str(&self) -> &'static str {
515        match self {
516            Self::Buy => "BUY",
517            Self::Sell => "SELL",
518        }
519    }
520}
521
522impl std::str::FromStr for OrderListPlaceSideEnum {
523    type Err = Box<dyn std::error::Error + Send + Sync>;
524
525    fn from_str(s: &str) -> Result<Self, Self::Err> {
526        match s {
527            "BUY" => Ok(Self::Buy),
528            "SELL" => Ok(Self::Sell),
529            other => Err(format!("invalid OrderListPlaceSideEnum: {}", other).into()),
530        }
531    }
532}
533
534#[allow(non_camel_case_types)]
535#[derive(Debug, Clone, Serialize, Deserialize)]
536pub enum OrderListPlaceStopLimitTimeInForceEnum {
537    #[serde(rename = "GTC")]
538    Gtc,
539    #[serde(rename = "IOC")]
540    Ioc,
541    #[serde(rename = "FOK")]
542    Fok,
543}
544
545impl OrderListPlaceStopLimitTimeInForceEnum {
546    #[must_use]
547    pub fn as_str(&self) -> &'static str {
548        match self {
549            Self::Gtc => "GTC",
550            Self::Ioc => "IOC",
551            Self::Fok => "FOK",
552        }
553    }
554}
555
556impl std::str::FromStr for OrderListPlaceStopLimitTimeInForceEnum {
557    type Err = Box<dyn std::error::Error + Send + Sync>;
558
559    fn from_str(s: &str) -> Result<Self, Self::Err> {
560        match s {
561            "GTC" => Ok(Self::Gtc),
562            "IOC" => Ok(Self::Ioc),
563            "FOK" => Ok(Self::Fok),
564            other => {
565                Err(format!("invalid OrderListPlaceStopLimitTimeInForceEnum: {}", other).into())
566            }
567        }
568    }
569}
570
571#[allow(non_camel_case_types)]
572#[derive(Debug, Clone, Serialize, Deserialize)]
573pub enum OrderListPlaceNewOrderRespTypeEnum {
574    #[serde(rename = "ACK")]
575    Ack,
576    #[serde(rename = "RESULT")]
577    Result,
578    #[serde(rename = "FULL")]
579    Full,
580}
581
582impl OrderListPlaceNewOrderRespTypeEnum {
583    #[must_use]
584    pub fn as_str(&self) -> &'static str {
585        match self {
586            Self::Ack => "ACK",
587            Self::Result => "RESULT",
588            Self::Full => "FULL",
589        }
590    }
591}
592
593impl std::str::FromStr for OrderListPlaceNewOrderRespTypeEnum {
594    type Err = Box<dyn std::error::Error + Send + Sync>;
595
596    fn from_str(s: &str) -> Result<Self, Self::Err> {
597        match s {
598            "ACK" => Ok(Self::Ack),
599            "RESULT" => Ok(Self::Result),
600            "FULL" => Ok(Self::Full),
601            other => Err(format!("invalid OrderListPlaceNewOrderRespTypeEnum: {}", other).into()),
602        }
603    }
604}
605
606#[allow(non_camel_case_types)]
607#[derive(Debug, Clone, Serialize, Deserialize)]
608pub enum OrderListPlaceSelfTradePreventionModeEnum {
609    #[serde(rename = "NONE")]
610    None,
611    #[serde(rename = "EXPIRE_TAKER")]
612    ExpireTaker,
613    #[serde(rename = "EXPIRE_MAKER")]
614    ExpireMaker,
615    #[serde(rename = "EXPIRE_BOTH")]
616    ExpireBoth,
617    #[serde(rename = "DECREMENT")]
618    Decrement,
619    #[serde(rename = "TRANSFER")]
620    Transfer,
621}
622
623impl OrderListPlaceSelfTradePreventionModeEnum {
624    #[must_use]
625    pub fn as_str(&self) -> &'static str {
626        match self {
627            Self::None => "NONE",
628            Self::ExpireTaker => "EXPIRE_TAKER",
629            Self::ExpireMaker => "EXPIRE_MAKER",
630            Self::ExpireBoth => "EXPIRE_BOTH",
631            Self::Decrement => "DECREMENT",
632            Self::Transfer => "TRANSFER",
633        }
634    }
635}
636
637impl std::str::FromStr for OrderListPlaceSelfTradePreventionModeEnum {
638    type Err = Box<dyn std::error::Error + Send + Sync>;
639
640    fn from_str(s: &str) -> Result<Self, Self::Err> {
641        match s {
642            "NONE" => Ok(Self::None),
643            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
644            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
645            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
646            "DECREMENT" => Ok(Self::Decrement),
647            "TRANSFER" => Ok(Self::Transfer),
648            other => Err(format!(
649                "invalid OrderListPlaceSelfTradePreventionModeEnum: {}",
650                other
651            )
652            .into()),
653        }
654    }
655}
656
657#[allow(non_camel_case_types)]
658#[derive(Debug, Clone, Serialize, Deserialize)]
659pub enum OrderListPlaceOcoSideEnum {
660    #[serde(rename = "BUY")]
661    Buy,
662    #[serde(rename = "SELL")]
663    Sell,
664}
665
666impl OrderListPlaceOcoSideEnum {
667    #[must_use]
668    pub fn as_str(&self) -> &'static str {
669        match self {
670            Self::Buy => "BUY",
671            Self::Sell => "SELL",
672        }
673    }
674}
675
676impl std::str::FromStr for OrderListPlaceOcoSideEnum {
677    type Err = Box<dyn std::error::Error + Send + Sync>;
678
679    fn from_str(s: &str) -> Result<Self, Self::Err> {
680        match s {
681            "BUY" => Ok(Self::Buy),
682            "SELL" => Ok(Self::Sell),
683            other => Err(format!("invalid OrderListPlaceOcoSideEnum: {}", other).into()),
684        }
685    }
686}
687
688#[allow(non_camel_case_types)]
689#[derive(Debug, Clone, Serialize, Deserialize)]
690pub enum OrderListPlaceOcoAboveTypeEnum {
691    #[serde(rename = "STOP_LOSS_LIMIT")]
692    StopLossLimit,
693    #[serde(rename = "STOP_LOSS")]
694    StopLoss,
695    #[serde(rename = "LIMIT_MAKER")]
696    LimitMaker,
697    #[serde(rename = "TAKE_PROFIT")]
698    TakeProfit,
699    #[serde(rename = "TAKE_PROFIT_LIMIT")]
700    TakeProfitLimit,
701}
702
703impl OrderListPlaceOcoAboveTypeEnum {
704    #[must_use]
705    pub fn as_str(&self) -> &'static str {
706        match self {
707            Self::StopLossLimit => "STOP_LOSS_LIMIT",
708            Self::StopLoss => "STOP_LOSS",
709            Self::LimitMaker => "LIMIT_MAKER",
710            Self::TakeProfit => "TAKE_PROFIT",
711            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
712        }
713    }
714}
715
716impl std::str::FromStr for OrderListPlaceOcoAboveTypeEnum {
717    type Err = Box<dyn std::error::Error + Send + Sync>;
718
719    fn from_str(s: &str) -> Result<Self, Self::Err> {
720        match s {
721            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
722            "STOP_LOSS" => Ok(Self::StopLoss),
723            "LIMIT_MAKER" => Ok(Self::LimitMaker),
724            "TAKE_PROFIT" => Ok(Self::TakeProfit),
725            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
726            other => Err(format!("invalid OrderListPlaceOcoAboveTypeEnum: {}", other).into()),
727        }
728    }
729}
730
731#[allow(non_camel_case_types)]
732#[derive(Debug, Clone, Serialize, Deserialize)]
733pub enum OrderListPlaceOcoBelowTypeEnum {
734    #[serde(rename = "STOP_LOSS")]
735    StopLoss,
736    #[serde(rename = "STOP_LOSS_LIMIT")]
737    StopLossLimit,
738    #[serde(rename = "TAKE_PROFIT")]
739    TakeProfit,
740    #[serde(rename = "TAKE_PROFIT_LIMIT")]
741    TakeProfitLimit,
742}
743
744impl OrderListPlaceOcoBelowTypeEnum {
745    #[must_use]
746    pub fn as_str(&self) -> &'static str {
747        match self {
748            Self::StopLoss => "STOP_LOSS",
749            Self::StopLossLimit => "STOP_LOSS_LIMIT",
750            Self::TakeProfit => "TAKE_PROFIT",
751            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
752        }
753    }
754}
755
756impl std::str::FromStr for OrderListPlaceOcoBelowTypeEnum {
757    type Err = Box<dyn std::error::Error + Send + Sync>;
758
759    fn from_str(s: &str) -> Result<Self, Self::Err> {
760        match s {
761            "STOP_LOSS" => Ok(Self::StopLoss),
762            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
763            "TAKE_PROFIT" => Ok(Self::TakeProfit),
764            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
765            other => Err(format!("invalid OrderListPlaceOcoBelowTypeEnum: {}", other).into()),
766        }
767    }
768}
769
770#[allow(non_camel_case_types)]
771#[derive(Debug, Clone, Serialize, Deserialize)]
772pub enum OrderListPlaceOcoAboveTimeInForceEnum {
773    #[serde(rename = "GTC")]
774    Gtc,
775    #[serde(rename = "IOC")]
776    Ioc,
777    #[serde(rename = "FOK")]
778    Fok,
779}
780
781impl OrderListPlaceOcoAboveTimeInForceEnum {
782    #[must_use]
783    pub fn as_str(&self) -> &'static str {
784        match self {
785            Self::Gtc => "GTC",
786            Self::Ioc => "IOC",
787            Self::Fok => "FOK",
788        }
789    }
790}
791
792impl std::str::FromStr for OrderListPlaceOcoAboveTimeInForceEnum {
793    type Err = Box<dyn std::error::Error + Send + Sync>;
794
795    fn from_str(s: &str) -> Result<Self, Self::Err> {
796        match s {
797            "GTC" => Ok(Self::Gtc),
798            "IOC" => Ok(Self::Ioc),
799            "FOK" => Ok(Self::Fok),
800            other => {
801                Err(format!("invalid OrderListPlaceOcoAboveTimeInForceEnum: {}", other).into())
802            }
803        }
804    }
805}
806
807#[allow(non_camel_case_types)]
808#[derive(Debug, Clone, Serialize, Deserialize)]
809pub enum OrderListPlaceOcoAbovePegPriceTypeEnum {
810    #[serde(rename = "PRIMARY_PEG")]
811    PrimaryPeg,
812    #[serde(rename = "MARKET_PEG")]
813    MarketPeg,
814}
815
816impl OrderListPlaceOcoAbovePegPriceTypeEnum {
817    #[must_use]
818    pub fn as_str(&self) -> &'static str {
819        match self {
820            Self::PrimaryPeg => "PRIMARY_PEG",
821            Self::MarketPeg => "MARKET_PEG",
822        }
823    }
824}
825
826impl std::str::FromStr for OrderListPlaceOcoAbovePegPriceTypeEnum {
827    type Err = Box<dyn std::error::Error + Send + Sync>;
828
829    fn from_str(s: &str) -> Result<Self, Self::Err> {
830        match s {
831            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
832            "MARKET_PEG" => Ok(Self::MarketPeg),
833            other => {
834                Err(format!("invalid OrderListPlaceOcoAbovePegPriceTypeEnum: {}", other).into())
835            }
836        }
837    }
838}
839
840#[allow(non_camel_case_types)]
841#[derive(Debug, Clone, Serialize, Deserialize)]
842pub enum OrderListPlaceOcoAbovePegOffsetTypeEnum {
843    #[serde(rename = "PRICE_LEVEL")]
844    PriceLevel,
845}
846
847impl OrderListPlaceOcoAbovePegOffsetTypeEnum {
848    #[must_use]
849    pub fn as_str(&self) -> &'static str {
850        match self {
851            Self::PriceLevel => "PRICE_LEVEL",
852        }
853    }
854}
855
856impl std::str::FromStr for OrderListPlaceOcoAbovePegOffsetTypeEnum {
857    type Err = Box<dyn std::error::Error + Send + Sync>;
858
859    fn from_str(s: &str) -> Result<Self, Self::Err> {
860        match s {
861            "PRICE_LEVEL" => Ok(Self::PriceLevel),
862            other => {
863                Err(format!("invalid OrderListPlaceOcoAbovePegOffsetTypeEnum: {}", other).into())
864            }
865        }
866    }
867}
868
869#[allow(non_camel_case_types)]
870#[derive(Debug, Clone, Serialize, Deserialize)]
871pub enum OrderListPlaceOcoBelowTimeInForceEnum {
872    #[serde(rename = "GTC")]
873    Gtc,
874    #[serde(rename = "IOC")]
875    Ioc,
876    #[serde(rename = "FOK")]
877    Fok,
878}
879
880impl OrderListPlaceOcoBelowTimeInForceEnum {
881    #[must_use]
882    pub fn as_str(&self) -> &'static str {
883        match self {
884            Self::Gtc => "GTC",
885            Self::Ioc => "IOC",
886            Self::Fok => "FOK",
887        }
888    }
889}
890
891impl std::str::FromStr for OrderListPlaceOcoBelowTimeInForceEnum {
892    type Err = Box<dyn std::error::Error + Send + Sync>;
893
894    fn from_str(s: &str) -> Result<Self, Self::Err> {
895        match s {
896            "GTC" => Ok(Self::Gtc),
897            "IOC" => Ok(Self::Ioc),
898            "FOK" => Ok(Self::Fok),
899            other => {
900                Err(format!("invalid OrderListPlaceOcoBelowTimeInForceEnum: {}", other).into())
901            }
902        }
903    }
904}
905
906#[allow(non_camel_case_types)]
907#[derive(Debug, Clone, Serialize, Deserialize)]
908pub enum OrderListPlaceOcoBelowPegPriceTypeEnum {
909    #[serde(rename = "PRIMARY_PEG")]
910    PrimaryPeg,
911    #[serde(rename = "MARKET_PEG")]
912    MarketPeg,
913}
914
915impl OrderListPlaceOcoBelowPegPriceTypeEnum {
916    #[must_use]
917    pub fn as_str(&self) -> &'static str {
918        match self {
919            Self::PrimaryPeg => "PRIMARY_PEG",
920            Self::MarketPeg => "MARKET_PEG",
921        }
922    }
923}
924
925impl std::str::FromStr for OrderListPlaceOcoBelowPegPriceTypeEnum {
926    type Err = Box<dyn std::error::Error + Send + Sync>;
927
928    fn from_str(s: &str) -> Result<Self, Self::Err> {
929        match s {
930            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
931            "MARKET_PEG" => Ok(Self::MarketPeg),
932            other => {
933                Err(format!("invalid OrderListPlaceOcoBelowPegPriceTypeEnum: {}", other).into())
934            }
935        }
936    }
937}
938
939#[allow(non_camel_case_types)]
940#[derive(Debug, Clone, Serialize, Deserialize)]
941pub enum OrderListPlaceOcoBelowPegOffsetTypeEnum {
942    #[serde(rename = "PRICE_LEVEL")]
943    PriceLevel,
944}
945
946impl OrderListPlaceOcoBelowPegOffsetTypeEnum {
947    #[must_use]
948    pub fn as_str(&self) -> &'static str {
949        match self {
950            Self::PriceLevel => "PRICE_LEVEL",
951        }
952    }
953}
954
955impl std::str::FromStr for OrderListPlaceOcoBelowPegOffsetTypeEnum {
956    type Err = Box<dyn std::error::Error + Send + Sync>;
957
958    fn from_str(s: &str) -> Result<Self, Self::Err> {
959        match s {
960            "PRICE_LEVEL" => Ok(Self::PriceLevel),
961            other => {
962                Err(format!("invalid OrderListPlaceOcoBelowPegOffsetTypeEnum: {}", other).into())
963            }
964        }
965    }
966}
967
968#[allow(non_camel_case_types)]
969#[derive(Debug, Clone, Serialize, Deserialize)]
970pub enum OrderListPlaceOcoNewOrderRespTypeEnum {
971    #[serde(rename = "ACK")]
972    Ack,
973    #[serde(rename = "RESULT")]
974    Result,
975    #[serde(rename = "FULL")]
976    Full,
977}
978
979impl OrderListPlaceOcoNewOrderRespTypeEnum {
980    #[must_use]
981    pub fn as_str(&self) -> &'static str {
982        match self {
983            Self::Ack => "ACK",
984            Self::Result => "RESULT",
985            Self::Full => "FULL",
986        }
987    }
988}
989
990impl std::str::FromStr for OrderListPlaceOcoNewOrderRespTypeEnum {
991    type Err = Box<dyn std::error::Error + Send + Sync>;
992
993    fn from_str(s: &str) -> Result<Self, Self::Err> {
994        match s {
995            "ACK" => Ok(Self::Ack),
996            "RESULT" => Ok(Self::Result),
997            "FULL" => Ok(Self::Full),
998            other => {
999                Err(format!("invalid OrderListPlaceOcoNewOrderRespTypeEnum: {}", other).into())
1000            }
1001        }
1002    }
1003}
1004
1005#[allow(non_camel_case_types)]
1006#[derive(Debug, Clone, Serialize, Deserialize)]
1007pub enum OrderListPlaceOcoSelfTradePreventionModeEnum {
1008    #[serde(rename = "NONE")]
1009    None,
1010    #[serde(rename = "EXPIRE_TAKER")]
1011    ExpireTaker,
1012    #[serde(rename = "EXPIRE_MAKER")]
1013    ExpireMaker,
1014    #[serde(rename = "EXPIRE_BOTH")]
1015    ExpireBoth,
1016    #[serde(rename = "DECREMENT")]
1017    Decrement,
1018    #[serde(rename = "TRANSFER")]
1019    Transfer,
1020}
1021
1022impl OrderListPlaceOcoSelfTradePreventionModeEnum {
1023    #[must_use]
1024    pub fn as_str(&self) -> &'static str {
1025        match self {
1026            Self::None => "NONE",
1027            Self::ExpireTaker => "EXPIRE_TAKER",
1028            Self::ExpireMaker => "EXPIRE_MAKER",
1029            Self::ExpireBoth => "EXPIRE_BOTH",
1030            Self::Decrement => "DECREMENT",
1031            Self::Transfer => "TRANSFER",
1032        }
1033    }
1034}
1035
1036impl std::str::FromStr for OrderListPlaceOcoSelfTradePreventionModeEnum {
1037    type Err = Box<dyn std::error::Error + Send + Sync>;
1038
1039    fn from_str(s: &str) -> Result<Self, Self::Err> {
1040        match s {
1041            "NONE" => Ok(Self::None),
1042            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
1043            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
1044            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
1045            "DECREMENT" => Ok(Self::Decrement),
1046            "TRANSFER" => Ok(Self::Transfer),
1047            other => Err(format!(
1048                "invalid OrderListPlaceOcoSelfTradePreventionModeEnum: {}",
1049                other
1050            )
1051            .into()),
1052        }
1053    }
1054}
1055
1056#[allow(non_camel_case_types)]
1057#[derive(Debug, Clone, Serialize, Deserialize)]
1058pub enum OrderListPlaceOpoWorkingTypeEnum {
1059    #[serde(rename = "LIMIT")]
1060    Limit,
1061    #[serde(rename = "LIMIT_MAKER")]
1062    LimitMaker,
1063}
1064
1065impl OrderListPlaceOpoWorkingTypeEnum {
1066    #[must_use]
1067    pub fn as_str(&self) -> &'static str {
1068        match self {
1069            Self::Limit => "LIMIT",
1070            Self::LimitMaker => "LIMIT_MAKER",
1071        }
1072    }
1073}
1074
1075impl std::str::FromStr for OrderListPlaceOpoWorkingTypeEnum {
1076    type Err = Box<dyn std::error::Error + Send + Sync>;
1077
1078    fn from_str(s: &str) -> Result<Self, Self::Err> {
1079        match s {
1080            "LIMIT" => Ok(Self::Limit),
1081            "LIMIT_MAKER" => Ok(Self::LimitMaker),
1082            other => Err(format!("invalid OrderListPlaceOpoWorkingTypeEnum: {}", other).into()),
1083        }
1084    }
1085}
1086
1087#[allow(non_camel_case_types)]
1088#[derive(Debug, Clone, Serialize, Deserialize)]
1089pub enum OrderListPlaceOpoWorkingSideEnum {
1090    #[serde(rename = "BUY")]
1091    Buy,
1092    #[serde(rename = "SELL")]
1093    Sell,
1094}
1095
1096impl OrderListPlaceOpoWorkingSideEnum {
1097    #[must_use]
1098    pub fn as_str(&self) -> &'static str {
1099        match self {
1100            Self::Buy => "BUY",
1101            Self::Sell => "SELL",
1102        }
1103    }
1104}
1105
1106impl std::str::FromStr for OrderListPlaceOpoWorkingSideEnum {
1107    type Err = Box<dyn std::error::Error + Send + Sync>;
1108
1109    fn from_str(s: &str) -> Result<Self, Self::Err> {
1110        match s {
1111            "BUY" => Ok(Self::Buy),
1112            "SELL" => Ok(Self::Sell),
1113            other => Err(format!("invalid OrderListPlaceOpoWorkingSideEnum: {}", other).into()),
1114        }
1115    }
1116}
1117
1118#[allow(non_camel_case_types)]
1119#[derive(Debug, Clone, Serialize, Deserialize)]
1120pub enum OrderListPlaceOpoPendingTypeEnum {
1121    #[serde(rename = "LIMIT")]
1122    Limit,
1123    #[serde(rename = "MARKET")]
1124    Market,
1125    #[serde(rename = "STOP_LOSS")]
1126    StopLoss,
1127    #[serde(rename = "STOP_LOSS_LIMIT")]
1128    StopLossLimit,
1129    #[serde(rename = "TAKE_PROFIT")]
1130    TakeProfit,
1131    #[serde(rename = "TAKE_PROFIT_LIMIT")]
1132    TakeProfitLimit,
1133    #[serde(rename = "LIMIT_MAKER")]
1134    LimitMaker,
1135}
1136
1137impl OrderListPlaceOpoPendingTypeEnum {
1138    #[must_use]
1139    pub fn as_str(&self) -> &'static str {
1140        match self {
1141            Self::Limit => "LIMIT",
1142            Self::Market => "MARKET",
1143            Self::StopLoss => "STOP_LOSS",
1144            Self::StopLossLimit => "STOP_LOSS_LIMIT",
1145            Self::TakeProfit => "TAKE_PROFIT",
1146            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
1147            Self::LimitMaker => "LIMIT_MAKER",
1148        }
1149    }
1150}
1151
1152impl std::str::FromStr for OrderListPlaceOpoPendingTypeEnum {
1153    type Err = Box<dyn std::error::Error + Send + Sync>;
1154
1155    fn from_str(s: &str) -> Result<Self, Self::Err> {
1156        match s {
1157            "LIMIT" => Ok(Self::Limit),
1158            "MARKET" => Ok(Self::Market),
1159            "STOP_LOSS" => Ok(Self::StopLoss),
1160            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
1161            "TAKE_PROFIT" => Ok(Self::TakeProfit),
1162            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
1163            "LIMIT_MAKER" => Ok(Self::LimitMaker),
1164            other => Err(format!("invalid OrderListPlaceOpoPendingTypeEnum: {}", other).into()),
1165        }
1166    }
1167}
1168
1169#[allow(non_camel_case_types)]
1170#[derive(Debug, Clone, Serialize, Deserialize)]
1171pub enum OrderListPlaceOpoPendingSideEnum {
1172    #[serde(rename = "BUY")]
1173    Buy,
1174    #[serde(rename = "SELL")]
1175    Sell,
1176}
1177
1178impl OrderListPlaceOpoPendingSideEnum {
1179    #[must_use]
1180    pub fn as_str(&self) -> &'static str {
1181        match self {
1182            Self::Buy => "BUY",
1183            Self::Sell => "SELL",
1184        }
1185    }
1186}
1187
1188impl std::str::FromStr for OrderListPlaceOpoPendingSideEnum {
1189    type Err = Box<dyn std::error::Error + Send + Sync>;
1190
1191    fn from_str(s: &str) -> Result<Self, Self::Err> {
1192        match s {
1193            "BUY" => Ok(Self::Buy),
1194            "SELL" => Ok(Self::Sell),
1195            other => Err(format!("invalid OrderListPlaceOpoPendingSideEnum: {}", other).into()),
1196        }
1197    }
1198}
1199
1200#[allow(non_camel_case_types)]
1201#[derive(Debug, Clone, Serialize, Deserialize)]
1202pub enum OrderListPlaceOpoNewOrderRespTypeEnum {
1203    #[serde(rename = "ACK")]
1204    Ack,
1205    #[serde(rename = "RESULT")]
1206    Result,
1207    #[serde(rename = "FULL")]
1208    Full,
1209}
1210
1211impl OrderListPlaceOpoNewOrderRespTypeEnum {
1212    #[must_use]
1213    pub fn as_str(&self) -> &'static str {
1214        match self {
1215            Self::Ack => "ACK",
1216            Self::Result => "RESULT",
1217            Self::Full => "FULL",
1218        }
1219    }
1220}
1221
1222impl std::str::FromStr for OrderListPlaceOpoNewOrderRespTypeEnum {
1223    type Err = Box<dyn std::error::Error + Send + Sync>;
1224
1225    fn from_str(s: &str) -> Result<Self, Self::Err> {
1226        match s {
1227            "ACK" => Ok(Self::Ack),
1228            "RESULT" => Ok(Self::Result),
1229            "FULL" => Ok(Self::Full),
1230            other => {
1231                Err(format!("invalid OrderListPlaceOpoNewOrderRespTypeEnum: {}", other).into())
1232            }
1233        }
1234    }
1235}
1236
1237#[allow(non_camel_case_types)]
1238#[derive(Debug, Clone, Serialize, Deserialize)]
1239pub enum OrderListPlaceOpoSelfTradePreventionModeEnum {
1240    #[serde(rename = "NONE")]
1241    None,
1242    #[serde(rename = "EXPIRE_TAKER")]
1243    ExpireTaker,
1244    #[serde(rename = "EXPIRE_MAKER")]
1245    ExpireMaker,
1246    #[serde(rename = "EXPIRE_BOTH")]
1247    ExpireBoth,
1248    #[serde(rename = "DECREMENT")]
1249    Decrement,
1250    #[serde(rename = "TRANSFER")]
1251    Transfer,
1252}
1253
1254impl OrderListPlaceOpoSelfTradePreventionModeEnum {
1255    #[must_use]
1256    pub fn as_str(&self) -> &'static str {
1257        match self {
1258            Self::None => "NONE",
1259            Self::ExpireTaker => "EXPIRE_TAKER",
1260            Self::ExpireMaker => "EXPIRE_MAKER",
1261            Self::ExpireBoth => "EXPIRE_BOTH",
1262            Self::Decrement => "DECREMENT",
1263            Self::Transfer => "TRANSFER",
1264        }
1265    }
1266}
1267
1268impl std::str::FromStr for OrderListPlaceOpoSelfTradePreventionModeEnum {
1269    type Err = Box<dyn std::error::Error + Send + Sync>;
1270
1271    fn from_str(s: &str) -> Result<Self, Self::Err> {
1272        match s {
1273            "NONE" => Ok(Self::None),
1274            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
1275            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
1276            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
1277            "DECREMENT" => Ok(Self::Decrement),
1278            "TRANSFER" => Ok(Self::Transfer),
1279            other => Err(format!(
1280                "invalid OrderListPlaceOpoSelfTradePreventionModeEnum: {}",
1281                other
1282            )
1283            .into()),
1284        }
1285    }
1286}
1287
1288#[allow(non_camel_case_types)]
1289#[derive(Debug, Clone, Serialize, Deserialize)]
1290pub enum OrderListPlaceOpoWorkingTimeInForceEnum {
1291    #[serde(rename = "GTC")]
1292    Gtc,
1293    #[serde(rename = "IOC")]
1294    Ioc,
1295    #[serde(rename = "FOK")]
1296    Fok,
1297}
1298
1299impl OrderListPlaceOpoWorkingTimeInForceEnum {
1300    #[must_use]
1301    pub fn as_str(&self) -> &'static str {
1302        match self {
1303            Self::Gtc => "GTC",
1304            Self::Ioc => "IOC",
1305            Self::Fok => "FOK",
1306        }
1307    }
1308}
1309
1310impl std::str::FromStr for OrderListPlaceOpoWorkingTimeInForceEnum {
1311    type Err = Box<dyn std::error::Error + Send + Sync>;
1312
1313    fn from_str(s: &str) -> Result<Self, Self::Err> {
1314        match s {
1315            "GTC" => Ok(Self::Gtc),
1316            "IOC" => Ok(Self::Ioc),
1317            "FOK" => Ok(Self::Fok),
1318            other => {
1319                Err(format!("invalid OrderListPlaceOpoWorkingTimeInForceEnum: {}", other).into())
1320            }
1321        }
1322    }
1323}
1324
1325#[allow(non_camel_case_types)]
1326#[derive(Debug, Clone, Serialize, Deserialize)]
1327pub enum OrderListPlaceOpoWorkingPegPriceTypeEnum {
1328    #[serde(rename = "PRIMARY_PEG")]
1329    PrimaryPeg,
1330    #[serde(rename = "MARKET_PEG")]
1331    MarketPeg,
1332}
1333
1334impl OrderListPlaceOpoWorkingPegPriceTypeEnum {
1335    #[must_use]
1336    pub fn as_str(&self) -> &'static str {
1337        match self {
1338            Self::PrimaryPeg => "PRIMARY_PEG",
1339            Self::MarketPeg => "MARKET_PEG",
1340        }
1341    }
1342}
1343
1344impl std::str::FromStr for OrderListPlaceOpoWorkingPegPriceTypeEnum {
1345    type Err = Box<dyn std::error::Error + Send + Sync>;
1346
1347    fn from_str(s: &str) -> Result<Self, Self::Err> {
1348        match s {
1349            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
1350            "MARKET_PEG" => Ok(Self::MarketPeg),
1351            other => Err(format!(
1352                "invalid OrderListPlaceOpoWorkingPegPriceTypeEnum: {}",
1353                other
1354            )
1355            .into()),
1356        }
1357    }
1358}
1359
1360#[allow(non_camel_case_types)]
1361#[derive(Debug, Clone, Serialize, Deserialize)]
1362pub enum OrderListPlaceOpoWorkingPegOffsetTypeEnum {
1363    #[serde(rename = "PRICE_LEVEL")]
1364    PriceLevel,
1365}
1366
1367impl OrderListPlaceOpoWorkingPegOffsetTypeEnum {
1368    #[must_use]
1369    pub fn as_str(&self) -> &'static str {
1370        match self {
1371            Self::PriceLevel => "PRICE_LEVEL",
1372        }
1373    }
1374}
1375
1376impl std::str::FromStr for OrderListPlaceOpoWorkingPegOffsetTypeEnum {
1377    type Err = Box<dyn std::error::Error + Send + Sync>;
1378
1379    fn from_str(s: &str) -> Result<Self, Self::Err> {
1380        match s {
1381            "PRICE_LEVEL" => Ok(Self::PriceLevel),
1382            other => Err(format!(
1383                "invalid OrderListPlaceOpoWorkingPegOffsetTypeEnum: {}",
1384                other
1385            )
1386            .into()),
1387        }
1388    }
1389}
1390
1391#[allow(non_camel_case_types)]
1392#[derive(Debug, Clone, Serialize, Deserialize)]
1393pub enum OrderListPlaceOpoPendingTimeInForceEnum {
1394    #[serde(rename = "GTC")]
1395    Gtc,
1396    #[serde(rename = "IOC")]
1397    Ioc,
1398    #[serde(rename = "FOK")]
1399    Fok,
1400}
1401
1402impl OrderListPlaceOpoPendingTimeInForceEnum {
1403    #[must_use]
1404    pub fn as_str(&self) -> &'static str {
1405        match self {
1406            Self::Gtc => "GTC",
1407            Self::Ioc => "IOC",
1408            Self::Fok => "FOK",
1409        }
1410    }
1411}
1412
1413impl std::str::FromStr for OrderListPlaceOpoPendingTimeInForceEnum {
1414    type Err = Box<dyn std::error::Error + Send + Sync>;
1415
1416    fn from_str(s: &str) -> Result<Self, Self::Err> {
1417        match s {
1418            "GTC" => Ok(Self::Gtc),
1419            "IOC" => Ok(Self::Ioc),
1420            "FOK" => Ok(Self::Fok),
1421            other => {
1422                Err(format!("invalid OrderListPlaceOpoPendingTimeInForceEnum: {}", other).into())
1423            }
1424        }
1425    }
1426}
1427
1428#[allow(non_camel_case_types)]
1429#[derive(Debug, Clone, Serialize, Deserialize)]
1430pub enum OrderListPlaceOpoPendingPegPriceTypeEnum {
1431    #[serde(rename = "PRIMARY_PEG")]
1432    PrimaryPeg,
1433    #[serde(rename = "MARKET_PEG")]
1434    MarketPeg,
1435}
1436
1437impl OrderListPlaceOpoPendingPegPriceTypeEnum {
1438    #[must_use]
1439    pub fn as_str(&self) -> &'static str {
1440        match self {
1441            Self::PrimaryPeg => "PRIMARY_PEG",
1442            Self::MarketPeg => "MARKET_PEG",
1443        }
1444    }
1445}
1446
1447impl std::str::FromStr for OrderListPlaceOpoPendingPegPriceTypeEnum {
1448    type Err = Box<dyn std::error::Error + Send + Sync>;
1449
1450    fn from_str(s: &str) -> Result<Self, Self::Err> {
1451        match s {
1452            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
1453            "MARKET_PEG" => Ok(Self::MarketPeg),
1454            other => Err(format!(
1455                "invalid OrderListPlaceOpoPendingPegPriceTypeEnum: {}",
1456                other
1457            )
1458            .into()),
1459        }
1460    }
1461}
1462
1463#[allow(non_camel_case_types)]
1464#[derive(Debug, Clone, Serialize, Deserialize)]
1465pub enum OrderListPlaceOpoPendingPegOffsetTypeEnum {
1466    #[serde(rename = "PRICE_LEVEL")]
1467    PriceLevel,
1468}
1469
1470impl OrderListPlaceOpoPendingPegOffsetTypeEnum {
1471    #[must_use]
1472    pub fn as_str(&self) -> &'static str {
1473        match self {
1474            Self::PriceLevel => "PRICE_LEVEL",
1475        }
1476    }
1477}
1478
1479impl std::str::FromStr for OrderListPlaceOpoPendingPegOffsetTypeEnum {
1480    type Err = Box<dyn std::error::Error + Send + Sync>;
1481
1482    fn from_str(s: &str) -> Result<Self, Self::Err> {
1483        match s {
1484            "PRICE_LEVEL" => Ok(Self::PriceLevel),
1485            other => Err(format!(
1486                "invalid OrderListPlaceOpoPendingPegOffsetTypeEnum: {}",
1487                other
1488            )
1489            .into()),
1490        }
1491    }
1492}
1493
1494#[allow(non_camel_case_types)]
1495#[derive(Debug, Clone, Serialize, Deserialize)]
1496pub enum OrderListPlaceOpocoWorkingTypeEnum {
1497    #[serde(rename = "LIMIT")]
1498    Limit,
1499    #[serde(rename = "LIMIT_MAKER")]
1500    LimitMaker,
1501}
1502
1503impl OrderListPlaceOpocoWorkingTypeEnum {
1504    #[must_use]
1505    pub fn as_str(&self) -> &'static str {
1506        match self {
1507            Self::Limit => "LIMIT",
1508            Self::LimitMaker => "LIMIT_MAKER",
1509        }
1510    }
1511}
1512
1513impl std::str::FromStr for OrderListPlaceOpocoWorkingTypeEnum {
1514    type Err = Box<dyn std::error::Error + Send + Sync>;
1515
1516    fn from_str(s: &str) -> Result<Self, Self::Err> {
1517        match s {
1518            "LIMIT" => Ok(Self::Limit),
1519            "LIMIT_MAKER" => Ok(Self::LimitMaker),
1520            other => Err(format!("invalid OrderListPlaceOpocoWorkingTypeEnum: {}", other).into()),
1521        }
1522    }
1523}
1524
1525#[allow(non_camel_case_types)]
1526#[derive(Debug, Clone, Serialize, Deserialize)]
1527pub enum OrderListPlaceOpocoWorkingSideEnum {
1528    #[serde(rename = "BUY")]
1529    Buy,
1530    #[serde(rename = "SELL")]
1531    Sell,
1532}
1533
1534impl OrderListPlaceOpocoWorkingSideEnum {
1535    #[must_use]
1536    pub fn as_str(&self) -> &'static str {
1537        match self {
1538            Self::Buy => "BUY",
1539            Self::Sell => "SELL",
1540        }
1541    }
1542}
1543
1544impl std::str::FromStr for OrderListPlaceOpocoWorkingSideEnum {
1545    type Err = Box<dyn std::error::Error + Send + Sync>;
1546
1547    fn from_str(s: &str) -> Result<Self, Self::Err> {
1548        match s {
1549            "BUY" => Ok(Self::Buy),
1550            "SELL" => Ok(Self::Sell),
1551            other => Err(format!("invalid OrderListPlaceOpocoWorkingSideEnum: {}", other).into()),
1552        }
1553    }
1554}
1555
1556#[allow(non_camel_case_types)]
1557#[derive(Debug, Clone, Serialize, Deserialize)]
1558pub enum OrderListPlaceOpocoPendingSideEnum {
1559    #[serde(rename = "BUY")]
1560    Buy,
1561    #[serde(rename = "SELL")]
1562    Sell,
1563}
1564
1565impl OrderListPlaceOpocoPendingSideEnum {
1566    #[must_use]
1567    pub fn as_str(&self) -> &'static str {
1568        match self {
1569            Self::Buy => "BUY",
1570            Self::Sell => "SELL",
1571        }
1572    }
1573}
1574
1575impl std::str::FromStr for OrderListPlaceOpocoPendingSideEnum {
1576    type Err = Box<dyn std::error::Error + Send + Sync>;
1577
1578    fn from_str(s: &str) -> Result<Self, Self::Err> {
1579        match s {
1580            "BUY" => Ok(Self::Buy),
1581            "SELL" => Ok(Self::Sell),
1582            other => Err(format!("invalid OrderListPlaceOpocoPendingSideEnum: {}", other).into()),
1583        }
1584    }
1585}
1586
1587#[allow(non_camel_case_types)]
1588#[derive(Debug, Clone, Serialize, Deserialize)]
1589pub enum OrderListPlaceOpocoPendingAboveTypeEnum {
1590    #[serde(rename = "STOP_LOSS_LIMIT")]
1591    StopLossLimit,
1592    #[serde(rename = "STOP_LOSS")]
1593    StopLoss,
1594    #[serde(rename = "LIMIT_MAKER")]
1595    LimitMaker,
1596    #[serde(rename = "TAKE_PROFIT")]
1597    TakeProfit,
1598    #[serde(rename = "TAKE_PROFIT_LIMIT")]
1599    TakeProfitLimit,
1600}
1601
1602impl OrderListPlaceOpocoPendingAboveTypeEnum {
1603    #[must_use]
1604    pub fn as_str(&self) -> &'static str {
1605        match self {
1606            Self::StopLossLimit => "STOP_LOSS_LIMIT",
1607            Self::StopLoss => "STOP_LOSS",
1608            Self::LimitMaker => "LIMIT_MAKER",
1609            Self::TakeProfit => "TAKE_PROFIT",
1610            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
1611        }
1612    }
1613}
1614
1615impl std::str::FromStr for OrderListPlaceOpocoPendingAboveTypeEnum {
1616    type Err = Box<dyn std::error::Error + Send + Sync>;
1617
1618    fn from_str(s: &str) -> Result<Self, Self::Err> {
1619        match s {
1620            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
1621            "STOP_LOSS" => Ok(Self::StopLoss),
1622            "LIMIT_MAKER" => Ok(Self::LimitMaker),
1623            "TAKE_PROFIT" => Ok(Self::TakeProfit),
1624            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
1625            other => {
1626                Err(format!("invalid OrderListPlaceOpocoPendingAboveTypeEnum: {}", other).into())
1627            }
1628        }
1629    }
1630}
1631
1632#[allow(non_camel_case_types)]
1633#[derive(Debug, Clone, Serialize, Deserialize)]
1634pub enum OrderListPlaceOpocoNewOrderRespTypeEnum {
1635    #[serde(rename = "ACK")]
1636    Ack,
1637    #[serde(rename = "RESULT")]
1638    Result,
1639    #[serde(rename = "FULL")]
1640    Full,
1641}
1642
1643impl OrderListPlaceOpocoNewOrderRespTypeEnum {
1644    #[must_use]
1645    pub fn as_str(&self) -> &'static str {
1646        match self {
1647            Self::Ack => "ACK",
1648            Self::Result => "RESULT",
1649            Self::Full => "FULL",
1650        }
1651    }
1652}
1653
1654impl std::str::FromStr for OrderListPlaceOpocoNewOrderRespTypeEnum {
1655    type Err = Box<dyn std::error::Error + Send + Sync>;
1656
1657    fn from_str(s: &str) -> Result<Self, Self::Err> {
1658        match s {
1659            "ACK" => Ok(Self::Ack),
1660            "RESULT" => Ok(Self::Result),
1661            "FULL" => Ok(Self::Full),
1662            other => {
1663                Err(format!("invalid OrderListPlaceOpocoNewOrderRespTypeEnum: {}", other).into())
1664            }
1665        }
1666    }
1667}
1668
1669#[allow(non_camel_case_types)]
1670#[derive(Debug, Clone, Serialize, Deserialize)]
1671pub enum OrderListPlaceOpocoSelfTradePreventionModeEnum {
1672    #[serde(rename = "NONE")]
1673    None,
1674    #[serde(rename = "EXPIRE_TAKER")]
1675    ExpireTaker,
1676    #[serde(rename = "EXPIRE_MAKER")]
1677    ExpireMaker,
1678    #[serde(rename = "EXPIRE_BOTH")]
1679    ExpireBoth,
1680    #[serde(rename = "DECREMENT")]
1681    Decrement,
1682    #[serde(rename = "TRANSFER")]
1683    Transfer,
1684}
1685
1686impl OrderListPlaceOpocoSelfTradePreventionModeEnum {
1687    #[must_use]
1688    pub fn as_str(&self) -> &'static str {
1689        match self {
1690            Self::None => "NONE",
1691            Self::ExpireTaker => "EXPIRE_TAKER",
1692            Self::ExpireMaker => "EXPIRE_MAKER",
1693            Self::ExpireBoth => "EXPIRE_BOTH",
1694            Self::Decrement => "DECREMENT",
1695            Self::Transfer => "TRANSFER",
1696        }
1697    }
1698}
1699
1700impl std::str::FromStr for OrderListPlaceOpocoSelfTradePreventionModeEnum {
1701    type Err = Box<dyn std::error::Error + Send + Sync>;
1702
1703    fn from_str(s: &str) -> Result<Self, Self::Err> {
1704        match s {
1705            "NONE" => Ok(Self::None),
1706            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
1707            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
1708            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
1709            "DECREMENT" => Ok(Self::Decrement),
1710            "TRANSFER" => Ok(Self::Transfer),
1711            other => Err(format!(
1712                "invalid OrderListPlaceOpocoSelfTradePreventionModeEnum: {}",
1713                other
1714            )
1715            .into()),
1716        }
1717    }
1718}
1719
1720#[allow(non_camel_case_types)]
1721#[derive(Debug, Clone, Serialize, Deserialize)]
1722pub enum OrderListPlaceOpocoWorkingTimeInForceEnum {
1723    #[serde(rename = "GTC")]
1724    Gtc,
1725    #[serde(rename = "IOC")]
1726    Ioc,
1727    #[serde(rename = "FOK")]
1728    Fok,
1729}
1730
1731impl OrderListPlaceOpocoWorkingTimeInForceEnum {
1732    #[must_use]
1733    pub fn as_str(&self) -> &'static str {
1734        match self {
1735            Self::Gtc => "GTC",
1736            Self::Ioc => "IOC",
1737            Self::Fok => "FOK",
1738        }
1739    }
1740}
1741
1742impl std::str::FromStr for OrderListPlaceOpocoWorkingTimeInForceEnum {
1743    type Err = Box<dyn std::error::Error + Send + Sync>;
1744
1745    fn from_str(s: &str) -> Result<Self, Self::Err> {
1746        match s {
1747            "GTC" => Ok(Self::Gtc),
1748            "IOC" => Ok(Self::Ioc),
1749            "FOK" => Ok(Self::Fok),
1750            other => Err(format!(
1751                "invalid OrderListPlaceOpocoWorkingTimeInForceEnum: {}",
1752                other
1753            )
1754            .into()),
1755        }
1756    }
1757}
1758
1759#[allow(non_camel_case_types)]
1760#[derive(Debug, Clone, Serialize, Deserialize)]
1761pub enum OrderListPlaceOpocoWorkingPegPriceTypeEnum {
1762    #[serde(rename = "PRIMARY_PEG")]
1763    PrimaryPeg,
1764    #[serde(rename = "MARKET_PEG")]
1765    MarketPeg,
1766}
1767
1768impl OrderListPlaceOpocoWorkingPegPriceTypeEnum {
1769    #[must_use]
1770    pub fn as_str(&self) -> &'static str {
1771        match self {
1772            Self::PrimaryPeg => "PRIMARY_PEG",
1773            Self::MarketPeg => "MARKET_PEG",
1774        }
1775    }
1776}
1777
1778impl std::str::FromStr for OrderListPlaceOpocoWorkingPegPriceTypeEnum {
1779    type Err = Box<dyn std::error::Error + Send + Sync>;
1780
1781    fn from_str(s: &str) -> Result<Self, Self::Err> {
1782        match s {
1783            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
1784            "MARKET_PEG" => Ok(Self::MarketPeg),
1785            other => Err(format!(
1786                "invalid OrderListPlaceOpocoWorkingPegPriceTypeEnum: {}",
1787                other
1788            )
1789            .into()),
1790        }
1791    }
1792}
1793
1794#[allow(non_camel_case_types)]
1795#[derive(Debug, Clone, Serialize, Deserialize)]
1796pub enum OrderListPlaceOpocoWorkingPegOffsetTypeEnum {
1797    #[serde(rename = "PRICE_LEVEL")]
1798    PriceLevel,
1799}
1800
1801impl OrderListPlaceOpocoWorkingPegOffsetTypeEnum {
1802    #[must_use]
1803    pub fn as_str(&self) -> &'static str {
1804        match self {
1805            Self::PriceLevel => "PRICE_LEVEL",
1806        }
1807    }
1808}
1809
1810impl std::str::FromStr for OrderListPlaceOpocoWorkingPegOffsetTypeEnum {
1811    type Err = Box<dyn std::error::Error + Send + Sync>;
1812
1813    fn from_str(s: &str) -> Result<Self, Self::Err> {
1814        match s {
1815            "PRICE_LEVEL" => Ok(Self::PriceLevel),
1816            other => Err(format!(
1817                "invalid OrderListPlaceOpocoWorkingPegOffsetTypeEnum: {}",
1818                other
1819            )
1820            .into()),
1821        }
1822    }
1823}
1824
1825#[allow(non_camel_case_types)]
1826#[derive(Debug, Clone, Serialize, Deserialize)]
1827pub enum OrderListPlaceOpocoPendingAboveTimeInForceEnum {
1828    #[serde(rename = "GTC")]
1829    Gtc,
1830    #[serde(rename = "IOC")]
1831    Ioc,
1832    #[serde(rename = "FOK")]
1833    Fok,
1834}
1835
1836impl OrderListPlaceOpocoPendingAboveTimeInForceEnum {
1837    #[must_use]
1838    pub fn as_str(&self) -> &'static str {
1839        match self {
1840            Self::Gtc => "GTC",
1841            Self::Ioc => "IOC",
1842            Self::Fok => "FOK",
1843        }
1844    }
1845}
1846
1847impl std::str::FromStr for OrderListPlaceOpocoPendingAboveTimeInForceEnum {
1848    type Err = Box<dyn std::error::Error + Send + Sync>;
1849
1850    fn from_str(s: &str) -> Result<Self, Self::Err> {
1851        match s {
1852            "GTC" => Ok(Self::Gtc),
1853            "IOC" => Ok(Self::Ioc),
1854            "FOK" => Ok(Self::Fok),
1855            other => Err(format!(
1856                "invalid OrderListPlaceOpocoPendingAboveTimeInForceEnum: {}",
1857                other
1858            )
1859            .into()),
1860        }
1861    }
1862}
1863
1864#[allow(non_camel_case_types)]
1865#[derive(Debug, Clone, Serialize, Deserialize)]
1866pub enum OrderListPlaceOpocoPendingAbovePegPriceTypeEnum {
1867    #[serde(rename = "PRIMARY_PEG")]
1868    PrimaryPeg,
1869    #[serde(rename = "MARKET_PEG")]
1870    MarketPeg,
1871}
1872
1873impl OrderListPlaceOpocoPendingAbovePegPriceTypeEnum {
1874    #[must_use]
1875    pub fn as_str(&self) -> &'static str {
1876        match self {
1877            Self::PrimaryPeg => "PRIMARY_PEG",
1878            Self::MarketPeg => "MARKET_PEG",
1879        }
1880    }
1881}
1882
1883impl std::str::FromStr for OrderListPlaceOpocoPendingAbovePegPriceTypeEnum {
1884    type Err = Box<dyn std::error::Error + Send + Sync>;
1885
1886    fn from_str(s: &str) -> Result<Self, Self::Err> {
1887        match s {
1888            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
1889            "MARKET_PEG" => Ok(Self::MarketPeg),
1890            other => Err(format!(
1891                "invalid OrderListPlaceOpocoPendingAbovePegPriceTypeEnum: {}",
1892                other
1893            )
1894            .into()),
1895        }
1896    }
1897}
1898
1899#[allow(non_camel_case_types)]
1900#[derive(Debug, Clone, Serialize, Deserialize)]
1901pub enum OrderListPlaceOpocoPendingAbovePegOffsetTypeEnum {
1902    #[serde(rename = "PRICE_LEVEL")]
1903    PriceLevel,
1904}
1905
1906impl OrderListPlaceOpocoPendingAbovePegOffsetTypeEnum {
1907    #[must_use]
1908    pub fn as_str(&self) -> &'static str {
1909        match self {
1910            Self::PriceLevel => "PRICE_LEVEL",
1911        }
1912    }
1913}
1914
1915impl std::str::FromStr for OrderListPlaceOpocoPendingAbovePegOffsetTypeEnum {
1916    type Err = Box<dyn std::error::Error + Send + Sync>;
1917
1918    fn from_str(s: &str) -> Result<Self, Self::Err> {
1919        match s {
1920            "PRICE_LEVEL" => Ok(Self::PriceLevel),
1921            other => Err(format!(
1922                "invalid OrderListPlaceOpocoPendingAbovePegOffsetTypeEnum: {}",
1923                other
1924            )
1925            .into()),
1926        }
1927    }
1928}
1929
1930#[allow(non_camel_case_types)]
1931#[derive(Debug, Clone, Serialize, Deserialize)]
1932pub enum OrderListPlaceOpocoPendingBelowTypeEnum {
1933    #[serde(rename = "STOP_LOSS")]
1934    StopLoss,
1935    #[serde(rename = "STOP_LOSS_LIMIT")]
1936    StopLossLimit,
1937    #[serde(rename = "TAKE_PROFIT")]
1938    TakeProfit,
1939    #[serde(rename = "TAKE_PROFIT_LIMIT")]
1940    TakeProfitLimit,
1941}
1942
1943impl OrderListPlaceOpocoPendingBelowTypeEnum {
1944    #[must_use]
1945    pub fn as_str(&self) -> &'static str {
1946        match self {
1947            Self::StopLoss => "STOP_LOSS",
1948            Self::StopLossLimit => "STOP_LOSS_LIMIT",
1949            Self::TakeProfit => "TAKE_PROFIT",
1950            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
1951        }
1952    }
1953}
1954
1955impl std::str::FromStr for OrderListPlaceOpocoPendingBelowTypeEnum {
1956    type Err = Box<dyn std::error::Error + Send + Sync>;
1957
1958    fn from_str(s: &str) -> Result<Self, Self::Err> {
1959        match s {
1960            "STOP_LOSS" => Ok(Self::StopLoss),
1961            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
1962            "TAKE_PROFIT" => Ok(Self::TakeProfit),
1963            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
1964            other => {
1965                Err(format!("invalid OrderListPlaceOpocoPendingBelowTypeEnum: {}", other).into())
1966            }
1967        }
1968    }
1969}
1970
1971#[allow(non_camel_case_types)]
1972#[derive(Debug, Clone, Serialize, Deserialize)]
1973pub enum OrderListPlaceOpocoPendingBelowTimeInForceEnum {
1974    #[serde(rename = "GTC")]
1975    Gtc,
1976    #[serde(rename = "IOC")]
1977    Ioc,
1978    #[serde(rename = "FOK")]
1979    Fok,
1980}
1981
1982impl OrderListPlaceOpocoPendingBelowTimeInForceEnum {
1983    #[must_use]
1984    pub fn as_str(&self) -> &'static str {
1985        match self {
1986            Self::Gtc => "GTC",
1987            Self::Ioc => "IOC",
1988            Self::Fok => "FOK",
1989        }
1990    }
1991}
1992
1993impl std::str::FromStr for OrderListPlaceOpocoPendingBelowTimeInForceEnum {
1994    type Err = Box<dyn std::error::Error + Send + Sync>;
1995
1996    fn from_str(s: &str) -> Result<Self, Self::Err> {
1997        match s {
1998            "GTC" => Ok(Self::Gtc),
1999            "IOC" => Ok(Self::Ioc),
2000            "FOK" => Ok(Self::Fok),
2001            other => Err(format!(
2002                "invalid OrderListPlaceOpocoPendingBelowTimeInForceEnum: {}",
2003                other
2004            )
2005            .into()),
2006        }
2007    }
2008}
2009
2010#[allow(non_camel_case_types)]
2011#[derive(Debug, Clone, Serialize, Deserialize)]
2012pub enum OrderListPlaceOpocoPendingBelowPegPriceTypeEnum {
2013    #[serde(rename = "PRIMARY_PEG")]
2014    PrimaryPeg,
2015    #[serde(rename = "MARKET_PEG")]
2016    MarketPeg,
2017}
2018
2019impl OrderListPlaceOpocoPendingBelowPegPriceTypeEnum {
2020    #[must_use]
2021    pub fn as_str(&self) -> &'static str {
2022        match self {
2023            Self::PrimaryPeg => "PRIMARY_PEG",
2024            Self::MarketPeg => "MARKET_PEG",
2025        }
2026    }
2027}
2028
2029impl std::str::FromStr for OrderListPlaceOpocoPendingBelowPegPriceTypeEnum {
2030    type Err = Box<dyn std::error::Error + Send + Sync>;
2031
2032    fn from_str(s: &str) -> Result<Self, Self::Err> {
2033        match s {
2034            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
2035            "MARKET_PEG" => Ok(Self::MarketPeg),
2036            other => Err(format!(
2037                "invalid OrderListPlaceOpocoPendingBelowPegPriceTypeEnum: {}",
2038                other
2039            )
2040            .into()),
2041        }
2042    }
2043}
2044
2045#[allow(non_camel_case_types)]
2046#[derive(Debug, Clone, Serialize, Deserialize)]
2047pub enum OrderListPlaceOpocoPendingBelowPegOffsetTypeEnum {
2048    #[serde(rename = "PRICE_LEVEL")]
2049    PriceLevel,
2050}
2051
2052impl OrderListPlaceOpocoPendingBelowPegOffsetTypeEnum {
2053    #[must_use]
2054    pub fn as_str(&self) -> &'static str {
2055        match self {
2056            Self::PriceLevel => "PRICE_LEVEL",
2057        }
2058    }
2059}
2060
2061impl std::str::FromStr for OrderListPlaceOpocoPendingBelowPegOffsetTypeEnum {
2062    type Err = Box<dyn std::error::Error + Send + Sync>;
2063
2064    fn from_str(s: &str) -> Result<Self, Self::Err> {
2065        match s {
2066            "PRICE_LEVEL" => Ok(Self::PriceLevel),
2067            other => Err(format!(
2068                "invalid OrderListPlaceOpocoPendingBelowPegOffsetTypeEnum: {}",
2069                other
2070            )
2071            .into()),
2072        }
2073    }
2074}
2075
2076#[allow(non_camel_case_types)]
2077#[derive(Debug, Clone, Serialize, Deserialize)]
2078pub enum OrderListPlaceOtoWorkingTypeEnum {
2079    #[serde(rename = "LIMIT")]
2080    Limit,
2081    #[serde(rename = "LIMIT_MAKER")]
2082    LimitMaker,
2083}
2084
2085impl OrderListPlaceOtoWorkingTypeEnum {
2086    #[must_use]
2087    pub fn as_str(&self) -> &'static str {
2088        match self {
2089            Self::Limit => "LIMIT",
2090            Self::LimitMaker => "LIMIT_MAKER",
2091        }
2092    }
2093}
2094
2095impl std::str::FromStr for OrderListPlaceOtoWorkingTypeEnum {
2096    type Err = Box<dyn std::error::Error + Send + Sync>;
2097
2098    fn from_str(s: &str) -> Result<Self, Self::Err> {
2099        match s {
2100            "LIMIT" => Ok(Self::Limit),
2101            "LIMIT_MAKER" => Ok(Self::LimitMaker),
2102            other => Err(format!("invalid OrderListPlaceOtoWorkingTypeEnum: {}", other).into()),
2103        }
2104    }
2105}
2106
2107#[allow(non_camel_case_types)]
2108#[derive(Debug, Clone, Serialize, Deserialize)]
2109pub enum OrderListPlaceOtoWorkingSideEnum {
2110    #[serde(rename = "BUY")]
2111    Buy,
2112    #[serde(rename = "SELL")]
2113    Sell,
2114}
2115
2116impl OrderListPlaceOtoWorkingSideEnum {
2117    #[must_use]
2118    pub fn as_str(&self) -> &'static str {
2119        match self {
2120            Self::Buy => "BUY",
2121            Self::Sell => "SELL",
2122        }
2123    }
2124}
2125
2126impl std::str::FromStr for OrderListPlaceOtoWorkingSideEnum {
2127    type Err = Box<dyn std::error::Error + Send + Sync>;
2128
2129    fn from_str(s: &str) -> Result<Self, Self::Err> {
2130        match s {
2131            "BUY" => Ok(Self::Buy),
2132            "SELL" => Ok(Self::Sell),
2133            other => Err(format!("invalid OrderListPlaceOtoWorkingSideEnum: {}", other).into()),
2134        }
2135    }
2136}
2137
2138#[allow(non_camel_case_types)]
2139#[derive(Debug, Clone, Serialize, Deserialize)]
2140pub enum OrderListPlaceOtoPendingTypeEnum {
2141    #[serde(rename = "LIMIT")]
2142    Limit,
2143    #[serde(rename = "MARKET")]
2144    Market,
2145    #[serde(rename = "STOP_LOSS")]
2146    StopLoss,
2147    #[serde(rename = "STOP_LOSS_LIMIT")]
2148    StopLossLimit,
2149    #[serde(rename = "TAKE_PROFIT")]
2150    TakeProfit,
2151    #[serde(rename = "TAKE_PROFIT_LIMIT")]
2152    TakeProfitLimit,
2153    #[serde(rename = "LIMIT_MAKER")]
2154    LimitMaker,
2155}
2156
2157impl OrderListPlaceOtoPendingTypeEnum {
2158    #[must_use]
2159    pub fn as_str(&self) -> &'static str {
2160        match self {
2161            Self::Limit => "LIMIT",
2162            Self::Market => "MARKET",
2163            Self::StopLoss => "STOP_LOSS",
2164            Self::StopLossLimit => "STOP_LOSS_LIMIT",
2165            Self::TakeProfit => "TAKE_PROFIT",
2166            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
2167            Self::LimitMaker => "LIMIT_MAKER",
2168        }
2169    }
2170}
2171
2172impl std::str::FromStr for OrderListPlaceOtoPendingTypeEnum {
2173    type Err = Box<dyn std::error::Error + Send + Sync>;
2174
2175    fn from_str(s: &str) -> Result<Self, Self::Err> {
2176        match s {
2177            "LIMIT" => Ok(Self::Limit),
2178            "MARKET" => Ok(Self::Market),
2179            "STOP_LOSS" => Ok(Self::StopLoss),
2180            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
2181            "TAKE_PROFIT" => Ok(Self::TakeProfit),
2182            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
2183            "LIMIT_MAKER" => Ok(Self::LimitMaker),
2184            other => Err(format!("invalid OrderListPlaceOtoPendingTypeEnum: {}", other).into()),
2185        }
2186    }
2187}
2188
2189#[allow(non_camel_case_types)]
2190#[derive(Debug, Clone, Serialize, Deserialize)]
2191pub enum OrderListPlaceOtoPendingSideEnum {
2192    #[serde(rename = "BUY")]
2193    Buy,
2194    #[serde(rename = "SELL")]
2195    Sell,
2196}
2197
2198impl OrderListPlaceOtoPendingSideEnum {
2199    #[must_use]
2200    pub fn as_str(&self) -> &'static str {
2201        match self {
2202            Self::Buy => "BUY",
2203            Self::Sell => "SELL",
2204        }
2205    }
2206}
2207
2208impl std::str::FromStr for OrderListPlaceOtoPendingSideEnum {
2209    type Err = Box<dyn std::error::Error + Send + Sync>;
2210
2211    fn from_str(s: &str) -> Result<Self, Self::Err> {
2212        match s {
2213            "BUY" => Ok(Self::Buy),
2214            "SELL" => Ok(Self::Sell),
2215            other => Err(format!("invalid OrderListPlaceOtoPendingSideEnum: {}", other).into()),
2216        }
2217    }
2218}
2219
2220#[allow(non_camel_case_types)]
2221#[derive(Debug, Clone, Serialize, Deserialize)]
2222pub enum OrderListPlaceOtoNewOrderRespTypeEnum {
2223    #[serde(rename = "ACK")]
2224    Ack,
2225    #[serde(rename = "RESULT")]
2226    Result,
2227    #[serde(rename = "FULL")]
2228    Full,
2229}
2230
2231impl OrderListPlaceOtoNewOrderRespTypeEnum {
2232    #[must_use]
2233    pub fn as_str(&self) -> &'static str {
2234        match self {
2235            Self::Ack => "ACK",
2236            Self::Result => "RESULT",
2237            Self::Full => "FULL",
2238        }
2239    }
2240}
2241
2242impl std::str::FromStr for OrderListPlaceOtoNewOrderRespTypeEnum {
2243    type Err = Box<dyn std::error::Error + Send + Sync>;
2244
2245    fn from_str(s: &str) -> Result<Self, Self::Err> {
2246        match s {
2247            "ACK" => Ok(Self::Ack),
2248            "RESULT" => Ok(Self::Result),
2249            "FULL" => Ok(Self::Full),
2250            other => {
2251                Err(format!("invalid OrderListPlaceOtoNewOrderRespTypeEnum: {}", other).into())
2252            }
2253        }
2254    }
2255}
2256
2257#[allow(non_camel_case_types)]
2258#[derive(Debug, Clone, Serialize, Deserialize)]
2259pub enum OrderListPlaceOtoSelfTradePreventionModeEnum {
2260    #[serde(rename = "NONE")]
2261    None,
2262    #[serde(rename = "EXPIRE_TAKER")]
2263    ExpireTaker,
2264    #[serde(rename = "EXPIRE_MAKER")]
2265    ExpireMaker,
2266    #[serde(rename = "EXPIRE_BOTH")]
2267    ExpireBoth,
2268    #[serde(rename = "DECREMENT")]
2269    Decrement,
2270    #[serde(rename = "TRANSFER")]
2271    Transfer,
2272}
2273
2274impl OrderListPlaceOtoSelfTradePreventionModeEnum {
2275    #[must_use]
2276    pub fn as_str(&self) -> &'static str {
2277        match self {
2278            Self::None => "NONE",
2279            Self::ExpireTaker => "EXPIRE_TAKER",
2280            Self::ExpireMaker => "EXPIRE_MAKER",
2281            Self::ExpireBoth => "EXPIRE_BOTH",
2282            Self::Decrement => "DECREMENT",
2283            Self::Transfer => "TRANSFER",
2284        }
2285    }
2286}
2287
2288impl std::str::FromStr for OrderListPlaceOtoSelfTradePreventionModeEnum {
2289    type Err = Box<dyn std::error::Error + Send + Sync>;
2290
2291    fn from_str(s: &str) -> Result<Self, Self::Err> {
2292        match s {
2293            "NONE" => Ok(Self::None),
2294            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
2295            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
2296            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
2297            "DECREMENT" => Ok(Self::Decrement),
2298            "TRANSFER" => Ok(Self::Transfer),
2299            other => Err(format!(
2300                "invalid OrderListPlaceOtoSelfTradePreventionModeEnum: {}",
2301                other
2302            )
2303            .into()),
2304        }
2305    }
2306}
2307
2308#[allow(non_camel_case_types)]
2309#[derive(Debug, Clone, Serialize, Deserialize)]
2310pub enum OrderListPlaceOtoWorkingTimeInForceEnum {
2311    #[serde(rename = "GTC")]
2312    Gtc,
2313    #[serde(rename = "IOC")]
2314    Ioc,
2315    #[serde(rename = "FOK")]
2316    Fok,
2317}
2318
2319impl OrderListPlaceOtoWorkingTimeInForceEnum {
2320    #[must_use]
2321    pub fn as_str(&self) -> &'static str {
2322        match self {
2323            Self::Gtc => "GTC",
2324            Self::Ioc => "IOC",
2325            Self::Fok => "FOK",
2326        }
2327    }
2328}
2329
2330impl std::str::FromStr for OrderListPlaceOtoWorkingTimeInForceEnum {
2331    type Err = Box<dyn std::error::Error + Send + Sync>;
2332
2333    fn from_str(s: &str) -> Result<Self, Self::Err> {
2334        match s {
2335            "GTC" => Ok(Self::Gtc),
2336            "IOC" => Ok(Self::Ioc),
2337            "FOK" => Ok(Self::Fok),
2338            other => {
2339                Err(format!("invalid OrderListPlaceOtoWorkingTimeInForceEnum: {}", other).into())
2340            }
2341        }
2342    }
2343}
2344
2345#[allow(non_camel_case_types)]
2346#[derive(Debug, Clone, Serialize, Deserialize)]
2347pub enum OrderListPlaceOtoWorkingPegPriceTypeEnum {
2348    #[serde(rename = "PRIMARY_PEG")]
2349    PrimaryPeg,
2350    #[serde(rename = "MARKET_PEG")]
2351    MarketPeg,
2352}
2353
2354impl OrderListPlaceOtoWorkingPegPriceTypeEnum {
2355    #[must_use]
2356    pub fn as_str(&self) -> &'static str {
2357        match self {
2358            Self::PrimaryPeg => "PRIMARY_PEG",
2359            Self::MarketPeg => "MARKET_PEG",
2360        }
2361    }
2362}
2363
2364impl std::str::FromStr for OrderListPlaceOtoWorkingPegPriceTypeEnum {
2365    type Err = Box<dyn std::error::Error + Send + Sync>;
2366
2367    fn from_str(s: &str) -> Result<Self, Self::Err> {
2368        match s {
2369            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
2370            "MARKET_PEG" => Ok(Self::MarketPeg),
2371            other => Err(format!(
2372                "invalid OrderListPlaceOtoWorkingPegPriceTypeEnum: {}",
2373                other
2374            )
2375            .into()),
2376        }
2377    }
2378}
2379
2380#[allow(non_camel_case_types)]
2381#[derive(Debug, Clone, Serialize, Deserialize)]
2382pub enum OrderListPlaceOtoWorkingPegOffsetTypeEnum {
2383    #[serde(rename = "PRICE_LEVEL")]
2384    PriceLevel,
2385}
2386
2387impl OrderListPlaceOtoWorkingPegOffsetTypeEnum {
2388    #[must_use]
2389    pub fn as_str(&self) -> &'static str {
2390        match self {
2391            Self::PriceLevel => "PRICE_LEVEL",
2392        }
2393    }
2394}
2395
2396impl std::str::FromStr for OrderListPlaceOtoWorkingPegOffsetTypeEnum {
2397    type Err = Box<dyn std::error::Error + Send + Sync>;
2398
2399    fn from_str(s: &str) -> Result<Self, Self::Err> {
2400        match s {
2401            "PRICE_LEVEL" => Ok(Self::PriceLevel),
2402            other => Err(format!(
2403                "invalid OrderListPlaceOtoWorkingPegOffsetTypeEnum: {}",
2404                other
2405            )
2406            .into()),
2407        }
2408    }
2409}
2410
2411#[allow(non_camel_case_types)]
2412#[derive(Debug, Clone, Serialize, Deserialize)]
2413pub enum OrderListPlaceOtoPendingTimeInForceEnum {
2414    #[serde(rename = "GTC")]
2415    Gtc,
2416    #[serde(rename = "IOC")]
2417    Ioc,
2418    #[serde(rename = "FOK")]
2419    Fok,
2420}
2421
2422impl OrderListPlaceOtoPendingTimeInForceEnum {
2423    #[must_use]
2424    pub fn as_str(&self) -> &'static str {
2425        match self {
2426            Self::Gtc => "GTC",
2427            Self::Ioc => "IOC",
2428            Self::Fok => "FOK",
2429        }
2430    }
2431}
2432
2433impl std::str::FromStr for OrderListPlaceOtoPendingTimeInForceEnum {
2434    type Err = Box<dyn std::error::Error + Send + Sync>;
2435
2436    fn from_str(s: &str) -> Result<Self, Self::Err> {
2437        match s {
2438            "GTC" => Ok(Self::Gtc),
2439            "IOC" => Ok(Self::Ioc),
2440            "FOK" => Ok(Self::Fok),
2441            other => {
2442                Err(format!("invalid OrderListPlaceOtoPendingTimeInForceEnum: {}", other).into())
2443            }
2444        }
2445    }
2446}
2447
2448#[allow(non_camel_case_types)]
2449#[derive(Debug, Clone, Serialize, Deserialize)]
2450pub enum OrderListPlaceOtoPendingPegOffsetTypeEnum {
2451    #[serde(rename = "PRICE_LEVEL")]
2452    PriceLevel,
2453}
2454
2455impl OrderListPlaceOtoPendingPegOffsetTypeEnum {
2456    #[must_use]
2457    pub fn as_str(&self) -> &'static str {
2458        match self {
2459            Self::PriceLevel => "PRICE_LEVEL",
2460        }
2461    }
2462}
2463
2464impl std::str::FromStr for OrderListPlaceOtoPendingPegOffsetTypeEnum {
2465    type Err = Box<dyn std::error::Error + Send + Sync>;
2466
2467    fn from_str(s: &str) -> Result<Self, Self::Err> {
2468        match s {
2469            "PRICE_LEVEL" => Ok(Self::PriceLevel),
2470            other => Err(format!(
2471                "invalid OrderListPlaceOtoPendingPegOffsetTypeEnum: {}",
2472                other
2473            )
2474            .into()),
2475        }
2476    }
2477}
2478
2479#[allow(non_camel_case_types)]
2480#[derive(Debug, Clone, Serialize, Deserialize)]
2481pub enum OrderListPlaceOtoPendingPegPriceTypeEnum {
2482    #[serde(rename = "PRIMARY_PEG")]
2483    PrimaryPeg,
2484    #[serde(rename = "MARKET_PEG")]
2485    MarketPeg,
2486}
2487
2488impl OrderListPlaceOtoPendingPegPriceTypeEnum {
2489    #[must_use]
2490    pub fn as_str(&self) -> &'static str {
2491        match self {
2492            Self::PrimaryPeg => "PRIMARY_PEG",
2493            Self::MarketPeg => "MARKET_PEG",
2494        }
2495    }
2496}
2497
2498impl std::str::FromStr for OrderListPlaceOtoPendingPegPriceTypeEnum {
2499    type Err = Box<dyn std::error::Error + Send + Sync>;
2500
2501    fn from_str(s: &str) -> Result<Self, Self::Err> {
2502        match s {
2503            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
2504            "MARKET_PEG" => Ok(Self::MarketPeg),
2505            other => Err(format!(
2506                "invalid OrderListPlaceOtoPendingPegPriceTypeEnum: {}",
2507                other
2508            )
2509            .into()),
2510        }
2511    }
2512}
2513
2514#[allow(non_camel_case_types)]
2515#[derive(Debug, Clone, Serialize, Deserialize)]
2516pub enum OrderListPlaceOtocoWorkingTypeEnum {
2517    #[serde(rename = "LIMIT")]
2518    Limit,
2519    #[serde(rename = "LIMIT_MAKER")]
2520    LimitMaker,
2521}
2522
2523impl OrderListPlaceOtocoWorkingTypeEnum {
2524    #[must_use]
2525    pub fn as_str(&self) -> &'static str {
2526        match self {
2527            Self::Limit => "LIMIT",
2528            Self::LimitMaker => "LIMIT_MAKER",
2529        }
2530    }
2531}
2532
2533impl std::str::FromStr for OrderListPlaceOtocoWorkingTypeEnum {
2534    type Err = Box<dyn std::error::Error + Send + Sync>;
2535
2536    fn from_str(s: &str) -> Result<Self, Self::Err> {
2537        match s {
2538            "LIMIT" => Ok(Self::Limit),
2539            "LIMIT_MAKER" => Ok(Self::LimitMaker),
2540            other => Err(format!("invalid OrderListPlaceOtocoWorkingTypeEnum: {}", other).into()),
2541        }
2542    }
2543}
2544
2545#[allow(non_camel_case_types)]
2546#[derive(Debug, Clone, Serialize, Deserialize)]
2547pub enum OrderListPlaceOtocoWorkingSideEnum {
2548    #[serde(rename = "BUY")]
2549    Buy,
2550    #[serde(rename = "SELL")]
2551    Sell,
2552}
2553
2554impl OrderListPlaceOtocoWorkingSideEnum {
2555    #[must_use]
2556    pub fn as_str(&self) -> &'static str {
2557        match self {
2558            Self::Buy => "BUY",
2559            Self::Sell => "SELL",
2560        }
2561    }
2562}
2563
2564impl std::str::FromStr for OrderListPlaceOtocoWorkingSideEnum {
2565    type Err = Box<dyn std::error::Error + Send + Sync>;
2566
2567    fn from_str(s: &str) -> Result<Self, Self::Err> {
2568        match s {
2569            "BUY" => Ok(Self::Buy),
2570            "SELL" => Ok(Self::Sell),
2571            other => Err(format!("invalid OrderListPlaceOtocoWorkingSideEnum: {}", other).into()),
2572        }
2573    }
2574}
2575
2576#[allow(non_camel_case_types)]
2577#[derive(Debug, Clone, Serialize, Deserialize)]
2578pub enum OrderListPlaceOtocoPendingSideEnum {
2579    #[serde(rename = "BUY")]
2580    Buy,
2581    #[serde(rename = "SELL")]
2582    Sell,
2583}
2584
2585impl OrderListPlaceOtocoPendingSideEnum {
2586    #[must_use]
2587    pub fn as_str(&self) -> &'static str {
2588        match self {
2589            Self::Buy => "BUY",
2590            Self::Sell => "SELL",
2591        }
2592    }
2593}
2594
2595impl std::str::FromStr for OrderListPlaceOtocoPendingSideEnum {
2596    type Err = Box<dyn std::error::Error + Send + Sync>;
2597
2598    fn from_str(s: &str) -> Result<Self, Self::Err> {
2599        match s {
2600            "BUY" => Ok(Self::Buy),
2601            "SELL" => Ok(Self::Sell),
2602            other => Err(format!("invalid OrderListPlaceOtocoPendingSideEnum: {}", other).into()),
2603        }
2604    }
2605}
2606
2607#[allow(non_camel_case_types)]
2608#[derive(Debug, Clone, Serialize, Deserialize)]
2609pub enum OrderListPlaceOtocoPendingAboveTypeEnum {
2610    #[serde(rename = "STOP_LOSS_LIMIT")]
2611    StopLossLimit,
2612    #[serde(rename = "STOP_LOSS")]
2613    StopLoss,
2614    #[serde(rename = "LIMIT_MAKER")]
2615    LimitMaker,
2616    #[serde(rename = "TAKE_PROFIT")]
2617    TakeProfit,
2618    #[serde(rename = "TAKE_PROFIT_LIMIT")]
2619    TakeProfitLimit,
2620}
2621
2622impl OrderListPlaceOtocoPendingAboveTypeEnum {
2623    #[must_use]
2624    pub fn as_str(&self) -> &'static str {
2625        match self {
2626            Self::StopLossLimit => "STOP_LOSS_LIMIT",
2627            Self::StopLoss => "STOP_LOSS",
2628            Self::LimitMaker => "LIMIT_MAKER",
2629            Self::TakeProfit => "TAKE_PROFIT",
2630            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
2631        }
2632    }
2633}
2634
2635impl std::str::FromStr for OrderListPlaceOtocoPendingAboveTypeEnum {
2636    type Err = Box<dyn std::error::Error + Send + Sync>;
2637
2638    fn from_str(s: &str) -> Result<Self, Self::Err> {
2639        match s {
2640            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
2641            "STOP_LOSS" => Ok(Self::StopLoss),
2642            "LIMIT_MAKER" => Ok(Self::LimitMaker),
2643            "TAKE_PROFIT" => Ok(Self::TakeProfit),
2644            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
2645            other => {
2646                Err(format!("invalid OrderListPlaceOtocoPendingAboveTypeEnum: {}", other).into())
2647            }
2648        }
2649    }
2650}
2651
2652#[allow(non_camel_case_types)]
2653#[derive(Debug, Clone, Serialize, Deserialize)]
2654pub enum OrderListPlaceOtocoNewOrderRespTypeEnum {
2655    #[serde(rename = "ACK")]
2656    Ack,
2657    #[serde(rename = "RESULT")]
2658    Result,
2659    #[serde(rename = "FULL")]
2660    Full,
2661}
2662
2663impl OrderListPlaceOtocoNewOrderRespTypeEnum {
2664    #[must_use]
2665    pub fn as_str(&self) -> &'static str {
2666        match self {
2667            Self::Ack => "ACK",
2668            Self::Result => "RESULT",
2669            Self::Full => "FULL",
2670        }
2671    }
2672}
2673
2674impl std::str::FromStr for OrderListPlaceOtocoNewOrderRespTypeEnum {
2675    type Err = Box<dyn std::error::Error + Send + Sync>;
2676
2677    fn from_str(s: &str) -> Result<Self, Self::Err> {
2678        match s {
2679            "ACK" => Ok(Self::Ack),
2680            "RESULT" => Ok(Self::Result),
2681            "FULL" => Ok(Self::Full),
2682            other => {
2683                Err(format!("invalid OrderListPlaceOtocoNewOrderRespTypeEnum: {}", other).into())
2684            }
2685        }
2686    }
2687}
2688
2689#[allow(non_camel_case_types)]
2690#[derive(Debug, Clone, Serialize, Deserialize)]
2691pub enum OrderListPlaceOtocoSelfTradePreventionModeEnum {
2692    #[serde(rename = "NONE")]
2693    None,
2694    #[serde(rename = "EXPIRE_TAKER")]
2695    ExpireTaker,
2696    #[serde(rename = "EXPIRE_MAKER")]
2697    ExpireMaker,
2698    #[serde(rename = "EXPIRE_BOTH")]
2699    ExpireBoth,
2700    #[serde(rename = "DECREMENT")]
2701    Decrement,
2702    #[serde(rename = "TRANSFER")]
2703    Transfer,
2704}
2705
2706impl OrderListPlaceOtocoSelfTradePreventionModeEnum {
2707    #[must_use]
2708    pub fn as_str(&self) -> &'static str {
2709        match self {
2710            Self::None => "NONE",
2711            Self::ExpireTaker => "EXPIRE_TAKER",
2712            Self::ExpireMaker => "EXPIRE_MAKER",
2713            Self::ExpireBoth => "EXPIRE_BOTH",
2714            Self::Decrement => "DECREMENT",
2715            Self::Transfer => "TRANSFER",
2716        }
2717    }
2718}
2719
2720impl std::str::FromStr for OrderListPlaceOtocoSelfTradePreventionModeEnum {
2721    type Err = Box<dyn std::error::Error + Send + Sync>;
2722
2723    fn from_str(s: &str) -> Result<Self, Self::Err> {
2724        match s {
2725            "NONE" => Ok(Self::None),
2726            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
2727            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
2728            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
2729            "DECREMENT" => Ok(Self::Decrement),
2730            "TRANSFER" => Ok(Self::Transfer),
2731            other => Err(format!(
2732                "invalid OrderListPlaceOtocoSelfTradePreventionModeEnum: {}",
2733                other
2734            )
2735            .into()),
2736        }
2737    }
2738}
2739
2740#[allow(non_camel_case_types)]
2741#[derive(Debug, Clone, Serialize, Deserialize)]
2742pub enum OrderListPlaceOtocoWorkingTimeInForceEnum {
2743    #[serde(rename = "GTC")]
2744    Gtc,
2745    #[serde(rename = "IOC")]
2746    Ioc,
2747    #[serde(rename = "FOK")]
2748    Fok,
2749}
2750
2751impl OrderListPlaceOtocoWorkingTimeInForceEnum {
2752    #[must_use]
2753    pub fn as_str(&self) -> &'static str {
2754        match self {
2755            Self::Gtc => "GTC",
2756            Self::Ioc => "IOC",
2757            Self::Fok => "FOK",
2758        }
2759    }
2760}
2761
2762impl std::str::FromStr for OrderListPlaceOtocoWorkingTimeInForceEnum {
2763    type Err = Box<dyn std::error::Error + Send + Sync>;
2764
2765    fn from_str(s: &str) -> Result<Self, Self::Err> {
2766        match s {
2767            "GTC" => Ok(Self::Gtc),
2768            "IOC" => Ok(Self::Ioc),
2769            "FOK" => Ok(Self::Fok),
2770            other => Err(format!(
2771                "invalid OrderListPlaceOtocoWorkingTimeInForceEnum: {}",
2772                other
2773            )
2774            .into()),
2775        }
2776    }
2777}
2778
2779#[allow(non_camel_case_types)]
2780#[derive(Debug, Clone, Serialize, Deserialize)]
2781pub enum OrderListPlaceOtocoWorkingPegPriceTypeEnum {
2782    #[serde(rename = "PRIMARY_PEG")]
2783    PrimaryPeg,
2784    #[serde(rename = "MARKET_PEG")]
2785    MarketPeg,
2786}
2787
2788impl OrderListPlaceOtocoWorkingPegPriceTypeEnum {
2789    #[must_use]
2790    pub fn as_str(&self) -> &'static str {
2791        match self {
2792            Self::PrimaryPeg => "PRIMARY_PEG",
2793            Self::MarketPeg => "MARKET_PEG",
2794        }
2795    }
2796}
2797
2798impl std::str::FromStr for OrderListPlaceOtocoWorkingPegPriceTypeEnum {
2799    type Err = Box<dyn std::error::Error + Send + Sync>;
2800
2801    fn from_str(s: &str) -> Result<Self, Self::Err> {
2802        match s {
2803            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
2804            "MARKET_PEG" => Ok(Self::MarketPeg),
2805            other => Err(format!(
2806                "invalid OrderListPlaceOtocoWorkingPegPriceTypeEnum: {}",
2807                other
2808            )
2809            .into()),
2810        }
2811    }
2812}
2813
2814#[allow(non_camel_case_types)]
2815#[derive(Debug, Clone, Serialize, Deserialize)]
2816pub enum OrderListPlaceOtocoWorkingPegOffsetTypeEnum {
2817    #[serde(rename = "PRICE_LEVEL")]
2818    PriceLevel,
2819}
2820
2821impl OrderListPlaceOtocoWorkingPegOffsetTypeEnum {
2822    #[must_use]
2823    pub fn as_str(&self) -> &'static str {
2824        match self {
2825            Self::PriceLevel => "PRICE_LEVEL",
2826        }
2827    }
2828}
2829
2830impl std::str::FromStr for OrderListPlaceOtocoWorkingPegOffsetTypeEnum {
2831    type Err = Box<dyn std::error::Error + Send + Sync>;
2832
2833    fn from_str(s: &str) -> Result<Self, Self::Err> {
2834        match s {
2835            "PRICE_LEVEL" => Ok(Self::PriceLevel),
2836            other => Err(format!(
2837                "invalid OrderListPlaceOtocoWorkingPegOffsetTypeEnum: {}",
2838                other
2839            )
2840            .into()),
2841        }
2842    }
2843}
2844
2845#[allow(non_camel_case_types)]
2846#[derive(Debug, Clone, Serialize, Deserialize)]
2847pub enum OrderListPlaceOtocoPendingAboveTimeInForceEnum {
2848    #[serde(rename = "GTC")]
2849    Gtc,
2850    #[serde(rename = "IOC")]
2851    Ioc,
2852    #[serde(rename = "FOK")]
2853    Fok,
2854}
2855
2856impl OrderListPlaceOtocoPendingAboveTimeInForceEnum {
2857    #[must_use]
2858    pub fn as_str(&self) -> &'static str {
2859        match self {
2860            Self::Gtc => "GTC",
2861            Self::Ioc => "IOC",
2862            Self::Fok => "FOK",
2863        }
2864    }
2865}
2866
2867impl std::str::FromStr for OrderListPlaceOtocoPendingAboveTimeInForceEnum {
2868    type Err = Box<dyn std::error::Error + Send + Sync>;
2869
2870    fn from_str(s: &str) -> Result<Self, Self::Err> {
2871        match s {
2872            "GTC" => Ok(Self::Gtc),
2873            "IOC" => Ok(Self::Ioc),
2874            "FOK" => Ok(Self::Fok),
2875            other => Err(format!(
2876                "invalid OrderListPlaceOtocoPendingAboveTimeInForceEnum: {}",
2877                other
2878            )
2879            .into()),
2880        }
2881    }
2882}
2883
2884#[allow(non_camel_case_types)]
2885#[derive(Debug, Clone, Serialize, Deserialize)]
2886pub enum OrderListPlaceOtocoPendingAbovePegPriceTypeEnum {
2887    #[serde(rename = "PRIMARY_PEG")]
2888    PrimaryPeg,
2889    #[serde(rename = "MARKET_PEG")]
2890    MarketPeg,
2891}
2892
2893impl OrderListPlaceOtocoPendingAbovePegPriceTypeEnum {
2894    #[must_use]
2895    pub fn as_str(&self) -> &'static str {
2896        match self {
2897            Self::PrimaryPeg => "PRIMARY_PEG",
2898            Self::MarketPeg => "MARKET_PEG",
2899        }
2900    }
2901}
2902
2903impl std::str::FromStr for OrderListPlaceOtocoPendingAbovePegPriceTypeEnum {
2904    type Err = Box<dyn std::error::Error + Send + Sync>;
2905
2906    fn from_str(s: &str) -> Result<Self, Self::Err> {
2907        match s {
2908            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
2909            "MARKET_PEG" => Ok(Self::MarketPeg),
2910            other => Err(format!(
2911                "invalid OrderListPlaceOtocoPendingAbovePegPriceTypeEnum: {}",
2912                other
2913            )
2914            .into()),
2915        }
2916    }
2917}
2918
2919#[allow(non_camel_case_types)]
2920#[derive(Debug, Clone, Serialize, Deserialize)]
2921pub enum OrderListPlaceOtocoPendingAbovePegOffsetTypeEnum {
2922    #[serde(rename = "PRICE_LEVEL")]
2923    PriceLevel,
2924}
2925
2926impl OrderListPlaceOtocoPendingAbovePegOffsetTypeEnum {
2927    #[must_use]
2928    pub fn as_str(&self) -> &'static str {
2929        match self {
2930            Self::PriceLevel => "PRICE_LEVEL",
2931        }
2932    }
2933}
2934
2935impl std::str::FromStr for OrderListPlaceOtocoPendingAbovePegOffsetTypeEnum {
2936    type Err = Box<dyn std::error::Error + Send + Sync>;
2937
2938    fn from_str(s: &str) -> Result<Self, Self::Err> {
2939        match s {
2940            "PRICE_LEVEL" => Ok(Self::PriceLevel),
2941            other => Err(format!(
2942                "invalid OrderListPlaceOtocoPendingAbovePegOffsetTypeEnum: {}",
2943                other
2944            )
2945            .into()),
2946        }
2947    }
2948}
2949
2950#[allow(non_camel_case_types)]
2951#[derive(Debug, Clone, Serialize, Deserialize)]
2952pub enum OrderListPlaceOtocoPendingBelowTypeEnum {
2953    #[serde(rename = "STOP_LOSS")]
2954    StopLoss,
2955    #[serde(rename = "STOP_LOSS_LIMIT")]
2956    StopLossLimit,
2957    #[serde(rename = "TAKE_PROFIT")]
2958    TakeProfit,
2959    #[serde(rename = "TAKE_PROFIT_LIMIT")]
2960    TakeProfitLimit,
2961}
2962
2963impl OrderListPlaceOtocoPendingBelowTypeEnum {
2964    #[must_use]
2965    pub fn as_str(&self) -> &'static str {
2966        match self {
2967            Self::StopLoss => "STOP_LOSS",
2968            Self::StopLossLimit => "STOP_LOSS_LIMIT",
2969            Self::TakeProfit => "TAKE_PROFIT",
2970            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
2971        }
2972    }
2973}
2974
2975impl std::str::FromStr for OrderListPlaceOtocoPendingBelowTypeEnum {
2976    type Err = Box<dyn std::error::Error + Send + Sync>;
2977
2978    fn from_str(s: &str) -> Result<Self, Self::Err> {
2979        match s {
2980            "STOP_LOSS" => Ok(Self::StopLoss),
2981            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
2982            "TAKE_PROFIT" => Ok(Self::TakeProfit),
2983            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
2984            other => {
2985                Err(format!("invalid OrderListPlaceOtocoPendingBelowTypeEnum: {}", other).into())
2986            }
2987        }
2988    }
2989}
2990
2991#[allow(non_camel_case_types)]
2992#[derive(Debug, Clone, Serialize, Deserialize)]
2993pub enum OrderListPlaceOtocoPendingBelowTimeInForceEnum {
2994    #[serde(rename = "GTC")]
2995    Gtc,
2996    #[serde(rename = "IOC")]
2997    Ioc,
2998    #[serde(rename = "FOK")]
2999    Fok,
3000}
3001
3002impl OrderListPlaceOtocoPendingBelowTimeInForceEnum {
3003    #[must_use]
3004    pub fn as_str(&self) -> &'static str {
3005        match self {
3006            Self::Gtc => "GTC",
3007            Self::Ioc => "IOC",
3008            Self::Fok => "FOK",
3009        }
3010    }
3011}
3012
3013impl std::str::FromStr for OrderListPlaceOtocoPendingBelowTimeInForceEnum {
3014    type Err = Box<dyn std::error::Error + Send + Sync>;
3015
3016    fn from_str(s: &str) -> Result<Self, Self::Err> {
3017        match s {
3018            "GTC" => Ok(Self::Gtc),
3019            "IOC" => Ok(Self::Ioc),
3020            "FOK" => Ok(Self::Fok),
3021            other => Err(format!(
3022                "invalid OrderListPlaceOtocoPendingBelowTimeInForceEnum: {}",
3023                other
3024            )
3025            .into()),
3026        }
3027    }
3028}
3029
3030#[allow(non_camel_case_types)]
3031#[derive(Debug, Clone, Serialize, Deserialize)]
3032pub enum OrderListPlaceOtocoPendingBelowPegPriceTypeEnum {
3033    #[serde(rename = "PRIMARY_PEG")]
3034    PrimaryPeg,
3035    #[serde(rename = "MARKET_PEG")]
3036    MarketPeg,
3037}
3038
3039impl OrderListPlaceOtocoPendingBelowPegPriceTypeEnum {
3040    #[must_use]
3041    pub fn as_str(&self) -> &'static str {
3042        match self {
3043            Self::PrimaryPeg => "PRIMARY_PEG",
3044            Self::MarketPeg => "MARKET_PEG",
3045        }
3046    }
3047}
3048
3049impl std::str::FromStr for OrderListPlaceOtocoPendingBelowPegPriceTypeEnum {
3050    type Err = Box<dyn std::error::Error + Send + Sync>;
3051
3052    fn from_str(s: &str) -> Result<Self, Self::Err> {
3053        match s {
3054            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
3055            "MARKET_PEG" => Ok(Self::MarketPeg),
3056            other => Err(format!(
3057                "invalid OrderListPlaceOtocoPendingBelowPegPriceTypeEnum: {}",
3058                other
3059            )
3060            .into()),
3061        }
3062    }
3063}
3064
3065#[allow(non_camel_case_types)]
3066#[derive(Debug, Clone, Serialize, Deserialize)]
3067pub enum OrderListPlaceOtocoPendingBelowPegOffsetTypeEnum {
3068    #[serde(rename = "PRICE_LEVEL")]
3069    PriceLevel,
3070}
3071
3072impl OrderListPlaceOtocoPendingBelowPegOffsetTypeEnum {
3073    #[must_use]
3074    pub fn as_str(&self) -> &'static str {
3075        match self {
3076            Self::PriceLevel => "PRICE_LEVEL",
3077        }
3078    }
3079}
3080
3081impl std::str::FromStr for OrderListPlaceOtocoPendingBelowPegOffsetTypeEnum {
3082    type Err = Box<dyn std::error::Error + Send + Sync>;
3083
3084    fn from_str(s: &str) -> Result<Self, Self::Err> {
3085        match s {
3086            "PRICE_LEVEL" => Ok(Self::PriceLevel),
3087            other => Err(format!(
3088                "invalid OrderListPlaceOtocoPendingBelowPegOffsetTypeEnum: {}",
3089                other
3090            )
3091            .into()),
3092        }
3093    }
3094}
3095
3096#[allow(non_camel_case_types)]
3097#[derive(Debug, Clone, Serialize, Deserialize)]
3098pub enum OrderPlaceSideEnum {
3099    #[serde(rename = "BUY")]
3100    Buy,
3101    #[serde(rename = "SELL")]
3102    Sell,
3103}
3104
3105impl OrderPlaceSideEnum {
3106    #[must_use]
3107    pub fn as_str(&self) -> &'static str {
3108        match self {
3109            Self::Buy => "BUY",
3110            Self::Sell => "SELL",
3111        }
3112    }
3113}
3114
3115impl std::str::FromStr for OrderPlaceSideEnum {
3116    type Err = Box<dyn std::error::Error + Send + Sync>;
3117
3118    fn from_str(s: &str) -> Result<Self, Self::Err> {
3119        match s {
3120            "BUY" => Ok(Self::Buy),
3121            "SELL" => Ok(Self::Sell),
3122            other => Err(format!("invalid OrderPlaceSideEnum: {}", other).into()),
3123        }
3124    }
3125}
3126
3127#[allow(non_camel_case_types)]
3128#[derive(Debug, Clone, Serialize, Deserialize)]
3129pub enum OrderPlaceTypeEnum {
3130    #[serde(rename = "MARKET")]
3131    Market,
3132    #[serde(rename = "LIMIT")]
3133    Limit,
3134    #[serde(rename = "STOP_LOSS")]
3135    StopLoss,
3136    #[serde(rename = "STOP_LOSS_LIMIT")]
3137    StopLossLimit,
3138    #[serde(rename = "TAKE_PROFIT")]
3139    TakeProfit,
3140    #[serde(rename = "TAKE_PROFIT_LIMIT")]
3141    TakeProfitLimit,
3142    #[serde(rename = "LIMIT_MAKER")]
3143    LimitMaker,
3144}
3145
3146impl OrderPlaceTypeEnum {
3147    #[must_use]
3148    pub fn as_str(&self) -> &'static str {
3149        match self {
3150            Self::Market => "MARKET",
3151            Self::Limit => "LIMIT",
3152            Self::StopLoss => "STOP_LOSS",
3153            Self::StopLossLimit => "STOP_LOSS_LIMIT",
3154            Self::TakeProfit => "TAKE_PROFIT",
3155            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
3156            Self::LimitMaker => "LIMIT_MAKER",
3157        }
3158    }
3159}
3160
3161impl std::str::FromStr for OrderPlaceTypeEnum {
3162    type Err = Box<dyn std::error::Error + Send + Sync>;
3163
3164    fn from_str(s: &str) -> Result<Self, Self::Err> {
3165        match s {
3166            "MARKET" => Ok(Self::Market),
3167            "LIMIT" => Ok(Self::Limit),
3168            "STOP_LOSS" => Ok(Self::StopLoss),
3169            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
3170            "TAKE_PROFIT" => Ok(Self::TakeProfit),
3171            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
3172            "LIMIT_MAKER" => Ok(Self::LimitMaker),
3173            other => Err(format!("invalid OrderPlaceTypeEnum: {}", other).into()),
3174        }
3175    }
3176}
3177
3178#[allow(non_camel_case_types)]
3179#[derive(Debug, Clone, Serialize, Deserialize)]
3180pub enum OrderPlaceTimeInForceEnum {
3181    #[serde(rename = "GTC")]
3182    Gtc,
3183    #[serde(rename = "IOC")]
3184    Ioc,
3185    #[serde(rename = "FOK")]
3186    Fok,
3187}
3188
3189impl OrderPlaceTimeInForceEnum {
3190    #[must_use]
3191    pub fn as_str(&self) -> &'static str {
3192        match self {
3193            Self::Gtc => "GTC",
3194            Self::Ioc => "IOC",
3195            Self::Fok => "FOK",
3196        }
3197    }
3198}
3199
3200impl std::str::FromStr for OrderPlaceTimeInForceEnum {
3201    type Err = Box<dyn std::error::Error + Send + Sync>;
3202
3203    fn from_str(s: &str) -> Result<Self, Self::Err> {
3204        match s {
3205            "GTC" => Ok(Self::Gtc),
3206            "IOC" => Ok(Self::Ioc),
3207            "FOK" => Ok(Self::Fok),
3208            other => Err(format!("invalid OrderPlaceTimeInForceEnum: {}", other).into()),
3209        }
3210    }
3211}
3212
3213#[allow(non_camel_case_types)]
3214#[derive(Debug, Clone, Serialize, Deserialize)]
3215pub enum OrderPlaceNewOrderRespTypeEnum {
3216    #[serde(rename = "ACK")]
3217    Ack,
3218    #[serde(rename = "RESULT")]
3219    Result,
3220    #[serde(rename = "FULL")]
3221    Full,
3222}
3223
3224impl OrderPlaceNewOrderRespTypeEnum {
3225    #[must_use]
3226    pub fn as_str(&self) -> &'static str {
3227        match self {
3228            Self::Ack => "ACK",
3229            Self::Result => "RESULT",
3230            Self::Full => "FULL",
3231        }
3232    }
3233}
3234
3235impl std::str::FromStr for OrderPlaceNewOrderRespTypeEnum {
3236    type Err = Box<dyn std::error::Error + Send + Sync>;
3237
3238    fn from_str(s: &str) -> Result<Self, Self::Err> {
3239        match s {
3240            "ACK" => Ok(Self::Ack),
3241            "RESULT" => Ok(Self::Result),
3242            "FULL" => Ok(Self::Full),
3243            other => Err(format!("invalid OrderPlaceNewOrderRespTypeEnum: {}", other).into()),
3244        }
3245    }
3246}
3247
3248#[allow(non_camel_case_types)]
3249#[derive(Debug, Clone, Serialize, Deserialize)]
3250pub enum OrderPlaceSelfTradePreventionModeEnum {
3251    #[serde(rename = "NONE")]
3252    None,
3253    #[serde(rename = "EXPIRE_TAKER")]
3254    ExpireTaker,
3255    #[serde(rename = "EXPIRE_MAKER")]
3256    ExpireMaker,
3257    #[serde(rename = "EXPIRE_BOTH")]
3258    ExpireBoth,
3259    #[serde(rename = "DECREMENT")]
3260    Decrement,
3261    #[serde(rename = "TRANSFER")]
3262    Transfer,
3263}
3264
3265impl OrderPlaceSelfTradePreventionModeEnum {
3266    #[must_use]
3267    pub fn as_str(&self) -> &'static str {
3268        match self {
3269            Self::None => "NONE",
3270            Self::ExpireTaker => "EXPIRE_TAKER",
3271            Self::ExpireMaker => "EXPIRE_MAKER",
3272            Self::ExpireBoth => "EXPIRE_BOTH",
3273            Self::Decrement => "DECREMENT",
3274            Self::Transfer => "TRANSFER",
3275        }
3276    }
3277}
3278
3279impl std::str::FromStr for OrderPlaceSelfTradePreventionModeEnum {
3280    type Err = Box<dyn std::error::Error + Send + Sync>;
3281
3282    fn from_str(s: &str) -> Result<Self, Self::Err> {
3283        match s {
3284            "NONE" => Ok(Self::None),
3285            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
3286            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
3287            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
3288            "DECREMENT" => Ok(Self::Decrement),
3289            "TRANSFER" => Ok(Self::Transfer),
3290            other => {
3291                Err(format!("invalid OrderPlaceSelfTradePreventionModeEnum: {}", other).into())
3292            }
3293        }
3294    }
3295}
3296
3297#[allow(non_camel_case_types)]
3298#[derive(Debug, Clone, Serialize, Deserialize)]
3299pub enum OrderPlacePegPriceTypeEnum {
3300    #[serde(rename = "PRIMARY_PEG")]
3301    PrimaryPeg,
3302    #[serde(rename = "MARKET_PEG")]
3303    MarketPeg,
3304}
3305
3306impl OrderPlacePegPriceTypeEnum {
3307    #[must_use]
3308    pub fn as_str(&self) -> &'static str {
3309        match self {
3310            Self::PrimaryPeg => "PRIMARY_PEG",
3311            Self::MarketPeg => "MARKET_PEG",
3312        }
3313    }
3314}
3315
3316impl std::str::FromStr for OrderPlacePegPriceTypeEnum {
3317    type Err = Box<dyn std::error::Error + Send + Sync>;
3318
3319    fn from_str(s: &str) -> Result<Self, Self::Err> {
3320        match s {
3321            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
3322            "MARKET_PEG" => Ok(Self::MarketPeg),
3323            other => Err(format!("invalid OrderPlacePegPriceTypeEnum: {}", other).into()),
3324        }
3325    }
3326}
3327
3328#[allow(non_camel_case_types)]
3329#[derive(Debug, Clone, Serialize, Deserialize)]
3330pub enum OrderPlacePegOffsetTypeEnum {
3331    #[serde(rename = "PRICE_LEVEL")]
3332    PriceLevel,
3333}
3334
3335impl OrderPlacePegOffsetTypeEnum {
3336    #[must_use]
3337    pub fn as_str(&self) -> &'static str {
3338        match self {
3339            Self::PriceLevel => "PRICE_LEVEL",
3340        }
3341    }
3342}
3343
3344impl std::str::FromStr for OrderPlacePegOffsetTypeEnum {
3345    type Err = Box<dyn std::error::Error + Send + Sync>;
3346
3347    fn from_str(s: &str) -> Result<Self, Self::Err> {
3348        match s {
3349            "PRICE_LEVEL" => Ok(Self::PriceLevel),
3350            other => Err(format!("invalid OrderPlacePegOffsetTypeEnum: {}", other).into()),
3351        }
3352    }
3353}
3354
3355#[allow(non_camel_case_types)]
3356#[derive(Debug, Clone, Serialize, Deserialize)]
3357pub enum OrderTestSideEnum {
3358    #[serde(rename = "BUY")]
3359    Buy,
3360    #[serde(rename = "SELL")]
3361    Sell,
3362}
3363
3364impl OrderTestSideEnum {
3365    #[must_use]
3366    pub fn as_str(&self) -> &'static str {
3367        match self {
3368            Self::Buy => "BUY",
3369            Self::Sell => "SELL",
3370        }
3371    }
3372}
3373
3374impl std::str::FromStr for OrderTestSideEnum {
3375    type Err = Box<dyn std::error::Error + Send + Sync>;
3376
3377    fn from_str(s: &str) -> Result<Self, Self::Err> {
3378        match s {
3379            "BUY" => Ok(Self::Buy),
3380            "SELL" => Ok(Self::Sell),
3381            other => Err(format!("invalid OrderTestSideEnum: {}", other).into()),
3382        }
3383    }
3384}
3385
3386#[allow(non_camel_case_types)]
3387#[derive(Debug, Clone, Serialize, Deserialize)]
3388pub enum OrderTestTypeEnum {
3389    #[serde(rename = "MARKET")]
3390    Market,
3391    #[serde(rename = "LIMIT")]
3392    Limit,
3393    #[serde(rename = "STOP_LOSS")]
3394    StopLoss,
3395    #[serde(rename = "STOP_LOSS_LIMIT")]
3396    StopLossLimit,
3397    #[serde(rename = "TAKE_PROFIT")]
3398    TakeProfit,
3399    #[serde(rename = "TAKE_PROFIT_LIMIT")]
3400    TakeProfitLimit,
3401    #[serde(rename = "LIMIT_MAKER")]
3402    LimitMaker,
3403}
3404
3405impl OrderTestTypeEnum {
3406    #[must_use]
3407    pub fn as_str(&self) -> &'static str {
3408        match self {
3409            Self::Market => "MARKET",
3410            Self::Limit => "LIMIT",
3411            Self::StopLoss => "STOP_LOSS",
3412            Self::StopLossLimit => "STOP_LOSS_LIMIT",
3413            Self::TakeProfit => "TAKE_PROFIT",
3414            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
3415            Self::LimitMaker => "LIMIT_MAKER",
3416        }
3417    }
3418}
3419
3420impl std::str::FromStr for OrderTestTypeEnum {
3421    type Err = Box<dyn std::error::Error + Send + Sync>;
3422
3423    fn from_str(s: &str) -> Result<Self, Self::Err> {
3424        match s {
3425            "MARKET" => Ok(Self::Market),
3426            "LIMIT" => Ok(Self::Limit),
3427            "STOP_LOSS" => Ok(Self::StopLoss),
3428            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
3429            "TAKE_PROFIT" => Ok(Self::TakeProfit),
3430            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
3431            "LIMIT_MAKER" => Ok(Self::LimitMaker),
3432            other => Err(format!("invalid OrderTestTypeEnum: {}", other).into()),
3433        }
3434    }
3435}
3436
3437#[allow(non_camel_case_types)]
3438#[derive(Debug, Clone, Serialize, Deserialize)]
3439pub enum OrderTestTimeInForceEnum {
3440    #[serde(rename = "GTC")]
3441    Gtc,
3442    #[serde(rename = "IOC")]
3443    Ioc,
3444    #[serde(rename = "FOK")]
3445    Fok,
3446}
3447
3448impl OrderTestTimeInForceEnum {
3449    #[must_use]
3450    pub fn as_str(&self) -> &'static str {
3451        match self {
3452            Self::Gtc => "GTC",
3453            Self::Ioc => "IOC",
3454            Self::Fok => "FOK",
3455        }
3456    }
3457}
3458
3459impl std::str::FromStr for OrderTestTimeInForceEnum {
3460    type Err = Box<dyn std::error::Error + Send + Sync>;
3461
3462    fn from_str(s: &str) -> Result<Self, Self::Err> {
3463        match s {
3464            "GTC" => Ok(Self::Gtc),
3465            "IOC" => Ok(Self::Ioc),
3466            "FOK" => Ok(Self::Fok),
3467            other => Err(format!("invalid OrderTestTimeInForceEnum: {}", other).into()),
3468        }
3469    }
3470}
3471
3472#[allow(non_camel_case_types)]
3473#[derive(Debug, Clone, Serialize, Deserialize)]
3474pub enum OrderTestNewOrderRespTypeEnum {
3475    #[serde(rename = "ACK")]
3476    Ack,
3477    #[serde(rename = "RESULT")]
3478    Result,
3479    #[serde(rename = "FULL")]
3480    Full,
3481}
3482
3483impl OrderTestNewOrderRespTypeEnum {
3484    #[must_use]
3485    pub fn as_str(&self) -> &'static str {
3486        match self {
3487            Self::Ack => "ACK",
3488            Self::Result => "RESULT",
3489            Self::Full => "FULL",
3490        }
3491    }
3492}
3493
3494impl std::str::FromStr for OrderTestNewOrderRespTypeEnum {
3495    type Err = Box<dyn std::error::Error + Send + Sync>;
3496
3497    fn from_str(s: &str) -> Result<Self, Self::Err> {
3498        match s {
3499            "ACK" => Ok(Self::Ack),
3500            "RESULT" => Ok(Self::Result),
3501            "FULL" => Ok(Self::Full),
3502            other => Err(format!("invalid OrderTestNewOrderRespTypeEnum: {}", other).into()),
3503        }
3504    }
3505}
3506
3507#[allow(non_camel_case_types)]
3508#[derive(Debug, Clone, Serialize, Deserialize)]
3509pub enum OrderTestSelfTradePreventionModeEnum {
3510    #[serde(rename = "NONE")]
3511    None,
3512    #[serde(rename = "EXPIRE_TAKER")]
3513    ExpireTaker,
3514    #[serde(rename = "EXPIRE_MAKER")]
3515    ExpireMaker,
3516    #[serde(rename = "EXPIRE_BOTH")]
3517    ExpireBoth,
3518    #[serde(rename = "DECREMENT")]
3519    Decrement,
3520    #[serde(rename = "TRANSFER")]
3521    Transfer,
3522}
3523
3524impl OrderTestSelfTradePreventionModeEnum {
3525    #[must_use]
3526    pub fn as_str(&self) -> &'static str {
3527        match self {
3528            Self::None => "NONE",
3529            Self::ExpireTaker => "EXPIRE_TAKER",
3530            Self::ExpireMaker => "EXPIRE_MAKER",
3531            Self::ExpireBoth => "EXPIRE_BOTH",
3532            Self::Decrement => "DECREMENT",
3533            Self::Transfer => "TRANSFER",
3534        }
3535    }
3536}
3537
3538impl std::str::FromStr for OrderTestSelfTradePreventionModeEnum {
3539    type Err = Box<dyn std::error::Error + Send + Sync>;
3540
3541    fn from_str(s: &str) -> Result<Self, Self::Err> {
3542        match s {
3543            "NONE" => Ok(Self::None),
3544            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
3545            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
3546            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
3547            "DECREMENT" => Ok(Self::Decrement),
3548            "TRANSFER" => Ok(Self::Transfer),
3549            other => Err(format!("invalid OrderTestSelfTradePreventionModeEnum: {}", other).into()),
3550        }
3551    }
3552}
3553
3554#[allow(non_camel_case_types)]
3555#[derive(Debug, Clone, Serialize, Deserialize)]
3556pub enum OrderTestPegPriceTypeEnum {
3557    #[serde(rename = "PRIMARY_PEG")]
3558    PrimaryPeg,
3559    #[serde(rename = "MARKET_PEG")]
3560    MarketPeg,
3561}
3562
3563impl OrderTestPegPriceTypeEnum {
3564    #[must_use]
3565    pub fn as_str(&self) -> &'static str {
3566        match self {
3567            Self::PrimaryPeg => "PRIMARY_PEG",
3568            Self::MarketPeg => "MARKET_PEG",
3569        }
3570    }
3571}
3572
3573impl std::str::FromStr for OrderTestPegPriceTypeEnum {
3574    type Err = Box<dyn std::error::Error + Send + Sync>;
3575
3576    fn from_str(s: &str) -> Result<Self, Self::Err> {
3577        match s {
3578            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
3579            "MARKET_PEG" => Ok(Self::MarketPeg),
3580            other => Err(format!("invalid OrderTestPegPriceTypeEnum: {}", other).into()),
3581        }
3582    }
3583}
3584
3585#[allow(non_camel_case_types)]
3586#[derive(Debug, Clone, Serialize, Deserialize)]
3587pub enum OrderTestPegOffsetTypeEnum {
3588    #[serde(rename = "PRICE_LEVEL")]
3589    PriceLevel,
3590}
3591
3592impl OrderTestPegOffsetTypeEnum {
3593    #[must_use]
3594    pub fn as_str(&self) -> &'static str {
3595        match self {
3596            Self::PriceLevel => "PRICE_LEVEL",
3597        }
3598    }
3599}
3600
3601impl std::str::FromStr for OrderTestPegOffsetTypeEnum {
3602    type Err = Box<dyn std::error::Error + Send + Sync>;
3603
3604    fn from_str(s: &str) -> Result<Self, Self::Err> {
3605        match s {
3606            "PRICE_LEVEL" => Ok(Self::PriceLevel),
3607            other => Err(format!("invalid OrderTestPegOffsetTypeEnum: {}", other).into()),
3608        }
3609    }
3610}
3611
3612#[allow(non_camel_case_types)]
3613#[derive(Debug, Clone, Serialize, Deserialize)]
3614pub enum SorOrderPlaceSideEnum {
3615    #[serde(rename = "BUY")]
3616    Buy,
3617    #[serde(rename = "SELL")]
3618    Sell,
3619}
3620
3621impl SorOrderPlaceSideEnum {
3622    #[must_use]
3623    pub fn as_str(&self) -> &'static str {
3624        match self {
3625            Self::Buy => "BUY",
3626            Self::Sell => "SELL",
3627        }
3628    }
3629}
3630
3631impl std::str::FromStr for SorOrderPlaceSideEnum {
3632    type Err = Box<dyn std::error::Error + Send + Sync>;
3633
3634    fn from_str(s: &str) -> Result<Self, Self::Err> {
3635        match s {
3636            "BUY" => Ok(Self::Buy),
3637            "SELL" => Ok(Self::Sell),
3638            other => Err(format!("invalid SorOrderPlaceSideEnum: {}", other).into()),
3639        }
3640    }
3641}
3642
3643#[allow(non_camel_case_types)]
3644#[derive(Debug, Clone, Serialize, Deserialize)]
3645pub enum SorOrderPlaceTypeEnum {
3646    #[serde(rename = "MARKET")]
3647    Market,
3648    #[serde(rename = "LIMIT")]
3649    Limit,
3650}
3651
3652impl SorOrderPlaceTypeEnum {
3653    #[must_use]
3654    pub fn as_str(&self) -> &'static str {
3655        match self {
3656            Self::Market => "MARKET",
3657            Self::Limit => "LIMIT",
3658        }
3659    }
3660}
3661
3662impl std::str::FromStr for SorOrderPlaceTypeEnum {
3663    type Err = Box<dyn std::error::Error + Send + Sync>;
3664
3665    fn from_str(s: &str) -> Result<Self, Self::Err> {
3666        match s {
3667            "MARKET" => Ok(Self::Market),
3668            "LIMIT" => Ok(Self::Limit),
3669            other => Err(format!("invalid SorOrderPlaceTypeEnum: {}", other).into()),
3670        }
3671    }
3672}
3673
3674#[allow(non_camel_case_types)]
3675#[derive(Debug, Clone, Serialize, Deserialize)]
3676pub enum SorOrderPlaceTimeInForceEnum {
3677    #[serde(rename = "GTC")]
3678    Gtc,
3679    #[serde(rename = "IOC")]
3680    Ioc,
3681    #[serde(rename = "FOK")]
3682    Fok,
3683}
3684
3685impl SorOrderPlaceTimeInForceEnum {
3686    #[must_use]
3687    pub fn as_str(&self) -> &'static str {
3688        match self {
3689            Self::Gtc => "GTC",
3690            Self::Ioc => "IOC",
3691            Self::Fok => "FOK",
3692        }
3693    }
3694}
3695
3696impl std::str::FromStr for SorOrderPlaceTimeInForceEnum {
3697    type Err = Box<dyn std::error::Error + Send + Sync>;
3698
3699    fn from_str(s: &str) -> Result<Self, Self::Err> {
3700        match s {
3701            "GTC" => Ok(Self::Gtc),
3702            "IOC" => Ok(Self::Ioc),
3703            "FOK" => Ok(Self::Fok),
3704            other => Err(format!("invalid SorOrderPlaceTimeInForceEnum: {}", other).into()),
3705        }
3706    }
3707}
3708
3709#[allow(non_camel_case_types)]
3710#[derive(Debug, Clone, Serialize, Deserialize)]
3711pub enum SorOrderPlaceNewOrderRespTypeEnum {
3712    #[serde(rename = "ACK")]
3713    Ack,
3714    #[serde(rename = "RESULT")]
3715    Result,
3716    #[serde(rename = "FULL")]
3717    Full,
3718}
3719
3720impl SorOrderPlaceNewOrderRespTypeEnum {
3721    #[must_use]
3722    pub fn as_str(&self) -> &'static str {
3723        match self {
3724            Self::Ack => "ACK",
3725            Self::Result => "RESULT",
3726            Self::Full => "FULL",
3727        }
3728    }
3729}
3730
3731impl std::str::FromStr for SorOrderPlaceNewOrderRespTypeEnum {
3732    type Err = Box<dyn std::error::Error + Send + Sync>;
3733
3734    fn from_str(s: &str) -> Result<Self, Self::Err> {
3735        match s {
3736            "ACK" => Ok(Self::Ack),
3737            "RESULT" => Ok(Self::Result),
3738            "FULL" => Ok(Self::Full),
3739            other => Err(format!("invalid SorOrderPlaceNewOrderRespTypeEnum: {}", other).into()),
3740        }
3741    }
3742}
3743
3744#[allow(non_camel_case_types)]
3745#[derive(Debug, Clone, Serialize, Deserialize)]
3746pub enum SorOrderPlaceSelfTradePreventionModeEnum {
3747    #[serde(rename = "NONE")]
3748    None,
3749    #[serde(rename = "EXPIRE_TAKER")]
3750    ExpireTaker,
3751    #[serde(rename = "EXPIRE_MAKER")]
3752    ExpireMaker,
3753    #[serde(rename = "EXPIRE_BOTH")]
3754    ExpireBoth,
3755    #[serde(rename = "DECREMENT")]
3756    Decrement,
3757    #[serde(rename = "TRANSFER")]
3758    Transfer,
3759}
3760
3761impl SorOrderPlaceSelfTradePreventionModeEnum {
3762    #[must_use]
3763    pub fn as_str(&self) -> &'static str {
3764        match self {
3765            Self::None => "NONE",
3766            Self::ExpireTaker => "EXPIRE_TAKER",
3767            Self::ExpireMaker => "EXPIRE_MAKER",
3768            Self::ExpireBoth => "EXPIRE_BOTH",
3769            Self::Decrement => "DECREMENT",
3770            Self::Transfer => "TRANSFER",
3771        }
3772    }
3773}
3774
3775impl std::str::FromStr for SorOrderPlaceSelfTradePreventionModeEnum {
3776    type Err = Box<dyn std::error::Error + Send + Sync>;
3777
3778    fn from_str(s: &str) -> Result<Self, Self::Err> {
3779        match s {
3780            "NONE" => Ok(Self::None),
3781            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
3782            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
3783            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
3784            "DECREMENT" => Ok(Self::Decrement),
3785            "TRANSFER" => Ok(Self::Transfer),
3786            other => Err(format!(
3787                "invalid SorOrderPlaceSelfTradePreventionModeEnum: {}",
3788                other
3789            )
3790            .into()),
3791        }
3792    }
3793}
3794
3795#[allow(non_camel_case_types)]
3796#[derive(Debug, Clone, Serialize, Deserialize)]
3797pub enum SorOrderTestSideEnum {
3798    #[serde(rename = "BUY")]
3799    Buy,
3800    #[serde(rename = "SELL")]
3801    Sell,
3802}
3803
3804impl SorOrderTestSideEnum {
3805    #[must_use]
3806    pub fn as_str(&self) -> &'static str {
3807        match self {
3808            Self::Buy => "BUY",
3809            Self::Sell => "SELL",
3810        }
3811    }
3812}
3813
3814impl std::str::FromStr for SorOrderTestSideEnum {
3815    type Err = Box<dyn std::error::Error + Send + Sync>;
3816
3817    fn from_str(s: &str) -> Result<Self, Self::Err> {
3818        match s {
3819            "BUY" => Ok(Self::Buy),
3820            "SELL" => Ok(Self::Sell),
3821            other => Err(format!("invalid SorOrderTestSideEnum: {}", other).into()),
3822        }
3823    }
3824}
3825
3826#[allow(non_camel_case_types)]
3827#[derive(Debug, Clone, Serialize, Deserialize)]
3828pub enum SorOrderTestTypeEnum {
3829    #[serde(rename = "MARKET")]
3830    Market,
3831    #[serde(rename = "LIMIT")]
3832    Limit,
3833}
3834
3835impl SorOrderTestTypeEnum {
3836    #[must_use]
3837    pub fn as_str(&self) -> &'static str {
3838        match self {
3839            Self::Market => "MARKET",
3840            Self::Limit => "LIMIT",
3841        }
3842    }
3843}
3844
3845impl std::str::FromStr for SorOrderTestTypeEnum {
3846    type Err = Box<dyn std::error::Error + Send + Sync>;
3847
3848    fn from_str(s: &str) -> Result<Self, Self::Err> {
3849        match s {
3850            "MARKET" => Ok(Self::Market),
3851            "LIMIT" => Ok(Self::Limit),
3852            other => Err(format!("invalid SorOrderTestTypeEnum: {}", other).into()),
3853        }
3854    }
3855}
3856
3857#[allow(non_camel_case_types)]
3858#[derive(Debug, Clone, Serialize, Deserialize)]
3859pub enum SorOrderTestTimeInForceEnum {
3860    #[serde(rename = "GTC")]
3861    Gtc,
3862    #[serde(rename = "IOC")]
3863    Ioc,
3864    #[serde(rename = "FOK")]
3865    Fok,
3866}
3867
3868impl SorOrderTestTimeInForceEnum {
3869    #[must_use]
3870    pub fn as_str(&self) -> &'static str {
3871        match self {
3872            Self::Gtc => "GTC",
3873            Self::Ioc => "IOC",
3874            Self::Fok => "FOK",
3875        }
3876    }
3877}
3878
3879impl std::str::FromStr for SorOrderTestTimeInForceEnum {
3880    type Err = Box<dyn std::error::Error + Send + Sync>;
3881
3882    fn from_str(s: &str) -> Result<Self, Self::Err> {
3883        match s {
3884            "GTC" => Ok(Self::Gtc),
3885            "IOC" => Ok(Self::Ioc),
3886            "FOK" => Ok(Self::Fok),
3887            other => Err(format!("invalid SorOrderTestTimeInForceEnum: {}", other).into()),
3888        }
3889    }
3890}
3891
3892#[allow(non_camel_case_types)]
3893#[derive(Debug, Clone, Serialize, Deserialize)]
3894pub enum SorOrderTestNewOrderRespTypeEnum {
3895    #[serde(rename = "ACK")]
3896    Ack,
3897    #[serde(rename = "RESULT")]
3898    Result,
3899    #[serde(rename = "FULL")]
3900    Full,
3901}
3902
3903impl SorOrderTestNewOrderRespTypeEnum {
3904    #[must_use]
3905    pub fn as_str(&self) -> &'static str {
3906        match self {
3907            Self::Ack => "ACK",
3908            Self::Result => "RESULT",
3909            Self::Full => "FULL",
3910        }
3911    }
3912}
3913
3914impl std::str::FromStr for SorOrderTestNewOrderRespTypeEnum {
3915    type Err = Box<dyn std::error::Error + Send + Sync>;
3916
3917    fn from_str(s: &str) -> Result<Self, Self::Err> {
3918        match s {
3919            "ACK" => Ok(Self::Ack),
3920            "RESULT" => Ok(Self::Result),
3921            "FULL" => Ok(Self::Full),
3922            other => Err(format!("invalid SorOrderTestNewOrderRespTypeEnum: {}", other).into()),
3923        }
3924    }
3925}
3926
3927#[allow(non_camel_case_types)]
3928#[derive(Debug, Clone, Serialize, Deserialize)]
3929pub enum SorOrderTestSelfTradePreventionModeEnum {
3930    #[serde(rename = "NONE")]
3931    None,
3932    #[serde(rename = "EXPIRE_TAKER")]
3933    ExpireTaker,
3934    #[serde(rename = "EXPIRE_MAKER")]
3935    ExpireMaker,
3936    #[serde(rename = "EXPIRE_BOTH")]
3937    ExpireBoth,
3938    #[serde(rename = "DECREMENT")]
3939    Decrement,
3940    #[serde(rename = "TRANSFER")]
3941    Transfer,
3942}
3943
3944impl SorOrderTestSelfTradePreventionModeEnum {
3945    #[must_use]
3946    pub fn as_str(&self) -> &'static str {
3947        match self {
3948            Self::None => "NONE",
3949            Self::ExpireTaker => "EXPIRE_TAKER",
3950            Self::ExpireMaker => "EXPIRE_MAKER",
3951            Self::ExpireBoth => "EXPIRE_BOTH",
3952            Self::Decrement => "DECREMENT",
3953            Self::Transfer => "TRANSFER",
3954        }
3955    }
3956}
3957
3958impl std::str::FromStr for SorOrderTestSelfTradePreventionModeEnum {
3959    type Err = Box<dyn std::error::Error + Send + Sync>;
3960
3961    fn from_str(s: &str) -> Result<Self, Self::Err> {
3962        match s {
3963            "NONE" => Ok(Self::None),
3964            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
3965            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
3966            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
3967            "DECREMENT" => Ok(Self::Decrement),
3968            "TRANSFER" => Ok(Self::Transfer),
3969            other => {
3970                Err(format!("invalid SorOrderTestSelfTradePreventionModeEnum: {}", other).into())
3971            }
3972        }
3973    }
3974}
3975
3976/// Request parameters for the [`open_orders_cancel_all`] operation.
3977///
3978/// This struct holds all of the inputs you can pass when calling
3979/// [`open_orders_cancel_all`](#method.open_orders_cancel_all).
3980#[derive(Clone, Debug, Builder, Deserialize)]
3981#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
3982pub struct OpenOrdersCancelAllParams {
3983    ///
3984    /// The `symbol` parameter.
3985    ///
3986    /// This field is **required.
3987    #[builder(setter(into))]
3988    #[serde(rename = "symbol")]
3989    pub symbol: String,
3990    /// Client-generated request identifier.
3991    ///
3992    /// This field is **optional.
3993    #[builder(setter(into), default)]
3994    #[serde(rename = "id", default)]
3995    pub id: Option<String>,
3996    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
3997    ///
3998    /// This field is **optional.
3999    #[builder(setter(into), default)]
4000    #[serde(rename = "recvWindow", default)]
4001    pub recv_window: Option<rust_decimal::Decimal>,
4002}
4003
4004impl OpenOrdersCancelAllParams {
4005    /// Create a builder for [`open_orders_cancel_all`].
4006    ///
4007    /// Required parameters:
4008    ///
4009    /// * `symbol` — String
4010    ///
4011    #[must_use]
4012    pub fn builder(symbol: String) -> OpenOrdersCancelAllParamsBuilder {
4013        OpenOrdersCancelAllParamsBuilder::default().symbol(symbol)
4014    }
4015}
4016/// Request parameters for the [`order_amend_keep_priority`] operation.
4017///
4018/// This struct holds all of the inputs you can pass when calling
4019/// [`order_amend_keep_priority`](#method.order_amend_keep_priority).
4020#[derive(Clone, Debug, Builder, Deserialize)]
4021#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4022pub struct OrderAmendKeepPriorityParams {
4023    ///
4024    /// The `symbol` parameter.
4025    ///
4026    /// This field is **required.
4027    #[builder(setter(into))]
4028    #[serde(rename = "symbol")]
4029    pub symbol: String,
4030    /// `newQty` must be greater than 0 and less than the order's quantity.
4031    ///
4032    /// This field is **required.
4033    #[builder(setter(into))]
4034    #[serde(rename = "newQty")]
4035    pub new_qty: rust_decimal::Decimal,
4036    /// Client-generated request identifier.
4037    ///
4038    /// This field is **optional.
4039    #[builder(setter(into), default)]
4040    #[serde(rename = "id", default)]
4041    pub id: Option<String>,
4042    /// `orderId` or `origClientOrderId` must be sent
4043    ///
4044    /// This field is **optional.
4045    #[builder(setter(into), default)]
4046    #[serde(rename = "orderId", default)]
4047    pub order_id: Option<i64>,
4048    /// `orderId` or `origClientOrderId` must be sent
4049    ///
4050    /// This field is **optional.
4051    #[builder(setter(into), default)]
4052    #[serde(rename = "origClientOrderId", default)]
4053    pub orig_client_order_id: Option<String>,
4054    /// The new client order ID for the order after being amended. <br> If not sent, one will be randomly generated. <br> It is possible to reuse the current clientOrderId by sending it as the `newClientOrderId`.
4055    ///
4056    /// This field is **optional.
4057    #[builder(setter(into), default)]
4058    #[serde(rename = "newClientOrderId", default)]
4059    pub new_client_order_id: Option<String>,
4060    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4061    ///
4062    /// This field is **optional.
4063    #[builder(setter(into), default)]
4064    #[serde(rename = "recvWindow", default)]
4065    pub recv_window: Option<rust_decimal::Decimal>,
4066}
4067
4068impl OrderAmendKeepPriorityParams {
4069    /// Create a builder for [`order_amend_keep_priority`].
4070    ///
4071    /// Required parameters:
4072    ///
4073    /// * `symbol` — String
4074    /// * `new_qty` — `newQty` must be greater than 0 and less than the order's quantity.
4075    ///
4076    #[must_use]
4077    pub fn builder(
4078        symbol: String,
4079        new_qty: rust_decimal::Decimal,
4080    ) -> OrderAmendKeepPriorityParamsBuilder {
4081        OrderAmendKeepPriorityParamsBuilder::default()
4082            .symbol(symbol)
4083            .new_qty(new_qty)
4084    }
4085}
4086/// Request parameters for the [`order_cancel`] operation.
4087///
4088/// This struct holds all of the inputs you can pass when calling
4089/// [`order_cancel`](#method.order_cancel).
4090#[derive(Clone, Debug, Builder, Deserialize)]
4091#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4092pub struct OrderCancelParams {
4093    ///
4094    /// The `symbol` parameter.
4095    ///
4096    /// This field is **required.
4097    #[builder(setter(into))]
4098    #[serde(rename = "symbol")]
4099    pub symbol: String,
4100    /// Client-generated request identifier.
4101    ///
4102    /// This field is **optional.
4103    #[builder(setter(into), default)]
4104    #[serde(rename = "id", default)]
4105    pub id: Option<String>,
4106    ///
4107    /// The `order_id` parameter.
4108    ///
4109    /// This field is **optional.
4110    #[builder(setter(into), default)]
4111    #[serde(rename = "orderId", default)]
4112    pub order_id: Option<i64>,
4113    ///
4114    /// The `orig_client_order_id` parameter.
4115    ///
4116    /// This field is **optional.
4117    #[builder(setter(into), default)]
4118    #[serde(rename = "origClientOrderId", default)]
4119    pub orig_client_order_id: Option<String>,
4120    /// Used to uniquely identify this cancel. Automatically generated by default.
4121    ///
4122    /// This field is **optional.
4123    #[builder(setter(into), default)]
4124    #[serde(rename = "newClientOrderId", default)]
4125    pub new_client_order_id: Option<String>,
4126    /// Supported values: <br>`ONLY_NEW` - Cancel will succeed if the order status is `NEW`.<br> `ONLY_PARTIALLY_FILLED` - Cancel will succeed if order status is `PARTIALLY_FILLED`.
4127    ///
4128    /// This field is **optional.
4129    #[builder(setter(into), default)]
4130    #[serde(rename = "cancelRestrictions", default)]
4131    pub cancel_restrictions: Option<OrderCancelCancelRestrictionsEnum>,
4132    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4133    ///
4134    /// This field is **optional.
4135    #[builder(setter(into), default)]
4136    #[serde(rename = "recvWindow", default)]
4137    pub recv_window: Option<rust_decimal::Decimal>,
4138}
4139
4140impl OrderCancelParams {
4141    /// Create a builder for [`order_cancel`].
4142    ///
4143    /// Required parameters:
4144    ///
4145    /// * `symbol` — String
4146    ///
4147    #[must_use]
4148    pub fn builder(symbol: String) -> OrderCancelParamsBuilder {
4149        OrderCancelParamsBuilder::default().symbol(symbol)
4150    }
4151}
4152/// Request parameters for the [`order_cancel_replace`] operation.
4153///
4154/// This struct holds all of the inputs you can pass when calling
4155/// [`order_cancel_replace`](#method.order_cancel_replace).
4156#[derive(Clone, Debug, Builder, Deserialize)]
4157#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4158pub struct OrderCancelReplaceParams {
4159    ///
4160    /// The `symbol` parameter.
4161    ///
4162    /// This field is **required.
4163    #[builder(setter(into))]
4164    #[serde(rename = "symbol")]
4165    pub symbol: String,
4166    /// The allowed values are: <br/> `STOP_ON_FAILURE` - If the cancel request fails, the new order placement will not be attempted. <br/> `ALLOW_FAILURE` - new order placement will be attempted even if cancel request fails.
4167    ///
4168    /// This field is **required.
4169    #[builder(setter(into))]
4170    #[serde(rename = "cancelReplaceMode")]
4171    pub cancel_replace_mode: OrderCancelReplaceCancelReplaceModeEnum,
4172    /// Please see [Enums](/products/spot/enums#side) for supported values.
4173    ///
4174    /// This field is **required.
4175    #[builder(setter(into))]
4176    #[serde(rename = "side")]
4177    pub side: OrderCancelReplaceSideEnum,
4178    /// Please see [Enums](/products/spot/enums#ordertypes) for supported values.
4179    ///
4180    /// This field is **required.
4181    #[builder(setter(into))]
4182    #[serde(rename = "type")]
4183    pub r#type: OrderCancelReplaceTypeEnum,
4184    /// Client-generated request identifier.
4185    ///
4186    /// This field is **optional.
4187    #[builder(setter(into), default)]
4188    #[serde(rename = "id", default)]
4189    pub id: Option<String>,
4190    /// Either `cancelOrderId` or `cancelOrigClientOrderId` must be sent. <br></br>If both `cancelOrderId` and `cancelOrigClientOrderId` parameters are provided, the `cancelOrderId` is searched first, then the `cancelOrigClientOrderId` from that result is checked against that order. <br></br>If both conditions are not met the request will be rejected.
4191    ///
4192    /// This field is **optional.
4193    #[builder(setter(into), default)]
4194    #[serde(rename = "cancelOrderId", default)]
4195    pub cancel_order_id: Option<i64>,
4196    /// Either `cancelOrderId` or `cancelOrigClientOrderId` must be sent. <br></br> If both `cancelOrderId` and `cancelOrigClientOrderId` parameters are provided, the `cancelOrderId` is searched first, then the `cancelOrigClientOrderId` from that result is checked against that order. <br></br> If both conditions are not met the request will be rejected.
4197    ///
4198    /// This field is **optional.
4199    #[builder(setter(into), default)]
4200    #[serde(rename = "cancelOrigClientOrderId", default)]
4201    pub cancel_orig_client_order_id: Option<String>,
4202    /// Used to uniquely identify this cancel. Automatically generated by default.
4203    ///
4204    /// This field is **optional.
4205    #[builder(setter(into), default)]
4206    #[serde(rename = "cancelNewClientOrderId", default)]
4207    pub cancel_new_client_order_id: Option<String>,
4208    /// Please see [Enums](/products/spot/enums#timeinforce) for supported values.
4209    ///
4210    /// This field is **optional.
4211    #[builder(setter(into), default)]
4212    #[serde(rename = "timeInForce", default)]
4213    pub time_in_force: Option<OrderCancelReplaceTimeInForceEnum>,
4214    ///
4215    /// The `price` parameter.
4216    ///
4217    /// This field is **optional.
4218    #[builder(setter(into), default)]
4219    #[serde(rename = "price", default)]
4220    pub price: Option<rust_decimal::Decimal>,
4221    ///
4222    /// The `quantity` parameter.
4223    ///
4224    /// This field is **optional.
4225    #[builder(setter(into), default)]
4226    #[serde(rename = "quantity", default)]
4227    pub quantity: Option<rust_decimal::Decimal>,
4228    ///
4229    /// The `quote_order_qty` parameter.
4230    ///
4231    /// This field is **optional.
4232    #[builder(setter(into), default)]
4233    #[serde(rename = "quoteOrderQty", default)]
4234    pub quote_order_qty: Option<rust_decimal::Decimal>,
4235    /// Used to identify the new order.
4236    ///
4237    /// This field is **optional.
4238    #[builder(setter(into), default)]
4239    #[serde(rename = "newClientOrderId", default)]
4240    pub new_client_order_id: Option<String>,
4241    /// Allowed values: <br/> `ACK`, `RESULT`, `FULL` <br/> `MARKET` and `LIMIT` orders types default to `FULL`; all other orders default to `ACK`
4242    ///
4243    /// This field is **optional.
4244    #[builder(setter(into), default)]
4245    #[serde(rename = "newOrderRespType", default)]
4246    pub new_order_resp_type: Option<OrderCancelReplaceNewOrderRespTypeEnum>,
4247    /// Used with `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, and `TAKE_PROFIT_LIMIT` orders.
4248    ///
4249    /// This field is **optional.
4250    #[builder(setter(into), default)]
4251    #[serde(rename = "stopPrice", default)]
4252    pub stop_price: Option<rust_decimal::Decimal>,
4253    /// See [Trailing Stop order FAQ](/products/spot/faqs/trailing-stop-faq)
4254    ///
4255    /// This field is **optional.
4256    #[builder(setter(into), default)]
4257    #[serde(rename = "trailingDelta", default)]
4258    pub trailing_delta: Option<rust_decimal::Decimal>,
4259    /// Used with `LIMIT`, `STOP_LOSS_LIMIT`, and `TAKE_PROFIT_LIMIT` to create an iceberg order.
4260    ///
4261    /// This field is **optional.
4262    #[builder(setter(into), default)]
4263    #[serde(rename = "icebergQty", default)]
4264    pub iceberg_qty: Option<rust_decimal::Decimal>,
4265    ///
4266    /// The `strategy_id` parameter.
4267    ///
4268    /// This field is **optional.
4269    #[builder(setter(into), default)]
4270    #[serde(rename = "strategyId", default)]
4271    pub strategy_id: Option<i64>,
4272    /// The value cannot be less than `1000000`.
4273    ///
4274    /// This field is **optional.
4275    #[builder(setter(into), default)]
4276    #[serde(rename = "strategyType", default)]
4277    pub strategy_type: Option<i32>,
4278    /// The allowed enums is dependent on what is configured on the symbol. The possible supported values are: [STP Modes](/products/spot/enums#stpmodes).
4279    ///
4280    /// This field is **optional.
4281    #[builder(setter(into), default)]
4282    #[serde(rename = "selfTradePreventionMode", default)]
4283    pub self_trade_prevention_mode: Option<OrderCancelReplaceSelfTradePreventionModeEnum>,
4284    /// Supported values: <br>`ONLY_NEW` - Cancel will succeed if the order status is `NEW`.<br> `ONLY_PARTIALLY_FILLED` - Cancel will succeed if order status is `PARTIALLY_FILLED`.
4285    ///
4286    /// This field is **optional.
4287    #[builder(setter(into), default)]
4288    #[serde(rename = "cancelRestrictions", default)]
4289    pub cancel_restrictions: Option<OrderCancelReplaceCancelRestrictionsEnum>,
4290    /// Supported values: <br> `DO_NOTHING` (default)- will only attempt to cancel the order if account has not exceeded the unfilled order rate limit<br> `CANCEL_ONLY` - will always cancel the order
4291    ///
4292    /// This field is **optional.
4293    #[builder(setter(into), default)]
4294    #[serde(rename = "orderRateLimitExceededMode", default)]
4295    pub order_rate_limit_exceeded_mode: Option<OrderCancelReplaceOrderRateLimitExceededModeEnum>,
4296    /// `PRIMARY_PEG` or `MARKET_PEG` <br> See Pegged Orders
4297    ///
4298    /// This field is **optional.
4299    #[builder(setter(into), default)]
4300    #[serde(rename = "pegPriceType", default)]
4301    pub peg_price_type: Option<OrderCancelReplacePegPriceTypeEnum>,
4302    /// Price level to peg the price to (max: 100) <br> See Pegged Orders
4303    ///
4304    /// This field is **optional.
4305    #[builder(setter(into), default)]
4306    #[serde(rename = "pegOffsetValue", default)]
4307    pub peg_offset_value: Option<i32>,
4308    /// Only `PRICE_LEVEL` is supported <br> See Pegged Orders
4309    ///
4310    /// This field is **optional.
4311    #[builder(setter(into), default)]
4312    #[serde(rename = "pegOffsetType", default)]
4313    pub peg_offset_type: Option<OrderCancelReplacePegOffsetTypeEnum>,
4314    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4315    ///
4316    /// This field is **optional.
4317    #[builder(setter(into), default)]
4318    #[serde(rename = "recvWindow", default)]
4319    pub recv_window: Option<rust_decimal::Decimal>,
4320}
4321
4322impl OrderCancelReplaceParams {
4323    /// Create a builder for [`order_cancel_replace`].
4324    ///
4325    /// Required parameters:
4326    ///
4327    /// * `symbol` — String
4328    /// * `cancel_replace_mode` — The allowed values are: <br/> `STOP_ON_FAILURE` - If the cancel request fails, the new order placement will not be attempted. <br/> `ALLOW_FAILURE` - new order placement will be attempted even if cancel request fails.
4329    /// * `side` — Please see [Enums](/products/spot/enums#side) for supported values.
4330    /// * `r#type` — Please see [Enums](/products/spot/enums#ordertypes) for supported values.
4331    ///
4332    #[must_use]
4333    pub fn builder(
4334        symbol: String,
4335        cancel_replace_mode: OrderCancelReplaceCancelReplaceModeEnum,
4336        side: OrderCancelReplaceSideEnum,
4337        r#type: OrderCancelReplaceTypeEnum,
4338    ) -> OrderCancelReplaceParamsBuilder {
4339        OrderCancelReplaceParamsBuilder::default()
4340            .symbol(symbol)
4341            .cancel_replace_mode(cancel_replace_mode)
4342            .side(side)
4343            .r#type(r#type)
4344    }
4345}
4346/// Request parameters for the [`order_list_cancel`] operation.
4347///
4348/// This struct holds all of the inputs you can pass when calling
4349/// [`order_list_cancel`](#method.order_list_cancel).
4350#[derive(Clone, Debug, Builder, Deserialize)]
4351#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4352pub struct OrderListCancelParams {
4353    ///
4354    /// The `symbol` parameter.
4355    ///
4356    /// This field is **required.
4357    #[builder(setter(into))]
4358    #[serde(rename = "symbol")]
4359    pub symbol: String,
4360    /// Client-generated request identifier.
4361    ///
4362    /// This field is **optional.
4363    #[builder(setter(into), default)]
4364    #[serde(rename = "id", default)]
4365    pub id: Option<String>,
4366    /// Either `orderListId` or `listClientOrderId` must be provided
4367    ///
4368    /// This field is **optional.
4369    #[builder(setter(into), default)]
4370    #[serde(rename = "orderListId", default)]
4371    pub order_list_id: Option<i32>,
4372    /// Either `orderListId` or `listClientOrderId` must be provided
4373    ///
4374    /// This field is **optional.
4375    #[builder(setter(into), default)]
4376    #[serde(rename = "listClientOrderId", default)]
4377    pub list_client_order_id: Option<String>,
4378    /// Used to uniquely identify this cancel. Automatically generated by default.
4379    ///
4380    /// This field is **optional.
4381    #[builder(setter(into), default)]
4382    #[serde(rename = "newClientOrderId", default)]
4383    pub new_client_order_id: Option<String>,
4384    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4385    ///
4386    /// This field is **optional.
4387    #[builder(setter(into), default)]
4388    #[serde(rename = "recvWindow", default)]
4389    pub recv_window: Option<rust_decimal::Decimal>,
4390}
4391
4392impl OrderListCancelParams {
4393    /// Create a builder for [`order_list_cancel`].
4394    ///
4395    /// Required parameters:
4396    ///
4397    /// * `symbol` — String
4398    ///
4399    #[must_use]
4400    pub fn builder(symbol: String) -> OrderListCancelParamsBuilder {
4401        OrderListCancelParamsBuilder::default().symbol(symbol)
4402    }
4403}
4404/// Request parameters for the [`order_list_place`] operation.
4405///
4406/// This struct holds all of the inputs you can pass when calling
4407/// [`order_list_place`](#method.order_list_place).
4408#[derive(Clone, Debug, Builder, Deserialize)]
4409#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4410pub struct OrderListPlaceParams {
4411    ///
4412    /// The `symbol` parameter.
4413    ///
4414    /// This field is **required.
4415    #[builder(setter(into))]
4416    #[serde(rename = "symbol")]
4417    pub symbol: String,
4418    /// Please see [Enums](/products/spot/enums#side) for supported values.
4419    ///
4420    /// This field is **required.
4421    #[builder(setter(into))]
4422    #[serde(rename = "side")]
4423    pub side: OrderListPlaceSideEnum,
4424    ///
4425    /// The `price` parameter.
4426    ///
4427    /// This field is **required.
4428    #[builder(setter(into))]
4429    #[serde(rename = "price")]
4430    pub price: rust_decimal::Decimal,
4431    ///
4432    /// The `quantity` parameter.
4433    ///
4434    /// This field is **required.
4435    #[builder(setter(into))]
4436    #[serde(rename = "quantity")]
4437    pub quantity: rust_decimal::Decimal,
4438    /// Client-generated request identifier.
4439    ///
4440    /// This field is **optional.
4441    #[builder(setter(into), default)]
4442    #[serde(rename = "id", default)]
4443    pub id: Option<String>,
4444    /// A unique Id for the entire orderList
4445    ///
4446    /// This field is **optional.
4447    #[builder(setter(into), default)]
4448    #[serde(rename = "listClientOrderId", default)]
4449    pub list_client_order_id: Option<String>,
4450    /// A unique Id for the limit order
4451    ///
4452    /// This field is **optional.
4453    #[builder(setter(into), default)]
4454    #[serde(rename = "limitClientOrderId", default)]
4455    pub limit_client_order_id: Option<String>,
4456    /// Used to make the `LIMIT_MAKER` leg an iceberg order.
4457    ///
4458    /// This field is **optional.
4459    #[builder(setter(into), default)]
4460    #[serde(rename = "limitIcebergQty", default)]
4461    pub limit_iceberg_qty: Option<rust_decimal::Decimal>,
4462    ///
4463    /// The `limit_strategy_id` parameter.
4464    ///
4465    /// This field is **optional.
4466    #[builder(setter(into), default)]
4467    #[serde(rename = "limitStrategyId", default)]
4468    pub limit_strategy_id: Option<i64>,
4469    /// The value cannot be less than `1000000`.
4470    ///
4471    /// This field is **optional.
4472    #[builder(setter(into), default)]
4473    #[serde(rename = "limitStrategyType", default)]
4474    pub limit_strategy_type: Option<i32>,
4475    ///
4476    /// The `stop_price` parameter.
4477    ///
4478    /// This field is **optional.
4479    #[builder(setter(into), default)]
4480    #[serde(rename = "stopPrice", default)]
4481    pub stop_price: Option<rust_decimal::Decimal>,
4482    ///
4483    /// The `trailing_delta` parameter.
4484    ///
4485    /// This field is **optional.
4486    #[builder(setter(into), default)]
4487    #[serde(rename = "trailingDelta", default)]
4488    pub trailing_delta: Option<i32>,
4489    /// A unique Id for the stop loss/stop loss limit leg
4490    ///
4491    /// This field is **optional.
4492    #[builder(setter(into), default)]
4493    #[serde(rename = "stopClientOrderId", default)]
4494    pub stop_client_order_id: Option<String>,
4495    /// If provided, `stopLimitTimeInForce` is required.
4496    ///
4497    /// This field is **optional.
4498    #[builder(setter(into), default)]
4499    #[serde(rename = "stopLimitPrice", default)]
4500    pub stop_limit_price: Option<rust_decimal::Decimal>,
4501    /// Valid values are `GTC`/`FOK`/`IOC`
4502    ///
4503    /// This field is **optional.
4504    #[builder(setter(into), default)]
4505    #[serde(rename = "stopLimitTimeInForce", default)]
4506    pub stop_limit_time_in_force: Option<OrderListPlaceStopLimitTimeInForceEnum>,
4507    /// Used with `STOP_LOSS_LIMIT` leg to make an iceberg order.
4508    ///
4509    /// This field is **optional.
4510    #[builder(setter(into), default)]
4511    #[serde(rename = "stopIcebergQty", default)]
4512    pub stop_iceberg_qty: Option<rust_decimal::Decimal>,
4513    ///
4514    /// The `stop_strategy_id` parameter.
4515    ///
4516    /// This field is **optional.
4517    #[builder(setter(into), default)]
4518    #[serde(rename = "stopStrategyId", default)]
4519    pub stop_strategy_id: Option<i64>,
4520    /// The value cannot be less than `1000000`.
4521    ///
4522    /// This field is **optional.
4523    #[builder(setter(into), default)]
4524    #[serde(rename = "stopStrategyType", default)]
4525    pub stop_strategy_type: Option<i32>,
4526    /// Format of the JSON response. Supported values: [Order Response Type](/products/spot/enums#orderresponsetype)
4527    ///
4528    /// This field is **optional.
4529    #[builder(setter(into), default)]
4530    #[serde(rename = "newOrderRespType", default)]
4531    pub new_order_resp_type: Option<OrderListPlaceNewOrderRespTypeEnum>,
4532    /// The allowed values are dependent on what is configured on the symbol. Supported values: [STP Modes](/products/spot/enums#stpmodes)
4533    ///
4534    /// This field is **optional.
4535    #[builder(setter(into), default)]
4536    #[serde(rename = "selfTradePreventionMode", default)]
4537    pub self_trade_prevention_mode: Option<OrderListPlaceSelfTradePreventionModeEnum>,
4538    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4539    ///
4540    /// This field is **optional.
4541    #[builder(setter(into), default)]
4542    #[serde(rename = "recvWindow", default)]
4543    pub recv_window: Option<rust_decimal::Decimal>,
4544}
4545
4546impl OrderListPlaceParams {
4547    /// Create a builder for [`order_list_place`].
4548    ///
4549    /// Required parameters:
4550    ///
4551    /// * `symbol` — String
4552    /// * `side` — Please see [Enums](/products/spot/enums#side) for supported values.
4553    /// * `price` — `rust_decimal::Decimal`
4554    /// * `quantity` — `rust_decimal::Decimal`
4555    ///
4556    #[must_use]
4557    pub fn builder(
4558        symbol: String,
4559        side: OrderListPlaceSideEnum,
4560        price: rust_decimal::Decimal,
4561        quantity: rust_decimal::Decimal,
4562    ) -> OrderListPlaceParamsBuilder {
4563        OrderListPlaceParamsBuilder::default()
4564            .symbol(symbol)
4565            .side(side)
4566            .price(price)
4567            .quantity(quantity)
4568    }
4569}
4570/// Request parameters for the [`order_list_place_oco`] operation.
4571///
4572/// This struct holds all of the inputs you can pass when calling
4573/// [`order_list_place_oco`](#method.order_list_place_oco).
4574#[derive(Clone, Debug, Builder, Deserialize)]
4575#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4576pub struct OrderListPlaceOcoParams {
4577    ///
4578    /// The `symbol` parameter.
4579    ///
4580    /// This field is **required.
4581    #[builder(setter(into))]
4582    #[serde(rename = "symbol")]
4583    pub symbol: String,
4584    /// `BUY` or `SELL`
4585    ///
4586    /// This field is **required.
4587    #[builder(setter(into))]
4588    #[serde(rename = "side")]
4589    pub side: OrderListPlaceOcoSideEnum,
4590    /// Quantity for both orders of the order list.
4591    ///
4592    /// This field is **required.
4593    #[builder(setter(into))]
4594    #[serde(rename = "quantity")]
4595    pub quantity: rust_decimal::Decimal,
4596    ///
4597    /// The `above_type` parameter.
4598    ///
4599    /// This field is **required.
4600    #[builder(setter(into))]
4601    #[serde(rename = "aboveType")]
4602    pub above_type: OrderListPlaceOcoAboveTypeEnum,
4603    /// Supported values: `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`
4604    ///
4605    /// This field is **required.
4606    #[builder(setter(into))]
4607    #[serde(rename = "belowType")]
4608    pub below_type: OrderListPlaceOcoBelowTypeEnum,
4609    /// Client-generated request identifier.
4610    ///
4611    /// This field is **optional.
4612    #[builder(setter(into), default)]
4613    #[serde(rename = "id", default)]
4614    pub id: Option<String>,
4615    /// Arbitrary unique ID among open order lists. Automatically generated if not sent. A new order list with the same `listClientOrderId` is accepted only when the previous one is filled or completely expired. `listClientOrderId` is distinct from the `aboveClientOrderId` and the `belowClientOrderId`.
4616    ///
4617    /// This field is **optional.
4618    #[builder(setter(into), default)]
4619    #[serde(rename = "listClientOrderId", default)]
4620    pub list_client_order_id: Option<String>,
4621    /// Arbitrary unique ID among open orders for the above order. Automatically generated if not sent.
4622    ///
4623    /// This field is **optional.
4624    #[builder(setter(into), default)]
4625    #[serde(rename = "aboveClientOrderId", default)]
4626    pub above_client_order_id: Option<String>,
4627    /// Note that this can only be used if `aboveTimeInForce` is `GTC`.
4628    ///
4629    /// This field is **optional.
4630    #[builder(setter(into), default)]
4631    #[serde(rename = "aboveIcebergQty", default)]
4632    pub above_iceberg_qty: Option<i64>,
4633    /// Can be used if `aboveType` is `STOP_LOSS_LIMIT`, `LIMIT_MAKER`, or `TAKE_PROFIT_LIMIT` to specify the limit price.
4634    ///
4635    /// This field is **optional.
4636    #[builder(setter(into), default)]
4637    #[serde(rename = "abovePrice", default)]
4638    pub above_price: Option<rust_decimal::Decimal>,
4639    /// Can be used if `aboveType` is `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`. Either `aboveStopPrice` or `aboveTrailingDelta` or both, must be specified.
4640    ///
4641    /// This field is **optional.
4642    #[builder(setter(into), default)]
4643    #[serde(rename = "aboveStopPrice", default)]
4644    pub above_stop_price: Option<rust_decimal::Decimal>,
4645    /// See [Trailing Stop order FAQ](/products/spot/faqs/trailing-stop-faq)
4646    ///
4647    /// This field is **optional.
4648    #[builder(setter(into), default)]
4649    #[serde(rename = "aboveTrailingDelta", default)]
4650    pub above_trailing_delta: Option<i64>,
4651    /// Required if `aboveType` is `STOP_LOSS_LIMIT` or `TAKE_PROFIT_LIMIT`.
4652    ///
4653    /// This field is **optional.
4654    #[builder(setter(into), default)]
4655    #[serde(rename = "aboveTimeInForce", default)]
4656    pub above_time_in_force: Option<OrderListPlaceOcoAboveTimeInForceEnum>,
4657    /// Arbitrary numeric value identifying the above order within an order strategy.
4658    ///
4659    /// This field is **optional.
4660    #[builder(setter(into), default)]
4661    #[serde(rename = "aboveStrategyId", default)]
4662    pub above_strategy_id: Option<i64>,
4663    /// Arbitrary numeric value identifying the above order strategy. Values smaller than `1000000` are reserved and cannot be used.
4664    ///
4665    /// This field is **optional.
4666    #[builder(setter(into), default)]
4667    #[serde(rename = "aboveStrategyType", default)]
4668    pub above_strategy_type: Option<i32>,
4669    /// `PRIMARY_PEG` or `MARKET_PEG`. See [Pegged Orders](/products/spot/faqs/pegged_orders)
4670    ///
4671    /// This field is **optional.
4672    #[builder(setter(into), default)]
4673    #[serde(rename = "abovePegPriceType", default)]
4674    pub above_peg_price_type: Option<OrderListPlaceOcoAbovePegPriceTypeEnum>,
4675    ///
4676    /// The `above_peg_offset_type` parameter.
4677    ///
4678    /// This field is **optional.
4679    #[builder(setter(into), default)]
4680    #[serde(rename = "abovePegOffsetType", default)]
4681    pub above_peg_offset_type: Option<OrderListPlaceOcoAbovePegOffsetTypeEnum>,
4682    ///
4683    /// The `above_peg_offset_value` parameter.
4684    ///
4685    /// This field is **optional.
4686    #[builder(setter(into), default)]
4687    #[serde(rename = "abovePegOffsetValue", default)]
4688    pub above_peg_offset_value: Option<i32>,
4689    /// Arbitrary unique ID among open orders for the below order. Automatically generated if not sent.
4690    ///
4691    /// This field is **optional.
4692    #[builder(setter(into), default)]
4693    #[serde(rename = "belowClientOrderId", default)]
4694    pub below_client_order_id: Option<String>,
4695    /// Note that this can only be used if `belowTimeInForce` is `GTC`.
4696    ///
4697    /// This field is **optional.
4698    #[builder(setter(into), default)]
4699    #[serde(rename = "belowIcebergQty", default)]
4700    pub below_iceberg_qty: Option<i64>,
4701    /// Can be used if `belowType` is `STOP_LOSS_LIMIT`, `LIMIT_MAKER`, or `TAKE_PROFIT_LIMIT` to specify the limit price.
4702    ///
4703    /// This field is **optional.
4704    #[builder(setter(into), default)]
4705    #[serde(rename = "belowPrice", default)]
4706    pub below_price: Option<rust_decimal::Decimal>,
4707    /// Can be used if `belowType` is `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`. Either `belowStopPrice` or `belowTrailingDelta` or both, must be specified.
4708    ///
4709    /// This field is **optional.
4710    #[builder(setter(into), default)]
4711    #[serde(rename = "belowStopPrice", default)]
4712    pub below_stop_price: Option<rust_decimal::Decimal>,
4713    /// See [Trailing Stop order FAQ](/products/spot/faqs/trailing-stop-faq)
4714    ///
4715    /// This field is **optional.
4716    #[builder(setter(into), default)]
4717    #[serde(rename = "belowTrailingDelta", default)]
4718    pub below_trailing_delta: Option<i64>,
4719    /// Required if `belowType` is `STOP_LOSS_LIMIT` or `TAKE_PROFIT_LIMIT`.
4720    ///
4721    /// This field is **optional.
4722    #[builder(setter(into), default)]
4723    #[serde(rename = "belowTimeInForce", default)]
4724    pub below_time_in_force: Option<OrderListPlaceOcoBelowTimeInForceEnum>,
4725    /// Arbitrary numeric value identifying the below order within an order strategy.
4726    ///
4727    /// This field is **optional.
4728    #[builder(setter(into), default)]
4729    #[serde(rename = "belowStrategyId", default)]
4730    pub below_strategy_id: Option<i64>,
4731    /// Arbitrary numeric value identifying the below order strategy. Values smaller than `1000000` are reserved and cannot be used.
4732    ///
4733    /// This field is **optional.
4734    #[builder(setter(into), default)]
4735    #[serde(rename = "belowStrategyType", default)]
4736    pub below_strategy_type: Option<i32>,
4737    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
4738    ///
4739    /// This field is **optional.
4740    #[builder(setter(into), default)]
4741    #[serde(rename = "belowPegPriceType", default)]
4742    pub below_peg_price_type: Option<OrderListPlaceOcoBelowPegPriceTypeEnum>,
4743    ///
4744    /// The `below_peg_offset_type` parameter.
4745    ///
4746    /// This field is **optional.
4747    #[builder(setter(into), default)]
4748    #[serde(rename = "belowPegOffsetType", default)]
4749    pub below_peg_offset_type: Option<OrderListPlaceOcoBelowPegOffsetTypeEnum>,
4750    ///
4751    /// The `below_peg_offset_value` parameter.
4752    ///
4753    /// This field is **optional.
4754    #[builder(setter(into), default)]
4755    #[serde(rename = "belowPegOffsetValue", default)]
4756    pub below_peg_offset_value: Option<i32>,
4757    /// Select response format: `ACK`, `RESULT`, `FULL`.
4758    ///
4759    /// This field is **optional.
4760    #[builder(setter(into), default)]
4761    #[serde(rename = "newOrderRespType", default)]
4762    pub new_order_resp_type: Option<OrderListPlaceOcoNewOrderRespTypeEnum>,
4763    /// The allowed enums is dependent on what is configured on the symbol. Supported values: [STP Modes](/products/spot/enums#stpmodes)
4764    ///
4765    /// This field is **optional.
4766    #[builder(setter(into), default)]
4767    #[serde(rename = "selfTradePreventionMode", default)]
4768    pub self_trade_prevention_mode: Option<OrderListPlaceOcoSelfTradePreventionModeEnum>,
4769    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4770    ///
4771    /// This field is **optional.
4772    #[builder(setter(into), default)]
4773    #[serde(rename = "recvWindow", default)]
4774    pub recv_window: Option<rust_decimal::Decimal>,
4775}
4776
4777impl OrderListPlaceOcoParams {
4778    /// Create a builder for [`order_list_place_oco`].
4779    ///
4780    /// Required parameters:
4781    ///
4782    /// * `symbol` — String
4783    /// * `side` — `BUY` or `SELL`
4784    /// * `quantity` — Quantity for both orders of the order list.
4785    /// * `above_type` — String
4786    /// * `below_type` — Supported values: `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`
4787    ///
4788    #[must_use]
4789    pub fn builder(
4790        symbol: String,
4791        side: OrderListPlaceOcoSideEnum,
4792        quantity: rust_decimal::Decimal,
4793        above_type: OrderListPlaceOcoAboveTypeEnum,
4794        below_type: OrderListPlaceOcoBelowTypeEnum,
4795    ) -> OrderListPlaceOcoParamsBuilder {
4796        OrderListPlaceOcoParamsBuilder::default()
4797            .symbol(symbol)
4798            .side(side)
4799            .quantity(quantity)
4800            .above_type(above_type)
4801            .below_type(below_type)
4802    }
4803}
4804/// Request parameters for the [`order_list_place_opo`] operation.
4805///
4806/// This struct holds all of the inputs you can pass when calling
4807/// [`order_list_place_opo`](#method.order_list_place_opo).
4808#[derive(Clone, Debug, Builder, Deserialize)]
4809#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4810pub struct OrderListPlaceOpoParams {
4811    ///
4812    /// The `symbol` parameter.
4813    ///
4814    /// This field is **required.
4815    #[builder(setter(into))]
4816    #[serde(rename = "symbol")]
4817    pub symbol: String,
4818    /// Supported values: `LIMIT`, `LIMIT_MAKER`
4819    ///
4820    /// This field is **required.
4821    #[builder(setter(into))]
4822    #[serde(rename = "workingType")]
4823    pub working_type: OrderListPlaceOpoWorkingTypeEnum,
4824    /// Supported values: [Order Side](/products/spot/enums#side)
4825    ///
4826    /// This field is **required.
4827    #[builder(setter(into))]
4828    #[serde(rename = "workingSide")]
4829    pub working_side: OrderListPlaceOpoWorkingSideEnum,
4830    /// Price for the working order.
4831    ///
4832    /// This field is **required.
4833    #[builder(setter(into))]
4834    #[serde(rename = "workingPrice")]
4835    pub working_price: rust_decimal::Decimal,
4836    /// Sets the quantity for the working order.
4837    ///
4838    /// This field is **required.
4839    #[builder(setter(into))]
4840    #[serde(rename = "workingQuantity")]
4841    pub working_quantity: rust_decimal::Decimal,
4842    /// Supported values: [Order Types](/products/spot/enums#ordertypes). Note that `MARKET` orders using `quoteOrderQty` are not supported.
4843    ///
4844    /// This field is **required.
4845    #[builder(setter(into))]
4846    #[serde(rename = "pendingType")]
4847    pub pending_type: OrderListPlaceOpoPendingTypeEnum,
4848    /// Supported values: [Order Side](/products/spot/enums#side)
4849    ///
4850    /// This field is **required.
4851    #[builder(setter(into))]
4852    #[serde(rename = "pendingSide")]
4853    pub pending_side: OrderListPlaceOpoPendingSideEnum,
4854    /// Client-generated request identifier.
4855    ///
4856    /// This field is **optional.
4857    #[builder(setter(into), default)]
4858    #[serde(rename = "id", default)]
4859    pub id: Option<String>,
4860    /// Arbitrary unique ID among open order lists. Automatically generated if not sent. A new order list with the same `listClientOrderId` is accepted only when the previous one is filled or completely expired. `listClientOrderId` is distinct from the `workingClientOrderId` and the `pendingClientOrderId`.
4861    ///
4862    /// This field is **optional.
4863    #[builder(setter(into), default)]
4864    #[serde(rename = "listClientOrderId", default)]
4865    pub list_client_order_id: Option<String>,
4866    /// Format of the JSON response. Supported values: [Order Response Type](/products/spot/enums#orderresponsetype)
4867    ///
4868    /// This field is **optional.
4869    #[builder(setter(into), default)]
4870    #[serde(rename = "newOrderRespType", default)]
4871    pub new_order_resp_type: Option<OrderListPlaceOpoNewOrderRespTypeEnum>,
4872    /// The allowed enums is dependent on what is configured on the symbol. Supported values: [STP Modes](/products/spot/enums#stpmodes)
4873    ///
4874    /// This field is **optional.
4875    #[builder(setter(into), default)]
4876    #[serde(rename = "selfTradePreventionMode", default)]
4877    pub self_trade_prevention_mode: Option<OrderListPlaceOpoSelfTradePreventionModeEnum>,
4878    /// Arbitrary unique ID among open orders for the working order. Automatically generated if not sent.
4879    ///
4880    /// This field is **optional.
4881    #[builder(setter(into), default)]
4882    #[serde(rename = "workingClientOrderId", default)]
4883    pub working_client_order_id: Option<String>,
4884    /// This can only be used if `workingTimeInForce` is `GTC`, or if `workingType` is `LIMIT_MAKER`.
4885    ///
4886    /// This field is **optional.
4887    #[builder(setter(into), default)]
4888    #[serde(rename = "workingIcebergQty", default)]
4889    pub working_iceberg_qty: Option<rust_decimal::Decimal>,
4890    /// Supported values: [Time In Force](/products/spot/enums#timeinforce)
4891    ///
4892    /// This field is **optional.
4893    #[builder(setter(into), default)]
4894    #[serde(rename = "workingTimeInForce", default)]
4895    pub working_time_in_force: Option<OrderListPlaceOpoWorkingTimeInForceEnum>,
4896    /// Arbitrary numeric value identifying the working order within an order strategy.
4897    ///
4898    /// This field is **optional.
4899    #[builder(setter(into), default)]
4900    #[serde(rename = "workingStrategyId", default)]
4901    pub working_strategy_id: Option<i64>,
4902    /// Arbitrary numeric value identifying the working order strategy. Values smaller than `1000000` are reserved and cannot be used.
4903    ///
4904    /// This field is **optional.
4905    #[builder(setter(into), default)]
4906    #[serde(rename = "workingStrategyType", default)]
4907    pub working_strategy_type: Option<i32>,
4908    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
4909    ///
4910    /// This field is **optional.
4911    #[builder(setter(into), default)]
4912    #[serde(rename = "workingPegPriceType", default)]
4913    pub working_peg_price_type: Option<OrderListPlaceOpoWorkingPegPriceTypeEnum>,
4914    ///
4915    /// The `working_peg_offset_type` parameter.
4916    ///
4917    /// This field is **optional.
4918    #[builder(setter(into), default)]
4919    #[serde(rename = "workingPegOffsetType", default)]
4920    pub working_peg_offset_type: Option<OrderListPlaceOpoWorkingPegOffsetTypeEnum>,
4921    ///
4922    /// The `working_peg_offset_value` parameter.
4923    ///
4924    /// This field is **optional.
4925    #[builder(setter(into), default)]
4926    #[serde(rename = "workingPegOffsetValue", default)]
4927    pub working_peg_offset_value: Option<i32>,
4928    /// Arbitrary unique ID among open orders for the pending order. Automatically generated if not sent.
4929    ///
4930    /// This field is **optional.
4931    #[builder(setter(into), default)]
4932    #[serde(rename = "pendingClientOrderId", default)]
4933    pub pending_client_order_id: Option<String>,
4934    /// Price for the pending order.
4935    ///
4936    /// This field is **optional.
4937    #[builder(setter(into), default)]
4938    #[serde(rename = "pendingPrice", default)]
4939    pub pending_price: Option<rust_decimal::Decimal>,
4940    /// Stop price for the pending order.
4941    ///
4942    /// This field is **optional.
4943    #[builder(setter(into), default)]
4944    #[serde(rename = "pendingStopPrice", default)]
4945    pub pending_stop_price: Option<rust_decimal::Decimal>,
4946    /// Trailing delta for the pending order.
4947    ///
4948    /// This field is **optional.
4949    #[builder(setter(into), default)]
4950    #[serde(rename = "pendingTrailingDelta", default)]
4951    pub pending_trailing_delta: Option<rust_decimal::Decimal>,
4952    /// This can only be used if `pendingTimeInForce` is `GTC` or if `pendingType` is `LIMIT_MAKER`.
4953    ///
4954    /// This field is **optional.
4955    #[builder(setter(into), default)]
4956    #[serde(rename = "pendingIcebergQty", default)]
4957    pub pending_iceberg_qty: Option<rust_decimal::Decimal>,
4958    /// Supported values: [Time In Force](/products/spot/enums#timeinforce)
4959    ///
4960    /// This field is **optional.
4961    #[builder(setter(into), default)]
4962    #[serde(rename = "pendingTimeInForce", default)]
4963    pub pending_time_in_force: Option<OrderListPlaceOpoPendingTimeInForceEnum>,
4964    /// Arbitrary numeric value identifying the pending order within an order strategy.
4965    ///
4966    /// This field is **optional.
4967    #[builder(setter(into), default)]
4968    #[serde(rename = "pendingStrategyId", default)]
4969    pub pending_strategy_id: Option<i64>,
4970    /// Arbitrary numeric value identifying the pending order strategy. Values smaller than `1000000` are reserved and cannot be used.
4971    ///
4972    /// This field is **optional.
4973    #[builder(setter(into), default)]
4974    #[serde(rename = "pendingStrategyType", default)]
4975    pub pending_strategy_type: Option<i32>,
4976    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
4977    ///
4978    /// This field is **optional.
4979    #[builder(setter(into), default)]
4980    #[serde(rename = "pendingPegPriceType", default)]
4981    pub pending_peg_price_type: Option<OrderListPlaceOpoPendingPegPriceTypeEnum>,
4982    ///
4983    /// The `pending_peg_offset_type` parameter.
4984    ///
4985    /// This field is **optional.
4986    #[builder(setter(into), default)]
4987    #[serde(rename = "pendingPegOffsetType", default)]
4988    pub pending_peg_offset_type: Option<OrderListPlaceOpoPendingPegOffsetTypeEnum>,
4989    ///
4990    /// The `pending_peg_offset_value` parameter.
4991    ///
4992    /// This field is **optional.
4993    #[builder(setter(into), default)]
4994    #[serde(rename = "pendingPegOffsetValue", default)]
4995    pub pending_peg_offset_value: Option<i32>,
4996    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4997    ///
4998    /// This field is **optional.
4999    #[builder(setter(into), default)]
5000    #[serde(rename = "recvWindow", default)]
5001    pub recv_window: Option<rust_decimal::Decimal>,
5002}
5003
5004impl OrderListPlaceOpoParams {
5005    /// Create a builder for [`order_list_place_opo`].
5006    ///
5007    /// Required parameters:
5008    ///
5009    /// * `symbol` — String
5010    /// * `working_type` — Supported values: `LIMIT`, `LIMIT_MAKER`
5011    /// * `working_side` — Supported values: [Order Side](/products/spot/enums#side)
5012    /// * `working_price` — Price for the working order.
5013    /// * `working_quantity` — Sets the quantity for the working order.
5014    /// * `pending_type` — Supported values: [Order Types](/products/spot/enums#ordertypes). Note that `MARKET` orders using `quoteOrderQty` are not supported.
5015    /// * `pending_side` — Supported values: [Order Side](/products/spot/enums#side)
5016    ///
5017    #[must_use]
5018    pub fn builder(
5019        symbol: String,
5020        working_type: OrderListPlaceOpoWorkingTypeEnum,
5021        working_side: OrderListPlaceOpoWorkingSideEnum,
5022        working_price: rust_decimal::Decimal,
5023        working_quantity: rust_decimal::Decimal,
5024        pending_type: OrderListPlaceOpoPendingTypeEnum,
5025        pending_side: OrderListPlaceOpoPendingSideEnum,
5026    ) -> OrderListPlaceOpoParamsBuilder {
5027        OrderListPlaceOpoParamsBuilder::default()
5028            .symbol(symbol)
5029            .working_type(working_type)
5030            .working_side(working_side)
5031            .working_price(working_price)
5032            .working_quantity(working_quantity)
5033            .pending_type(pending_type)
5034            .pending_side(pending_side)
5035    }
5036}
5037/// Request parameters for the [`order_list_place_opoco`] operation.
5038///
5039/// This struct holds all of the inputs you can pass when calling
5040/// [`order_list_place_opoco`](#method.order_list_place_opoco).
5041#[derive(Clone, Debug, Builder, Deserialize)]
5042#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
5043pub struct OrderListPlaceOpocoParams {
5044    ///
5045    /// The `symbol` parameter.
5046    ///
5047    /// This field is **required.
5048    #[builder(setter(into))]
5049    #[serde(rename = "symbol")]
5050    pub symbol: String,
5051    ///
5052    /// The `working_type` parameter.
5053    ///
5054    /// This field is **required.
5055    #[builder(setter(into))]
5056    #[serde(rename = "workingType")]
5057    pub working_type: OrderListPlaceOpocoWorkingTypeEnum,
5058    /// Supported values: [Order Side](/products/spot/enums#side)
5059    ///
5060    /// This field is **required.
5061    #[builder(setter(into))]
5062    #[serde(rename = "workingSide")]
5063    pub working_side: OrderListPlaceOpocoWorkingSideEnum,
5064    /// Price for the working order.
5065    ///
5066    /// This field is **required.
5067    #[builder(setter(into))]
5068    #[serde(rename = "workingPrice")]
5069    pub working_price: rust_decimal::Decimal,
5070    /// Sets the quantity for the working order.
5071    ///
5072    /// This field is **required.
5073    #[builder(setter(into))]
5074    #[serde(rename = "workingQuantity")]
5075    pub working_quantity: rust_decimal::Decimal,
5076    /// Supported values: [Order Side](/products/spot/enums#side)
5077    ///
5078    /// This field is **required.
5079    #[builder(setter(into))]
5080    #[serde(rename = "pendingSide")]
5081    pub pending_side: OrderListPlaceOpocoPendingSideEnum,
5082    /// Supported values: `STOP_LOSS_LIMIT`, `STOP_LOSS`, `LIMIT_MAKER`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`
5083    ///
5084    /// This field is **required.
5085    #[builder(setter(into))]
5086    #[serde(rename = "pendingAboveType")]
5087    pub pending_above_type: OrderListPlaceOpocoPendingAboveTypeEnum,
5088    /// Client-generated request identifier.
5089    ///
5090    /// This field is **optional.
5091    #[builder(setter(into), default)]
5092    #[serde(rename = "id", default)]
5093    pub id: Option<String>,
5094    /// Arbitrary unique ID among open order lists. Automatically generated if not sent. A new order list with the same `listClientOrderId` is accepted only when the previous one is filled or completely expired. `listClientOrderId` is distinct from the `workingClientOrderId` and the `pendingClientOrderId`.
5095    ///
5096    /// This field is **optional.
5097    #[builder(setter(into), default)]
5098    #[serde(rename = "listClientOrderId", default)]
5099    pub list_client_order_id: Option<String>,
5100    /// Format of the JSON response. Supported values: [Order Response Type](/products/spot/enums#orderresponsetype)
5101    ///
5102    /// This field is **optional.
5103    #[builder(setter(into), default)]
5104    #[serde(rename = "newOrderRespType", default)]
5105    pub new_order_resp_type: Option<OrderListPlaceOpocoNewOrderRespTypeEnum>,
5106    /// The allowed enums is dependent on what is configured on the symbol. Supported values: [STP Modes](/products/spot/enums#stpmodes)
5107    ///
5108    /// This field is **optional.
5109    #[builder(setter(into), default)]
5110    #[serde(rename = "selfTradePreventionMode", default)]
5111    pub self_trade_prevention_mode: Option<OrderListPlaceOpocoSelfTradePreventionModeEnum>,
5112    /// Arbitrary unique ID among open orders for the working order. Automatically generated if not sent.
5113    ///
5114    /// This field is **optional.
5115    #[builder(setter(into), default)]
5116    #[serde(rename = "workingClientOrderId", default)]
5117    pub working_client_order_id: Option<String>,
5118    /// This can only be used if `workingTimeInForce` is `GTC`, or if `workingType` is `LIMIT_MAKER`.
5119    ///
5120    /// This field is **optional.
5121    #[builder(setter(into), default)]
5122    #[serde(rename = "workingIcebergQty", default)]
5123    pub working_iceberg_qty: Option<rust_decimal::Decimal>,
5124    /// Supported values: [Time In Force](/products/spot/enums#timeinforce)
5125    ///
5126    /// This field is **optional.
5127    #[builder(setter(into), default)]
5128    #[serde(rename = "workingTimeInForce", default)]
5129    pub working_time_in_force: Option<OrderListPlaceOpocoWorkingTimeInForceEnum>,
5130    /// Arbitrary numeric value identifying the working order within an order strategy.
5131    ///
5132    /// This field is **optional.
5133    #[builder(setter(into), default)]
5134    #[serde(rename = "workingStrategyId", default)]
5135    pub working_strategy_id: Option<i64>,
5136    /// Arbitrary numeric value identifying the working order strategy. Values smaller than `1000000` are reserved and cannot be used.
5137    ///
5138    /// This field is **optional.
5139    #[builder(setter(into), default)]
5140    #[serde(rename = "workingStrategyType", default)]
5141    pub working_strategy_type: Option<i32>,
5142    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
5143    ///
5144    /// This field is **optional.
5145    #[builder(setter(into), default)]
5146    #[serde(rename = "workingPegPriceType", default)]
5147    pub working_peg_price_type: Option<OrderListPlaceOpocoWorkingPegPriceTypeEnum>,
5148    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
5149    ///
5150    /// This field is **optional.
5151    #[builder(setter(into), default)]
5152    #[serde(rename = "workingPegOffsetType", default)]
5153    pub working_peg_offset_type: Option<OrderListPlaceOpocoWorkingPegOffsetTypeEnum>,
5154    /// Price level for pegging (max: 100). See [Pegged Orders](/products/spot/faqs/pegged_orders)
5155    ///
5156    /// This field is **optional.
5157    #[builder(setter(into), default)]
5158    #[serde(rename = "workingPegOffsetValue", default)]
5159    pub working_peg_offset_value: Option<i32>,
5160    /// Arbitrary unique ID among open orders for the pending above order. Automatically generated if not sent.
5161    ///
5162    /// This field is **optional.
5163    #[builder(setter(into), default)]
5164    #[serde(rename = "pendingAboveClientOrderId", default)]
5165    pub pending_above_client_order_id: Option<String>,
5166    /// Can be used if `pendingAboveType` is `STOP_LOSS_LIMIT`, `LIMIT_MAKER`, or `TAKE_PROFIT_LIMIT` to specify the limit price.
5167    ///
5168    /// This field is **optional.
5169    #[builder(setter(into), default)]
5170    #[serde(rename = "pendingAbovePrice", default)]
5171    pub pending_above_price: Option<rust_decimal::Decimal>,
5172    /// Can be used if `pendingAboveType` is `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`.
5173    ///
5174    /// This field is **optional.
5175    #[builder(setter(into), default)]
5176    #[serde(rename = "pendingAboveStopPrice", default)]
5177    pub pending_above_stop_price: Option<rust_decimal::Decimal>,
5178    /// See [Trailing Stop order FAQ](/products/spot/faqs/trailing-stop-faq)
5179    ///
5180    /// This field is **optional.
5181    #[builder(setter(into), default)]
5182    #[serde(rename = "pendingAboveTrailingDelta", default)]
5183    pub pending_above_trailing_delta: Option<rust_decimal::Decimal>,
5184    /// This can only be used if `pendingAboveTimeInForce` is `GTC` or `pendingAboveType` is `LIMIT_MAKER`.
5185    ///
5186    /// This field is **optional.
5187    #[builder(setter(into), default)]
5188    #[serde(rename = "pendingAboveIcebergQty", default)]
5189    pub pending_above_iceberg_qty: Option<rust_decimal::Decimal>,
5190    /// Required if `pendingAboveType` is `STOP_LOSS_LIMIT` or `TAKE_PROFIT_LIMIT`.
5191    ///
5192    /// This field is **optional.
5193    #[builder(setter(into), default)]
5194    #[serde(rename = "pendingAboveTimeInForce", default)]
5195    pub pending_above_time_in_force: Option<OrderListPlaceOpocoPendingAboveTimeInForceEnum>,
5196    /// Arbitrary numeric value identifying the pending above order within an order strategy.
5197    ///
5198    /// This field is **optional.
5199    #[builder(setter(into), default)]
5200    #[serde(rename = "pendingAboveStrategyId", default)]
5201    pub pending_above_strategy_id: Option<i64>,
5202    /// Arbitrary numeric value identifying the pending above order strategy. Values smaller than `1000000` are reserved and cannot be used.
5203    ///
5204    /// This field is **optional.
5205    #[builder(setter(into), default)]
5206    #[serde(rename = "pendingAboveStrategyType", default)]
5207    pub pending_above_strategy_type: Option<i32>,
5208    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
5209    ///
5210    /// This field is **optional.
5211    #[builder(setter(into), default)]
5212    #[serde(rename = "pendingAbovePegPriceType", default)]
5213    pub pending_above_peg_price_type: Option<OrderListPlaceOpocoPendingAbovePegPriceTypeEnum>,
5214    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
5215    ///
5216    /// This field is **optional.
5217    #[builder(setter(into), default)]
5218    #[serde(rename = "pendingAbovePegOffsetType", default)]
5219    pub pending_above_peg_offset_type: Option<OrderListPlaceOpocoPendingAbovePegOffsetTypeEnum>,
5220    /// Price level for pegging (max: 100). See [Pegged Orders](/products/spot/faqs/pegged_orders)
5221    ///
5222    /// This field is **optional.
5223    #[builder(setter(into), default)]
5224    #[serde(rename = "pendingAbovePegOffsetValue", default)]
5225    pub pending_above_peg_offset_value: Option<i32>,
5226    /// Supported values: `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`
5227    ///
5228    /// This field is **optional.
5229    #[builder(setter(into), default)]
5230    #[serde(rename = "pendingBelowType", default)]
5231    pub pending_below_type: Option<OrderListPlaceOpocoPendingBelowTypeEnum>,
5232    /// Arbitrary unique ID among open orders for the pending below order. Automatically generated if not sent.
5233    ///
5234    /// This field is **optional.
5235    #[builder(setter(into), default)]
5236    #[serde(rename = "pendingBelowClientOrderId", default)]
5237    pub pending_below_client_order_id: Option<String>,
5238    /// Can be used if `pendingBelowType` is `STOP_LOSS_LIMIT` or `TAKE_PROFIT_LIMIT` to specify the limit price.
5239    ///
5240    /// This field is **optional.
5241    #[builder(setter(into), default)]
5242    #[serde(rename = "pendingBelowPrice", default)]
5243    pub pending_below_price: Option<rust_decimal::Decimal>,
5244    /// Can be used if `pendingBelowType` is `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`. Either `pendingBelowStopPrice` or `pendingBelowTrailingDelta` or both, must be specified.
5245    ///
5246    /// This field is **optional.
5247    #[builder(setter(into), default)]
5248    #[serde(rename = "pendingBelowStopPrice", default)]
5249    pub pending_below_stop_price: Option<rust_decimal::Decimal>,
5250    /// See [Trailing Stop order FAQ](/products/spot/faqs/trailing-stop-faq)
5251    ///
5252    /// This field is **optional.
5253    #[builder(setter(into), default)]
5254    #[serde(rename = "pendingBelowTrailingDelta", default)]
5255    pub pending_below_trailing_delta: Option<rust_decimal::Decimal>,
5256    /// This can only be used if `pendingBelowTimeInForce` is `GTC` or `pendingBelowType` is `LIMIT_MAKER`.
5257    ///
5258    /// This field is **optional.
5259    #[builder(setter(into), default)]
5260    #[serde(rename = "pendingBelowIcebergQty", default)]
5261    pub pending_below_iceberg_qty: Option<rust_decimal::Decimal>,
5262    /// Supported values: [Time In Force](/products/spot/enums#timeinforce)
5263    ///
5264    /// This field is **optional.
5265    #[builder(setter(into), default)]
5266    #[serde(rename = "pendingBelowTimeInForce", default)]
5267    pub pending_below_time_in_force: Option<OrderListPlaceOpocoPendingBelowTimeInForceEnum>,
5268    /// Arbitrary numeric value identifying the pending below order within an order strategy.
5269    ///
5270    /// This field is **optional.
5271    #[builder(setter(into), default)]
5272    #[serde(rename = "pendingBelowStrategyId", default)]
5273    pub pending_below_strategy_id: Option<i64>,
5274    /// Arbitrary numeric value identifying the pending below order strategy. Values smaller than `1000000` are reserved and cannot be used.
5275    ///
5276    /// This field is **optional.
5277    #[builder(setter(into), default)]
5278    #[serde(rename = "pendingBelowStrategyType", default)]
5279    pub pending_below_strategy_type: Option<i32>,
5280    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
5281    ///
5282    /// This field is **optional.
5283    #[builder(setter(into), default)]
5284    #[serde(rename = "pendingBelowPegPriceType", default)]
5285    pub pending_below_peg_price_type: Option<OrderListPlaceOpocoPendingBelowPegPriceTypeEnum>,
5286    ///
5287    /// The `pending_below_peg_offset_type` parameter.
5288    ///
5289    /// This field is **optional.
5290    #[builder(setter(into), default)]
5291    #[serde(rename = "pendingBelowPegOffsetType", default)]
5292    pub pending_below_peg_offset_type: Option<OrderListPlaceOpocoPendingBelowPegOffsetTypeEnum>,
5293    ///
5294    /// The `pending_below_peg_offset_value` parameter.
5295    ///
5296    /// This field is **optional.
5297    #[builder(setter(into), default)]
5298    #[serde(rename = "pendingBelowPegOffsetValue", default)]
5299    pub pending_below_peg_offset_value: Option<i32>,
5300    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
5301    ///
5302    /// This field is **optional.
5303    #[builder(setter(into), default)]
5304    #[serde(rename = "recvWindow", default)]
5305    pub recv_window: Option<rust_decimal::Decimal>,
5306}
5307
5308impl OrderListPlaceOpocoParams {
5309    /// Create a builder for [`order_list_place_opoco`].
5310    ///
5311    /// Required parameters:
5312    ///
5313    /// * `symbol` — String
5314    /// * `working_type` — String
5315    /// * `working_side` — Supported values: [Order Side](/products/spot/enums#side)
5316    /// * `working_price` — Price for the working order.
5317    /// * `working_quantity` — Sets the quantity for the working order.
5318    /// * `pending_side` — Supported values: [Order Side](/products/spot/enums#side)
5319    /// * `pending_above_type` — Supported values: `STOP_LOSS_LIMIT`, `STOP_LOSS`, `LIMIT_MAKER`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`
5320    ///
5321    #[must_use]
5322    pub fn builder(
5323        symbol: String,
5324        working_type: OrderListPlaceOpocoWorkingTypeEnum,
5325        working_side: OrderListPlaceOpocoWorkingSideEnum,
5326        working_price: rust_decimal::Decimal,
5327        working_quantity: rust_decimal::Decimal,
5328        pending_side: OrderListPlaceOpocoPendingSideEnum,
5329        pending_above_type: OrderListPlaceOpocoPendingAboveTypeEnum,
5330    ) -> OrderListPlaceOpocoParamsBuilder {
5331        OrderListPlaceOpocoParamsBuilder::default()
5332            .symbol(symbol)
5333            .working_type(working_type)
5334            .working_side(working_side)
5335            .working_price(working_price)
5336            .working_quantity(working_quantity)
5337            .pending_side(pending_side)
5338            .pending_above_type(pending_above_type)
5339    }
5340}
5341/// Request parameters for the [`order_list_place_oto`] operation.
5342///
5343/// This struct holds all of the inputs you can pass when calling
5344/// [`order_list_place_oto`](#method.order_list_place_oto).
5345#[derive(Clone, Debug, Builder, Deserialize)]
5346#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
5347pub struct OrderListPlaceOtoParams {
5348    ///
5349    /// The `symbol` parameter.
5350    ///
5351    /// This field is **required.
5352    #[builder(setter(into))]
5353    #[serde(rename = "symbol")]
5354    pub symbol: String,
5355    /// Supported values: `LIMIT`, `LIMIT_MAKER`
5356    ///
5357    /// This field is **required.
5358    #[builder(setter(into))]
5359    #[serde(rename = "workingType")]
5360    pub working_type: OrderListPlaceOtoWorkingTypeEnum,
5361    /// Supported values: [Order Side](/products/spot/enums#side)
5362    ///
5363    /// This field is **required.
5364    #[builder(setter(into))]
5365    #[serde(rename = "workingSide")]
5366    pub working_side: OrderListPlaceOtoWorkingSideEnum,
5367    ///
5368    /// The `working_price` parameter.
5369    ///
5370    /// This field is **required.
5371    #[builder(setter(into))]
5372    #[serde(rename = "workingPrice")]
5373    pub working_price: rust_decimal::Decimal,
5374    /// Sets the quantity for the working order.
5375    ///
5376    /// This field is **required.
5377    #[builder(setter(into))]
5378    #[serde(rename = "workingQuantity")]
5379    pub working_quantity: rust_decimal::Decimal,
5380    /// Supported values: [Order Types](/products/spot/enums#ordertypes). Note that `MARKET` orders using `quoteOrderQty` are not supported.
5381    ///
5382    /// This field is **required.
5383    #[builder(setter(into))]
5384    #[serde(rename = "pendingType")]
5385    pub pending_type: OrderListPlaceOtoPendingTypeEnum,
5386    /// Supported values: [Order Side](/products/spot/enums#side)
5387    ///
5388    /// This field is **required.
5389    #[builder(setter(into))]
5390    #[serde(rename = "pendingSide")]
5391    pub pending_side: OrderListPlaceOtoPendingSideEnum,
5392    /// Sets the quantity for the pending order.
5393    ///
5394    /// This field is **required.
5395    #[builder(setter(into))]
5396    #[serde(rename = "pendingQuantity")]
5397    pub pending_quantity: rust_decimal::Decimal,
5398    /// Client-generated request identifier.
5399    ///
5400    /// This field is **optional.
5401    #[builder(setter(into), default)]
5402    #[serde(rename = "id", default)]
5403    pub id: Option<String>,
5404    /// Arbitrary unique ID among open order lists. Automatically generated if not sent. A new order list with the same `listClientOrderId` is accepted only when the previous one is filled or completely expired. `listClientOrderId` is distinct from the `workingClientOrderId` and the `pendingClientOrderId`.
5405    ///
5406    /// This field is **optional.
5407    #[builder(setter(into), default)]
5408    #[serde(rename = "listClientOrderId", default)]
5409    pub list_client_order_id: Option<String>,
5410    /// Format of the JSON response. Supported values: [Order Response Type](/products/spot/enums#orderresponsetype)
5411    ///
5412    /// This field is **optional.
5413    #[builder(setter(into), default)]
5414    #[serde(rename = "newOrderRespType", default)]
5415    pub new_order_resp_type: Option<OrderListPlaceOtoNewOrderRespTypeEnum>,
5416    /// The allowed enums is dependent on what is configured on the symbol. Supported values: [STP Modes](/products/spot/enums#stpmodes)
5417    ///
5418    /// This field is **optional.
5419    #[builder(setter(into), default)]
5420    #[serde(rename = "selfTradePreventionMode", default)]
5421    pub self_trade_prevention_mode: Option<OrderListPlaceOtoSelfTradePreventionModeEnum>,
5422    /// Arbitrary unique ID among open orders for the working order. Automatically generated if not sent.
5423    ///
5424    /// This field is **optional.
5425    #[builder(setter(into), default)]
5426    #[serde(rename = "workingClientOrderId", default)]
5427    pub working_client_order_id: Option<String>,
5428    /// This can only be used if `workingTimeInForce` is `GTC`, or if `workingType` is `LIMIT_MAKER`.
5429    ///
5430    /// This field is **optional.
5431    #[builder(setter(into), default)]
5432    #[serde(rename = "workingIcebergQty", default)]
5433    pub working_iceberg_qty: Option<rust_decimal::Decimal>,
5434    /// Supported values: [Time In Force](/products/spot/enums#timeinforce)
5435    ///
5436    /// This field is **optional.
5437    #[builder(setter(into), default)]
5438    #[serde(rename = "workingTimeInForce", default)]
5439    pub working_time_in_force: Option<OrderListPlaceOtoWorkingTimeInForceEnum>,
5440    /// Arbitrary numeric value identifying the working order within an order strategy.
5441    ///
5442    /// This field is **optional.
5443    #[builder(setter(into), default)]
5444    #[serde(rename = "workingStrategyId", default)]
5445    pub working_strategy_id: Option<i64>,
5446    /// Arbitrary numeric value identifying the working order strategy. Values smaller than `1000000` are reserved and cannot be used.
5447    ///
5448    /// This field is **optional.
5449    #[builder(setter(into), default)]
5450    #[serde(rename = "workingStrategyType", default)]
5451    pub working_strategy_type: Option<i32>,
5452    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
5453    ///
5454    /// This field is **optional.
5455    #[builder(setter(into), default)]
5456    #[serde(rename = "workingPegPriceType", default)]
5457    pub working_peg_price_type: Option<OrderListPlaceOtoWorkingPegPriceTypeEnum>,
5458    ///
5459    /// The `working_peg_offset_type` parameter.
5460    ///
5461    /// This field is **optional.
5462    #[builder(setter(into), default)]
5463    #[serde(rename = "workingPegOffsetType", default)]
5464    pub working_peg_offset_type: Option<OrderListPlaceOtoWorkingPegOffsetTypeEnum>,
5465    ///
5466    /// The `working_peg_offset_value` parameter.
5467    ///
5468    /// This field is **optional.
5469    #[builder(setter(into), default)]
5470    #[serde(rename = "workingPegOffsetValue", default)]
5471    pub working_peg_offset_value: Option<i32>,
5472    /// Arbitrary unique ID among open orders for the pending order. Automatically generated if not sent.
5473    ///
5474    /// This field is **optional.
5475    #[builder(setter(into), default)]
5476    #[serde(rename = "pendingClientOrderId", default)]
5477    pub pending_client_order_id: Option<String>,
5478    ///
5479    /// The `pending_price` parameter.
5480    ///
5481    /// This field is **optional.
5482    #[builder(setter(into), default)]
5483    #[serde(rename = "pendingPrice", default)]
5484    pub pending_price: Option<rust_decimal::Decimal>,
5485    ///
5486    /// The `pending_stop_price` parameter.
5487    ///
5488    /// This field is **optional.
5489    #[builder(setter(into), default)]
5490    #[serde(rename = "pendingStopPrice", default)]
5491    pub pending_stop_price: Option<rust_decimal::Decimal>,
5492    ///
5493    /// The `pending_trailing_delta` parameter.
5494    ///
5495    /// This field is **optional.
5496    #[builder(setter(into), default)]
5497    #[serde(rename = "pendingTrailingDelta", default)]
5498    pub pending_trailing_delta: Option<rust_decimal::Decimal>,
5499    /// This can only be used if `pendingTimeInForce` is `GTC` or if `pendingType` is `LIMIT_MAKER`.
5500    ///
5501    /// This field is **optional.
5502    #[builder(setter(into), default)]
5503    #[serde(rename = "pendingIcebergQty", default)]
5504    pub pending_iceberg_qty: Option<rust_decimal::Decimal>,
5505    /// Supported values: [Time In Force](/products/spot/enums#timeinforce)
5506    ///
5507    /// This field is **optional.
5508    #[builder(setter(into), default)]
5509    #[serde(rename = "pendingTimeInForce", default)]
5510    pub pending_time_in_force: Option<OrderListPlaceOtoPendingTimeInForceEnum>,
5511    /// Arbitrary numeric value identifying the pending order within an order strategy.
5512    ///
5513    /// This field is **optional.
5514    #[builder(setter(into), default)]
5515    #[serde(rename = "pendingStrategyId", default)]
5516    pub pending_strategy_id: Option<i64>,
5517    /// Arbitrary numeric value identifying the pending order strategy. Values smaller than `1000000` are reserved and cannot be used.
5518    ///
5519    /// This field is **optional.
5520    #[builder(setter(into), default)]
5521    #[serde(rename = "pendingStrategyType", default)]
5522    pub pending_strategy_type: Option<i32>,
5523    ///
5524    /// The `pending_peg_offset_type` parameter.
5525    ///
5526    /// This field is **optional.
5527    #[builder(setter(into), default)]
5528    #[serde(rename = "pendingPegOffsetType", default)]
5529    pub pending_peg_offset_type: Option<OrderListPlaceOtoPendingPegOffsetTypeEnum>,
5530    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
5531    ///
5532    /// This field is **optional.
5533    #[builder(setter(into), default)]
5534    #[serde(rename = "pendingPegPriceType", default)]
5535    pub pending_peg_price_type: Option<OrderListPlaceOtoPendingPegPriceTypeEnum>,
5536    ///
5537    /// The `pending_peg_offset_value` parameter.
5538    ///
5539    /// This field is **optional.
5540    #[builder(setter(into), default)]
5541    #[serde(rename = "pendingPegOffsetValue", default)]
5542    pub pending_peg_offset_value: Option<i32>,
5543    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
5544    ///
5545    /// This field is **optional.
5546    #[builder(setter(into), default)]
5547    #[serde(rename = "recvWindow", default)]
5548    pub recv_window: Option<rust_decimal::Decimal>,
5549}
5550
5551impl OrderListPlaceOtoParams {
5552    /// Create a builder for [`order_list_place_oto`].
5553    ///
5554    /// Required parameters:
5555    ///
5556    /// * `symbol` — String
5557    /// * `working_type` — Supported values: `LIMIT`, `LIMIT_MAKER`
5558    /// * `working_side` — Supported values: [Order Side](/products/spot/enums#side)
5559    /// * `working_price` — `rust_decimal::Decimal`
5560    /// * `working_quantity` — Sets the quantity for the working order.
5561    /// * `pending_type` — Supported values: [Order Types](/products/spot/enums#ordertypes). Note that `MARKET` orders using `quoteOrderQty` are not supported.
5562    /// * `pending_side` — Supported values: [Order Side](/products/spot/enums#side)
5563    /// * `pending_quantity` — Sets the quantity for the pending order.
5564    ///
5565    #[must_use]
5566    pub fn builder(
5567        symbol: String,
5568        working_type: OrderListPlaceOtoWorkingTypeEnum,
5569        working_side: OrderListPlaceOtoWorkingSideEnum,
5570        working_price: rust_decimal::Decimal,
5571        working_quantity: rust_decimal::Decimal,
5572        pending_type: OrderListPlaceOtoPendingTypeEnum,
5573        pending_side: OrderListPlaceOtoPendingSideEnum,
5574        pending_quantity: rust_decimal::Decimal,
5575    ) -> OrderListPlaceOtoParamsBuilder {
5576        OrderListPlaceOtoParamsBuilder::default()
5577            .symbol(symbol)
5578            .working_type(working_type)
5579            .working_side(working_side)
5580            .working_price(working_price)
5581            .working_quantity(working_quantity)
5582            .pending_type(pending_type)
5583            .pending_side(pending_side)
5584            .pending_quantity(pending_quantity)
5585    }
5586}
5587/// Request parameters for the [`order_list_place_otoco`] operation.
5588///
5589/// This struct holds all of the inputs you can pass when calling
5590/// [`order_list_place_otoco`](#method.order_list_place_otoco).
5591#[derive(Clone, Debug, Builder, Deserialize)]
5592#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
5593pub struct OrderListPlaceOtocoParams {
5594    ///
5595    /// The `symbol` parameter.
5596    ///
5597    /// This field is **required.
5598    #[builder(setter(into))]
5599    #[serde(rename = "symbol")]
5600    pub symbol: String,
5601    /// Supported values: `LIMIT`, `LIMIT_MAKER`
5602    ///
5603    /// This field is **required.
5604    #[builder(setter(into))]
5605    #[serde(rename = "workingType")]
5606    pub working_type: OrderListPlaceOtocoWorkingTypeEnum,
5607    /// Supported values: [Order Side](/products/spot/enums#side)
5608    ///
5609    /// This field is **required.
5610    #[builder(setter(into))]
5611    #[serde(rename = "workingSide")]
5612    pub working_side: OrderListPlaceOtocoWorkingSideEnum,
5613    ///
5614    /// The `working_price` parameter.
5615    ///
5616    /// This field is **required.
5617    #[builder(setter(into))]
5618    #[serde(rename = "workingPrice")]
5619    pub working_price: rust_decimal::Decimal,
5620    /// Sets the quantity for the working order.
5621    ///
5622    /// This field is **required.
5623    #[builder(setter(into))]
5624    #[serde(rename = "workingQuantity")]
5625    pub working_quantity: rust_decimal::Decimal,
5626    /// Supported values: [Order Side](/products/spot/enums#side)
5627    ///
5628    /// This field is **required.
5629    #[builder(setter(into))]
5630    #[serde(rename = "pendingSide")]
5631    pub pending_side: OrderListPlaceOtocoPendingSideEnum,
5632    /// Sets the quantity for the pending orders.
5633    ///
5634    /// This field is **required.
5635    #[builder(setter(into))]
5636    #[serde(rename = "pendingQuantity")]
5637    pub pending_quantity: rust_decimal::Decimal,
5638    /// Supported values: `STOP_LOSS_LIMIT`, `STOP_LOSS`, `LIMIT_MAKER`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`
5639    ///
5640    /// This field is **required.
5641    #[builder(setter(into))]
5642    #[serde(rename = "pendingAboveType")]
5643    pub pending_above_type: OrderListPlaceOtocoPendingAboveTypeEnum,
5644    /// Client-generated request identifier.
5645    ///
5646    /// This field is **optional.
5647    #[builder(setter(into), default)]
5648    #[serde(rename = "id", default)]
5649    pub id: Option<String>,
5650    /// Arbitrary unique ID among open order lists. Automatically generated if not sent. A new order list with the same `listClientOrderId` is accepted only when the previous one is filled or completely expired. `listClientOrderId` is distinct from the `workingClientOrderId` and the `pendingClientOrderId`.
5651    ///
5652    /// This field is **optional.
5653    #[builder(setter(into), default)]
5654    #[serde(rename = "listClientOrderId", default)]
5655    pub list_client_order_id: Option<String>,
5656    /// Format of the JSON response. Supported values: [Order Response Type](/products/spot/enums#orderresponsetype)
5657    ///
5658    /// This field is **optional.
5659    #[builder(setter(into), default)]
5660    #[serde(rename = "newOrderRespType", default)]
5661    pub new_order_resp_type: Option<OrderListPlaceOtocoNewOrderRespTypeEnum>,
5662    /// The allowed enums is dependent on what is configured on the symbol. Supported values: [STP Modes](/products/spot/enums#stpmodes)
5663    ///
5664    /// This field is **optional.
5665    #[builder(setter(into), default)]
5666    #[serde(rename = "selfTradePreventionMode", default)]
5667    pub self_trade_prevention_mode: Option<OrderListPlaceOtocoSelfTradePreventionModeEnum>,
5668    /// Arbitrary unique ID among open orders for the working order. Automatically generated if not sent.
5669    ///
5670    /// This field is **optional.
5671    #[builder(setter(into), default)]
5672    #[serde(rename = "workingClientOrderId", default)]
5673    pub working_client_order_id: Option<String>,
5674    /// This can only be used if `workingTimeInForce` is `GTC`, or if `workingType` is `LIMIT_MAKER`.
5675    ///
5676    /// This field is **optional.
5677    #[builder(setter(into), default)]
5678    #[serde(rename = "workingIcebergQty", default)]
5679    pub working_iceberg_qty: Option<rust_decimal::Decimal>,
5680    /// Supported values: [Time In Force](/products/spot/enums#timeinforce)
5681    ///
5682    /// This field is **optional.
5683    #[builder(setter(into), default)]
5684    #[serde(rename = "workingTimeInForce", default)]
5685    pub working_time_in_force: Option<OrderListPlaceOtocoWorkingTimeInForceEnum>,
5686    /// Arbitrary numeric value identifying the working order within an order strategy.
5687    ///
5688    /// This field is **optional.
5689    #[builder(setter(into), default)]
5690    #[serde(rename = "workingStrategyId", default)]
5691    pub working_strategy_id: Option<i64>,
5692    /// Arbitrary numeric value identifying the working order strategy. Values smaller than `1000000` are reserved and cannot be used.
5693    ///
5694    /// This field is **optional.
5695    #[builder(setter(into), default)]
5696    #[serde(rename = "workingStrategyType", default)]
5697    pub working_strategy_type: Option<i32>,
5698    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
5699    ///
5700    /// This field is **optional.
5701    #[builder(setter(into), default)]
5702    #[serde(rename = "workingPegPriceType", default)]
5703    pub working_peg_price_type: Option<OrderListPlaceOtocoWorkingPegPriceTypeEnum>,
5704    ///
5705    /// The `working_peg_offset_type` parameter.
5706    ///
5707    /// This field is **optional.
5708    #[builder(setter(into), default)]
5709    #[serde(rename = "workingPegOffsetType", default)]
5710    pub working_peg_offset_type: Option<OrderListPlaceOtocoWorkingPegOffsetTypeEnum>,
5711    ///
5712    /// The `working_peg_offset_value` parameter.
5713    ///
5714    /// This field is **optional.
5715    #[builder(setter(into), default)]
5716    #[serde(rename = "workingPegOffsetValue", default)]
5717    pub working_peg_offset_value: Option<i32>,
5718    /// Arbitrary unique ID among open orders for the pending above order. Automatically generated if not sent.
5719    ///
5720    /// This field is **optional.
5721    #[builder(setter(into), default)]
5722    #[serde(rename = "pendingAboveClientOrderId", default)]
5723    pub pending_above_client_order_id: Option<String>,
5724    /// Can be used if `pendingAboveType` is `STOP_LOSS_LIMIT`, `LIMIT_MAKER`, or `TAKE_PROFIT_LIMIT` to specify the limit price.
5725    ///
5726    /// This field is **optional.
5727    #[builder(setter(into), default)]
5728    #[serde(rename = "pendingAbovePrice", default)]
5729    pub pending_above_price: Option<rust_decimal::Decimal>,
5730    /// Can be used if `pendingAboveType` is `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`.
5731    ///
5732    /// This field is **optional.
5733    #[builder(setter(into), default)]
5734    #[serde(rename = "pendingAboveStopPrice", default)]
5735    pub pending_above_stop_price: Option<rust_decimal::Decimal>,
5736    /// See [Trailing Stop order FAQ](/products/spot/faqs/trailing-stop-faq)
5737    ///
5738    /// This field is **optional.
5739    #[builder(setter(into), default)]
5740    #[serde(rename = "pendingAboveTrailingDelta", default)]
5741    pub pending_above_trailing_delta: Option<rust_decimal::Decimal>,
5742    /// This can only be used if `pendingAboveTimeInForce` is `GTC` or if `pendingAboveType` is `LIMIT_MAKER`.
5743    ///
5744    /// This field is **optional.
5745    #[builder(setter(into), default)]
5746    #[serde(rename = "pendingAboveIcebergQty", default)]
5747    pub pending_above_iceberg_qty: Option<rust_decimal::Decimal>,
5748    /// Required if `pendingAboveType` is `STOP_LOSS_LIMIT` or `TAKE_PROFIT_LIMIT`.
5749    ///
5750    /// This field is **optional.
5751    #[builder(setter(into), default)]
5752    #[serde(rename = "pendingAboveTimeInForce", default)]
5753    pub pending_above_time_in_force: Option<OrderListPlaceOtocoPendingAboveTimeInForceEnum>,
5754    /// Arbitrary numeric value identifying the pending above order within an order strategy.
5755    ///
5756    /// This field is **optional.
5757    #[builder(setter(into), default)]
5758    #[serde(rename = "pendingAboveStrategyId", default)]
5759    pub pending_above_strategy_id: Option<i64>,
5760    /// Arbitrary numeric value identifying the pending above order strategy. Values smaller than `1000000` are reserved and cannot be used.
5761    ///
5762    /// This field is **optional.
5763    #[builder(setter(into), default)]
5764    #[serde(rename = "pendingAboveStrategyType", default)]
5765    pub pending_above_strategy_type: Option<i32>,
5766    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
5767    ///
5768    /// This field is **optional.
5769    #[builder(setter(into), default)]
5770    #[serde(rename = "pendingAbovePegPriceType", default)]
5771    pub pending_above_peg_price_type: Option<OrderListPlaceOtocoPendingAbovePegPriceTypeEnum>,
5772    ///
5773    /// The `pending_above_peg_offset_type` parameter.
5774    ///
5775    /// This field is **optional.
5776    #[builder(setter(into), default)]
5777    #[serde(rename = "pendingAbovePegOffsetType", default)]
5778    pub pending_above_peg_offset_type: Option<OrderListPlaceOtocoPendingAbovePegOffsetTypeEnum>,
5779    ///
5780    /// The `pending_above_peg_offset_value` parameter.
5781    ///
5782    /// This field is **optional.
5783    #[builder(setter(into), default)]
5784    #[serde(rename = "pendingAbovePegOffsetValue", default)]
5785    pub pending_above_peg_offset_value: Option<i32>,
5786    /// Supported values: `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`
5787    ///
5788    /// This field is **optional.
5789    #[builder(setter(into), default)]
5790    #[serde(rename = "pendingBelowType", default)]
5791    pub pending_below_type: Option<OrderListPlaceOtocoPendingBelowTypeEnum>,
5792    /// Arbitrary unique ID among open orders for the pending below order. Automatically generated if not sent.
5793    ///
5794    /// This field is **optional.
5795    #[builder(setter(into), default)]
5796    #[serde(rename = "pendingBelowClientOrderId", default)]
5797    pub pending_below_client_order_id: Option<String>,
5798    /// Can be used if `pendingBelowType` is `STOP_LOSS_LIMIT` or `TAKE_PROFIT_LIMIT` to specify the limit price.
5799    ///
5800    /// This field is **optional.
5801    #[builder(setter(into), default)]
5802    #[serde(rename = "pendingBelowPrice", default)]
5803    pub pending_below_price: Option<rust_decimal::Decimal>,
5804    /// Can be used if `pendingBelowType` is `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`. Either `pendingBelowStopPrice` or `pendingBelowTrailingDelta` or both, must be specified.
5805    ///
5806    /// This field is **optional.
5807    #[builder(setter(into), default)]
5808    #[serde(rename = "pendingBelowStopPrice", default)]
5809    pub pending_below_stop_price: Option<rust_decimal::Decimal>,
5810    /// See [Trailing Stop order FAQ](/products/spot/faqs/trailing-stop-faq)
5811    ///
5812    /// This field is **optional.
5813    #[builder(setter(into), default)]
5814    #[serde(rename = "pendingBelowTrailingDelta", default)]
5815    pub pending_below_trailing_delta: Option<rust_decimal::Decimal>,
5816    /// This can only be used if `pendingBelowTimeInForce` is `GTC`, or if `pendingBelowType` is `LIMIT_MAKER`.
5817    ///
5818    /// This field is **optional.
5819    #[builder(setter(into), default)]
5820    #[serde(rename = "pendingBelowIcebergQty", default)]
5821    pub pending_below_iceberg_qty: Option<rust_decimal::Decimal>,
5822    /// Required if `pendingBelowType` is `STOP_LOSS_LIMIT` or `TAKE_PROFIT_LIMIT`.
5823    ///
5824    /// This field is **optional.
5825    #[builder(setter(into), default)]
5826    #[serde(rename = "pendingBelowTimeInForce", default)]
5827    pub pending_below_time_in_force: Option<OrderListPlaceOtocoPendingBelowTimeInForceEnum>,
5828    /// Arbitrary numeric value identifying the pending below order within an order strategy.
5829    ///
5830    /// This field is **optional.
5831    #[builder(setter(into), default)]
5832    #[serde(rename = "pendingBelowStrategyId", default)]
5833    pub pending_below_strategy_id: Option<i64>,
5834    /// Arbitrary numeric value identifying the pending below order strategy. Values smaller than `1000000` are reserved and cannot be used.
5835    ///
5836    /// This field is **optional.
5837    #[builder(setter(into), default)]
5838    #[serde(rename = "pendingBelowStrategyType", default)]
5839    pub pending_below_strategy_type: Option<i32>,
5840    /// See [Pegged Orders](/products/spot/faqs/pegged_orders)
5841    ///
5842    /// This field is **optional.
5843    #[builder(setter(into), default)]
5844    #[serde(rename = "pendingBelowPegPriceType", default)]
5845    pub pending_below_peg_price_type: Option<OrderListPlaceOtocoPendingBelowPegPriceTypeEnum>,
5846    ///
5847    /// The `pending_below_peg_offset_type` parameter.
5848    ///
5849    /// This field is **optional.
5850    #[builder(setter(into), default)]
5851    #[serde(rename = "pendingBelowPegOffsetType", default)]
5852    pub pending_below_peg_offset_type: Option<OrderListPlaceOtocoPendingBelowPegOffsetTypeEnum>,
5853    ///
5854    /// The `pending_below_peg_offset_value` parameter.
5855    ///
5856    /// This field is **optional.
5857    #[builder(setter(into), default)]
5858    #[serde(rename = "pendingBelowPegOffsetValue", default)]
5859    pub pending_below_peg_offset_value: Option<i32>,
5860    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
5861    ///
5862    /// This field is **optional.
5863    #[builder(setter(into), default)]
5864    #[serde(rename = "recvWindow", default)]
5865    pub recv_window: Option<rust_decimal::Decimal>,
5866}
5867
5868impl OrderListPlaceOtocoParams {
5869    /// Create a builder for [`order_list_place_otoco`].
5870    ///
5871    /// Required parameters:
5872    ///
5873    /// * `symbol` — String
5874    /// * `working_type` — Supported values: `LIMIT`, `LIMIT_MAKER`
5875    /// * `working_side` — Supported values: [Order Side](/products/spot/enums#side)
5876    /// * `working_price` — `rust_decimal::Decimal`
5877    /// * `working_quantity` — Sets the quantity for the working order.
5878    /// * `pending_side` — Supported values: [Order Side](/products/spot/enums#side)
5879    /// * `pending_quantity` — Sets the quantity for the pending orders.
5880    /// * `pending_above_type` — Supported values: `STOP_LOSS_LIMIT`, `STOP_LOSS`, `LIMIT_MAKER`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`
5881    ///
5882    #[must_use]
5883    pub fn builder(
5884        symbol: String,
5885        working_type: OrderListPlaceOtocoWorkingTypeEnum,
5886        working_side: OrderListPlaceOtocoWorkingSideEnum,
5887        working_price: rust_decimal::Decimal,
5888        working_quantity: rust_decimal::Decimal,
5889        pending_side: OrderListPlaceOtocoPendingSideEnum,
5890        pending_quantity: rust_decimal::Decimal,
5891        pending_above_type: OrderListPlaceOtocoPendingAboveTypeEnum,
5892    ) -> OrderListPlaceOtocoParamsBuilder {
5893        OrderListPlaceOtocoParamsBuilder::default()
5894            .symbol(symbol)
5895            .working_type(working_type)
5896            .working_side(working_side)
5897            .working_price(working_price)
5898            .working_quantity(working_quantity)
5899            .pending_side(pending_side)
5900            .pending_quantity(pending_quantity)
5901            .pending_above_type(pending_above_type)
5902    }
5903}
5904/// Request parameters for the [`order_place`] operation.
5905///
5906/// This struct holds all of the inputs you can pass when calling
5907/// [`order_place`](#method.order_place).
5908#[derive(Clone, Debug, Builder, Deserialize)]
5909#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
5910pub struct OrderPlaceParams {
5911    ///
5912    /// The `symbol` parameter.
5913    ///
5914    /// This field is **required.
5915    #[builder(setter(into))]
5916    #[serde(rename = "symbol")]
5917    pub symbol: String,
5918    /// Please see [Enums](/products/spot/enums#side) for supported values.
5919    ///
5920    /// This field is **required.
5921    #[builder(setter(into))]
5922    #[serde(rename = "side")]
5923    pub side: OrderPlaceSideEnum,
5924    /// Please see [Enums](/products/spot/enums#ordertypes) for supported values.
5925    ///
5926    /// This field is **required.
5927    #[builder(setter(into))]
5928    #[serde(rename = "type")]
5929    pub r#type: OrderPlaceTypeEnum,
5930    /// Client-generated request identifier.
5931    ///
5932    /// This field is **optional.
5933    #[builder(setter(into), default)]
5934    #[serde(rename = "id", default)]
5935    pub id: Option<String>,
5936    /// Please see [Enums](/products/spot/enums#timeinforce) for supported values.
5937    ///
5938    /// This field is **optional.
5939    #[builder(setter(into), default)]
5940    #[serde(rename = "timeInForce", default)]
5941    pub time_in_force: Option<OrderPlaceTimeInForceEnum>,
5942    ///
5943    /// The `price` parameter.
5944    ///
5945    /// This field is **optional.
5946    #[builder(setter(into), default)]
5947    #[serde(rename = "price", default)]
5948    pub price: Option<rust_decimal::Decimal>,
5949    ///
5950    /// The `quantity` parameter.
5951    ///
5952    /// This field is **optional.
5953    #[builder(setter(into), default)]
5954    #[serde(rename = "quantity", default)]
5955    pub quantity: Option<rust_decimal::Decimal>,
5956    ///
5957    /// The `quote_order_qty` parameter.
5958    ///
5959    /// This field is **optional.
5960    #[builder(setter(into), default)]
5961    #[serde(rename = "quoteOrderQty", default)]
5962    pub quote_order_qty: Option<rust_decimal::Decimal>,
5963    /// A unique id among open orders. Automatically generated if not sent.<br/> Orders with the same `newClientOrderID` can be accepted only when the previous one is filled, otherwise the order will be rejected.
5964    ///
5965    /// This field is **optional.
5966    #[builder(setter(into), default)]
5967    #[serde(rename = "newClientOrderId", default)]
5968    pub new_client_order_id: Option<String>,
5969    /// `MARKET` and `LIMIT` order types default to `FULL`, all other orders default to `ACK`.
5970    ///
5971    /// This field is **optional.
5972    #[builder(setter(into), default)]
5973    #[serde(rename = "newOrderRespType", default)]
5974    pub new_order_resp_type: Option<OrderPlaceNewOrderRespTypeEnum>,
5975    /// Used with `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, and `TAKE_PROFIT_LIMIT` orders.
5976    ///
5977    /// This field is **optional.
5978    #[builder(setter(into), default)]
5979    #[serde(rename = "stopPrice", default)]
5980    pub stop_price: Option<rust_decimal::Decimal>,
5981    /// See Trailing Stop order FAQ
5982    ///
5983    /// This field is **optional.
5984    #[builder(setter(into), default)]
5985    #[serde(rename = "trailingDelta", default)]
5986    pub trailing_delta: Option<i32>,
5987    /// Used with `LIMIT`, `STOP_LOSS_LIMIT`, and `TAKE_PROFIT_LIMIT` to create an iceberg order.
5988    ///
5989    /// This field is **optional.
5990    #[builder(setter(into), default)]
5991    #[serde(rename = "icebergQty", default)]
5992    pub iceberg_qty: Option<rust_decimal::Decimal>,
5993    ///
5994    /// The `strategy_id` parameter.
5995    ///
5996    /// This field is **optional.
5997    #[builder(setter(into), default)]
5998    #[serde(rename = "strategyId", default)]
5999    pub strategy_id: Option<i64>,
6000    /// The value cannot be less than `1000000`.
6001    ///
6002    /// This field is **optional.
6003    #[builder(setter(into), default)]
6004    #[serde(rename = "strategyType", default)]
6005    pub strategy_type: Option<i32>,
6006    /// The allowed enums is dependent on what is configured on the symbol.
6007    ///
6008    /// This field is **optional.
6009    #[builder(setter(into), default)]
6010    #[serde(rename = "selfTradePreventionMode", default)]
6011    pub self_trade_prevention_mode: Option<OrderPlaceSelfTradePreventionModeEnum>,
6012    /// See Pegged Orders Info
6013    ///
6014    /// This field is **optional.
6015    #[builder(setter(into), default)]
6016    #[serde(rename = "pegPriceType", default)]
6017    pub peg_price_type: Option<OrderPlacePegPriceTypeEnum>,
6018    /// Price level to peg the price to (max: 100). See Pegged Orders Info
6019    ///
6020    /// This field is **optional.
6021    #[builder(setter(into), default)]
6022    #[serde(rename = "pegOffsetValue", default)]
6023    pub peg_offset_value: Option<i32>,
6024    /// Only `PRICE_LEVEL` is supported. See Pegged Orders Info
6025    ///
6026    /// This field is **optional.
6027    #[builder(setter(into), default)]
6028    #[serde(rename = "pegOffsetType", default)]
6029    pub peg_offset_type: Option<OrderPlacePegOffsetTypeEnum>,
6030    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
6031    ///
6032    /// This field is **optional.
6033    #[builder(setter(into), default)]
6034    #[serde(rename = "recvWindow", default)]
6035    pub recv_window: Option<rust_decimal::Decimal>,
6036}
6037
6038impl OrderPlaceParams {
6039    /// Create a builder for [`order_place`].
6040    ///
6041    /// Required parameters:
6042    ///
6043    /// * `symbol` — String
6044    /// * `side` — Please see [Enums](/products/spot/enums#side) for supported values.
6045    /// * `r#type` — Please see [Enums](/products/spot/enums#ordertypes) for supported values.
6046    ///
6047    #[must_use]
6048    pub fn builder(
6049        symbol: String,
6050        side: OrderPlaceSideEnum,
6051        r#type: OrderPlaceTypeEnum,
6052    ) -> OrderPlaceParamsBuilder {
6053        OrderPlaceParamsBuilder::default()
6054            .symbol(symbol)
6055            .side(side)
6056            .r#type(r#type)
6057    }
6058}
6059/// Request parameters for the [`order_test`] operation.
6060///
6061/// This struct holds all of the inputs you can pass when calling
6062/// [`order_test`](#method.order_test).
6063#[derive(Clone, Debug, Builder, Deserialize)]
6064#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
6065pub struct OrderTestParams {
6066    ///
6067    /// The `symbol` parameter.
6068    ///
6069    /// This field is **required.
6070    #[builder(setter(into))]
6071    #[serde(rename = "symbol")]
6072    pub symbol: String,
6073    /// Please see [Enums](/products/spot/enums#side) for supported values.
6074    ///
6075    /// This field is **required.
6076    #[builder(setter(into))]
6077    #[serde(rename = "side")]
6078    pub side: OrderTestSideEnum,
6079    /// Please see [Enums](/products/spot/enums#ordertypes) for supported values.
6080    ///
6081    /// This field is **required.
6082    #[builder(setter(into))]
6083    #[serde(rename = "type")]
6084    pub r#type: OrderTestTypeEnum,
6085    /// Client-generated request identifier.
6086    ///
6087    /// This field is **optional.
6088    #[builder(setter(into), default)]
6089    #[serde(rename = "id", default)]
6090    pub id: Option<String>,
6091    /// Default: `false` <br> See [Commissions FAQ](/products/spot/faqs/commission_faq#test-order-diferences) to learn more.
6092    ///
6093    /// This field is **optional.
6094    #[builder(setter(into), default)]
6095    #[serde(rename = "computeCommissionRates", default)]
6096    pub compute_commission_rates: Option<bool>,
6097    /// Please see [Enums](/products/spot/enums#timeinforce) for supported values.
6098    ///
6099    /// This field is **optional.
6100    #[builder(setter(into), default)]
6101    #[serde(rename = "timeInForce", default)]
6102    pub time_in_force: Option<OrderTestTimeInForceEnum>,
6103    ///
6104    /// The `price` parameter.
6105    ///
6106    /// This field is **optional.
6107    #[builder(setter(into), default)]
6108    #[serde(rename = "price", default)]
6109    pub price: Option<rust_decimal::Decimal>,
6110    ///
6111    /// The `quantity` parameter.
6112    ///
6113    /// This field is **optional.
6114    #[builder(setter(into), default)]
6115    #[serde(rename = "quantity", default)]
6116    pub quantity: Option<rust_decimal::Decimal>,
6117    ///
6118    /// The `quote_order_qty` parameter.
6119    ///
6120    /// This field is **optional.
6121    #[builder(setter(into), default)]
6122    #[serde(rename = "quoteOrderQty", default)]
6123    pub quote_order_qty: Option<rust_decimal::Decimal>,
6124    /// A unique id among open orders. Automatically generated if not sent. Orders with the same `newClientOrderID` can be accepted only when the previous one is filled, otherwise the order will be rejected.
6125    ///
6126    /// This field is **optional.
6127    #[builder(setter(into), default)]
6128    #[serde(rename = "newClientOrderId", default)]
6129    pub new_client_order_id: Option<String>,
6130    /// Set the response JSON. `ACK`, `RESULT`, or `FULL`; `MARKET` and `LIMIT` order types default to `FULL`, all other orders default to `ACK`.
6131    ///
6132    /// This field is **optional.
6133    #[builder(setter(into), default)]
6134    #[serde(rename = "newOrderRespType", default)]
6135    pub new_order_resp_type: Option<OrderTestNewOrderRespTypeEnum>,
6136    /// Used with `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, and `TAKE_PROFIT_LIMIT` orders.
6137    ///
6138    /// This field is **optional.
6139    #[builder(setter(into), default)]
6140    #[serde(rename = "stopPrice", default)]
6141    pub stop_price: Option<rust_decimal::Decimal>,
6142    /// See [Trailing Stop order FAQ](/products/spot/faqs/trailing-stop-faq)
6143    ///
6144    /// This field is **optional.
6145    #[builder(setter(into), default)]
6146    #[serde(rename = "trailingDelta", default)]
6147    pub trailing_delta: Option<i32>,
6148    /// Used with `LIMIT`, `STOP_LOSS_LIMIT`, and `TAKE_PROFIT_LIMIT` to create an iceberg order.
6149    ///
6150    /// This field is **optional.
6151    #[builder(setter(into), default)]
6152    #[serde(rename = "icebergQty", default)]
6153    pub iceberg_qty: Option<rust_decimal::Decimal>,
6154    ///
6155    /// The `strategy_id` parameter.
6156    ///
6157    /// This field is **optional.
6158    #[builder(setter(into), default)]
6159    #[serde(rename = "strategyId", default)]
6160    pub strategy_id: Option<i64>,
6161    /// The value cannot be less than `1000000`.
6162    ///
6163    /// This field is **optional.
6164    #[builder(setter(into), default)]
6165    #[serde(rename = "strategyType", default)]
6166    pub strategy_type: Option<i32>,
6167    /// The allowed enums is dependent on what is configured on the symbol. Supported values: [STP Modes](/products/spot/enums#stpmodes)
6168    ///
6169    /// This field is **optional.
6170    #[builder(setter(into), default)]
6171    #[serde(rename = "selfTradePreventionMode", default)]
6172    pub self_trade_prevention_mode: Option<OrderTestSelfTradePreventionModeEnum>,
6173    /// `PRIMARY_PEG` or `MARKET_PEG`. See [Pegged Orders](/products/spot/faqs/pegged_orders)
6174    ///
6175    /// This field is **optional.
6176    #[builder(setter(into), default)]
6177    #[serde(rename = "pegPriceType", default)]
6178    pub peg_price_type: Option<OrderTestPegPriceTypeEnum>,
6179    /// Price level for pegging (max: 100). See [Pegged Orders](/products/spot/faqs/pegged_orders)
6180    ///
6181    /// This field is **optional.
6182    #[builder(setter(into), default)]
6183    #[serde(rename = "pegOffsetValue", default)]
6184    pub peg_offset_value: Option<i32>,
6185    /// Only `PRICE_LEVEL` is supported. See [Pegged Orders](/products/spot/faqs/pegged_orders)
6186    ///
6187    /// This field is **optional.
6188    #[builder(setter(into), default)]
6189    #[serde(rename = "pegOffsetType", default)]
6190    pub peg_offset_type: Option<OrderTestPegOffsetTypeEnum>,
6191    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
6192    ///
6193    /// This field is **optional.
6194    #[builder(setter(into), default)]
6195    #[serde(rename = "recvWindow", default)]
6196    pub recv_window: Option<rust_decimal::Decimal>,
6197}
6198
6199impl OrderTestParams {
6200    /// Create a builder for [`order_test`].
6201    ///
6202    /// Required parameters:
6203    ///
6204    /// * `symbol` — String
6205    /// * `side` — Please see [Enums](/products/spot/enums#side) for supported values.
6206    /// * `r#type` — Please see [Enums](/products/spot/enums#ordertypes) for supported values.
6207    ///
6208    #[must_use]
6209    pub fn builder(
6210        symbol: String,
6211        side: OrderTestSideEnum,
6212        r#type: OrderTestTypeEnum,
6213    ) -> OrderTestParamsBuilder {
6214        OrderTestParamsBuilder::default()
6215            .symbol(symbol)
6216            .side(side)
6217            .r#type(r#type)
6218    }
6219}
6220/// Request parameters for the [`sor_order_place`] operation.
6221///
6222/// This struct holds all of the inputs you can pass when calling
6223/// [`sor_order_place`](#method.sor_order_place).
6224#[derive(Clone, Debug, Builder, Deserialize)]
6225#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
6226pub struct SorOrderPlaceParams {
6227    ///
6228    /// The `symbol` parameter.
6229    ///
6230    /// This field is **required.
6231    #[builder(setter(into))]
6232    #[serde(rename = "symbol")]
6233    pub symbol: String,
6234    /// `BUY` or `SELL`
6235    ///
6236    /// This field is **required.
6237    #[builder(setter(into))]
6238    #[serde(rename = "side")]
6239    pub side: SorOrderPlaceSideEnum,
6240    /// Only `LIMIT` and `MARKET` orders are supported.
6241    ///
6242    /// This field is **required.
6243    #[builder(setter(into))]
6244    #[serde(rename = "type")]
6245    pub r#type: SorOrderPlaceTypeEnum,
6246    ///
6247    /// The `quantity` parameter.
6248    ///
6249    /// This field is **required.
6250    #[builder(setter(into))]
6251    #[serde(rename = "quantity")]
6252    pub quantity: rust_decimal::Decimal,
6253    /// Client-generated request identifier.
6254    ///
6255    /// This field is **optional.
6256    #[builder(setter(into), default)]
6257    #[serde(rename = "id", default)]
6258    pub id: Option<String>,
6259    /// Applicable only to `LIMIT` order type.
6260    ///
6261    /// This field is **optional.
6262    #[builder(setter(into), default)]
6263    #[serde(rename = "timeInForce", default)]
6264    pub time_in_force: Option<SorOrderPlaceTimeInForceEnum>,
6265    ///
6266    /// The `price` parameter.
6267    ///
6268    /// This field is **optional.
6269    #[builder(setter(into), default)]
6270    #[serde(rename = "price", default)]
6271    pub price: Option<rust_decimal::Decimal>,
6272    /// A unique id among open orders. Automatically generated if not sent.<br/> Orders with the same `newClientOrderID` can be accepted only when the previous one is filled, otherwise the order will be rejected.
6273    ///
6274    /// This field is **optional.
6275    #[builder(setter(into), default)]
6276    #[serde(rename = "newClientOrderId", default)]
6277    pub new_client_order_id: Option<String>,
6278    /// Set the response JSON. `ACK`, `RESULT`, or `FULL`. Default to `FULL`
6279    ///
6280    /// This field is **optional.
6281    #[builder(setter(into), default)]
6282    #[serde(rename = "newOrderRespType", default)]
6283    pub new_order_resp_type: Option<SorOrderPlaceNewOrderRespTypeEnum>,
6284    /// Used with `LIMIT` to create an iceberg order.
6285    ///
6286    /// This field is **optional.
6287    #[builder(setter(into), default)]
6288    #[serde(rename = "icebergQty", default)]
6289    pub iceberg_qty: Option<rust_decimal::Decimal>,
6290    ///
6291    /// The `strategy_id` parameter.
6292    ///
6293    /// This field is **optional.
6294    #[builder(setter(into), default)]
6295    #[serde(rename = "strategyId", default)]
6296    pub strategy_id: Option<i64>,
6297    /// The value cannot be less than `1000000`.
6298    ///
6299    /// This field is **optional.
6300    #[builder(setter(into), default)]
6301    #[serde(rename = "strategyType", default)]
6302    pub strategy_type: Option<i32>,
6303    /// The allowed enums is dependent on what is configured on the symbol. The possible supported values are: [STP Modes](/products/spot/enums#stpmodes).
6304    ///
6305    /// This field is **optional.
6306    #[builder(setter(into), default)]
6307    #[serde(rename = "selfTradePreventionMode", default)]
6308    pub self_trade_prevention_mode: Option<SorOrderPlaceSelfTradePreventionModeEnum>,
6309    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
6310    ///
6311    /// This field is **optional.
6312    #[builder(setter(into), default)]
6313    #[serde(rename = "recvWindow", default)]
6314    pub recv_window: Option<rust_decimal::Decimal>,
6315}
6316
6317impl SorOrderPlaceParams {
6318    /// Create a builder for [`sor_order_place`].
6319    ///
6320    /// Required parameters:
6321    ///
6322    /// * `symbol` — String
6323    /// * `side` — `BUY` or `SELL`
6324    /// * `r#type` — Only `LIMIT` and `MARKET` orders are supported.
6325    /// * `quantity` — `rust_decimal::Decimal`
6326    ///
6327    #[must_use]
6328    pub fn builder(
6329        symbol: String,
6330        side: SorOrderPlaceSideEnum,
6331        r#type: SorOrderPlaceTypeEnum,
6332        quantity: rust_decimal::Decimal,
6333    ) -> SorOrderPlaceParamsBuilder {
6334        SorOrderPlaceParamsBuilder::default()
6335            .symbol(symbol)
6336            .side(side)
6337            .r#type(r#type)
6338            .quantity(quantity)
6339    }
6340}
6341/// Request parameters for the [`sor_order_test`] operation.
6342///
6343/// This struct holds all of the inputs you can pass when calling
6344/// [`sor_order_test`](#method.sor_order_test).
6345#[derive(Clone, Debug, Builder, Deserialize)]
6346#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
6347pub struct SorOrderTestParams {
6348    ///
6349    /// The `symbol` parameter.
6350    ///
6351    /// This field is **required.
6352    #[builder(setter(into))]
6353    #[serde(rename = "symbol")]
6354    pub symbol: String,
6355    /// Please see [Enums](/products/spot/enums#side) for supported values.
6356    ///
6357    /// This field is **required.
6358    #[builder(setter(into))]
6359    #[serde(rename = "side")]
6360    pub side: SorOrderTestSideEnum,
6361    /// Please see [Enums](/products/spot/enums#ordertypes) for supported values.
6362    ///
6363    /// This field is **required.
6364    #[builder(setter(into))]
6365    #[serde(rename = "type")]
6366    pub r#type: SorOrderTestTypeEnum,
6367    ///
6368    /// The `quantity` parameter.
6369    ///
6370    /// This field is **required.
6371    #[builder(setter(into))]
6372    #[serde(rename = "quantity")]
6373    pub quantity: rust_decimal::Decimal,
6374    /// Client-generated request identifier.
6375    ///
6376    /// This field is **optional.
6377    #[builder(setter(into), default)]
6378    #[serde(rename = "id", default)]
6379    pub id: Option<String>,
6380    /// Default: `false`
6381    ///
6382    /// This field is **optional.
6383    #[builder(setter(into), default)]
6384    #[serde(rename = "computeCommissionRates", default)]
6385    pub compute_commission_rates: Option<bool>,
6386    /// Please see [Enums](/products/spot/enums#timeinforce) for supported values.
6387    ///
6388    /// This field is **optional.
6389    #[builder(setter(into), default)]
6390    #[serde(rename = "timeInForce", default)]
6391    pub time_in_force: Option<SorOrderTestTimeInForceEnum>,
6392    ///
6393    /// The `price` parameter.
6394    ///
6395    /// This field is **optional.
6396    #[builder(setter(into), default)]
6397    #[serde(rename = "price", default)]
6398    pub price: Option<rust_decimal::Decimal>,
6399    /// A unique id among open orders. Automatically generated if not sent. Orders with the same `newClientOrderID` can be accepted only when the previous one is filled, otherwise the order will be rejected.
6400    ///
6401    /// This field is **optional.
6402    #[builder(setter(into), default)]
6403    #[serde(rename = "newClientOrderId", default)]
6404    pub new_client_order_id: Option<String>,
6405    /// Set the response JSON. `ACK`, `RESULT`, or `FULL`. Default to `FULL`.
6406    ///
6407    /// This field is **optional.
6408    #[builder(setter(into), default)]
6409    #[serde(rename = "newOrderRespType", default)]
6410    pub new_order_resp_type: Option<SorOrderTestNewOrderRespTypeEnum>,
6411    /// Used with `LIMIT` to create an iceberg order.
6412    ///
6413    /// This field is **optional.
6414    #[builder(setter(into), default)]
6415    #[serde(rename = "icebergQty", default)]
6416    pub iceberg_qty: Option<rust_decimal::Decimal>,
6417    ///
6418    /// The `strategy_id` parameter.
6419    ///
6420    /// This field is **optional.
6421    #[builder(setter(into), default)]
6422    #[serde(rename = "strategyId", default)]
6423    pub strategy_id: Option<i64>,
6424    /// The value cannot be less than `1000000`.
6425    ///
6426    /// This field is **optional.
6427    #[builder(setter(into), default)]
6428    #[serde(rename = "strategyType", default)]
6429    pub strategy_type: Option<i32>,
6430    /// The allowed enums is dependent on what is configured on the symbol. Supported values: [STP Modes](/products/spot/enums#stpmodes)
6431    ///
6432    /// This field is **optional.
6433    #[builder(setter(into), default)]
6434    #[serde(rename = "selfTradePreventionMode", default)]
6435    pub self_trade_prevention_mode: Option<SorOrderTestSelfTradePreventionModeEnum>,
6436    /// Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
6437    ///
6438    /// This field is **optional.
6439    #[builder(setter(into), default)]
6440    #[serde(rename = "recvWindow", default)]
6441    pub recv_window: Option<rust_decimal::Decimal>,
6442}
6443
6444impl SorOrderTestParams {
6445    /// Create a builder for [`sor_order_test`].
6446    ///
6447    /// Required parameters:
6448    ///
6449    /// * `symbol` — String
6450    /// * `side` — Please see [Enums](/products/spot/enums#side) for supported values.
6451    /// * `r#type` — Please see [Enums](/products/spot/enums#ordertypes) for supported values.
6452    /// * `quantity` — `rust_decimal::Decimal`
6453    ///
6454    #[must_use]
6455    pub fn builder(
6456        symbol: String,
6457        side: SorOrderTestSideEnum,
6458        r#type: SorOrderTestTypeEnum,
6459        quantity: rust_decimal::Decimal,
6460    ) -> SorOrderTestParamsBuilder {
6461        SorOrderTestParamsBuilder::default()
6462            .symbol(symbol)
6463            .side(side)
6464            .r#type(r#type)
6465            .quantity(quantity)
6466    }
6467}
6468
6469#[async_trait]
6470impl TradeApi for TradeApiClient {
6471    async fn open_orders_cancel_all(
6472        &self,
6473        params: OpenOrdersCancelAllParams,
6474    ) -> anyhow::Result<WebsocketApiResponse<Vec<models::OpenOrdersCancelAllResponseResultInner>>>
6475    {
6476        let OpenOrdersCancelAllParams {
6477            symbol,
6478            id,
6479            recv_window,
6480        } = params;
6481
6482        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6483        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6484        if let Some(value) = id {
6485            payload.insert("id".to_string(), serde_json::json!(value));
6486        }
6487        if let Some(value) = recv_window {
6488            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6489        }
6490        let payload = remove_empty_value(payload);
6491
6492        self.websocket_api_base
6493            .send_message::<Vec<models::OpenOrdersCancelAllResponseResultInner>>(
6494                "/openOrders.cancelAll".trim_start_matches('/'),
6495                payload,
6496                WebsocketMessageSendOptions::new().signed(),
6497            )
6498            .await
6499            .map_err(anyhow::Error::from)?
6500            .into_iter()
6501            .next()
6502            .ok_or(WebsocketError::NoResponse)
6503            .map_err(anyhow::Error::from)
6504    }
6505
6506    async fn order_amend_keep_priority(
6507        &self,
6508        params: OrderAmendKeepPriorityParams,
6509    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderAmendKeepPriorityResponseResult>>>
6510    {
6511        let OrderAmendKeepPriorityParams {
6512            symbol,
6513            new_qty,
6514            id,
6515            order_id,
6516            orig_client_order_id,
6517            new_client_order_id,
6518            recv_window,
6519        } = params;
6520
6521        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6522        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6523        payload.insert("newQty".to_string(), serde_json::json!(new_qty));
6524        if let Some(value) = id {
6525            payload.insert("id".to_string(), serde_json::json!(value));
6526        }
6527        if let Some(value) = order_id {
6528            payload.insert("orderId".to_string(), serde_json::json!(value));
6529        }
6530        if let Some(value) = orig_client_order_id {
6531            payload.insert("origClientOrderId".to_string(), serde_json::json!(value));
6532        }
6533        if let Some(value) = new_client_order_id {
6534            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
6535        }
6536        if let Some(value) = recv_window {
6537            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6538        }
6539        let payload = remove_empty_value(payload);
6540
6541        self.websocket_api_base
6542            .send_message::<Box<models::OrderAmendKeepPriorityResponseResult>>(
6543                "/order.amend.keepPriority".trim_start_matches('/'),
6544                payload,
6545                WebsocketMessageSendOptions::new().signed(),
6546            )
6547            .await
6548            .map_err(anyhow::Error::from)?
6549            .into_iter()
6550            .next()
6551            .ok_or(WebsocketError::NoResponse)
6552            .map_err(anyhow::Error::from)
6553    }
6554
6555    async fn order_cancel(
6556        &self,
6557        params: OrderCancelParams,
6558    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderCancelResponseResult>>> {
6559        let OrderCancelParams {
6560            symbol,
6561            id,
6562            order_id,
6563            orig_client_order_id,
6564            new_client_order_id,
6565            cancel_restrictions,
6566            recv_window,
6567        } = params;
6568
6569        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6570        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6571        if let Some(value) = id {
6572            payload.insert("id".to_string(), serde_json::json!(value));
6573        }
6574        if let Some(value) = order_id {
6575            payload.insert("orderId".to_string(), serde_json::json!(value));
6576        }
6577        if let Some(value) = orig_client_order_id {
6578            payload.insert("origClientOrderId".to_string(), serde_json::json!(value));
6579        }
6580        if let Some(value) = new_client_order_id {
6581            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
6582        }
6583        if let Some(value) = cancel_restrictions {
6584            payload.insert("cancelRestrictions".to_string(), serde_json::json!(value));
6585        }
6586        if let Some(value) = recv_window {
6587            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6588        }
6589        let payload = remove_empty_value(payload);
6590
6591        self.websocket_api_base
6592            .send_message::<Box<models::OrderCancelResponseResult>>(
6593                "/order.cancel".trim_start_matches('/'),
6594                payload,
6595                WebsocketMessageSendOptions::new().signed(),
6596            )
6597            .await
6598            .map_err(anyhow::Error::from)?
6599            .into_iter()
6600            .next()
6601            .ok_or(WebsocketError::NoResponse)
6602            .map_err(anyhow::Error::from)
6603    }
6604
6605    async fn order_cancel_replace(
6606        &self,
6607        params: OrderCancelReplaceParams,
6608    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderCancelReplaceResponseResult>>> {
6609        let OrderCancelReplaceParams {
6610            symbol,
6611            cancel_replace_mode,
6612            side,
6613            r#type,
6614            id,
6615            cancel_order_id,
6616            cancel_orig_client_order_id,
6617            cancel_new_client_order_id,
6618            time_in_force,
6619            price,
6620            quantity,
6621            quote_order_qty,
6622            new_client_order_id,
6623            new_order_resp_type,
6624            stop_price,
6625            trailing_delta,
6626            iceberg_qty,
6627            strategy_id,
6628            strategy_type,
6629            self_trade_prevention_mode,
6630            cancel_restrictions,
6631            order_rate_limit_exceeded_mode,
6632            peg_price_type,
6633            peg_offset_value,
6634            peg_offset_type,
6635            recv_window,
6636        } = params;
6637
6638        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6639        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6640        payload.insert(
6641            "cancelReplaceMode".to_string(),
6642            serde_json::json!(cancel_replace_mode),
6643        );
6644        payload.insert("side".to_string(), serde_json::json!(side));
6645        payload.insert("type".to_string(), serde_json::json!(r#type));
6646        if let Some(value) = id {
6647            payload.insert("id".to_string(), serde_json::json!(value));
6648        }
6649        if let Some(value) = cancel_order_id {
6650            payload.insert("cancelOrderId".to_string(), serde_json::json!(value));
6651        }
6652        if let Some(value) = cancel_orig_client_order_id {
6653            payload.insert(
6654                "cancelOrigClientOrderId".to_string(),
6655                serde_json::json!(value),
6656            );
6657        }
6658        if let Some(value) = cancel_new_client_order_id {
6659            payload.insert(
6660                "cancelNewClientOrderId".to_string(),
6661                serde_json::json!(value),
6662            );
6663        }
6664        if let Some(value) = time_in_force {
6665            payload.insert("timeInForce".to_string(), serde_json::json!(value));
6666        }
6667        if let Some(value) = price {
6668            payload.insert("price".to_string(), serde_json::json!(value));
6669        }
6670        if let Some(value) = quantity {
6671            payload.insert("quantity".to_string(), serde_json::json!(value));
6672        }
6673        if let Some(value) = quote_order_qty {
6674            payload.insert("quoteOrderQty".to_string(), serde_json::json!(value));
6675        }
6676        if let Some(value) = new_client_order_id {
6677            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
6678        }
6679        if let Some(value) = new_order_resp_type {
6680            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
6681        }
6682        if let Some(value) = stop_price {
6683            payload.insert("stopPrice".to_string(), serde_json::json!(value));
6684        }
6685        if let Some(value) = trailing_delta {
6686            payload.insert("trailingDelta".to_string(), serde_json::json!(value));
6687        }
6688        if let Some(value) = iceberg_qty {
6689            payload.insert("icebergQty".to_string(), serde_json::json!(value));
6690        }
6691        if let Some(value) = strategy_id {
6692            payload.insert("strategyId".to_string(), serde_json::json!(value));
6693        }
6694        if let Some(value) = strategy_type {
6695            payload.insert("strategyType".to_string(), serde_json::json!(value));
6696        }
6697        if let Some(value) = self_trade_prevention_mode {
6698            payload.insert(
6699                "selfTradePreventionMode".to_string(),
6700                serde_json::json!(value),
6701            );
6702        }
6703        if let Some(value) = cancel_restrictions {
6704            payload.insert("cancelRestrictions".to_string(), serde_json::json!(value));
6705        }
6706        if let Some(value) = order_rate_limit_exceeded_mode {
6707            payload.insert(
6708                "orderRateLimitExceededMode".to_string(),
6709                serde_json::json!(value),
6710            );
6711        }
6712        if let Some(value) = peg_price_type {
6713            payload.insert("pegPriceType".to_string(), serde_json::json!(value));
6714        }
6715        if let Some(value) = peg_offset_value {
6716            payload.insert("pegOffsetValue".to_string(), serde_json::json!(value));
6717        }
6718        if let Some(value) = peg_offset_type {
6719            payload.insert("pegOffsetType".to_string(), serde_json::json!(value));
6720        }
6721        if let Some(value) = recv_window {
6722            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6723        }
6724        let payload = remove_empty_value(payload);
6725
6726        self.websocket_api_base
6727            .send_message::<Box<models::OrderCancelReplaceResponseResult>>(
6728                "/order.cancelReplace".trim_start_matches('/'),
6729                payload,
6730                WebsocketMessageSendOptions::new().signed(),
6731            )
6732            .await
6733            .map_err(anyhow::Error::from)?
6734            .into_iter()
6735            .next()
6736            .ok_or(WebsocketError::NoResponse)
6737            .map_err(anyhow::Error::from)
6738    }
6739
6740    async fn order_list_cancel(
6741        &self,
6742        params: OrderListCancelParams,
6743    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListCancelResponseResult>>> {
6744        let OrderListCancelParams {
6745            symbol,
6746            id,
6747            order_list_id,
6748            list_client_order_id,
6749            new_client_order_id,
6750            recv_window,
6751        } = params;
6752
6753        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6754        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6755        if let Some(value) = id {
6756            payload.insert("id".to_string(), serde_json::json!(value));
6757        }
6758        if let Some(value) = order_list_id {
6759            payload.insert("orderListId".to_string(), serde_json::json!(value));
6760        }
6761        if let Some(value) = list_client_order_id {
6762            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
6763        }
6764        if let Some(value) = new_client_order_id {
6765            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
6766        }
6767        if let Some(value) = recv_window {
6768            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6769        }
6770        let payload = remove_empty_value(payload);
6771
6772        self.websocket_api_base
6773            .send_message::<Box<models::OrderListCancelResponseResult>>(
6774                "/orderList.cancel".trim_start_matches('/'),
6775                payload,
6776                WebsocketMessageSendOptions::new().signed(),
6777            )
6778            .await
6779            .map_err(anyhow::Error::from)?
6780            .into_iter()
6781            .next()
6782            .ok_or(WebsocketError::NoResponse)
6783            .map_err(anyhow::Error::from)
6784    }
6785
6786    async fn order_list_place(
6787        &self,
6788        params: OrderListPlaceParams,
6789    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceResponseResult>>> {
6790        let OrderListPlaceParams {
6791            symbol,
6792            side,
6793            price,
6794            quantity,
6795            id,
6796            list_client_order_id,
6797            limit_client_order_id,
6798            limit_iceberg_qty,
6799            limit_strategy_id,
6800            limit_strategy_type,
6801            stop_price,
6802            trailing_delta,
6803            stop_client_order_id,
6804            stop_limit_price,
6805            stop_limit_time_in_force,
6806            stop_iceberg_qty,
6807            stop_strategy_id,
6808            stop_strategy_type,
6809            new_order_resp_type,
6810            self_trade_prevention_mode,
6811            recv_window,
6812        } = params;
6813
6814        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6815        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6816        payload.insert("side".to_string(), serde_json::json!(side));
6817        payload.insert("price".to_string(), serde_json::json!(price));
6818        payload.insert("quantity".to_string(), serde_json::json!(quantity));
6819        if let Some(value) = id {
6820            payload.insert("id".to_string(), serde_json::json!(value));
6821        }
6822        if let Some(value) = list_client_order_id {
6823            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
6824        }
6825        if let Some(value) = limit_client_order_id {
6826            payload.insert("limitClientOrderId".to_string(), serde_json::json!(value));
6827        }
6828        if let Some(value) = limit_iceberg_qty {
6829            payload.insert("limitIcebergQty".to_string(), serde_json::json!(value));
6830        }
6831        if let Some(value) = limit_strategy_id {
6832            payload.insert("limitStrategyId".to_string(), serde_json::json!(value));
6833        }
6834        if let Some(value) = limit_strategy_type {
6835            payload.insert("limitStrategyType".to_string(), serde_json::json!(value));
6836        }
6837        if let Some(value) = stop_price {
6838            payload.insert("stopPrice".to_string(), serde_json::json!(value));
6839        }
6840        if let Some(value) = trailing_delta {
6841            payload.insert("trailingDelta".to_string(), serde_json::json!(value));
6842        }
6843        if let Some(value) = stop_client_order_id {
6844            payload.insert("stopClientOrderId".to_string(), serde_json::json!(value));
6845        }
6846        if let Some(value) = stop_limit_price {
6847            payload.insert("stopLimitPrice".to_string(), serde_json::json!(value));
6848        }
6849        if let Some(value) = stop_limit_time_in_force {
6850            payload.insert("stopLimitTimeInForce".to_string(), serde_json::json!(value));
6851        }
6852        if let Some(value) = stop_iceberg_qty {
6853            payload.insert("stopIcebergQty".to_string(), serde_json::json!(value));
6854        }
6855        if let Some(value) = stop_strategy_id {
6856            payload.insert("stopStrategyId".to_string(), serde_json::json!(value));
6857        }
6858        if let Some(value) = stop_strategy_type {
6859            payload.insert("stopStrategyType".to_string(), serde_json::json!(value));
6860        }
6861        if let Some(value) = new_order_resp_type {
6862            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
6863        }
6864        if let Some(value) = self_trade_prevention_mode {
6865            payload.insert(
6866                "selfTradePreventionMode".to_string(),
6867                serde_json::json!(value),
6868            );
6869        }
6870        if let Some(value) = recv_window {
6871            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6872        }
6873        let payload = remove_empty_value(payload);
6874
6875        self.websocket_api_base
6876            .send_message::<Box<models::OrderListPlaceResponseResult>>(
6877                "/orderList.place".trim_start_matches('/'),
6878                payload,
6879                WebsocketMessageSendOptions::new().signed(),
6880            )
6881            .await
6882            .map_err(anyhow::Error::from)?
6883            .into_iter()
6884            .next()
6885            .ok_or(WebsocketError::NoResponse)
6886            .map_err(anyhow::Error::from)
6887    }
6888
6889    async fn order_list_place_oco(
6890        &self,
6891        params: OrderListPlaceOcoParams,
6892    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOcoResponseResult>>> {
6893        let OrderListPlaceOcoParams {
6894            symbol,
6895            side,
6896            quantity,
6897            above_type,
6898            below_type,
6899            id,
6900            list_client_order_id,
6901            above_client_order_id,
6902            above_iceberg_qty,
6903            above_price,
6904            above_stop_price,
6905            above_trailing_delta,
6906            above_time_in_force,
6907            above_strategy_id,
6908            above_strategy_type,
6909            above_peg_price_type,
6910            above_peg_offset_type,
6911            above_peg_offset_value,
6912            below_client_order_id,
6913            below_iceberg_qty,
6914            below_price,
6915            below_stop_price,
6916            below_trailing_delta,
6917            below_time_in_force,
6918            below_strategy_id,
6919            below_strategy_type,
6920            below_peg_price_type,
6921            below_peg_offset_type,
6922            below_peg_offset_value,
6923            new_order_resp_type,
6924            self_trade_prevention_mode,
6925            recv_window,
6926        } = params;
6927
6928        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6929        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6930        payload.insert("side".to_string(), serde_json::json!(side));
6931        payload.insert("quantity".to_string(), serde_json::json!(quantity));
6932        payload.insert("aboveType".to_string(), serde_json::json!(above_type));
6933        payload.insert("belowType".to_string(), serde_json::json!(below_type));
6934        if let Some(value) = id {
6935            payload.insert("id".to_string(), serde_json::json!(value));
6936        }
6937        if let Some(value) = list_client_order_id {
6938            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
6939        }
6940        if let Some(value) = above_client_order_id {
6941            payload.insert("aboveClientOrderId".to_string(), serde_json::json!(value));
6942        }
6943        if let Some(value) = above_iceberg_qty {
6944            payload.insert("aboveIcebergQty".to_string(), serde_json::json!(value));
6945        }
6946        if let Some(value) = above_price {
6947            payload.insert("abovePrice".to_string(), serde_json::json!(value));
6948        }
6949        if let Some(value) = above_stop_price {
6950            payload.insert("aboveStopPrice".to_string(), serde_json::json!(value));
6951        }
6952        if let Some(value) = above_trailing_delta {
6953            payload.insert("aboveTrailingDelta".to_string(), serde_json::json!(value));
6954        }
6955        if let Some(value) = above_time_in_force {
6956            payload.insert("aboveTimeInForce".to_string(), serde_json::json!(value));
6957        }
6958        if let Some(value) = above_strategy_id {
6959            payload.insert("aboveStrategyId".to_string(), serde_json::json!(value));
6960        }
6961        if let Some(value) = above_strategy_type {
6962            payload.insert("aboveStrategyType".to_string(), serde_json::json!(value));
6963        }
6964        if let Some(value) = above_peg_price_type {
6965            payload.insert("abovePegPriceType".to_string(), serde_json::json!(value));
6966        }
6967        if let Some(value) = above_peg_offset_type {
6968            payload.insert("abovePegOffsetType".to_string(), serde_json::json!(value));
6969        }
6970        if let Some(value) = above_peg_offset_value {
6971            payload.insert("abovePegOffsetValue".to_string(), serde_json::json!(value));
6972        }
6973        if let Some(value) = below_client_order_id {
6974            payload.insert("belowClientOrderId".to_string(), serde_json::json!(value));
6975        }
6976        if let Some(value) = below_iceberg_qty {
6977            payload.insert("belowIcebergQty".to_string(), serde_json::json!(value));
6978        }
6979        if let Some(value) = below_price {
6980            payload.insert("belowPrice".to_string(), serde_json::json!(value));
6981        }
6982        if let Some(value) = below_stop_price {
6983            payload.insert("belowStopPrice".to_string(), serde_json::json!(value));
6984        }
6985        if let Some(value) = below_trailing_delta {
6986            payload.insert("belowTrailingDelta".to_string(), serde_json::json!(value));
6987        }
6988        if let Some(value) = below_time_in_force {
6989            payload.insert("belowTimeInForce".to_string(), serde_json::json!(value));
6990        }
6991        if let Some(value) = below_strategy_id {
6992            payload.insert("belowStrategyId".to_string(), serde_json::json!(value));
6993        }
6994        if let Some(value) = below_strategy_type {
6995            payload.insert("belowStrategyType".to_string(), serde_json::json!(value));
6996        }
6997        if let Some(value) = below_peg_price_type {
6998            payload.insert("belowPegPriceType".to_string(), serde_json::json!(value));
6999        }
7000        if let Some(value) = below_peg_offset_type {
7001            payload.insert("belowPegOffsetType".to_string(), serde_json::json!(value));
7002        }
7003        if let Some(value) = below_peg_offset_value {
7004            payload.insert("belowPegOffsetValue".to_string(), serde_json::json!(value));
7005        }
7006        if let Some(value) = new_order_resp_type {
7007            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7008        }
7009        if let Some(value) = self_trade_prevention_mode {
7010            payload.insert(
7011                "selfTradePreventionMode".to_string(),
7012                serde_json::json!(value),
7013            );
7014        }
7015        if let Some(value) = recv_window {
7016            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7017        }
7018        let payload = remove_empty_value(payload);
7019
7020        self.websocket_api_base
7021            .send_message::<Box<models::OrderListPlaceOcoResponseResult>>(
7022                "/orderList.place.oco".trim_start_matches('/'),
7023                payload,
7024                WebsocketMessageSendOptions::new().signed(),
7025            )
7026            .await
7027            .map_err(anyhow::Error::from)?
7028            .into_iter()
7029            .next()
7030            .ok_or(WebsocketError::NoResponse)
7031            .map_err(anyhow::Error::from)
7032    }
7033
7034    async fn order_list_place_opo(
7035        &self,
7036        params: OrderListPlaceOpoParams,
7037    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOpoResponseResult>>> {
7038        let OrderListPlaceOpoParams {
7039            symbol,
7040            working_type,
7041            working_side,
7042            working_price,
7043            working_quantity,
7044            pending_type,
7045            pending_side,
7046            id,
7047            list_client_order_id,
7048            new_order_resp_type,
7049            self_trade_prevention_mode,
7050            working_client_order_id,
7051            working_iceberg_qty,
7052            working_time_in_force,
7053            working_strategy_id,
7054            working_strategy_type,
7055            working_peg_price_type,
7056            working_peg_offset_type,
7057            working_peg_offset_value,
7058            pending_client_order_id,
7059            pending_price,
7060            pending_stop_price,
7061            pending_trailing_delta,
7062            pending_iceberg_qty,
7063            pending_time_in_force,
7064            pending_strategy_id,
7065            pending_strategy_type,
7066            pending_peg_price_type,
7067            pending_peg_offset_type,
7068            pending_peg_offset_value,
7069            recv_window,
7070        } = params;
7071
7072        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
7073        payload.insert("symbol".to_string(), serde_json::json!(symbol));
7074        payload.insert("workingType".to_string(), serde_json::json!(working_type));
7075        payload.insert("workingSide".to_string(), serde_json::json!(working_side));
7076        payload.insert("workingPrice".to_string(), serde_json::json!(working_price));
7077        payload.insert(
7078            "workingQuantity".to_string(),
7079            serde_json::json!(working_quantity),
7080        );
7081        payload.insert("pendingType".to_string(), serde_json::json!(pending_type));
7082        payload.insert("pendingSide".to_string(), serde_json::json!(pending_side));
7083        if let Some(value) = id {
7084            payload.insert("id".to_string(), serde_json::json!(value));
7085        }
7086        if let Some(value) = list_client_order_id {
7087            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
7088        }
7089        if let Some(value) = new_order_resp_type {
7090            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7091        }
7092        if let Some(value) = self_trade_prevention_mode {
7093            payload.insert(
7094                "selfTradePreventionMode".to_string(),
7095                serde_json::json!(value),
7096            );
7097        }
7098        if let Some(value) = working_client_order_id {
7099            payload.insert("workingClientOrderId".to_string(), serde_json::json!(value));
7100        }
7101        if let Some(value) = working_iceberg_qty {
7102            payload.insert("workingIcebergQty".to_string(), serde_json::json!(value));
7103        }
7104        if let Some(value) = working_time_in_force {
7105            payload.insert("workingTimeInForce".to_string(), serde_json::json!(value));
7106        }
7107        if let Some(value) = working_strategy_id {
7108            payload.insert("workingStrategyId".to_string(), serde_json::json!(value));
7109        }
7110        if let Some(value) = working_strategy_type {
7111            payload.insert("workingStrategyType".to_string(), serde_json::json!(value));
7112        }
7113        if let Some(value) = working_peg_price_type {
7114            payload.insert("workingPegPriceType".to_string(), serde_json::json!(value));
7115        }
7116        if let Some(value) = working_peg_offset_type {
7117            payload.insert("workingPegOffsetType".to_string(), serde_json::json!(value));
7118        }
7119        if let Some(value) = working_peg_offset_value {
7120            payload.insert(
7121                "workingPegOffsetValue".to_string(),
7122                serde_json::json!(value),
7123            );
7124        }
7125        if let Some(value) = pending_client_order_id {
7126            payload.insert("pendingClientOrderId".to_string(), serde_json::json!(value));
7127        }
7128        if let Some(value) = pending_price {
7129            payload.insert("pendingPrice".to_string(), serde_json::json!(value));
7130        }
7131        if let Some(value) = pending_stop_price {
7132            payload.insert("pendingStopPrice".to_string(), serde_json::json!(value));
7133        }
7134        if let Some(value) = pending_trailing_delta {
7135            payload.insert("pendingTrailingDelta".to_string(), serde_json::json!(value));
7136        }
7137        if let Some(value) = pending_iceberg_qty {
7138            payload.insert("pendingIcebergQty".to_string(), serde_json::json!(value));
7139        }
7140        if let Some(value) = pending_time_in_force {
7141            payload.insert("pendingTimeInForce".to_string(), serde_json::json!(value));
7142        }
7143        if let Some(value) = pending_strategy_id {
7144            payload.insert("pendingStrategyId".to_string(), serde_json::json!(value));
7145        }
7146        if let Some(value) = pending_strategy_type {
7147            payload.insert("pendingStrategyType".to_string(), serde_json::json!(value));
7148        }
7149        if let Some(value) = pending_peg_price_type {
7150            payload.insert("pendingPegPriceType".to_string(), serde_json::json!(value));
7151        }
7152        if let Some(value) = pending_peg_offset_type {
7153            payload.insert("pendingPegOffsetType".to_string(), serde_json::json!(value));
7154        }
7155        if let Some(value) = pending_peg_offset_value {
7156            payload.insert(
7157                "pendingPegOffsetValue".to_string(),
7158                serde_json::json!(value),
7159            );
7160        }
7161        if let Some(value) = recv_window {
7162            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7163        }
7164        let payload = remove_empty_value(payload);
7165
7166        self.websocket_api_base
7167            .send_message::<Box<models::OrderListPlaceOpoResponseResult>>(
7168                "/orderList.place.opo".trim_start_matches('/'),
7169                payload,
7170                WebsocketMessageSendOptions::new().signed(),
7171            )
7172            .await
7173            .map_err(anyhow::Error::from)?
7174            .into_iter()
7175            .next()
7176            .ok_or(WebsocketError::NoResponse)
7177            .map_err(anyhow::Error::from)
7178    }
7179
7180    async fn order_list_place_opoco(
7181        &self,
7182        params: OrderListPlaceOpocoParams,
7183    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOpocoResponseResult>>> {
7184        let OrderListPlaceOpocoParams {
7185            symbol,
7186            working_type,
7187            working_side,
7188            working_price,
7189            working_quantity,
7190            pending_side,
7191            pending_above_type,
7192            id,
7193            list_client_order_id,
7194            new_order_resp_type,
7195            self_trade_prevention_mode,
7196            working_client_order_id,
7197            working_iceberg_qty,
7198            working_time_in_force,
7199            working_strategy_id,
7200            working_strategy_type,
7201            working_peg_price_type,
7202            working_peg_offset_type,
7203            working_peg_offset_value,
7204            pending_above_client_order_id,
7205            pending_above_price,
7206            pending_above_stop_price,
7207            pending_above_trailing_delta,
7208            pending_above_iceberg_qty,
7209            pending_above_time_in_force,
7210            pending_above_strategy_id,
7211            pending_above_strategy_type,
7212            pending_above_peg_price_type,
7213            pending_above_peg_offset_type,
7214            pending_above_peg_offset_value,
7215            pending_below_type,
7216            pending_below_client_order_id,
7217            pending_below_price,
7218            pending_below_stop_price,
7219            pending_below_trailing_delta,
7220            pending_below_iceberg_qty,
7221            pending_below_time_in_force,
7222            pending_below_strategy_id,
7223            pending_below_strategy_type,
7224            pending_below_peg_price_type,
7225            pending_below_peg_offset_type,
7226            pending_below_peg_offset_value,
7227            recv_window,
7228        } = params;
7229
7230        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
7231        payload.insert("symbol".to_string(), serde_json::json!(symbol));
7232        payload.insert("workingType".to_string(), serde_json::json!(working_type));
7233        payload.insert("workingSide".to_string(), serde_json::json!(working_side));
7234        payload.insert("workingPrice".to_string(), serde_json::json!(working_price));
7235        payload.insert(
7236            "workingQuantity".to_string(),
7237            serde_json::json!(working_quantity),
7238        );
7239        payload.insert("pendingSide".to_string(), serde_json::json!(pending_side));
7240        payload.insert(
7241            "pendingAboveType".to_string(),
7242            serde_json::json!(pending_above_type),
7243        );
7244        if let Some(value) = id {
7245            payload.insert("id".to_string(), serde_json::json!(value));
7246        }
7247        if let Some(value) = list_client_order_id {
7248            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
7249        }
7250        if let Some(value) = new_order_resp_type {
7251            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7252        }
7253        if let Some(value) = self_trade_prevention_mode {
7254            payload.insert(
7255                "selfTradePreventionMode".to_string(),
7256                serde_json::json!(value),
7257            );
7258        }
7259        if let Some(value) = working_client_order_id {
7260            payload.insert("workingClientOrderId".to_string(), serde_json::json!(value));
7261        }
7262        if let Some(value) = working_iceberg_qty {
7263            payload.insert("workingIcebergQty".to_string(), serde_json::json!(value));
7264        }
7265        if let Some(value) = working_time_in_force {
7266            payload.insert("workingTimeInForce".to_string(), serde_json::json!(value));
7267        }
7268        if let Some(value) = working_strategy_id {
7269            payload.insert("workingStrategyId".to_string(), serde_json::json!(value));
7270        }
7271        if let Some(value) = working_strategy_type {
7272            payload.insert("workingStrategyType".to_string(), serde_json::json!(value));
7273        }
7274        if let Some(value) = working_peg_price_type {
7275            payload.insert("workingPegPriceType".to_string(), serde_json::json!(value));
7276        }
7277        if let Some(value) = working_peg_offset_type {
7278            payload.insert("workingPegOffsetType".to_string(), serde_json::json!(value));
7279        }
7280        if let Some(value) = working_peg_offset_value {
7281            payload.insert(
7282                "workingPegOffsetValue".to_string(),
7283                serde_json::json!(value),
7284            );
7285        }
7286        if let Some(value) = pending_above_client_order_id {
7287            payload.insert(
7288                "pendingAboveClientOrderId".to_string(),
7289                serde_json::json!(value),
7290            );
7291        }
7292        if let Some(value) = pending_above_price {
7293            payload.insert("pendingAbovePrice".to_string(), serde_json::json!(value));
7294        }
7295        if let Some(value) = pending_above_stop_price {
7296            payload.insert(
7297                "pendingAboveStopPrice".to_string(),
7298                serde_json::json!(value),
7299            );
7300        }
7301        if let Some(value) = pending_above_trailing_delta {
7302            payload.insert(
7303                "pendingAboveTrailingDelta".to_string(),
7304                serde_json::json!(value),
7305            );
7306        }
7307        if let Some(value) = pending_above_iceberg_qty {
7308            payload.insert(
7309                "pendingAboveIcebergQty".to_string(),
7310                serde_json::json!(value),
7311            );
7312        }
7313        if let Some(value) = pending_above_time_in_force {
7314            payload.insert(
7315                "pendingAboveTimeInForce".to_string(),
7316                serde_json::json!(value),
7317            );
7318        }
7319        if let Some(value) = pending_above_strategy_id {
7320            payload.insert(
7321                "pendingAboveStrategyId".to_string(),
7322                serde_json::json!(value),
7323            );
7324        }
7325        if let Some(value) = pending_above_strategy_type {
7326            payload.insert(
7327                "pendingAboveStrategyType".to_string(),
7328                serde_json::json!(value),
7329            );
7330        }
7331        if let Some(value) = pending_above_peg_price_type {
7332            payload.insert(
7333                "pendingAbovePegPriceType".to_string(),
7334                serde_json::json!(value),
7335            );
7336        }
7337        if let Some(value) = pending_above_peg_offset_type {
7338            payload.insert(
7339                "pendingAbovePegOffsetType".to_string(),
7340                serde_json::json!(value),
7341            );
7342        }
7343        if let Some(value) = pending_above_peg_offset_value {
7344            payload.insert(
7345                "pendingAbovePegOffsetValue".to_string(),
7346                serde_json::json!(value),
7347            );
7348        }
7349        if let Some(value) = pending_below_type {
7350            payload.insert("pendingBelowType".to_string(), serde_json::json!(value));
7351        }
7352        if let Some(value) = pending_below_client_order_id {
7353            payload.insert(
7354                "pendingBelowClientOrderId".to_string(),
7355                serde_json::json!(value),
7356            );
7357        }
7358        if let Some(value) = pending_below_price {
7359            payload.insert("pendingBelowPrice".to_string(), serde_json::json!(value));
7360        }
7361        if let Some(value) = pending_below_stop_price {
7362            payload.insert(
7363                "pendingBelowStopPrice".to_string(),
7364                serde_json::json!(value),
7365            );
7366        }
7367        if let Some(value) = pending_below_trailing_delta {
7368            payload.insert(
7369                "pendingBelowTrailingDelta".to_string(),
7370                serde_json::json!(value),
7371            );
7372        }
7373        if let Some(value) = pending_below_iceberg_qty {
7374            payload.insert(
7375                "pendingBelowIcebergQty".to_string(),
7376                serde_json::json!(value),
7377            );
7378        }
7379        if let Some(value) = pending_below_time_in_force {
7380            payload.insert(
7381                "pendingBelowTimeInForce".to_string(),
7382                serde_json::json!(value),
7383            );
7384        }
7385        if let Some(value) = pending_below_strategy_id {
7386            payload.insert(
7387                "pendingBelowStrategyId".to_string(),
7388                serde_json::json!(value),
7389            );
7390        }
7391        if let Some(value) = pending_below_strategy_type {
7392            payload.insert(
7393                "pendingBelowStrategyType".to_string(),
7394                serde_json::json!(value),
7395            );
7396        }
7397        if let Some(value) = pending_below_peg_price_type {
7398            payload.insert(
7399                "pendingBelowPegPriceType".to_string(),
7400                serde_json::json!(value),
7401            );
7402        }
7403        if let Some(value) = pending_below_peg_offset_type {
7404            payload.insert(
7405                "pendingBelowPegOffsetType".to_string(),
7406                serde_json::json!(value),
7407            );
7408        }
7409        if let Some(value) = pending_below_peg_offset_value {
7410            payload.insert(
7411                "pendingBelowPegOffsetValue".to_string(),
7412                serde_json::json!(value),
7413            );
7414        }
7415        if let Some(value) = recv_window {
7416            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7417        }
7418        let payload = remove_empty_value(payload);
7419
7420        self.websocket_api_base
7421            .send_message::<Box<models::OrderListPlaceOpocoResponseResult>>(
7422                "/orderList.place.opoco".trim_start_matches('/'),
7423                payload,
7424                WebsocketMessageSendOptions::new().signed(),
7425            )
7426            .await
7427            .map_err(anyhow::Error::from)?
7428            .into_iter()
7429            .next()
7430            .ok_or(WebsocketError::NoResponse)
7431            .map_err(anyhow::Error::from)
7432    }
7433
7434    async fn order_list_place_oto(
7435        &self,
7436        params: OrderListPlaceOtoParams,
7437    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOtoResponseResult>>> {
7438        let OrderListPlaceOtoParams {
7439            symbol,
7440            working_type,
7441            working_side,
7442            working_price,
7443            working_quantity,
7444            pending_type,
7445            pending_side,
7446            pending_quantity,
7447            id,
7448            list_client_order_id,
7449            new_order_resp_type,
7450            self_trade_prevention_mode,
7451            working_client_order_id,
7452            working_iceberg_qty,
7453            working_time_in_force,
7454            working_strategy_id,
7455            working_strategy_type,
7456            working_peg_price_type,
7457            working_peg_offset_type,
7458            working_peg_offset_value,
7459            pending_client_order_id,
7460            pending_price,
7461            pending_stop_price,
7462            pending_trailing_delta,
7463            pending_iceberg_qty,
7464            pending_time_in_force,
7465            pending_strategy_id,
7466            pending_strategy_type,
7467            pending_peg_offset_type,
7468            pending_peg_price_type,
7469            pending_peg_offset_value,
7470            recv_window,
7471        } = params;
7472
7473        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
7474        payload.insert("symbol".to_string(), serde_json::json!(symbol));
7475        payload.insert("workingType".to_string(), serde_json::json!(working_type));
7476        payload.insert("workingSide".to_string(), serde_json::json!(working_side));
7477        payload.insert("workingPrice".to_string(), serde_json::json!(working_price));
7478        payload.insert(
7479            "workingQuantity".to_string(),
7480            serde_json::json!(working_quantity),
7481        );
7482        payload.insert("pendingType".to_string(), serde_json::json!(pending_type));
7483        payload.insert("pendingSide".to_string(), serde_json::json!(pending_side));
7484        payload.insert(
7485            "pendingQuantity".to_string(),
7486            serde_json::json!(pending_quantity),
7487        );
7488        if let Some(value) = id {
7489            payload.insert("id".to_string(), serde_json::json!(value));
7490        }
7491        if let Some(value) = list_client_order_id {
7492            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
7493        }
7494        if let Some(value) = new_order_resp_type {
7495            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7496        }
7497        if let Some(value) = self_trade_prevention_mode {
7498            payload.insert(
7499                "selfTradePreventionMode".to_string(),
7500                serde_json::json!(value),
7501            );
7502        }
7503        if let Some(value) = working_client_order_id {
7504            payload.insert("workingClientOrderId".to_string(), serde_json::json!(value));
7505        }
7506        if let Some(value) = working_iceberg_qty {
7507            payload.insert("workingIcebergQty".to_string(), serde_json::json!(value));
7508        }
7509        if let Some(value) = working_time_in_force {
7510            payload.insert("workingTimeInForce".to_string(), serde_json::json!(value));
7511        }
7512        if let Some(value) = working_strategy_id {
7513            payload.insert("workingStrategyId".to_string(), serde_json::json!(value));
7514        }
7515        if let Some(value) = working_strategy_type {
7516            payload.insert("workingStrategyType".to_string(), serde_json::json!(value));
7517        }
7518        if let Some(value) = working_peg_price_type {
7519            payload.insert("workingPegPriceType".to_string(), serde_json::json!(value));
7520        }
7521        if let Some(value) = working_peg_offset_type {
7522            payload.insert("workingPegOffsetType".to_string(), serde_json::json!(value));
7523        }
7524        if let Some(value) = working_peg_offset_value {
7525            payload.insert(
7526                "workingPegOffsetValue".to_string(),
7527                serde_json::json!(value),
7528            );
7529        }
7530        if let Some(value) = pending_client_order_id {
7531            payload.insert("pendingClientOrderId".to_string(), serde_json::json!(value));
7532        }
7533        if let Some(value) = pending_price {
7534            payload.insert("pendingPrice".to_string(), serde_json::json!(value));
7535        }
7536        if let Some(value) = pending_stop_price {
7537            payload.insert("pendingStopPrice".to_string(), serde_json::json!(value));
7538        }
7539        if let Some(value) = pending_trailing_delta {
7540            payload.insert("pendingTrailingDelta".to_string(), serde_json::json!(value));
7541        }
7542        if let Some(value) = pending_iceberg_qty {
7543            payload.insert("pendingIcebergQty".to_string(), serde_json::json!(value));
7544        }
7545        if let Some(value) = pending_time_in_force {
7546            payload.insert("pendingTimeInForce".to_string(), serde_json::json!(value));
7547        }
7548        if let Some(value) = pending_strategy_id {
7549            payload.insert("pendingStrategyId".to_string(), serde_json::json!(value));
7550        }
7551        if let Some(value) = pending_strategy_type {
7552            payload.insert("pendingStrategyType".to_string(), serde_json::json!(value));
7553        }
7554        if let Some(value) = pending_peg_offset_type {
7555            payload.insert("pendingPegOffsetType".to_string(), serde_json::json!(value));
7556        }
7557        if let Some(value) = pending_peg_price_type {
7558            payload.insert("pendingPegPriceType".to_string(), serde_json::json!(value));
7559        }
7560        if let Some(value) = pending_peg_offset_value {
7561            payload.insert(
7562                "pendingPegOffsetValue".to_string(),
7563                serde_json::json!(value),
7564            );
7565        }
7566        if let Some(value) = recv_window {
7567            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7568        }
7569        let payload = remove_empty_value(payload);
7570
7571        self.websocket_api_base
7572            .send_message::<Box<models::OrderListPlaceOtoResponseResult>>(
7573                "/orderList.place.oto".trim_start_matches('/'),
7574                payload,
7575                WebsocketMessageSendOptions::new().signed(),
7576            )
7577            .await
7578            .map_err(anyhow::Error::from)?
7579            .into_iter()
7580            .next()
7581            .ok_or(WebsocketError::NoResponse)
7582            .map_err(anyhow::Error::from)
7583    }
7584
7585    async fn order_list_place_otoco(
7586        &self,
7587        params: OrderListPlaceOtocoParams,
7588    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOtocoResponseResult>>> {
7589        let OrderListPlaceOtocoParams {
7590            symbol,
7591            working_type,
7592            working_side,
7593            working_price,
7594            working_quantity,
7595            pending_side,
7596            pending_quantity,
7597            pending_above_type,
7598            id,
7599            list_client_order_id,
7600            new_order_resp_type,
7601            self_trade_prevention_mode,
7602            working_client_order_id,
7603            working_iceberg_qty,
7604            working_time_in_force,
7605            working_strategy_id,
7606            working_strategy_type,
7607            working_peg_price_type,
7608            working_peg_offset_type,
7609            working_peg_offset_value,
7610            pending_above_client_order_id,
7611            pending_above_price,
7612            pending_above_stop_price,
7613            pending_above_trailing_delta,
7614            pending_above_iceberg_qty,
7615            pending_above_time_in_force,
7616            pending_above_strategy_id,
7617            pending_above_strategy_type,
7618            pending_above_peg_price_type,
7619            pending_above_peg_offset_type,
7620            pending_above_peg_offset_value,
7621            pending_below_type,
7622            pending_below_client_order_id,
7623            pending_below_price,
7624            pending_below_stop_price,
7625            pending_below_trailing_delta,
7626            pending_below_iceberg_qty,
7627            pending_below_time_in_force,
7628            pending_below_strategy_id,
7629            pending_below_strategy_type,
7630            pending_below_peg_price_type,
7631            pending_below_peg_offset_type,
7632            pending_below_peg_offset_value,
7633            recv_window,
7634        } = params;
7635
7636        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
7637        payload.insert("symbol".to_string(), serde_json::json!(symbol));
7638        payload.insert("workingType".to_string(), serde_json::json!(working_type));
7639        payload.insert("workingSide".to_string(), serde_json::json!(working_side));
7640        payload.insert("workingPrice".to_string(), serde_json::json!(working_price));
7641        payload.insert(
7642            "workingQuantity".to_string(),
7643            serde_json::json!(working_quantity),
7644        );
7645        payload.insert("pendingSide".to_string(), serde_json::json!(pending_side));
7646        payload.insert(
7647            "pendingQuantity".to_string(),
7648            serde_json::json!(pending_quantity),
7649        );
7650        payload.insert(
7651            "pendingAboveType".to_string(),
7652            serde_json::json!(pending_above_type),
7653        );
7654        if let Some(value) = id {
7655            payload.insert("id".to_string(), serde_json::json!(value));
7656        }
7657        if let Some(value) = list_client_order_id {
7658            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
7659        }
7660        if let Some(value) = new_order_resp_type {
7661            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7662        }
7663        if let Some(value) = self_trade_prevention_mode {
7664            payload.insert(
7665                "selfTradePreventionMode".to_string(),
7666                serde_json::json!(value),
7667            );
7668        }
7669        if let Some(value) = working_client_order_id {
7670            payload.insert("workingClientOrderId".to_string(), serde_json::json!(value));
7671        }
7672        if let Some(value) = working_iceberg_qty {
7673            payload.insert("workingIcebergQty".to_string(), serde_json::json!(value));
7674        }
7675        if let Some(value) = working_time_in_force {
7676            payload.insert("workingTimeInForce".to_string(), serde_json::json!(value));
7677        }
7678        if let Some(value) = working_strategy_id {
7679            payload.insert("workingStrategyId".to_string(), serde_json::json!(value));
7680        }
7681        if let Some(value) = working_strategy_type {
7682            payload.insert("workingStrategyType".to_string(), serde_json::json!(value));
7683        }
7684        if let Some(value) = working_peg_price_type {
7685            payload.insert("workingPegPriceType".to_string(), serde_json::json!(value));
7686        }
7687        if let Some(value) = working_peg_offset_type {
7688            payload.insert("workingPegOffsetType".to_string(), serde_json::json!(value));
7689        }
7690        if let Some(value) = working_peg_offset_value {
7691            payload.insert(
7692                "workingPegOffsetValue".to_string(),
7693                serde_json::json!(value),
7694            );
7695        }
7696        if let Some(value) = pending_above_client_order_id {
7697            payload.insert(
7698                "pendingAboveClientOrderId".to_string(),
7699                serde_json::json!(value),
7700            );
7701        }
7702        if let Some(value) = pending_above_price {
7703            payload.insert("pendingAbovePrice".to_string(), serde_json::json!(value));
7704        }
7705        if let Some(value) = pending_above_stop_price {
7706            payload.insert(
7707                "pendingAboveStopPrice".to_string(),
7708                serde_json::json!(value),
7709            );
7710        }
7711        if let Some(value) = pending_above_trailing_delta {
7712            payload.insert(
7713                "pendingAboveTrailingDelta".to_string(),
7714                serde_json::json!(value),
7715            );
7716        }
7717        if let Some(value) = pending_above_iceberg_qty {
7718            payload.insert(
7719                "pendingAboveIcebergQty".to_string(),
7720                serde_json::json!(value),
7721            );
7722        }
7723        if let Some(value) = pending_above_time_in_force {
7724            payload.insert(
7725                "pendingAboveTimeInForce".to_string(),
7726                serde_json::json!(value),
7727            );
7728        }
7729        if let Some(value) = pending_above_strategy_id {
7730            payload.insert(
7731                "pendingAboveStrategyId".to_string(),
7732                serde_json::json!(value),
7733            );
7734        }
7735        if let Some(value) = pending_above_strategy_type {
7736            payload.insert(
7737                "pendingAboveStrategyType".to_string(),
7738                serde_json::json!(value),
7739            );
7740        }
7741        if let Some(value) = pending_above_peg_price_type {
7742            payload.insert(
7743                "pendingAbovePegPriceType".to_string(),
7744                serde_json::json!(value),
7745            );
7746        }
7747        if let Some(value) = pending_above_peg_offset_type {
7748            payload.insert(
7749                "pendingAbovePegOffsetType".to_string(),
7750                serde_json::json!(value),
7751            );
7752        }
7753        if let Some(value) = pending_above_peg_offset_value {
7754            payload.insert(
7755                "pendingAbovePegOffsetValue".to_string(),
7756                serde_json::json!(value),
7757            );
7758        }
7759        if let Some(value) = pending_below_type {
7760            payload.insert("pendingBelowType".to_string(), serde_json::json!(value));
7761        }
7762        if let Some(value) = pending_below_client_order_id {
7763            payload.insert(
7764                "pendingBelowClientOrderId".to_string(),
7765                serde_json::json!(value),
7766            );
7767        }
7768        if let Some(value) = pending_below_price {
7769            payload.insert("pendingBelowPrice".to_string(), serde_json::json!(value));
7770        }
7771        if let Some(value) = pending_below_stop_price {
7772            payload.insert(
7773                "pendingBelowStopPrice".to_string(),
7774                serde_json::json!(value),
7775            );
7776        }
7777        if let Some(value) = pending_below_trailing_delta {
7778            payload.insert(
7779                "pendingBelowTrailingDelta".to_string(),
7780                serde_json::json!(value),
7781            );
7782        }
7783        if let Some(value) = pending_below_iceberg_qty {
7784            payload.insert(
7785                "pendingBelowIcebergQty".to_string(),
7786                serde_json::json!(value),
7787            );
7788        }
7789        if let Some(value) = pending_below_time_in_force {
7790            payload.insert(
7791                "pendingBelowTimeInForce".to_string(),
7792                serde_json::json!(value),
7793            );
7794        }
7795        if let Some(value) = pending_below_strategy_id {
7796            payload.insert(
7797                "pendingBelowStrategyId".to_string(),
7798                serde_json::json!(value),
7799            );
7800        }
7801        if let Some(value) = pending_below_strategy_type {
7802            payload.insert(
7803                "pendingBelowStrategyType".to_string(),
7804                serde_json::json!(value),
7805            );
7806        }
7807        if let Some(value) = pending_below_peg_price_type {
7808            payload.insert(
7809                "pendingBelowPegPriceType".to_string(),
7810                serde_json::json!(value),
7811            );
7812        }
7813        if let Some(value) = pending_below_peg_offset_type {
7814            payload.insert(
7815                "pendingBelowPegOffsetType".to_string(),
7816                serde_json::json!(value),
7817            );
7818        }
7819        if let Some(value) = pending_below_peg_offset_value {
7820            payload.insert(
7821                "pendingBelowPegOffsetValue".to_string(),
7822                serde_json::json!(value),
7823            );
7824        }
7825        if let Some(value) = recv_window {
7826            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7827        }
7828        let payload = remove_empty_value(payload);
7829
7830        self.websocket_api_base
7831            .send_message::<Box<models::OrderListPlaceOtocoResponseResult>>(
7832                "/orderList.place.otoco".trim_start_matches('/'),
7833                payload,
7834                WebsocketMessageSendOptions::new().signed(),
7835            )
7836            .await
7837            .map_err(anyhow::Error::from)?
7838            .into_iter()
7839            .next()
7840            .ok_or(WebsocketError::NoResponse)
7841            .map_err(anyhow::Error::from)
7842    }
7843
7844    async fn order_place(
7845        &self,
7846        params: OrderPlaceParams,
7847    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderPlaceResponseResult>>> {
7848        let OrderPlaceParams {
7849            symbol,
7850            side,
7851            r#type,
7852            id,
7853            time_in_force,
7854            price,
7855            quantity,
7856            quote_order_qty,
7857            new_client_order_id,
7858            new_order_resp_type,
7859            stop_price,
7860            trailing_delta,
7861            iceberg_qty,
7862            strategy_id,
7863            strategy_type,
7864            self_trade_prevention_mode,
7865            peg_price_type,
7866            peg_offset_value,
7867            peg_offset_type,
7868            recv_window,
7869        } = params;
7870
7871        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
7872        payload.insert("symbol".to_string(), serde_json::json!(symbol));
7873        payload.insert("side".to_string(), serde_json::json!(side));
7874        payload.insert("type".to_string(), serde_json::json!(r#type));
7875        if let Some(value) = id {
7876            payload.insert("id".to_string(), serde_json::json!(value));
7877        }
7878        if let Some(value) = time_in_force {
7879            payload.insert("timeInForce".to_string(), serde_json::json!(value));
7880        }
7881        if let Some(value) = price {
7882            payload.insert("price".to_string(), serde_json::json!(value));
7883        }
7884        if let Some(value) = quantity {
7885            payload.insert("quantity".to_string(), serde_json::json!(value));
7886        }
7887        if let Some(value) = quote_order_qty {
7888            payload.insert("quoteOrderQty".to_string(), serde_json::json!(value));
7889        }
7890        if let Some(value) = new_client_order_id {
7891            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
7892        }
7893        if let Some(value) = new_order_resp_type {
7894            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7895        }
7896        if let Some(value) = stop_price {
7897            payload.insert("stopPrice".to_string(), serde_json::json!(value));
7898        }
7899        if let Some(value) = trailing_delta {
7900            payload.insert("trailingDelta".to_string(), serde_json::json!(value));
7901        }
7902        if let Some(value) = iceberg_qty {
7903            payload.insert("icebergQty".to_string(), serde_json::json!(value));
7904        }
7905        if let Some(value) = strategy_id {
7906            payload.insert("strategyId".to_string(), serde_json::json!(value));
7907        }
7908        if let Some(value) = strategy_type {
7909            payload.insert("strategyType".to_string(), serde_json::json!(value));
7910        }
7911        if let Some(value) = self_trade_prevention_mode {
7912            payload.insert(
7913                "selfTradePreventionMode".to_string(),
7914                serde_json::json!(value),
7915            );
7916        }
7917        if let Some(value) = peg_price_type {
7918            payload.insert("pegPriceType".to_string(), serde_json::json!(value));
7919        }
7920        if let Some(value) = peg_offset_value {
7921            payload.insert("pegOffsetValue".to_string(), serde_json::json!(value));
7922        }
7923        if let Some(value) = peg_offset_type {
7924            payload.insert("pegOffsetType".to_string(), serde_json::json!(value));
7925        }
7926        if let Some(value) = recv_window {
7927            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7928        }
7929        let payload = remove_empty_value(payload);
7930
7931        self.websocket_api_base
7932            .send_message::<Box<models::OrderPlaceResponseResult>>(
7933                "/order.place".trim_start_matches('/'),
7934                payload,
7935                WebsocketMessageSendOptions::new().signed(),
7936            )
7937            .await
7938            .map_err(anyhow::Error::from)?
7939            .into_iter()
7940            .next()
7941            .ok_or(WebsocketError::NoResponse)
7942            .map_err(anyhow::Error::from)
7943    }
7944
7945    async fn order_test(
7946        &self,
7947        params: OrderTestParams,
7948    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderTestResponseResult>>> {
7949        let OrderTestParams {
7950            symbol,
7951            side,
7952            r#type,
7953            id,
7954            compute_commission_rates,
7955            time_in_force,
7956            price,
7957            quantity,
7958            quote_order_qty,
7959            new_client_order_id,
7960            new_order_resp_type,
7961            stop_price,
7962            trailing_delta,
7963            iceberg_qty,
7964            strategy_id,
7965            strategy_type,
7966            self_trade_prevention_mode,
7967            peg_price_type,
7968            peg_offset_value,
7969            peg_offset_type,
7970            recv_window,
7971        } = params;
7972
7973        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
7974        payload.insert("symbol".to_string(), serde_json::json!(symbol));
7975        payload.insert("side".to_string(), serde_json::json!(side));
7976        payload.insert("type".to_string(), serde_json::json!(r#type));
7977        if let Some(value) = id {
7978            payload.insert("id".to_string(), serde_json::json!(value));
7979        }
7980        if let Some(value) = compute_commission_rates {
7981            payload.insert(
7982                "computeCommissionRates".to_string(),
7983                serde_json::json!(value),
7984            );
7985        }
7986        if let Some(value) = time_in_force {
7987            payload.insert("timeInForce".to_string(), serde_json::json!(value));
7988        }
7989        if let Some(value) = price {
7990            payload.insert("price".to_string(), serde_json::json!(value));
7991        }
7992        if let Some(value) = quantity {
7993            payload.insert("quantity".to_string(), serde_json::json!(value));
7994        }
7995        if let Some(value) = quote_order_qty {
7996            payload.insert("quoteOrderQty".to_string(), serde_json::json!(value));
7997        }
7998        if let Some(value) = new_client_order_id {
7999            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
8000        }
8001        if let Some(value) = new_order_resp_type {
8002            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
8003        }
8004        if let Some(value) = stop_price {
8005            payload.insert("stopPrice".to_string(), serde_json::json!(value));
8006        }
8007        if let Some(value) = trailing_delta {
8008            payload.insert("trailingDelta".to_string(), serde_json::json!(value));
8009        }
8010        if let Some(value) = iceberg_qty {
8011            payload.insert("icebergQty".to_string(), serde_json::json!(value));
8012        }
8013        if let Some(value) = strategy_id {
8014            payload.insert("strategyId".to_string(), serde_json::json!(value));
8015        }
8016        if let Some(value) = strategy_type {
8017            payload.insert("strategyType".to_string(), serde_json::json!(value));
8018        }
8019        if let Some(value) = self_trade_prevention_mode {
8020            payload.insert(
8021                "selfTradePreventionMode".to_string(),
8022                serde_json::json!(value),
8023            );
8024        }
8025        if let Some(value) = peg_price_type {
8026            payload.insert("pegPriceType".to_string(), serde_json::json!(value));
8027        }
8028        if let Some(value) = peg_offset_value {
8029            payload.insert("pegOffsetValue".to_string(), serde_json::json!(value));
8030        }
8031        if let Some(value) = peg_offset_type {
8032            payload.insert("pegOffsetType".to_string(), serde_json::json!(value));
8033        }
8034        if let Some(value) = recv_window {
8035            payload.insert("recvWindow".to_string(), serde_json::json!(value));
8036        }
8037        let payload = remove_empty_value(payload);
8038
8039        self.websocket_api_base
8040            .send_message::<Box<models::OrderTestResponseResult>>(
8041                "/order.test".trim_start_matches('/'),
8042                payload,
8043                WebsocketMessageSendOptions::new().signed(),
8044            )
8045            .await
8046            .map_err(anyhow::Error::from)?
8047            .into_iter()
8048            .next()
8049            .ok_or(WebsocketError::NoResponse)
8050            .map_err(anyhow::Error::from)
8051    }
8052
8053    async fn sor_order_place(
8054        &self,
8055        params: SorOrderPlaceParams,
8056    ) -> anyhow::Result<WebsocketApiResponse<Vec<models::SorOrderPlaceResponseResultInner>>> {
8057        let SorOrderPlaceParams {
8058            symbol,
8059            side,
8060            r#type,
8061            quantity,
8062            id,
8063            time_in_force,
8064            price,
8065            new_client_order_id,
8066            new_order_resp_type,
8067            iceberg_qty,
8068            strategy_id,
8069            strategy_type,
8070            self_trade_prevention_mode,
8071            recv_window,
8072        } = params;
8073
8074        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
8075        payload.insert("symbol".to_string(), serde_json::json!(symbol));
8076        payload.insert("side".to_string(), serde_json::json!(side));
8077        payload.insert("type".to_string(), serde_json::json!(r#type));
8078        payload.insert("quantity".to_string(), serde_json::json!(quantity));
8079        if let Some(value) = id {
8080            payload.insert("id".to_string(), serde_json::json!(value));
8081        }
8082        if let Some(value) = time_in_force {
8083            payload.insert("timeInForce".to_string(), serde_json::json!(value));
8084        }
8085        if let Some(value) = price {
8086            payload.insert("price".to_string(), serde_json::json!(value));
8087        }
8088        if let Some(value) = new_client_order_id {
8089            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
8090        }
8091        if let Some(value) = new_order_resp_type {
8092            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
8093        }
8094        if let Some(value) = iceberg_qty {
8095            payload.insert("icebergQty".to_string(), serde_json::json!(value));
8096        }
8097        if let Some(value) = strategy_id {
8098            payload.insert("strategyId".to_string(), serde_json::json!(value));
8099        }
8100        if let Some(value) = strategy_type {
8101            payload.insert("strategyType".to_string(), serde_json::json!(value));
8102        }
8103        if let Some(value) = self_trade_prevention_mode {
8104            payload.insert(
8105                "selfTradePreventionMode".to_string(),
8106                serde_json::json!(value),
8107            );
8108        }
8109        if let Some(value) = recv_window {
8110            payload.insert("recvWindow".to_string(), serde_json::json!(value));
8111        }
8112        let payload = remove_empty_value(payload);
8113
8114        self.websocket_api_base
8115            .send_message::<Vec<models::SorOrderPlaceResponseResultInner>>(
8116                "/sor.order.place".trim_start_matches('/'),
8117                payload,
8118                WebsocketMessageSendOptions::new().signed(),
8119            )
8120            .await
8121            .map_err(anyhow::Error::from)?
8122            .into_iter()
8123            .next()
8124            .ok_or(WebsocketError::NoResponse)
8125            .map_err(anyhow::Error::from)
8126    }
8127
8128    async fn sor_order_test(
8129        &self,
8130        params: SorOrderTestParams,
8131    ) -> anyhow::Result<WebsocketApiResponse<Box<models::SorOrderTestResponseResult>>> {
8132        let SorOrderTestParams {
8133            symbol,
8134            side,
8135            r#type,
8136            quantity,
8137            id,
8138            compute_commission_rates,
8139            time_in_force,
8140            price,
8141            new_client_order_id,
8142            new_order_resp_type,
8143            iceberg_qty,
8144            strategy_id,
8145            strategy_type,
8146            self_trade_prevention_mode,
8147            recv_window,
8148        } = params;
8149
8150        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
8151        payload.insert("symbol".to_string(), serde_json::json!(symbol));
8152        payload.insert("side".to_string(), serde_json::json!(side));
8153        payload.insert("type".to_string(), serde_json::json!(r#type));
8154        payload.insert("quantity".to_string(), serde_json::json!(quantity));
8155        if let Some(value) = id {
8156            payload.insert("id".to_string(), serde_json::json!(value));
8157        }
8158        if let Some(value) = compute_commission_rates {
8159            payload.insert(
8160                "computeCommissionRates".to_string(),
8161                serde_json::json!(value),
8162            );
8163        }
8164        if let Some(value) = time_in_force {
8165            payload.insert("timeInForce".to_string(), serde_json::json!(value));
8166        }
8167        if let Some(value) = price {
8168            payload.insert("price".to_string(), serde_json::json!(value));
8169        }
8170        if let Some(value) = new_client_order_id {
8171            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
8172        }
8173        if let Some(value) = new_order_resp_type {
8174            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
8175        }
8176        if let Some(value) = iceberg_qty {
8177            payload.insert("icebergQty".to_string(), serde_json::json!(value));
8178        }
8179        if let Some(value) = strategy_id {
8180            payload.insert("strategyId".to_string(), serde_json::json!(value));
8181        }
8182        if let Some(value) = strategy_type {
8183            payload.insert("strategyType".to_string(), serde_json::json!(value));
8184        }
8185        if let Some(value) = self_trade_prevention_mode {
8186            payload.insert(
8187                "selfTradePreventionMode".to_string(),
8188                serde_json::json!(value),
8189            );
8190        }
8191        if let Some(value) = recv_window {
8192            payload.insert("recvWindow".to_string(), serde_json::json!(value));
8193        }
8194        let payload = remove_empty_value(payload);
8195
8196        self.websocket_api_base
8197            .send_message::<Box<models::SorOrderTestResponseResult>>(
8198                "/sor.order.test".trim_start_matches('/'),
8199                payload,
8200                WebsocketMessageSendOptions::new().signed(),
8201            )
8202            .await
8203            .map_err(anyhow::Error::from)?
8204            .into_iter()
8205            .next()
8206            .ok_or(WebsocketError::NoResponse)
8207            .map_err(anyhow::Error::from)
8208    }
8209}
8210
8211#[cfg(all(test, feature = "spot"))]
8212mod tests {
8213    use super::*;
8214    use crate::TOKIO_SHARED_RT;
8215    use crate::common::websocket::{WebsocketApi, WebsocketConnection, WebsocketHandler};
8216    use crate::config::ConfigurationWebsocketApi;
8217    use crate::errors::WebsocketError;
8218    use crate::models::WebsocketApiRateLimit;
8219    use serde_json::{Value, json};
8220    use tokio::spawn;
8221    use tokio::sync::mpsc::{UnboundedReceiver, unbounded_channel};
8222    use tokio::time::{Duration, timeout};
8223    use tokio_tungstenite::tungstenite::Message;
8224
8225    async fn setup() -> (
8226        Arc<WebsocketApi>,
8227        Arc<WebsocketConnection>,
8228        UnboundedReceiver<Message>,
8229    ) {
8230        let conn = WebsocketConnection::new("test-conn");
8231        let (tx, rx) = unbounded_channel::<Message>();
8232        {
8233            let mut conn_state = conn.state.lock().await;
8234            conn_state.ws_write_tx = Some(tx);
8235        }
8236
8237        let config = ConfigurationWebsocketApi::builder()
8238            .api_key("key")
8239            .api_secret("secret")
8240            .build()
8241            .expect("Failed to build configuration");
8242        let ws_api = WebsocketApi::new(config, vec![conn.clone()]);
8243        conn.set_handler(ws_api.clone() as Arc<dyn WebsocketHandler>)
8244            .await;
8245        ws_api.clone().connect().await.unwrap();
8246
8247        (ws_api, conn, rx)
8248    }
8249
8250    #[test]
8251    fn open_orders_cancel_all_success() {
8252        TOKIO_SHARED_RT.block_on(async {
8253            let (ws_api, conn, mut rx) = setup().await;
8254            let client = TradeApiClient::new(ws_api.clone());
8255
8256            let handle = spawn(async move {
8257                let params = OpenOrdersCancelAllParams::builder("BNBUSDT".to_string(),).build().unwrap();
8258                client.open_orders_cancel_all(params).await
8259            });
8260
8261            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8262            let Message::Text(text) = sent else { panic!() };
8263            let v: Value = serde_json::from_str(&text).unwrap();
8264            let id = v["id"].as_str().unwrap();
8265            assert_eq!(v["method"], "/openOrders.cancelAll".trim_start_matches('/'));
8266            let mut resp_json: Value = serde_json::from_str(r#"{"id":"778f938f-9041-4b88-9914-efbf64eeacc8","status":200,"result":[{"orderListId":-1,"contingencyType":"OCO","listStatusType":"ALL_DONE","listOrderStatus":"ALL_DONE","listClientOrderId":"iuVNVJYYrByz6C4yGOPPK0","transactionTime":1660803702431,"symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":12569099453,"clientOrderId":"bX5wROblo6YeDwa9iTLeyY"}],"orderReports":[{"symbol":"BTCUSDT","origClientOrderId":"bX5wROblo6YeDwa9iTLeyY","orderId":12569099453,"orderListId":19431,"clientOrderId":"OFFXQtxVFZ6Nbcg4PgE2DA","transactTime":1684804350068,"status":"CANCELED","timeInForce":"GTC","type":"STOP_LOSS_LIMIT","side":"BUY","selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","stopPrice":"0.00000000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}],"origClientOrderId":"4d96324ff9d44481926157","orderId":12569099453,"clientOrderId":"91fe37ce9e69c90d6358c0","transactTime":1684804350068,"status":"CANCELED","timeInForce":"GTC","type":"LIMIT","side":"SELL","stopPrice":"0.00000000","trailingDelta":10,"trailingTime":-1,"icebergQty":"0.00000000","strategyId":1,"strategyType":1000000,"selfTradePreventionMode":"NONE","preventedMatchId":0,"preventedQuantity":"1.200000","usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}],"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
8267            resp_json["id"] = id.into();
8268
8269            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8270            let expected_data: Vec<models::OpenOrdersCancelAllResponseResultInner> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8271            let empty_array = Value::Array(vec![]);
8272            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8273            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8274                match raw_rate_limits.as_array() {
8275                    Some(arr) if arr.is_empty() => None,
8276                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8277                    None => None,
8278                };
8279
8280            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8281
8282            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
8283
8284
8285            let response_rate_limits = response.rate_limits.clone();
8286            let response_data = response.data().expect("deserialize data");
8287
8288            assert_eq!(response_rate_limits, expected_rate_limits);
8289            assert_eq!(response_data, expected_data);
8290        });
8291    }
8292
8293    #[test]
8294    fn open_orders_cancel_all_error_response() {
8295        TOKIO_SHARED_RT.block_on(async {
8296            let (ws_api, conn, mut rx) = setup().await;
8297            let client = TradeApiClient::new(ws_api.clone());
8298
8299            let handle = tokio::spawn(async move {
8300                let params = OpenOrdersCancelAllParams::builder("BNBUSDT".to_string(),).build().unwrap();
8301                client.open_orders_cancel_all(params).await
8302            });
8303
8304            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
8305            let Message::Text(text) = sent else { panic!() };
8306            let v: Value = serde_json::from_str(&text).unwrap();
8307            let id = v["id"].as_str().unwrap().to_string();
8308
8309            let resp_json = json!({
8310                "id": id,
8311                "status": 400,
8312                    "error": {
8313                        "code": -2010,
8314                        "msg": "Account has insufficient balance for requested action.",
8315                    },
8316                    "rateLimits": [
8317                        {
8318                            "rateLimitType": "ORDERS",
8319                            "interval": "SECOND",
8320                            "intervalNum": 10,
8321                            "limit": 50,
8322                            "count": 13
8323                        },
8324                    ],
8325            });
8326            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8327
8328            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
8329            match join {
8330                Ok(Err(e)) => {
8331                    let msg = e.to_string();
8332                    assert!(
8333                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
8334                        "Expected error msg to contain server error, got: {msg}"
8335                    );
8336                }
8337                Ok(Ok(_)) => panic!("Expected error"),
8338                Err(_) => panic!("Task panicked"),
8339            }
8340        });
8341    }
8342
8343    #[test]
8344    fn open_orders_cancel_all_request_timeout() {
8345        TOKIO_SHARED_RT.block_on(async {
8346            let (ws_api, _conn, mut rx) = setup().await;
8347            let client = TradeApiClient::new(ws_api.clone());
8348
8349            let handle = spawn(async move {
8350                let params = OpenOrdersCancelAllParams::builder("BNBUSDT".to_string())
8351                    .build()
8352                    .unwrap();
8353                client.open_orders_cancel_all(params).await
8354            });
8355
8356            let sent = timeout(Duration::from_secs(1), rx.recv())
8357                .await
8358                .expect("send should occur")
8359                .expect("channel closed");
8360            let Message::Text(text) = sent else {
8361                panic!("expected Message Text")
8362            };
8363
8364            let _: Value = serde_json::from_str(&text).unwrap();
8365
8366            let result = handle.await.expect("task completed");
8367            match result {
8368                Err(e) => {
8369                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
8370                        assert!(matches!(inner, WebsocketError::Timeout));
8371                    } else {
8372                        panic!("Unexpected error type: {:?}", e);
8373                    }
8374                }
8375                Ok(_) => panic!("Expected timeout error"),
8376            }
8377        });
8378    }
8379
8380    #[test]
8381    fn order_amend_keep_priority_success() {
8382        TOKIO_SHARED_RT.block_on(async {
8383            let (ws_api, conn, mut rx) = setup().await;
8384            let client = TradeApiClient::new(ws_api.clone());
8385
8386            let handle = spawn(async move {
8387                let params = OrderAmendKeepPriorityParams::builder("BNBUSDT".to_string(),dec!(1),).build().unwrap();
8388                client.order_amend_keep_priority(params).await
8389            });
8390
8391            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8392            let Message::Text(text) = sent else { panic!() };
8393            let v: Value = serde_json::from_str(&text).unwrap();
8394            let id = v["id"].as_str().unwrap();
8395            assert_eq!(v["method"], "/order.amend.keepPriority".trim_start_matches('/'));
8396            let mut resp_json: Value = serde_json::from_str(r#"{"id":"56374b46-3061-486b-a311-89ee972eb648","status":200,"result":{"transactTime":1741924229819,"executionId":60,"amendedOrder":{"symbol":"BTUCSDT","orderId":23,"orderListId":4,"origClientOrderId":"my_pending_order","clientOrderId":"xbxXh5SSwaHS7oUEOCI88B","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","workingTime":1741924204920,"selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","stopPrice":"0.00000000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"},"listStatus":{"orderListId":4,"contingencyType":"OTO","listOrderStatus":"EXECUTING","listClientOrderId":"8nOGLLawudj1QoOiwbroRH","symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":22,"clientOrderId":"g04EWsjaackzedjC9wRkWD"}]}},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
8397            resp_json["id"] = id.into();
8398
8399            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8400            let expected_data: Box<models::OrderAmendKeepPriorityResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8401            let empty_array = Value::Array(vec![]);
8402            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8403            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8404                match raw_rate_limits.as_array() {
8405                    Some(arr) if arr.is_empty() => None,
8406                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8407                    None => None,
8408                };
8409
8410            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8411
8412            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
8413
8414
8415            let response_rate_limits = response.rate_limits.clone();
8416            let response_data = response.data().expect("deserialize data");
8417
8418            assert_eq!(response_rate_limits, expected_rate_limits);
8419            assert_eq!(response_data, expected_data);
8420        });
8421    }
8422
8423    #[test]
8424    fn order_amend_keep_priority_error_response() {
8425        TOKIO_SHARED_RT.block_on(async {
8426            let (ws_api, conn, mut rx) = setup().await;
8427            let client = TradeApiClient::new(ws_api.clone());
8428
8429            let handle = tokio::spawn(async move {
8430                let params = OrderAmendKeepPriorityParams::builder("BNBUSDT".to_string(),dec!(1),).build().unwrap();
8431                client.order_amend_keep_priority(params).await
8432            });
8433
8434            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
8435            let Message::Text(text) = sent else { panic!() };
8436            let v: Value = serde_json::from_str(&text).unwrap();
8437            let id = v["id"].as_str().unwrap().to_string();
8438
8439            let resp_json = json!({
8440                "id": id,
8441                "status": 400,
8442                    "error": {
8443                        "code": -2010,
8444                        "msg": "Account has insufficient balance for requested action.",
8445                    },
8446                    "rateLimits": [
8447                        {
8448                            "rateLimitType": "ORDERS",
8449                            "interval": "SECOND",
8450                            "intervalNum": 10,
8451                            "limit": 50,
8452                            "count": 13
8453                        },
8454                    ],
8455            });
8456            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8457
8458            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
8459            match join {
8460                Ok(Err(e)) => {
8461                    let msg = e.to_string();
8462                    assert!(
8463                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
8464                        "Expected error msg to contain server error, got: {msg}"
8465                    );
8466                }
8467                Ok(Ok(_)) => panic!("Expected error"),
8468                Err(_) => panic!("Task panicked"),
8469            }
8470        });
8471    }
8472
8473    #[test]
8474    fn order_amend_keep_priority_request_timeout() {
8475        TOKIO_SHARED_RT.block_on(async {
8476            let (ws_api, _conn, mut rx) = setup().await;
8477            let client = TradeApiClient::new(ws_api.clone());
8478
8479            let handle = spawn(async move {
8480                let params = OrderAmendKeepPriorityParams::builder("BNBUSDT".to_string(), dec!(1))
8481                    .build()
8482                    .unwrap();
8483                client.order_amend_keep_priority(params).await
8484            });
8485
8486            let sent = timeout(Duration::from_secs(1), rx.recv())
8487                .await
8488                .expect("send should occur")
8489                .expect("channel closed");
8490            let Message::Text(text) = sent else {
8491                panic!("expected Message Text")
8492            };
8493
8494            let _: Value = serde_json::from_str(&text).unwrap();
8495
8496            let result = handle.await.expect("task completed");
8497            match result {
8498                Err(e) => {
8499                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
8500                        assert!(matches!(inner, WebsocketError::Timeout));
8501                    } else {
8502                        panic!("Unexpected error type: {:?}", e);
8503                    }
8504                }
8505                Ok(_) => panic!("Expected timeout error"),
8506            }
8507        });
8508    }
8509
8510    #[test]
8511    fn order_cancel_success() {
8512        TOKIO_SHARED_RT.block_on(async {
8513            let (ws_api, conn, mut rx) = setup().await;
8514            let client = TradeApiClient::new(ws_api.clone());
8515
8516            let handle = spawn(async move {
8517                let params = OrderCancelParams::builder("BNBUSDT".to_string(),).build().unwrap();
8518                client.order_cancel(params).await
8519            });
8520
8521            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8522            let Message::Text(text) = sent else { panic!() };
8523            let v: Value = serde_json::from_str(&text).unwrap();
8524            let id = v["id"].as_str().unwrap();
8525            assert_eq!(v["method"], "/order.cancel".trim_start_matches('/'));
8526            let mut resp_json: Value = serde_json::from_str(r#"{"id":"16eaf097-bbec-44b9-96ff-e97e6e875870","status":200,"result":{"symbol":"BTCUSDT","origClientOrderId":"4d96324ff9d44481926157","orderId":12569099453,"orderListId":19431,"clientOrderId":"91fe37ce9e69c90d6358c0","transactTime":1684804350068,"status":"CANCELED","timeInForce":"GTC","type":"LIMIT","side":"SELL","stopPrice":"0.00000000","trailingDelta":10,"icebergQty":"0.00000000","strategyId":1,"strategyType":1000000,"selfTradePreventionMode":"NONE","preventedMatchId":0,"preventedQuantity":"1.200000","trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY","contingencyType":"OCO","listStatusType":"ALL_DONE","listOrderStatus":"ALL_DONE","listClientOrderId":"iuVNVJYYrByz6C4yGOPPK0","transactionTime":1660803702431,"orders":[{"symbol":"BTCUSDT","orderId":12569099453,"clientOrderId":"bX5wROblo6YeDwa9iTLeyY"}],"orderReports":[{"symbol":"BTCUSDT","origClientOrderId":"bX5wROblo6YeDwa9iTLeyY","orderId":12569099453,"orderListId":19431,"clientOrderId":"OFFXQtxVFZ6Nbcg4PgE2DA","transactTime":1684804350068,"status":"CANCELED","timeInForce":"GTC","type":"STOP_LOSS_LIMIT","side":"BUY","selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","stopPrice":"0.00000000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
8527            resp_json["id"] = id.into();
8528
8529            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8530            let expected_data: Box<models::OrderCancelResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8531            let empty_array = Value::Array(vec![]);
8532            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8533            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8534                match raw_rate_limits.as_array() {
8535                    Some(arr) if arr.is_empty() => None,
8536                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8537                    None => None,
8538                };
8539
8540            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8541
8542            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
8543
8544
8545            let response_rate_limits = response.rate_limits.clone();
8546            let response_data = response.data().expect("deserialize data");
8547
8548            assert_eq!(response_rate_limits, expected_rate_limits);
8549            assert_eq!(response_data, expected_data);
8550        });
8551    }
8552
8553    #[test]
8554    fn order_cancel_error_response() {
8555        TOKIO_SHARED_RT.block_on(async {
8556            let (ws_api, conn, mut rx) = setup().await;
8557            let client = TradeApiClient::new(ws_api.clone());
8558
8559            let handle = tokio::spawn(async move {
8560                let params = OrderCancelParams::builder("BNBUSDT".to_string(),).build().unwrap();
8561                client.order_cancel(params).await
8562            });
8563
8564            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
8565            let Message::Text(text) = sent else { panic!() };
8566            let v: Value = serde_json::from_str(&text).unwrap();
8567            let id = v["id"].as_str().unwrap().to_string();
8568
8569            let resp_json = json!({
8570                "id": id,
8571                "status": 400,
8572                    "error": {
8573                        "code": -2010,
8574                        "msg": "Account has insufficient balance for requested action.",
8575                    },
8576                    "rateLimits": [
8577                        {
8578                            "rateLimitType": "ORDERS",
8579                            "interval": "SECOND",
8580                            "intervalNum": 10,
8581                            "limit": 50,
8582                            "count": 13
8583                        },
8584                    ],
8585            });
8586            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8587
8588            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
8589            match join {
8590                Ok(Err(e)) => {
8591                    let msg = e.to_string();
8592                    assert!(
8593                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
8594                        "Expected error msg to contain server error, got: {msg}"
8595                    );
8596                }
8597                Ok(Ok(_)) => panic!("Expected error"),
8598                Err(_) => panic!("Task panicked"),
8599            }
8600        });
8601    }
8602
8603    #[test]
8604    fn order_cancel_request_timeout() {
8605        TOKIO_SHARED_RT.block_on(async {
8606            let (ws_api, _conn, mut rx) = setup().await;
8607            let client = TradeApiClient::new(ws_api.clone());
8608
8609            let handle = spawn(async move {
8610                let params = OrderCancelParams::builder("BNBUSDT".to_string())
8611                    .build()
8612                    .unwrap();
8613                client.order_cancel(params).await
8614            });
8615
8616            let sent = timeout(Duration::from_secs(1), rx.recv())
8617                .await
8618                .expect("send should occur")
8619                .expect("channel closed");
8620            let Message::Text(text) = sent else {
8621                panic!("expected Message Text")
8622            };
8623
8624            let _: Value = serde_json::from_str(&text).unwrap();
8625
8626            let result = handle.await.expect("task completed");
8627            match result {
8628                Err(e) => {
8629                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
8630                        assert!(matches!(inner, WebsocketError::Timeout));
8631                    } else {
8632                        panic!("Unexpected error type: {:?}", e);
8633                    }
8634                }
8635                Ok(_) => panic!("Expected timeout error"),
8636            }
8637        });
8638    }
8639
8640    #[test]
8641    fn order_cancel_replace_success() {
8642        TOKIO_SHARED_RT.block_on(async {
8643            let (ws_api, conn, mut rx) = setup().await;
8644            let client = TradeApiClient::new(ws_api.clone());
8645
8646            let handle = spawn(async move {
8647                let params = OrderCancelReplaceParams::builder("BNBUSDT".to_string(),OrderCancelReplaceCancelReplaceModeEnum::StopOnFailure,OrderCancelReplaceSideEnum::Buy,OrderCancelReplaceTypeEnum::Market,).build().unwrap();
8648                client.order_cancel_replace(params).await
8649            });
8650
8651            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8652            let Message::Text(text) = sent else { panic!() };
8653            let v: Value = serde_json::from_str(&text).unwrap();
8654            let id = v["id"].as_str().unwrap();
8655            assert_eq!(v["method"], "/order.cancelReplace".trim_start_matches('/'));
8656            let mut resp_json: Value = serde_json::from_str(r#"{"id":"99de1036-b5e2-4e0f-9b5c-13d751c93a1a","status":200,"result":{"cancelResult":"SUCCESS","newOrderResult":"SUCCESS","cancelResponse":{"symbol":"BTCUSDT","origClientOrderId":"4d96324ff9d44481926157","orderId":125690984230,"orderListId":-1,"clientOrderId":"91fe37ce9e69c90d6358c0","transactTime":1684804350068,"status":"CANCELED","timeInForce":"GTC","type":"LIMIT","side":"SELL","selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","stopPrice":"0.00000000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"},"newOrderResponse":{"symbol":"BTCUSDT","orderId":12569099453,"orderListId":-1,"clientOrderId":"bX5wROblo6YeDwa9iTLeyY","transactTime":1660813156959,"status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"SELL","selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","stopPrice":"0.00000000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
8657            resp_json["id"] = id.into();
8658
8659            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8660            let expected_data: Box<models::OrderCancelReplaceResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8661            let empty_array = Value::Array(vec![]);
8662            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8663            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8664                match raw_rate_limits.as_array() {
8665                    Some(arr) if arr.is_empty() => None,
8666                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8667                    None => None,
8668                };
8669
8670            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8671
8672            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
8673
8674
8675            let response_rate_limits = response.rate_limits.clone();
8676            let response_data = response.data().expect("deserialize data");
8677
8678            assert_eq!(response_rate_limits, expected_rate_limits);
8679            assert_eq!(response_data, expected_data);
8680        });
8681    }
8682
8683    #[test]
8684    fn order_cancel_replace_error_response() {
8685        TOKIO_SHARED_RT.block_on(async {
8686            let (ws_api, conn, mut rx) = setup().await;
8687            let client = TradeApiClient::new(ws_api.clone());
8688
8689            let handle = tokio::spawn(async move {
8690                let params = OrderCancelReplaceParams::builder("BNBUSDT".to_string(),OrderCancelReplaceCancelReplaceModeEnum::StopOnFailure,OrderCancelReplaceSideEnum::Buy,OrderCancelReplaceTypeEnum::Market,).build().unwrap();
8691                client.order_cancel_replace(params).await
8692            });
8693
8694            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
8695            let Message::Text(text) = sent else { panic!() };
8696            let v: Value = serde_json::from_str(&text).unwrap();
8697            let id = v["id"].as_str().unwrap().to_string();
8698
8699            let resp_json = json!({
8700                "id": id,
8701                "status": 400,
8702                    "error": {
8703                        "code": -2010,
8704                        "msg": "Account has insufficient balance for requested action.",
8705                    },
8706                    "rateLimits": [
8707                        {
8708                            "rateLimitType": "ORDERS",
8709                            "interval": "SECOND",
8710                            "intervalNum": 10,
8711                            "limit": 50,
8712                            "count": 13
8713                        },
8714                    ],
8715            });
8716            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8717
8718            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
8719            match join {
8720                Ok(Err(e)) => {
8721                    let msg = e.to_string();
8722                    assert!(
8723                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
8724                        "Expected error msg to contain server error, got: {msg}"
8725                    );
8726                }
8727                Ok(Ok(_)) => panic!("Expected error"),
8728                Err(_) => panic!("Task panicked"),
8729            }
8730        });
8731    }
8732
8733    #[test]
8734    fn order_cancel_replace_request_timeout() {
8735        TOKIO_SHARED_RT.block_on(async {
8736            let (ws_api, _conn, mut rx) = setup().await;
8737            let client = TradeApiClient::new(ws_api.clone());
8738
8739            let handle = spawn(async move {
8740                let params = OrderCancelReplaceParams::builder(
8741                    "BNBUSDT".to_string(),
8742                    OrderCancelReplaceCancelReplaceModeEnum::StopOnFailure,
8743                    OrderCancelReplaceSideEnum::Buy,
8744                    OrderCancelReplaceTypeEnum::Market,
8745                )
8746                .build()
8747                .unwrap();
8748                client.order_cancel_replace(params).await
8749            });
8750
8751            let sent = timeout(Duration::from_secs(1), rx.recv())
8752                .await
8753                .expect("send should occur")
8754                .expect("channel closed");
8755            let Message::Text(text) = sent else {
8756                panic!("expected Message Text")
8757            };
8758
8759            let _: Value = serde_json::from_str(&text).unwrap();
8760
8761            let result = handle.await.expect("task completed");
8762            match result {
8763                Err(e) => {
8764                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
8765                        assert!(matches!(inner, WebsocketError::Timeout));
8766                    } else {
8767                        panic!("Unexpected error type: {:?}", e);
8768                    }
8769                }
8770                Ok(_) => panic!("Expected timeout error"),
8771            }
8772        });
8773    }
8774
8775    #[test]
8776    fn order_list_cancel_success() {
8777        TOKIO_SHARED_RT.block_on(async {
8778            let (ws_api, conn, mut rx) = setup().await;
8779            let client = TradeApiClient::new(ws_api.clone());
8780
8781            let handle = spawn(async move {
8782                let params = OrderListCancelParams::builder("BNBUSDT".to_string(),).build().unwrap();
8783                client.order_list_cancel(params).await
8784            });
8785
8786            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8787            let Message::Text(text) = sent else { panic!() };
8788            let v: Value = serde_json::from_str(&text).unwrap();
8789            let id = v["id"].as_str().unwrap();
8790            assert_eq!(v["method"], "/orderList.cancel".trim_start_matches('/'));
8791            let mut resp_json: Value = serde_json::from_str(r#"{"id":"c5899911-d3f4-47ae-8835-97da553d27d0","status":200,"result":{"orderListId":1274512,"contingencyType":"OCO","listStatusType":"ALL_DONE","listOrderStatus":"ALL_DONE","listClientOrderId":"6023531d7edaad348f5aff","transactionTime":1660801720215,"symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":12569138901,"clientOrderId":"BqtFCj5odMoWtSqGk2X9tU"}],"orderReports":[{"symbol":"BTCUSDT","orderId":12569138901,"orderListId":1274512,"clientOrderId":"BqtFCj5odMoWtSqGk2X9tU","transactTime":1660801720215,"status":"CANCELED","timeInForce":"GTC","type":"STOP_LOSS_LIMIT","side":"SELL","selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
8792            resp_json["id"] = id.into();
8793
8794            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8795            let expected_data: Box<models::OrderListCancelResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8796            let empty_array = Value::Array(vec![]);
8797            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8798            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8799                match raw_rate_limits.as_array() {
8800                    Some(arr) if arr.is_empty() => None,
8801                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8802                    None => None,
8803                };
8804
8805            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8806
8807            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
8808
8809
8810            let response_rate_limits = response.rate_limits.clone();
8811            let response_data = response.data().expect("deserialize data");
8812
8813            assert_eq!(response_rate_limits, expected_rate_limits);
8814            assert_eq!(response_data, expected_data);
8815        });
8816    }
8817
8818    #[test]
8819    fn order_list_cancel_error_response() {
8820        TOKIO_SHARED_RT.block_on(async {
8821            let (ws_api, conn, mut rx) = setup().await;
8822            let client = TradeApiClient::new(ws_api.clone());
8823
8824            let handle = tokio::spawn(async move {
8825                let params = OrderListCancelParams::builder("BNBUSDT".to_string(),).build().unwrap();
8826                client.order_list_cancel(params).await
8827            });
8828
8829            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
8830            let Message::Text(text) = sent else { panic!() };
8831            let v: Value = serde_json::from_str(&text).unwrap();
8832            let id = v["id"].as_str().unwrap().to_string();
8833
8834            let resp_json = json!({
8835                "id": id,
8836                "status": 400,
8837                    "error": {
8838                        "code": -2010,
8839                        "msg": "Account has insufficient balance for requested action.",
8840                    },
8841                    "rateLimits": [
8842                        {
8843                            "rateLimitType": "ORDERS",
8844                            "interval": "SECOND",
8845                            "intervalNum": 10,
8846                            "limit": 50,
8847                            "count": 13
8848                        },
8849                    ],
8850            });
8851            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8852
8853            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
8854            match join {
8855                Ok(Err(e)) => {
8856                    let msg = e.to_string();
8857                    assert!(
8858                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
8859                        "Expected error msg to contain server error, got: {msg}"
8860                    );
8861                }
8862                Ok(Ok(_)) => panic!("Expected error"),
8863                Err(_) => panic!("Task panicked"),
8864            }
8865        });
8866    }
8867
8868    #[test]
8869    fn order_list_cancel_request_timeout() {
8870        TOKIO_SHARED_RT.block_on(async {
8871            let (ws_api, _conn, mut rx) = setup().await;
8872            let client = TradeApiClient::new(ws_api.clone());
8873
8874            let handle = spawn(async move {
8875                let params = OrderListCancelParams::builder("BNBUSDT".to_string())
8876                    .build()
8877                    .unwrap();
8878                client.order_list_cancel(params).await
8879            });
8880
8881            let sent = timeout(Duration::from_secs(1), rx.recv())
8882                .await
8883                .expect("send should occur")
8884                .expect("channel closed");
8885            let Message::Text(text) = sent else {
8886                panic!("expected Message Text")
8887            };
8888
8889            let _: Value = serde_json::from_str(&text).unwrap();
8890
8891            let result = handle.await.expect("task completed");
8892            match result {
8893                Err(e) => {
8894                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
8895                        assert!(matches!(inner, WebsocketError::Timeout));
8896                    } else {
8897                        panic!("Unexpected error type: {:?}", e);
8898                    }
8899                }
8900                Ok(_) => panic!("Expected timeout error"),
8901            }
8902        });
8903    }
8904
8905    #[test]
8906    fn order_list_place_success() {
8907        TOKIO_SHARED_RT.block_on(async {
8908            let (ws_api, conn, mut rx) = setup().await;
8909            let client = TradeApiClient::new(ws_api.clone());
8910
8911            let handle = spawn(async move {
8912                let params = OrderListPlaceParams::builder("BNBUSDT".to_string(),OrderListPlaceSideEnum::Buy,dec!(1),dec!(1),).build().unwrap();
8913                client.order_list_place(params).await
8914            });
8915
8916            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8917            let Message::Text(text) = sent else { panic!() };
8918            let v: Value = serde_json::from_str(&text).unwrap();
8919            let id = v["id"].as_str().unwrap();
8920            assert_eq!(v["method"], "/orderList.place".trim_start_matches('/'));
8921            let mut resp_json: Value = serde_json::from_str(r#"{"id":"57833dc0-e3f2-43fb-ba20-46480973b0aa","status":200,"result":{"orderListId":1274512,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"08985fedd9ea2cf6b28996","transactionTime":1660801713793,"symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":12569138901,"clientOrderId":"BqtFCj5odMoWtSqGk2X9tU"}],"orderReports":[{"symbol":"BTCUSDT","orderId":12569138901,"orderListId":1274512,"clientOrderId":"BqtFCj5odMoWtSqGk2X9tU","transactTime":1660801713793,"status":"NEW","timeInForce":"GTC","type":"STOP_LOSS_LIMIT","side":"SELL","workingTime":-1,"selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
8922            resp_json["id"] = id.into();
8923
8924            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8925            let expected_data: Box<models::OrderListPlaceResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8926            let empty_array = Value::Array(vec![]);
8927            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8928            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8929                match raw_rate_limits.as_array() {
8930                    Some(arr) if arr.is_empty() => None,
8931                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8932                    None => None,
8933                };
8934
8935            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8936
8937            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
8938
8939
8940            let response_rate_limits = response.rate_limits.clone();
8941            let response_data = response.data().expect("deserialize data");
8942
8943            assert_eq!(response_rate_limits, expected_rate_limits);
8944            assert_eq!(response_data, expected_data);
8945        });
8946    }
8947
8948    #[test]
8949    fn order_list_place_error_response() {
8950        TOKIO_SHARED_RT.block_on(async {
8951            let (ws_api, conn, mut rx) = setup().await;
8952            let client = TradeApiClient::new(ws_api.clone());
8953
8954            let handle = tokio::spawn(async move {
8955                let params = OrderListPlaceParams::builder("BNBUSDT".to_string(),OrderListPlaceSideEnum::Buy,dec!(1),dec!(1),).build().unwrap();
8956                client.order_list_place(params).await
8957            });
8958
8959            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
8960            let Message::Text(text) = sent else { panic!() };
8961            let v: Value = serde_json::from_str(&text).unwrap();
8962            let id = v["id"].as_str().unwrap().to_string();
8963
8964            let resp_json = json!({
8965                "id": id,
8966                "status": 400,
8967                    "error": {
8968                        "code": -2010,
8969                        "msg": "Account has insufficient balance for requested action.",
8970                    },
8971                    "rateLimits": [
8972                        {
8973                            "rateLimitType": "ORDERS",
8974                            "interval": "SECOND",
8975                            "intervalNum": 10,
8976                            "limit": 50,
8977                            "count": 13
8978                        },
8979                    ],
8980            });
8981            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8982
8983            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
8984            match join {
8985                Ok(Err(e)) => {
8986                    let msg = e.to_string();
8987                    assert!(
8988                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
8989                        "Expected error msg to contain server error, got: {msg}"
8990                    );
8991                }
8992                Ok(Ok(_)) => panic!("Expected error"),
8993                Err(_) => panic!("Task panicked"),
8994            }
8995        });
8996    }
8997
8998    #[test]
8999    fn order_list_place_request_timeout() {
9000        TOKIO_SHARED_RT.block_on(async {
9001            let (ws_api, _conn, mut rx) = setup().await;
9002            let client = TradeApiClient::new(ws_api.clone());
9003
9004            let handle = spawn(async move {
9005                let params = OrderListPlaceParams::builder(
9006                    "BNBUSDT".to_string(),
9007                    OrderListPlaceSideEnum::Buy,
9008                    dec!(1),
9009                    dec!(1),
9010                )
9011                .build()
9012                .unwrap();
9013                client.order_list_place(params).await
9014            });
9015
9016            let sent = timeout(Duration::from_secs(1), rx.recv())
9017                .await
9018                .expect("send should occur")
9019                .expect("channel closed");
9020            let Message::Text(text) = sent else {
9021                panic!("expected Message Text")
9022            };
9023
9024            let _: Value = serde_json::from_str(&text).unwrap();
9025
9026            let result = handle.await.expect("task completed");
9027            match result {
9028                Err(e) => {
9029                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9030                        assert!(matches!(inner, WebsocketError::Timeout));
9031                    } else {
9032                        panic!("Unexpected error type: {:?}", e);
9033                    }
9034                }
9035                Ok(_) => panic!("Expected timeout error"),
9036            }
9037        });
9038    }
9039
9040    #[test]
9041    fn order_list_place_oco_success() {
9042        TOKIO_SHARED_RT.block_on(async {
9043            let (ws_api, conn, mut rx) = setup().await;
9044            let client = TradeApiClient::new(ws_api.clone());
9045
9046            let handle = spawn(async move {
9047                let params = OrderListPlaceOcoParams::builder("BNBUSDT".to_string(),OrderListPlaceOcoSideEnum::Buy,dec!(1),OrderListPlaceOcoAboveTypeEnum::StopLossLimit,OrderListPlaceOcoBelowTypeEnum::StopLoss,).build().unwrap();
9048                client.order_list_place_oco(params).await
9049            });
9050
9051            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9052            let Message::Text(text) = sent else { panic!() };
9053            let v: Value = serde_json::from_str(&text).unwrap();
9054            let id = v["id"].as_str().unwrap();
9055            assert_eq!(v["method"], "/orderList.place.oco".trim_start_matches('/'));
9056            let mut resp_json: Value = serde_json::from_str(r#"{"id":"56374a46-3261-486b-a211-99ed972eb648","status":200,"result":{"orderListId":2,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"cKPMnDCbcLQILtDYM4f4fX","transactionTime":1711062760648,"symbol":"LTCBNB","orders":[{"symbol":"LTCBNB","orderId":2,"clientOrderId":"0m6I4wfxvTUrOBSMUl0OPU"}],"orderReports":[{"symbol":"LTCBNB","orderId":2,"orderListId":2,"clientOrderId":"0m6I4wfxvTUrOBSMUl0OPU","transactTime":1711062760648,"status":"NEW","timeInForce":"GTC","type":"STOP_LOSS_LIMIT","side":"BUY","workingTime":-1,"selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
9057            resp_json["id"] = id.into();
9058
9059            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9060            let expected_data: Box<models::OrderListPlaceOcoResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9061            let empty_array = Value::Array(vec![]);
9062            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9063            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9064                match raw_rate_limits.as_array() {
9065                    Some(arr) if arr.is_empty() => None,
9066                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9067                    None => None,
9068                };
9069
9070            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9071
9072            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9073
9074
9075            let response_rate_limits = response.rate_limits.clone();
9076            let response_data = response.data().expect("deserialize data");
9077
9078            assert_eq!(response_rate_limits, expected_rate_limits);
9079            assert_eq!(response_data, expected_data);
9080        });
9081    }
9082
9083    #[test]
9084    fn order_list_place_oco_error_response() {
9085        TOKIO_SHARED_RT.block_on(async {
9086            let (ws_api, conn, mut rx) = setup().await;
9087            let client = TradeApiClient::new(ws_api.clone());
9088
9089            let handle = tokio::spawn(async move {
9090                let params = OrderListPlaceOcoParams::builder("BNBUSDT".to_string(),OrderListPlaceOcoSideEnum::Buy,dec!(1),OrderListPlaceOcoAboveTypeEnum::StopLossLimit,OrderListPlaceOcoBelowTypeEnum::StopLoss,).build().unwrap();
9091                client.order_list_place_oco(params).await
9092            });
9093
9094            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9095            let Message::Text(text) = sent else { panic!() };
9096            let v: Value = serde_json::from_str(&text).unwrap();
9097            let id = v["id"].as_str().unwrap().to_string();
9098
9099            let resp_json = json!({
9100                "id": id,
9101                "status": 400,
9102                    "error": {
9103                        "code": -2010,
9104                        "msg": "Account has insufficient balance for requested action.",
9105                    },
9106                    "rateLimits": [
9107                        {
9108                            "rateLimitType": "ORDERS",
9109                            "interval": "SECOND",
9110                            "intervalNum": 10,
9111                            "limit": 50,
9112                            "count": 13
9113                        },
9114                    ],
9115            });
9116            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9117
9118            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9119            match join {
9120                Ok(Err(e)) => {
9121                    let msg = e.to_string();
9122                    assert!(
9123                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9124                        "Expected error msg to contain server error, got: {msg}"
9125                    );
9126                }
9127                Ok(Ok(_)) => panic!("Expected error"),
9128                Err(_) => panic!("Task panicked"),
9129            }
9130        });
9131    }
9132
9133    #[test]
9134    fn order_list_place_oco_request_timeout() {
9135        TOKIO_SHARED_RT.block_on(async {
9136            let (ws_api, _conn, mut rx) = setup().await;
9137            let client = TradeApiClient::new(ws_api.clone());
9138
9139            let handle = spawn(async move {
9140                let params = OrderListPlaceOcoParams::builder(
9141                    "BNBUSDT".to_string(),
9142                    OrderListPlaceOcoSideEnum::Buy,
9143                    dec!(1),
9144                    OrderListPlaceOcoAboveTypeEnum::StopLossLimit,
9145                    OrderListPlaceOcoBelowTypeEnum::StopLoss,
9146                )
9147                .build()
9148                .unwrap();
9149                client.order_list_place_oco(params).await
9150            });
9151
9152            let sent = timeout(Duration::from_secs(1), rx.recv())
9153                .await
9154                .expect("send should occur")
9155                .expect("channel closed");
9156            let Message::Text(text) = sent else {
9157                panic!("expected Message Text")
9158            };
9159
9160            let _: Value = serde_json::from_str(&text).unwrap();
9161
9162            let result = handle.await.expect("task completed");
9163            match result {
9164                Err(e) => {
9165                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9166                        assert!(matches!(inner, WebsocketError::Timeout));
9167                    } else {
9168                        panic!("Unexpected error type: {:?}", e);
9169                    }
9170                }
9171                Ok(_) => panic!("Expected timeout error"),
9172            }
9173        });
9174    }
9175
9176    #[test]
9177    fn order_list_place_opo_success() {
9178        TOKIO_SHARED_RT.block_on(async {
9179            let (ws_api, conn, mut rx) = setup().await;
9180            let client = TradeApiClient::new(ws_api.clone());
9181
9182            let handle = spawn(async move {
9183                let params = OrderListPlaceOpoParams::builder("BNBUSDT".to_string(),OrderListPlaceOpoWorkingTypeEnum::Limit,OrderListPlaceOpoWorkingSideEnum::Buy,dec!(1),dec!(1),OrderListPlaceOpoPendingTypeEnum::Limit,OrderListPlaceOpoPendingSideEnum::Buy,).build().unwrap();
9184                client.order_list_place_opo(params).await
9185            });
9186
9187            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9188            let Message::Text(text) = sent else { panic!() };
9189            let v: Value = serde_json::from_str(&text).unwrap();
9190            let id = v["id"].as_str().unwrap();
9191            assert_eq!(v["method"], "/orderList.place.opo".trim_start_matches('/'));
9192            let mut resp_json: Value = serde_json::from_str(r#"{"status":200,"result":{"orderListId":2,"contingencyType":"OTO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"OiOgqvRagBefpzdM5gjYX3","transactionTime":1762941318142,"symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":2,"clientOrderId":"pUzhKBbc0ZVdMScIRAqitH"}],"orderReports":[{"symbol":"BTCUSDT","orderId":2,"orderListId":2,"clientOrderId":"pUzhKBbc0ZVdMScIRAqitH","transactTime":1762941318142,"status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","workingTime":1762941318142,"selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","stopPrice":"0.00000000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]}}"#).unwrap_or_else(|_| serde_json::json!({}));
9193            resp_json["id"] = id.into();
9194
9195            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9196            let expected_data: Box<models::OrderListPlaceOpoResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9197            let empty_array = Value::Array(vec![]);
9198            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9199            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9200                match raw_rate_limits.as_array() {
9201                    Some(arr) if arr.is_empty() => None,
9202                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9203                    None => None,
9204                };
9205
9206            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9207
9208            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9209
9210
9211            let response_rate_limits = response.rate_limits.clone();
9212            let response_data = response.data().expect("deserialize data");
9213
9214            assert_eq!(response_rate_limits, expected_rate_limits);
9215            assert_eq!(response_data, expected_data);
9216        });
9217    }
9218
9219    #[test]
9220    fn order_list_place_opo_error_response() {
9221        TOKIO_SHARED_RT.block_on(async {
9222            let (ws_api, conn, mut rx) = setup().await;
9223            let client = TradeApiClient::new(ws_api.clone());
9224
9225            let handle = tokio::spawn(async move {
9226                let params = OrderListPlaceOpoParams::builder("BNBUSDT".to_string(),OrderListPlaceOpoWorkingTypeEnum::Limit,OrderListPlaceOpoWorkingSideEnum::Buy,dec!(1),dec!(1),OrderListPlaceOpoPendingTypeEnum::Limit,OrderListPlaceOpoPendingSideEnum::Buy,).build().unwrap();
9227                client.order_list_place_opo(params).await
9228            });
9229
9230            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9231            let Message::Text(text) = sent else { panic!() };
9232            let v: Value = serde_json::from_str(&text).unwrap();
9233            let id = v["id"].as_str().unwrap().to_string();
9234
9235            let resp_json = json!({
9236                "id": id,
9237                "status": 400,
9238                    "error": {
9239                        "code": -2010,
9240                        "msg": "Account has insufficient balance for requested action.",
9241                    },
9242                    "rateLimits": [
9243                        {
9244                            "rateLimitType": "ORDERS",
9245                            "interval": "SECOND",
9246                            "intervalNum": 10,
9247                            "limit": 50,
9248                            "count": 13
9249                        },
9250                    ],
9251            });
9252            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9253
9254            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9255            match join {
9256                Ok(Err(e)) => {
9257                    let msg = e.to_string();
9258                    assert!(
9259                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9260                        "Expected error msg to contain server error, got: {msg}"
9261                    );
9262                }
9263                Ok(Ok(_)) => panic!("Expected error"),
9264                Err(_) => panic!("Task panicked"),
9265            }
9266        });
9267    }
9268
9269    #[test]
9270    fn order_list_place_opo_request_timeout() {
9271        TOKIO_SHARED_RT.block_on(async {
9272            let (ws_api, _conn, mut rx) = setup().await;
9273            let client = TradeApiClient::new(ws_api.clone());
9274
9275            let handle = spawn(async move {
9276                let params = OrderListPlaceOpoParams::builder(
9277                    "BNBUSDT".to_string(),
9278                    OrderListPlaceOpoWorkingTypeEnum::Limit,
9279                    OrderListPlaceOpoWorkingSideEnum::Buy,
9280                    dec!(1),
9281                    dec!(1),
9282                    OrderListPlaceOpoPendingTypeEnum::Limit,
9283                    OrderListPlaceOpoPendingSideEnum::Buy,
9284                )
9285                .build()
9286                .unwrap();
9287                client.order_list_place_opo(params).await
9288            });
9289
9290            let sent = timeout(Duration::from_secs(1), rx.recv())
9291                .await
9292                .expect("send should occur")
9293                .expect("channel closed");
9294            let Message::Text(text) = sent else {
9295                panic!("expected Message Text")
9296            };
9297
9298            let _: Value = serde_json::from_str(&text).unwrap();
9299
9300            let result = handle.await.expect("task completed");
9301            match result {
9302                Err(e) => {
9303                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9304                        assert!(matches!(inner, WebsocketError::Timeout));
9305                    } else {
9306                        panic!("Unexpected error type: {:?}", e);
9307                    }
9308                }
9309                Ok(_) => panic!("Expected timeout error"),
9310            }
9311        });
9312    }
9313
9314    #[test]
9315    fn order_list_place_opoco_success() {
9316        TOKIO_SHARED_RT.block_on(async {
9317            let (ws_api, conn, mut rx) = setup().await;
9318            let client = TradeApiClient::new(ws_api.clone());
9319
9320            let handle = spawn(async move {
9321                let params = OrderListPlaceOpocoParams::builder("BNBUSDT".to_string(),OrderListPlaceOpocoWorkingTypeEnum::Limit,OrderListPlaceOpocoWorkingSideEnum::Buy,dec!(1),dec!(1),OrderListPlaceOpocoPendingSideEnum::Buy,OrderListPlaceOpocoPendingAboveTypeEnum::StopLossLimit,).build().unwrap();
9322                client.order_list_place_opoco(params).await
9323            });
9324
9325            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9326            let Message::Text(text) = sent else { panic!() };
9327            let v: Value = serde_json::from_str(&text).unwrap();
9328            let id = v["id"].as_str().unwrap();
9329            assert_eq!(v["method"], "/orderList.place.opoco".trim_start_matches('/'));
9330            let mut resp_json: Value = serde_json::from_str(r#"{"status":200,"result":{"orderListId":1,"contingencyType":"OTO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"TVbG6ymkYMXTj7tczbOsBf","transactionTime":1763000139104,"symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":6,"clientOrderId":"3czuJSeyjPwV9Xo28j1Dv3"}],"orderReports":[{"symbol":"BTCUSDT","orderId":6,"orderListId":1,"clientOrderId":"3czuJSeyjPwV9Xo28j1Dv3","transactTime":1763000139104,"status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","workingTime":1763000139104,"selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]}}"#).unwrap_or_else(|_| serde_json::json!({}));
9331            resp_json["id"] = id.into();
9332
9333            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9334            let expected_data: Box<models::OrderListPlaceOpocoResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9335            let empty_array = Value::Array(vec![]);
9336            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9337            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9338                match raw_rate_limits.as_array() {
9339                    Some(arr) if arr.is_empty() => None,
9340                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9341                    None => None,
9342                };
9343
9344            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9345
9346            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9347
9348
9349            let response_rate_limits = response.rate_limits.clone();
9350            let response_data = response.data().expect("deserialize data");
9351
9352            assert_eq!(response_rate_limits, expected_rate_limits);
9353            assert_eq!(response_data, expected_data);
9354        });
9355    }
9356
9357    #[test]
9358    fn order_list_place_opoco_error_response() {
9359        TOKIO_SHARED_RT.block_on(async {
9360            let (ws_api, conn, mut rx) = setup().await;
9361            let client = TradeApiClient::new(ws_api.clone());
9362
9363            let handle = tokio::spawn(async move {
9364                let params = OrderListPlaceOpocoParams::builder("BNBUSDT".to_string(),OrderListPlaceOpocoWorkingTypeEnum::Limit,OrderListPlaceOpocoWorkingSideEnum::Buy,dec!(1),dec!(1),OrderListPlaceOpocoPendingSideEnum::Buy,OrderListPlaceOpocoPendingAboveTypeEnum::StopLossLimit,).build().unwrap();
9365                client.order_list_place_opoco(params).await
9366            });
9367
9368            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9369            let Message::Text(text) = sent else { panic!() };
9370            let v: Value = serde_json::from_str(&text).unwrap();
9371            let id = v["id"].as_str().unwrap().to_string();
9372
9373            let resp_json = json!({
9374                "id": id,
9375                "status": 400,
9376                    "error": {
9377                        "code": -2010,
9378                        "msg": "Account has insufficient balance for requested action.",
9379                    },
9380                    "rateLimits": [
9381                        {
9382                            "rateLimitType": "ORDERS",
9383                            "interval": "SECOND",
9384                            "intervalNum": 10,
9385                            "limit": 50,
9386                            "count": 13
9387                        },
9388                    ],
9389            });
9390            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9391
9392            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9393            match join {
9394                Ok(Err(e)) => {
9395                    let msg = e.to_string();
9396                    assert!(
9397                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9398                        "Expected error msg to contain server error, got: {msg}"
9399                    );
9400                }
9401                Ok(Ok(_)) => panic!("Expected error"),
9402                Err(_) => panic!("Task panicked"),
9403            }
9404        });
9405    }
9406
9407    #[test]
9408    fn order_list_place_opoco_request_timeout() {
9409        TOKIO_SHARED_RT.block_on(async {
9410            let (ws_api, _conn, mut rx) = setup().await;
9411            let client = TradeApiClient::new(ws_api.clone());
9412
9413            let handle = spawn(async move {
9414                let params = OrderListPlaceOpocoParams::builder(
9415                    "BNBUSDT".to_string(),
9416                    OrderListPlaceOpocoWorkingTypeEnum::Limit,
9417                    OrderListPlaceOpocoWorkingSideEnum::Buy,
9418                    dec!(1),
9419                    dec!(1),
9420                    OrderListPlaceOpocoPendingSideEnum::Buy,
9421                    OrderListPlaceOpocoPendingAboveTypeEnum::StopLossLimit,
9422                )
9423                .build()
9424                .unwrap();
9425                client.order_list_place_opoco(params).await
9426            });
9427
9428            let sent = timeout(Duration::from_secs(1), rx.recv())
9429                .await
9430                .expect("send should occur")
9431                .expect("channel closed");
9432            let Message::Text(text) = sent else {
9433                panic!("expected Message Text")
9434            };
9435
9436            let _: Value = serde_json::from_str(&text).unwrap();
9437
9438            let result = handle.await.expect("task completed");
9439            match result {
9440                Err(e) => {
9441                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9442                        assert!(matches!(inner, WebsocketError::Timeout));
9443                    } else {
9444                        panic!("Unexpected error type: {:?}", e);
9445                    }
9446                }
9447                Ok(_) => panic!("Expected timeout error"),
9448            }
9449        });
9450    }
9451
9452    #[test]
9453    fn order_list_place_oto_success() {
9454        TOKIO_SHARED_RT.block_on(async {
9455            let (ws_api, conn, mut rx) = setup().await;
9456            let client = TradeApiClient::new(ws_api.clone());
9457
9458            let handle = spawn(async move {
9459                let params = OrderListPlaceOtoParams::builder("BNBUSDT".to_string(),OrderListPlaceOtoWorkingTypeEnum::Limit,OrderListPlaceOtoWorkingSideEnum::Buy,dec!(1),dec!(1),OrderListPlaceOtoPendingTypeEnum::Limit,OrderListPlaceOtoPendingSideEnum::Buy,dec!(1),).build().unwrap();
9460                client.order_list_place_oto(params).await
9461            });
9462
9463            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9464            let Message::Text(text) = sent else { panic!() };
9465            let v: Value = serde_json::from_str(&text).unwrap();
9466            let id = v["id"].as_str().unwrap();
9467            assert_eq!(v["method"], "/orderList.place.oto".trim_start_matches('/'));
9468            let mut resp_json: Value = serde_json::from_str(r#"{"status":200,"result":{"orderListId":626,"contingencyType":"OTO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"KA4EBjGnzvSwSCQsDdTrlf","transactionTime":1712544395981,"orders":[{"symbol":"LTCBNB","orderId":13,"clientOrderId":"YiAUtM9yJjl1a2jXHSp9Ny"}],"orderReports":[{"symbol":"LTCBNB","orderId":13,"orderListId":626,"clientOrderId":"YiAUtM9yJjl1a2jXHSp9Ny","transactTime":1712544395981,"status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"SELL","workingTime":1712544395981,"selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","stopPrice":"0.00000000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
9469            resp_json["id"] = id.into();
9470
9471            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9472            let expected_data: Box<models::OrderListPlaceOtoResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9473            let empty_array = Value::Array(vec![]);
9474            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9475            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9476                match raw_rate_limits.as_array() {
9477                    Some(arr) if arr.is_empty() => None,
9478                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9479                    None => None,
9480                };
9481
9482            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9483
9484            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9485
9486
9487            let response_rate_limits = response.rate_limits.clone();
9488            let response_data = response.data().expect("deserialize data");
9489
9490            assert_eq!(response_rate_limits, expected_rate_limits);
9491            assert_eq!(response_data, expected_data);
9492        });
9493    }
9494
9495    #[test]
9496    fn order_list_place_oto_error_response() {
9497        TOKIO_SHARED_RT.block_on(async {
9498            let (ws_api, conn, mut rx) = setup().await;
9499            let client = TradeApiClient::new(ws_api.clone());
9500
9501            let handle = tokio::spawn(async move {
9502                let params = OrderListPlaceOtoParams::builder("BNBUSDT".to_string(),OrderListPlaceOtoWorkingTypeEnum::Limit,OrderListPlaceOtoWorkingSideEnum::Buy,dec!(1),dec!(1),OrderListPlaceOtoPendingTypeEnum::Limit,OrderListPlaceOtoPendingSideEnum::Buy,dec!(1),).build().unwrap();
9503                client.order_list_place_oto(params).await
9504            });
9505
9506            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9507            let Message::Text(text) = sent else { panic!() };
9508            let v: Value = serde_json::from_str(&text).unwrap();
9509            let id = v["id"].as_str().unwrap().to_string();
9510
9511            let resp_json = json!({
9512                "id": id,
9513                "status": 400,
9514                    "error": {
9515                        "code": -2010,
9516                        "msg": "Account has insufficient balance for requested action.",
9517                    },
9518                    "rateLimits": [
9519                        {
9520                            "rateLimitType": "ORDERS",
9521                            "interval": "SECOND",
9522                            "intervalNum": 10,
9523                            "limit": 50,
9524                            "count": 13
9525                        },
9526                    ],
9527            });
9528            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9529
9530            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9531            match join {
9532                Ok(Err(e)) => {
9533                    let msg = e.to_string();
9534                    assert!(
9535                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9536                        "Expected error msg to contain server error, got: {msg}"
9537                    );
9538                }
9539                Ok(Ok(_)) => panic!("Expected error"),
9540                Err(_) => panic!("Task panicked"),
9541            }
9542        });
9543    }
9544
9545    #[test]
9546    fn order_list_place_oto_request_timeout() {
9547        TOKIO_SHARED_RT.block_on(async {
9548            let (ws_api, _conn, mut rx) = setup().await;
9549            let client = TradeApiClient::new(ws_api.clone());
9550
9551            let handle = spawn(async move {
9552                let params = OrderListPlaceOtoParams::builder(
9553                    "BNBUSDT".to_string(),
9554                    OrderListPlaceOtoWorkingTypeEnum::Limit,
9555                    OrderListPlaceOtoWorkingSideEnum::Buy,
9556                    dec!(1),
9557                    dec!(1),
9558                    OrderListPlaceOtoPendingTypeEnum::Limit,
9559                    OrderListPlaceOtoPendingSideEnum::Buy,
9560                    dec!(1),
9561                )
9562                .build()
9563                .unwrap();
9564                client.order_list_place_oto(params).await
9565            });
9566
9567            let sent = timeout(Duration::from_secs(1), rx.recv())
9568                .await
9569                .expect("send should occur")
9570                .expect("channel closed");
9571            let Message::Text(text) = sent else {
9572                panic!("expected Message Text")
9573            };
9574
9575            let _: Value = serde_json::from_str(&text).unwrap();
9576
9577            let result = handle.await.expect("task completed");
9578            match result {
9579                Err(e) => {
9580                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9581                        assert!(matches!(inner, WebsocketError::Timeout));
9582                    } else {
9583                        panic!("Unexpected error type: {:?}", e);
9584                    }
9585                }
9586                Ok(_) => panic!("Expected timeout error"),
9587            }
9588        });
9589    }
9590
9591    #[test]
9592    fn order_list_place_otoco_success() {
9593        TOKIO_SHARED_RT.block_on(async {
9594            let (ws_api, conn, mut rx) = setup().await;
9595            let client = TradeApiClient::new(ws_api.clone());
9596
9597            let handle = spawn(async move {
9598                let params = OrderListPlaceOtocoParams::builder("BNBUSDT".to_string(),OrderListPlaceOtocoWorkingTypeEnum::Limit,OrderListPlaceOtocoWorkingSideEnum::Buy,dec!(1),dec!(1),OrderListPlaceOtocoPendingSideEnum::Buy,dec!(1),OrderListPlaceOtocoPendingAboveTypeEnum::StopLossLimit,).build().unwrap();
9599                client.order_list_place_otoco(params).await
9600            });
9601
9602            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9603            let Message::Text(text) = sent else { panic!() };
9604            let v: Value = serde_json::from_str(&text).unwrap();
9605            let id = v["id"].as_str().unwrap();
9606            assert_eq!(v["method"], "/orderList.place.otoco".trim_start_matches('/'));
9607            let mut resp_json: Value = serde_json::from_str(r#"{"status":200,"result":{"orderListId":629,"contingencyType":"OTO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"GaeJHjZPasPItFj4x7Mqm6","transactionTime":1712544408537,"orders":[{"symbol":"LTCBNB","orderId":23,"clientOrderId":"OVQOpKwfmPCfaBTD0n7e7H"}],"orderReports":[{"symbol":"LTCBNB","orderId":23,"orderListId":629,"clientOrderId":"OVQOpKwfmPCfaBTD0n7e7H","transactTime":1712544408537,"status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","workingTime":1712544408537,"selfTradePreventionMode":"NONE","icebergQty":"0.00000000","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
9608            resp_json["id"] = id.into();
9609
9610            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9611            let expected_data: Box<models::OrderListPlaceOtocoResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9612            let empty_array = Value::Array(vec![]);
9613            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9614            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9615                match raw_rate_limits.as_array() {
9616                    Some(arr) if arr.is_empty() => None,
9617                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9618                    None => None,
9619                };
9620
9621            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9622
9623            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9624
9625
9626            let response_rate_limits = response.rate_limits.clone();
9627            let response_data = response.data().expect("deserialize data");
9628
9629            assert_eq!(response_rate_limits, expected_rate_limits);
9630            assert_eq!(response_data, expected_data);
9631        });
9632    }
9633
9634    #[test]
9635    fn order_list_place_otoco_error_response() {
9636        TOKIO_SHARED_RT.block_on(async {
9637            let (ws_api, conn, mut rx) = setup().await;
9638            let client = TradeApiClient::new(ws_api.clone());
9639
9640            let handle = tokio::spawn(async move {
9641                let params = OrderListPlaceOtocoParams::builder("BNBUSDT".to_string(),OrderListPlaceOtocoWorkingTypeEnum::Limit,OrderListPlaceOtocoWorkingSideEnum::Buy,dec!(1),dec!(1),OrderListPlaceOtocoPendingSideEnum::Buy,dec!(1),OrderListPlaceOtocoPendingAboveTypeEnum::StopLossLimit,).build().unwrap();
9642                client.order_list_place_otoco(params).await
9643            });
9644
9645            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9646            let Message::Text(text) = sent else { panic!() };
9647            let v: Value = serde_json::from_str(&text).unwrap();
9648            let id = v["id"].as_str().unwrap().to_string();
9649
9650            let resp_json = json!({
9651                "id": id,
9652                "status": 400,
9653                    "error": {
9654                        "code": -2010,
9655                        "msg": "Account has insufficient balance for requested action.",
9656                    },
9657                    "rateLimits": [
9658                        {
9659                            "rateLimitType": "ORDERS",
9660                            "interval": "SECOND",
9661                            "intervalNum": 10,
9662                            "limit": 50,
9663                            "count": 13
9664                        },
9665                    ],
9666            });
9667            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9668
9669            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9670            match join {
9671                Ok(Err(e)) => {
9672                    let msg = e.to_string();
9673                    assert!(
9674                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9675                        "Expected error msg to contain server error, got: {msg}"
9676                    );
9677                }
9678                Ok(Ok(_)) => panic!("Expected error"),
9679                Err(_) => panic!("Task panicked"),
9680            }
9681        });
9682    }
9683
9684    #[test]
9685    fn order_list_place_otoco_request_timeout() {
9686        TOKIO_SHARED_RT.block_on(async {
9687            let (ws_api, _conn, mut rx) = setup().await;
9688            let client = TradeApiClient::new(ws_api.clone());
9689
9690            let handle = spawn(async move {
9691                let params = OrderListPlaceOtocoParams::builder(
9692                    "BNBUSDT".to_string(),
9693                    OrderListPlaceOtocoWorkingTypeEnum::Limit,
9694                    OrderListPlaceOtocoWorkingSideEnum::Buy,
9695                    dec!(1),
9696                    dec!(1),
9697                    OrderListPlaceOtocoPendingSideEnum::Buy,
9698                    dec!(1),
9699                    OrderListPlaceOtocoPendingAboveTypeEnum::StopLossLimit,
9700                )
9701                .build()
9702                .unwrap();
9703                client.order_list_place_otoco(params).await
9704            });
9705
9706            let sent = timeout(Duration::from_secs(1), rx.recv())
9707                .await
9708                .expect("send should occur")
9709                .expect("channel closed");
9710            let Message::Text(text) = sent else {
9711                panic!("expected Message Text")
9712            };
9713
9714            let _: Value = serde_json::from_str(&text).unwrap();
9715
9716            let result = handle.await.expect("task completed");
9717            match result {
9718                Err(e) => {
9719                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9720                        assert!(matches!(inner, WebsocketError::Timeout));
9721                    } else {
9722                        panic!("Unexpected error type: {:?}", e);
9723                    }
9724                }
9725                Ok(_) => panic!("Expected timeout error"),
9726            }
9727        });
9728    }
9729
9730    #[test]
9731    fn order_place_success() {
9732        TOKIO_SHARED_RT.block_on(async {
9733            let (ws_api, conn, mut rx) = setup().await;
9734            let client = TradeApiClient::new(ws_api.clone());
9735
9736            let handle = spawn(async move {
9737                let params = OrderPlaceParams::builder("BNBUSDT".to_string(),OrderPlaceSideEnum::Buy,OrderPlaceTypeEnum::Market,).build().unwrap();
9738                client.order_place(params).await
9739            });
9740
9741            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9742            let Message::Text(text) = sent else { panic!() };
9743            let v: Value = serde_json::from_str(&text).unwrap();
9744            let id = v["id"].as_str().unwrap();
9745            assert_eq!(v["method"], "/order.place".trim_start_matches('/'));
9746            let mut resp_json: Value = serde_json::from_str(r#"{"id":"56374a46-3061-486b-a311-99ee972eb648","status":200,"result":{"symbol":"BTCUSDT","orderId":12569099453,"orderListId":-1,"clientOrderId":"4d96324ff9d44481926157ec08158a40","transactTime":1660801715793,"status":"FILLED","timeInForce":"GTC","type":"LIMIT","side":"SELL","workingTime":1660801715639,"selfTradePreventionMode":"NONE","stopPrice":"0.00000000","trailingDelta":10,"icebergQty":"0.00000000","strategyId":1,"strategyType":1000000,"preventedMatchId":0,"preventedQuantity":"1.200000","trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY","fills":[{"commissionAsset":"BNB","tradeId":1650422481}]},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
9747            resp_json["id"] = id.into();
9748
9749            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9750            let expected_data: Box<models::OrderPlaceResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9751            let empty_array = Value::Array(vec![]);
9752            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9753            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9754                match raw_rate_limits.as_array() {
9755                    Some(arr) if arr.is_empty() => None,
9756                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9757                    None => None,
9758                };
9759
9760            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9761
9762            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9763
9764
9765            let response_rate_limits = response.rate_limits.clone();
9766            let response_data = response.data().expect("deserialize data");
9767
9768            assert_eq!(response_rate_limits, expected_rate_limits);
9769            assert_eq!(response_data, expected_data);
9770        });
9771    }
9772
9773    #[test]
9774    fn order_place_error_response() {
9775        TOKIO_SHARED_RT.block_on(async {
9776            let (ws_api, conn, mut rx) = setup().await;
9777            let client = TradeApiClient::new(ws_api.clone());
9778
9779            let handle = tokio::spawn(async move {
9780                let params = OrderPlaceParams::builder("BNBUSDT".to_string(),OrderPlaceSideEnum::Buy,OrderPlaceTypeEnum::Market,).build().unwrap();
9781                client.order_place(params).await
9782            });
9783
9784            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9785            let Message::Text(text) = sent else { panic!() };
9786            let v: Value = serde_json::from_str(&text).unwrap();
9787            let id = v["id"].as_str().unwrap().to_string();
9788
9789            let resp_json = json!({
9790                "id": id,
9791                "status": 400,
9792                    "error": {
9793                        "code": -2010,
9794                        "msg": "Account has insufficient balance for requested action.",
9795                    },
9796                    "rateLimits": [
9797                        {
9798                            "rateLimitType": "ORDERS",
9799                            "interval": "SECOND",
9800                            "intervalNum": 10,
9801                            "limit": 50,
9802                            "count": 13
9803                        },
9804                    ],
9805            });
9806            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9807
9808            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9809            match join {
9810                Ok(Err(e)) => {
9811                    let msg = e.to_string();
9812                    assert!(
9813                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9814                        "Expected error msg to contain server error, got: {msg}"
9815                    );
9816                }
9817                Ok(Ok(_)) => panic!("Expected error"),
9818                Err(_) => panic!("Task panicked"),
9819            }
9820        });
9821    }
9822
9823    #[test]
9824    fn order_place_request_timeout() {
9825        TOKIO_SHARED_RT.block_on(async {
9826            let (ws_api, _conn, mut rx) = setup().await;
9827            let client = TradeApiClient::new(ws_api.clone());
9828
9829            let handle = spawn(async move {
9830                let params = OrderPlaceParams::builder(
9831                    "BNBUSDT".to_string(),
9832                    OrderPlaceSideEnum::Buy,
9833                    OrderPlaceTypeEnum::Market,
9834                )
9835                .build()
9836                .unwrap();
9837                client.order_place(params).await
9838            });
9839
9840            let sent = timeout(Duration::from_secs(1), rx.recv())
9841                .await
9842                .expect("send should occur")
9843                .expect("channel closed");
9844            let Message::Text(text) = sent else {
9845                panic!("expected Message Text")
9846            };
9847
9848            let _: Value = serde_json::from_str(&text).unwrap();
9849
9850            let result = handle.await.expect("task completed");
9851            match result {
9852                Err(e) => {
9853                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9854                        assert!(matches!(inner, WebsocketError::Timeout));
9855                    } else {
9856                        panic!("Unexpected error type: {:?}", e);
9857                    }
9858                }
9859                Ok(_) => panic!("Expected timeout error"),
9860            }
9861        });
9862    }
9863
9864    #[test]
9865    fn order_test_success() {
9866        TOKIO_SHARED_RT.block_on(async {
9867            let (ws_api, conn, mut rx) = setup().await;
9868            let client = TradeApiClient::new(ws_api.clone());
9869
9870            let handle = spawn(async move {
9871                let params = OrderTestParams::builder("BNBUSDT".to_string(),OrderTestSideEnum::Buy,OrderTestTypeEnum::Market,).build().unwrap();
9872                client.order_test(params).await
9873            });
9874
9875            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9876            let Message::Text(text) = sent else { panic!() };
9877            let v: Value = serde_json::from_str(&text).unwrap();
9878            let id = v["id"].as_str().unwrap();
9879            assert_eq!(v["method"], "/order.test".trim_start_matches('/'));
9880            let mut resp_json: Value = serde_json::from_str(r#"{"id":"6ffebe91-01d9-43ac-be99-57cf062e0e30","status":200,"result":{"discount":{"enabledForAccount":true,"enabledForSymbol":true,"discountAsset":"BNB"}},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
9881            resp_json["id"] = id.into();
9882
9883            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9884            let expected_data: Box<models::OrderTestResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9885            let empty_array = Value::Array(vec![]);
9886            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9887            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9888                match raw_rate_limits.as_array() {
9889                    Some(arr) if arr.is_empty() => None,
9890                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9891                    None => None,
9892                };
9893
9894            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9895
9896            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9897
9898
9899            let response_rate_limits = response.rate_limits.clone();
9900            let response_data = response.data().expect("deserialize data");
9901
9902            assert_eq!(response_rate_limits, expected_rate_limits);
9903            assert_eq!(response_data, expected_data);
9904        });
9905    }
9906
9907    #[test]
9908    fn order_test_error_response() {
9909        TOKIO_SHARED_RT.block_on(async {
9910            let (ws_api, conn, mut rx) = setup().await;
9911            let client = TradeApiClient::new(ws_api.clone());
9912
9913            let handle = tokio::spawn(async move {
9914                let params = OrderTestParams::builder("BNBUSDT".to_string(),OrderTestSideEnum::Buy,OrderTestTypeEnum::Market,).build().unwrap();
9915                client.order_test(params).await
9916            });
9917
9918            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9919            let Message::Text(text) = sent else { panic!() };
9920            let v: Value = serde_json::from_str(&text).unwrap();
9921            let id = v["id"].as_str().unwrap().to_string();
9922
9923            let resp_json = json!({
9924                "id": id,
9925                "status": 400,
9926                    "error": {
9927                        "code": -2010,
9928                        "msg": "Account has insufficient balance for requested action.",
9929                    },
9930                    "rateLimits": [
9931                        {
9932                            "rateLimitType": "ORDERS",
9933                            "interval": "SECOND",
9934                            "intervalNum": 10,
9935                            "limit": 50,
9936                            "count": 13
9937                        },
9938                    ],
9939            });
9940            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9941
9942            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9943            match join {
9944                Ok(Err(e)) => {
9945                    let msg = e.to_string();
9946                    assert!(
9947                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9948                        "Expected error msg to contain server error, got: {msg}"
9949                    );
9950                }
9951                Ok(Ok(_)) => panic!("Expected error"),
9952                Err(_) => panic!("Task panicked"),
9953            }
9954        });
9955    }
9956
9957    #[test]
9958    fn order_test_request_timeout() {
9959        TOKIO_SHARED_RT.block_on(async {
9960            let (ws_api, _conn, mut rx) = setup().await;
9961            let client = TradeApiClient::new(ws_api.clone());
9962
9963            let handle = spawn(async move {
9964                let params = OrderTestParams::builder(
9965                    "BNBUSDT".to_string(),
9966                    OrderTestSideEnum::Buy,
9967                    OrderTestTypeEnum::Market,
9968                )
9969                .build()
9970                .unwrap();
9971                client.order_test(params).await
9972            });
9973
9974            let sent = timeout(Duration::from_secs(1), rx.recv())
9975                .await
9976                .expect("send should occur")
9977                .expect("channel closed");
9978            let Message::Text(text) = sent else {
9979                panic!("expected Message Text")
9980            };
9981
9982            let _: Value = serde_json::from_str(&text).unwrap();
9983
9984            let result = handle.await.expect("task completed");
9985            match result {
9986                Err(e) => {
9987                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9988                        assert!(matches!(inner, WebsocketError::Timeout));
9989                    } else {
9990                        panic!("Unexpected error type: {:?}", e);
9991                    }
9992                }
9993                Ok(_) => panic!("Expected timeout error"),
9994            }
9995        });
9996    }
9997
9998    #[test]
9999    fn sor_order_place_success() {
10000        TOKIO_SHARED_RT.block_on(async {
10001            let (ws_api, conn, mut rx) = setup().await;
10002            let client = TradeApiClient::new(ws_api.clone());
10003
10004            let handle = spawn(async move {
10005                let params = SorOrderPlaceParams::builder("BNBUSDT".to_string(),SorOrderPlaceSideEnum::Buy,SorOrderPlaceTypeEnum::Market,dec!(1),).build().unwrap();
10006                client.sor_order_place(params).await
10007            });
10008
10009            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
10010            let Message::Text(text) = sent else { panic!() };
10011            let v: Value = serde_json::from_str(&text).unwrap();
10012            let id = v["id"].as_str().unwrap();
10013            assert_eq!(v["method"], "/sor.order.place".trim_start_matches('/'));
10014            let mut resp_json: Value = serde_json::from_str(r#"{"id":"3a4437e2-41a3-4c19-897c-9cadc5dce8b6","status":200,"result":[{"symbol":"BTCUSDT","orderId":2,"orderListId":-1,"clientOrderId":"sBI1KM6nNtOfj5tccZSKly","transactTime":1689149087774,"status":"FILLED","timeInForce":"GTC","type":"LIMIT","side":"BUY","workingTime":1689149087774,"fills":[{"matchType":"ONE_PARTY_TRADE_REPORT","commissionAsset":"BTC","tradeId":-1,"allocId":0}],"workingFloor":"SOR","selfTradePreventionMode":"NONE","usedSor":true,"stopPrice":"0.00000000","trailingDelta":10,"icebergQty":"0.00000000","strategyId":1,"strategyType":1000000,"preventedMatchId":0,"preventedQuantity":"1.200000","trailingTime":-1,"pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}],"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
10015            resp_json["id"] = id.into();
10016
10017            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
10018            let expected_data: Vec<models::SorOrderPlaceResponseResultInner> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
10019            let empty_array = Value::Array(vec![]);
10020            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
10021            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
10022                match raw_rate_limits.as_array() {
10023                    Some(arr) if arr.is_empty() => None,
10024                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
10025                    None => None,
10026                };
10027
10028            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
10029
10030            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
10031
10032
10033            let response_rate_limits = response.rate_limits.clone();
10034            let response_data = response.data().expect("deserialize data");
10035
10036            assert_eq!(response_rate_limits, expected_rate_limits);
10037            assert_eq!(response_data, expected_data);
10038        });
10039    }
10040
10041    #[test]
10042    fn sor_order_place_error_response() {
10043        TOKIO_SHARED_RT.block_on(async {
10044            let (ws_api, conn, mut rx) = setup().await;
10045            let client = TradeApiClient::new(ws_api.clone());
10046
10047            let handle = tokio::spawn(async move {
10048                let params = SorOrderPlaceParams::builder("BNBUSDT".to_string(),SorOrderPlaceSideEnum::Buy,SorOrderPlaceTypeEnum::Market,dec!(1),).build().unwrap();
10049                client.sor_order_place(params).await
10050            });
10051
10052            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
10053            let Message::Text(text) = sent else { panic!() };
10054            let v: Value = serde_json::from_str(&text).unwrap();
10055            let id = v["id"].as_str().unwrap().to_string();
10056
10057            let resp_json = json!({
10058                "id": id,
10059                "status": 400,
10060                    "error": {
10061                        "code": -2010,
10062                        "msg": "Account has insufficient balance for requested action.",
10063                    },
10064                    "rateLimits": [
10065                        {
10066                            "rateLimitType": "ORDERS",
10067                            "interval": "SECOND",
10068                            "intervalNum": 10,
10069                            "limit": 50,
10070                            "count": 13
10071                        },
10072                    ],
10073            });
10074            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
10075
10076            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
10077            match join {
10078                Ok(Err(e)) => {
10079                    let msg = e.to_string();
10080                    assert!(
10081                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
10082                        "Expected error msg to contain server error, got: {msg}"
10083                    );
10084                }
10085                Ok(Ok(_)) => panic!("Expected error"),
10086                Err(_) => panic!("Task panicked"),
10087            }
10088        });
10089    }
10090
10091    #[test]
10092    fn sor_order_place_request_timeout() {
10093        TOKIO_SHARED_RT.block_on(async {
10094            let (ws_api, _conn, mut rx) = setup().await;
10095            let client = TradeApiClient::new(ws_api.clone());
10096
10097            let handle = spawn(async move {
10098                let params = SorOrderPlaceParams::builder(
10099                    "BNBUSDT".to_string(),
10100                    SorOrderPlaceSideEnum::Buy,
10101                    SorOrderPlaceTypeEnum::Market,
10102                    dec!(1),
10103                )
10104                .build()
10105                .unwrap();
10106                client.sor_order_place(params).await
10107            });
10108
10109            let sent = timeout(Duration::from_secs(1), rx.recv())
10110                .await
10111                .expect("send should occur")
10112                .expect("channel closed");
10113            let Message::Text(text) = sent else {
10114                panic!("expected Message Text")
10115            };
10116
10117            let _: Value = serde_json::from_str(&text).unwrap();
10118
10119            let result = handle.await.expect("task completed");
10120            match result {
10121                Err(e) => {
10122                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
10123                        assert!(matches!(inner, WebsocketError::Timeout));
10124                    } else {
10125                        panic!("Unexpected error type: {:?}", e);
10126                    }
10127                }
10128                Ok(_) => panic!("Expected timeout error"),
10129            }
10130        });
10131    }
10132
10133    #[test]
10134    fn sor_order_test_success() {
10135        TOKIO_SHARED_RT.block_on(async {
10136            let (ws_api, conn, mut rx) = setup().await;
10137            let client = TradeApiClient::new(ws_api.clone());
10138
10139            let handle = spawn(async move {
10140                let params = SorOrderTestParams::builder("BNBUSDT".to_string(),SorOrderTestSideEnum::Buy,SorOrderTestTypeEnum::Market,dec!(1),).build().unwrap();
10141                client.sor_order_test(params).await
10142            });
10143
10144            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
10145            let Message::Text(text) = sent else { panic!() };
10146            let v: Value = serde_json::from_str(&text).unwrap();
10147            let id = v["id"].as_str().unwrap();
10148            assert_eq!(v["method"], "/sor.order.test".trim_start_matches('/'));
10149            let mut resp_json: Value = serde_json::from_str(r#"{"id":"3a4437e2-41a3-4c19-897c-9cadc5dce8b6","status":200,"result":{"discount":{"enabledForAccount":true,"enabledForSymbol":true,"discountAsset":"BNB"}},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
10150            resp_json["id"] = id.into();
10151
10152            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
10153            let expected_data: Box<models::SorOrderTestResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
10154            let empty_array = Value::Array(vec![]);
10155            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
10156            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
10157                match raw_rate_limits.as_array() {
10158                    Some(arr) if arr.is_empty() => None,
10159                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
10160                    None => None,
10161                };
10162
10163            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
10164
10165            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
10166
10167
10168            let response_rate_limits = response.rate_limits.clone();
10169            let response_data = response.data().expect("deserialize data");
10170
10171            assert_eq!(response_rate_limits, expected_rate_limits);
10172            assert_eq!(response_data, expected_data);
10173        });
10174    }
10175
10176    #[test]
10177    fn sor_order_test_error_response() {
10178        TOKIO_SHARED_RT.block_on(async {
10179            let (ws_api, conn, mut rx) = setup().await;
10180            let client = TradeApiClient::new(ws_api.clone());
10181
10182            let handle = tokio::spawn(async move {
10183                let params = SorOrderTestParams::builder("BNBUSDT".to_string(),SorOrderTestSideEnum::Buy,SorOrderTestTypeEnum::Market,dec!(1),).build().unwrap();
10184                client.sor_order_test(params).await
10185            });
10186
10187            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
10188            let Message::Text(text) = sent else { panic!() };
10189            let v: Value = serde_json::from_str(&text).unwrap();
10190            let id = v["id"].as_str().unwrap().to_string();
10191
10192            let resp_json = json!({
10193                "id": id,
10194                "status": 400,
10195                    "error": {
10196                        "code": -2010,
10197                        "msg": "Account has insufficient balance for requested action.",
10198                    },
10199                    "rateLimits": [
10200                        {
10201                            "rateLimitType": "ORDERS",
10202                            "interval": "SECOND",
10203                            "intervalNum": 10,
10204                            "limit": 50,
10205                            "count": 13
10206                        },
10207                    ],
10208            });
10209            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
10210
10211            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
10212            match join {
10213                Ok(Err(e)) => {
10214                    let msg = e.to_string();
10215                    assert!(
10216                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
10217                        "Expected error msg to contain server error, got: {msg}"
10218                    );
10219                }
10220                Ok(Ok(_)) => panic!("Expected error"),
10221                Err(_) => panic!("Task panicked"),
10222            }
10223        });
10224    }
10225
10226    #[test]
10227    fn sor_order_test_request_timeout() {
10228        TOKIO_SHARED_RT.block_on(async {
10229            let (ws_api, _conn, mut rx) = setup().await;
10230            let client = TradeApiClient::new(ws_api.clone());
10231
10232            let handle = spawn(async move {
10233                let params = SorOrderTestParams::builder(
10234                    "BNBUSDT".to_string(),
10235                    SorOrderTestSideEnum::Buy,
10236                    SorOrderTestTypeEnum::Market,
10237                    dec!(1),
10238                )
10239                .build()
10240                .unwrap();
10241                client.sor_order_test(params).await
10242            });
10243
10244            let sent = timeout(Duration::from_secs(1), rx.recv())
10245                .await
10246                .expect("send should occur")
10247                .expect("channel closed");
10248            let Message::Text(text) = sent else {
10249                panic!("expected Message Text")
10250            };
10251
10252            let _: Value = serde_json::from_str(&text).unwrap();
10253
10254            let result = handle.await.expect("task completed");
10255            match result {
10256                Err(e) => {
10257                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
10258                        assert!(matches!(inner, WebsocketError::Timeout));
10259                    } else {
10260                        panic!("Unexpected error type: {:?}", e);
10261                    }
10262                }
10263                Ok(_) => panic!("Expected timeout error"),
10264            }
10265        });
10266    }
10267}