1#![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#[derive(Clone, Debug, Builder, Deserialize)]
3981#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
3982pub struct OpenOrdersCancelAllParams {
3983 #[builder(setter(into))]
3988 #[serde(rename = "symbol")]
3989 pub symbol: String,
3990 #[builder(setter(into), default)]
3994 #[serde(rename = "id", default)]
3995 pub id: Option<String>,
3996 #[builder(setter(into), default)]
4000 #[serde(rename = "recvWindow", default)]
4001 pub recv_window: Option<rust_decimal::Decimal>,
4002}
4003
4004impl OpenOrdersCancelAllParams {
4005 #[must_use]
4012 pub fn builder(symbol: String) -> OpenOrdersCancelAllParamsBuilder {
4013 OpenOrdersCancelAllParamsBuilder::default().symbol(symbol)
4014 }
4015}
4016#[derive(Clone, Debug, Builder, Deserialize)]
4021#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4022pub struct OrderAmendKeepPriorityParams {
4023 #[builder(setter(into))]
4028 #[serde(rename = "symbol")]
4029 pub symbol: String,
4030 #[builder(setter(into))]
4034 #[serde(rename = "newQty")]
4035 pub new_qty: rust_decimal::Decimal,
4036 #[builder(setter(into), default)]
4040 #[serde(rename = "id", default)]
4041 pub id: Option<String>,
4042 #[builder(setter(into), default)]
4046 #[serde(rename = "orderId", default)]
4047 pub order_id: Option<i64>,
4048 #[builder(setter(into), default)]
4052 #[serde(rename = "origClientOrderId", default)]
4053 pub orig_client_order_id: Option<String>,
4054 #[builder(setter(into), default)]
4058 #[serde(rename = "newClientOrderId", default)]
4059 pub new_client_order_id: Option<String>,
4060 #[builder(setter(into), default)]
4064 #[serde(rename = "recvWindow", default)]
4065 pub recv_window: Option<rust_decimal::Decimal>,
4066}
4067
4068impl OrderAmendKeepPriorityParams {
4069 #[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#[derive(Clone, Debug, Builder, Deserialize)]
4091#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4092pub struct OrderCancelParams {
4093 #[builder(setter(into))]
4098 #[serde(rename = "symbol")]
4099 pub symbol: String,
4100 #[builder(setter(into), default)]
4104 #[serde(rename = "id", default)]
4105 pub id: Option<String>,
4106 #[builder(setter(into), default)]
4111 #[serde(rename = "orderId", default)]
4112 pub order_id: Option<i64>,
4113 #[builder(setter(into), default)]
4118 #[serde(rename = "origClientOrderId", default)]
4119 pub orig_client_order_id: Option<String>,
4120 #[builder(setter(into), default)]
4124 #[serde(rename = "newClientOrderId", default)]
4125 pub new_client_order_id: Option<String>,
4126 #[builder(setter(into), default)]
4130 #[serde(rename = "cancelRestrictions", default)]
4131 pub cancel_restrictions: Option<OrderCancelCancelRestrictionsEnum>,
4132 #[builder(setter(into), default)]
4136 #[serde(rename = "recvWindow", default)]
4137 pub recv_window: Option<rust_decimal::Decimal>,
4138}
4139
4140impl OrderCancelParams {
4141 #[must_use]
4148 pub fn builder(symbol: String) -> OrderCancelParamsBuilder {
4149 OrderCancelParamsBuilder::default().symbol(symbol)
4150 }
4151}
4152#[derive(Clone, Debug, Builder, Deserialize)]
4157#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4158pub struct OrderCancelReplaceParams {
4159 #[builder(setter(into))]
4164 #[serde(rename = "symbol")]
4165 pub symbol: String,
4166 #[builder(setter(into))]
4170 #[serde(rename = "cancelReplaceMode")]
4171 pub cancel_replace_mode: OrderCancelReplaceCancelReplaceModeEnum,
4172 #[builder(setter(into))]
4176 #[serde(rename = "side")]
4177 pub side: OrderCancelReplaceSideEnum,
4178 #[builder(setter(into))]
4182 #[serde(rename = "type")]
4183 pub r#type: OrderCancelReplaceTypeEnum,
4184 #[builder(setter(into), default)]
4188 #[serde(rename = "id", default)]
4189 pub id: Option<String>,
4190 #[builder(setter(into), default)]
4194 #[serde(rename = "cancelOrderId", default)]
4195 pub cancel_order_id: Option<i64>,
4196 #[builder(setter(into), default)]
4200 #[serde(rename = "cancelOrigClientOrderId", default)]
4201 pub cancel_orig_client_order_id: Option<String>,
4202 #[builder(setter(into), default)]
4206 #[serde(rename = "cancelNewClientOrderId", default)]
4207 pub cancel_new_client_order_id: Option<String>,
4208 #[builder(setter(into), default)]
4212 #[serde(rename = "timeInForce", default)]
4213 pub time_in_force: Option<OrderCancelReplaceTimeInForceEnum>,
4214 #[builder(setter(into), default)]
4219 #[serde(rename = "price", default)]
4220 pub price: Option<rust_decimal::Decimal>,
4221 #[builder(setter(into), default)]
4226 #[serde(rename = "quantity", default)]
4227 pub quantity: Option<rust_decimal::Decimal>,
4228 #[builder(setter(into), default)]
4233 #[serde(rename = "quoteOrderQty", default)]
4234 pub quote_order_qty: Option<rust_decimal::Decimal>,
4235 #[builder(setter(into), default)]
4239 #[serde(rename = "newClientOrderId", default)]
4240 pub new_client_order_id: Option<String>,
4241 #[builder(setter(into), default)]
4245 #[serde(rename = "newOrderRespType", default)]
4246 pub new_order_resp_type: Option<OrderCancelReplaceNewOrderRespTypeEnum>,
4247 #[builder(setter(into), default)]
4251 #[serde(rename = "stopPrice", default)]
4252 pub stop_price: Option<rust_decimal::Decimal>,
4253 #[builder(setter(into), default)]
4257 #[serde(rename = "trailingDelta", default)]
4258 pub trailing_delta: Option<rust_decimal::Decimal>,
4259 #[builder(setter(into), default)]
4263 #[serde(rename = "icebergQty", default)]
4264 pub iceberg_qty: Option<rust_decimal::Decimal>,
4265 #[builder(setter(into), default)]
4270 #[serde(rename = "strategyId", default)]
4271 pub strategy_id: Option<i64>,
4272 #[builder(setter(into), default)]
4276 #[serde(rename = "strategyType", default)]
4277 pub strategy_type: Option<i32>,
4278 #[builder(setter(into), default)]
4282 #[serde(rename = "selfTradePreventionMode", default)]
4283 pub self_trade_prevention_mode: Option<OrderCancelReplaceSelfTradePreventionModeEnum>,
4284 #[builder(setter(into), default)]
4288 #[serde(rename = "cancelRestrictions", default)]
4289 pub cancel_restrictions: Option<OrderCancelReplaceCancelRestrictionsEnum>,
4290 #[builder(setter(into), default)]
4294 #[serde(rename = "orderRateLimitExceededMode", default)]
4295 pub order_rate_limit_exceeded_mode: Option<OrderCancelReplaceOrderRateLimitExceededModeEnum>,
4296 #[builder(setter(into), default)]
4300 #[serde(rename = "pegPriceType", default)]
4301 pub peg_price_type: Option<OrderCancelReplacePegPriceTypeEnum>,
4302 #[builder(setter(into), default)]
4306 #[serde(rename = "pegOffsetValue", default)]
4307 pub peg_offset_value: Option<i32>,
4308 #[builder(setter(into), default)]
4312 #[serde(rename = "pegOffsetType", default)]
4313 pub peg_offset_type: Option<OrderCancelReplacePegOffsetTypeEnum>,
4314 #[builder(setter(into), default)]
4318 #[serde(rename = "recvWindow", default)]
4319 pub recv_window: Option<rust_decimal::Decimal>,
4320}
4321
4322impl OrderCancelReplaceParams {
4323 #[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#[derive(Clone, Debug, Builder, Deserialize)]
4351#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4352pub struct OrderListCancelParams {
4353 #[builder(setter(into))]
4358 #[serde(rename = "symbol")]
4359 pub symbol: String,
4360 #[builder(setter(into), default)]
4364 #[serde(rename = "id", default)]
4365 pub id: Option<String>,
4366 #[builder(setter(into), default)]
4370 #[serde(rename = "orderListId", default)]
4371 pub order_list_id: Option<i32>,
4372 #[builder(setter(into), default)]
4376 #[serde(rename = "listClientOrderId", default)]
4377 pub list_client_order_id: Option<String>,
4378 #[builder(setter(into), default)]
4382 #[serde(rename = "newClientOrderId", default)]
4383 pub new_client_order_id: Option<String>,
4384 #[builder(setter(into), default)]
4388 #[serde(rename = "recvWindow", default)]
4389 pub recv_window: Option<rust_decimal::Decimal>,
4390}
4391
4392impl OrderListCancelParams {
4393 #[must_use]
4400 pub fn builder(symbol: String) -> OrderListCancelParamsBuilder {
4401 OrderListCancelParamsBuilder::default().symbol(symbol)
4402 }
4403}
4404#[derive(Clone, Debug, Builder, Deserialize)]
4409#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4410pub struct OrderListPlaceParams {
4411 #[builder(setter(into))]
4416 #[serde(rename = "symbol")]
4417 pub symbol: String,
4418 #[builder(setter(into))]
4422 #[serde(rename = "side")]
4423 pub side: OrderListPlaceSideEnum,
4424 #[builder(setter(into))]
4429 #[serde(rename = "price")]
4430 pub price: rust_decimal::Decimal,
4431 #[builder(setter(into))]
4436 #[serde(rename = "quantity")]
4437 pub quantity: rust_decimal::Decimal,
4438 #[builder(setter(into), default)]
4442 #[serde(rename = "id", default)]
4443 pub id: Option<String>,
4444 #[builder(setter(into), default)]
4448 #[serde(rename = "listClientOrderId", default)]
4449 pub list_client_order_id: Option<String>,
4450 #[builder(setter(into), default)]
4454 #[serde(rename = "limitClientOrderId", default)]
4455 pub limit_client_order_id: Option<String>,
4456 #[builder(setter(into), default)]
4460 #[serde(rename = "limitIcebergQty", default)]
4461 pub limit_iceberg_qty: Option<rust_decimal::Decimal>,
4462 #[builder(setter(into), default)]
4467 #[serde(rename = "limitStrategyId", default)]
4468 pub limit_strategy_id: Option<i64>,
4469 #[builder(setter(into), default)]
4473 #[serde(rename = "limitStrategyType", default)]
4474 pub limit_strategy_type: Option<i32>,
4475 #[builder(setter(into), default)]
4480 #[serde(rename = "stopPrice", default)]
4481 pub stop_price: Option<rust_decimal::Decimal>,
4482 #[builder(setter(into), default)]
4487 #[serde(rename = "trailingDelta", default)]
4488 pub trailing_delta: Option<i32>,
4489 #[builder(setter(into), default)]
4493 #[serde(rename = "stopClientOrderId", default)]
4494 pub stop_client_order_id: Option<String>,
4495 #[builder(setter(into), default)]
4499 #[serde(rename = "stopLimitPrice", default)]
4500 pub stop_limit_price: Option<rust_decimal::Decimal>,
4501 #[builder(setter(into), default)]
4505 #[serde(rename = "stopLimitTimeInForce", default)]
4506 pub stop_limit_time_in_force: Option<OrderListPlaceStopLimitTimeInForceEnum>,
4507 #[builder(setter(into), default)]
4511 #[serde(rename = "stopIcebergQty", default)]
4512 pub stop_iceberg_qty: Option<rust_decimal::Decimal>,
4513 #[builder(setter(into), default)]
4518 #[serde(rename = "stopStrategyId", default)]
4519 pub stop_strategy_id: Option<i64>,
4520 #[builder(setter(into), default)]
4524 #[serde(rename = "stopStrategyType", default)]
4525 pub stop_strategy_type: Option<i32>,
4526 #[builder(setter(into), default)]
4530 #[serde(rename = "newOrderRespType", default)]
4531 pub new_order_resp_type: Option<OrderListPlaceNewOrderRespTypeEnum>,
4532 #[builder(setter(into), default)]
4536 #[serde(rename = "selfTradePreventionMode", default)]
4537 pub self_trade_prevention_mode: Option<OrderListPlaceSelfTradePreventionModeEnum>,
4538 #[builder(setter(into), default)]
4542 #[serde(rename = "recvWindow", default)]
4543 pub recv_window: Option<rust_decimal::Decimal>,
4544}
4545
4546impl OrderListPlaceParams {
4547 #[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#[derive(Clone, Debug, Builder, Deserialize)]
4575#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4576pub struct OrderListPlaceOcoParams {
4577 #[builder(setter(into))]
4582 #[serde(rename = "symbol")]
4583 pub symbol: String,
4584 #[builder(setter(into))]
4588 #[serde(rename = "side")]
4589 pub side: OrderListPlaceOcoSideEnum,
4590 #[builder(setter(into))]
4594 #[serde(rename = "quantity")]
4595 pub quantity: rust_decimal::Decimal,
4596 #[builder(setter(into))]
4601 #[serde(rename = "aboveType")]
4602 pub above_type: OrderListPlaceOcoAboveTypeEnum,
4603 #[builder(setter(into))]
4607 #[serde(rename = "belowType")]
4608 pub below_type: OrderListPlaceOcoBelowTypeEnum,
4609 #[builder(setter(into), default)]
4613 #[serde(rename = "id", default)]
4614 pub id: Option<String>,
4615 #[builder(setter(into), default)]
4619 #[serde(rename = "listClientOrderId", default)]
4620 pub list_client_order_id: Option<String>,
4621 #[builder(setter(into), default)]
4625 #[serde(rename = "aboveClientOrderId", default)]
4626 pub above_client_order_id: Option<String>,
4627 #[builder(setter(into), default)]
4631 #[serde(rename = "aboveIcebergQty", default)]
4632 pub above_iceberg_qty: Option<i64>,
4633 #[builder(setter(into), default)]
4637 #[serde(rename = "abovePrice", default)]
4638 pub above_price: Option<rust_decimal::Decimal>,
4639 #[builder(setter(into), default)]
4643 #[serde(rename = "aboveStopPrice", default)]
4644 pub above_stop_price: Option<rust_decimal::Decimal>,
4645 #[builder(setter(into), default)]
4649 #[serde(rename = "aboveTrailingDelta", default)]
4650 pub above_trailing_delta: Option<i64>,
4651 #[builder(setter(into), default)]
4655 #[serde(rename = "aboveTimeInForce", default)]
4656 pub above_time_in_force: Option<OrderListPlaceOcoAboveTimeInForceEnum>,
4657 #[builder(setter(into), default)]
4661 #[serde(rename = "aboveStrategyId", default)]
4662 pub above_strategy_id: Option<i64>,
4663 #[builder(setter(into), default)]
4667 #[serde(rename = "aboveStrategyType", default)]
4668 pub above_strategy_type: Option<i32>,
4669 #[builder(setter(into), default)]
4673 #[serde(rename = "abovePegPriceType", default)]
4674 pub above_peg_price_type: Option<OrderListPlaceOcoAbovePegPriceTypeEnum>,
4675 #[builder(setter(into), default)]
4680 #[serde(rename = "abovePegOffsetType", default)]
4681 pub above_peg_offset_type: Option<OrderListPlaceOcoAbovePegOffsetTypeEnum>,
4682 #[builder(setter(into), default)]
4687 #[serde(rename = "abovePegOffsetValue", default)]
4688 pub above_peg_offset_value: Option<i32>,
4689 #[builder(setter(into), default)]
4693 #[serde(rename = "belowClientOrderId", default)]
4694 pub below_client_order_id: Option<String>,
4695 #[builder(setter(into), default)]
4699 #[serde(rename = "belowIcebergQty", default)]
4700 pub below_iceberg_qty: Option<i64>,
4701 #[builder(setter(into), default)]
4705 #[serde(rename = "belowPrice", default)]
4706 pub below_price: Option<rust_decimal::Decimal>,
4707 #[builder(setter(into), default)]
4711 #[serde(rename = "belowStopPrice", default)]
4712 pub below_stop_price: Option<rust_decimal::Decimal>,
4713 #[builder(setter(into), default)]
4717 #[serde(rename = "belowTrailingDelta", default)]
4718 pub below_trailing_delta: Option<i64>,
4719 #[builder(setter(into), default)]
4723 #[serde(rename = "belowTimeInForce", default)]
4724 pub below_time_in_force: Option<OrderListPlaceOcoBelowTimeInForceEnum>,
4725 #[builder(setter(into), default)]
4729 #[serde(rename = "belowStrategyId", default)]
4730 pub below_strategy_id: Option<i64>,
4731 #[builder(setter(into), default)]
4735 #[serde(rename = "belowStrategyType", default)]
4736 pub below_strategy_type: Option<i32>,
4737 #[builder(setter(into), default)]
4741 #[serde(rename = "belowPegPriceType", default)]
4742 pub below_peg_price_type: Option<OrderListPlaceOcoBelowPegPriceTypeEnum>,
4743 #[builder(setter(into), default)]
4748 #[serde(rename = "belowPegOffsetType", default)]
4749 pub below_peg_offset_type: Option<OrderListPlaceOcoBelowPegOffsetTypeEnum>,
4750 #[builder(setter(into), default)]
4755 #[serde(rename = "belowPegOffsetValue", default)]
4756 pub below_peg_offset_value: Option<i32>,
4757 #[builder(setter(into), default)]
4761 #[serde(rename = "newOrderRespType", default)]
4762 pub new_order_resp_type: Option<OrderListPlaceOcoNewOrderRespTypeEnum>,
4763 #[builder(setter(into), default)]
4767 #[serde(rename = "selfTradePreventionMode", default)]
4768 pub self_trade_prevention_mode: Option<OrderListPlaceOcoSelfTradePreventionModeEnum>,
4769 #[builder(setter(into), default)]
4773 #[serde(rename = "recvWindow", default)]
4774 pub recv_window: Option<rust_decimal::Decimal>,
4775}
4776
4777impl OrderListPlaceOcoParams {
4778 #[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#[derive(Clone, Debug, Builder, Deserialize)]
4809#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4810pub struct OrderListPlaceOpoParams {
4811 #[builder(setter(into))]
4816 #[serde(rename = "symbol")]
4817 pub symbol: String,
4818 #[builder(setter(into))]
4822 #[serde(rename = "workingType")]
4823 pub working_type: OrderListPlaceOpoWorkingTypeEnum,
4824 #[builder(setter(into))]
4828 #[serde(rename = "workingSide")]
4829 pub working_side: OrderListPlaceOpoWorkingSideEnum,
4830 #[builder(setter(into))]
4834 #[serde(rename = "workingPrice")]
4835 pub working_price: rust_decimal::Decimal,
4836 #[builder(setter(into))]
4840 #[serde(rename = "workingQuantity")]
4841 pub working_quantity: rust_decimal::Decimal,
4842 #[builder(setter(into))]
4846 #[serde(rename = "pendingType")]
4847 pub pending_type: OrderListPlaceOpoPendingTypeEnum,
4848 #[builder(setter(into))]
4852 #[serde(rename = "pendingSide")]
4853 pub pending_side: OrderListPlaceOpoPendingSideEnum,
4854 #[builder(setter(into), default)]
4858 #[serde(rename = "id", default)]
4859 pub id: Option<String>,
4860 #[builder(setter(into), default)]
4864 #[serde(rename = "listClientOrderId", default)]
4865 pub list_client_order_id: Option<String>,
4866 #[builder(setter(into), default)]
4870 #[serde(rename = "newOrderRespType", default)]
4871 pub new_order_resp_type: Option<OrderListPlaceOpoNewOrderRespTypeEnum>,
4872 #[builder(setter(into), default)]
4876 #[serde(rename = "selfTradePreventionMode", default)]
4877 pub self_trade_prevention_mode: Option<OrderListPlaceOpoSelfTradePreventionModeEnum>,
4878 #[builder(setter(into), default)]
4882 #[serde(rename = "workingClientOrderId", default)]
4883 pub working_client_order_id: Option<String>,
4884 #[builder(setter(into), default)]
4888 #[serde(rename = "workingIcebergQty", default)]
4889 pub working_iceberg_qty: Option<rust_decimal::Decimal>,
4890 #[builder(setter(into), default)]
4894 #[serde(rename = "workingTimeInForce", default)]
4895 pub working_time_in_force: Option<OrderListPlaceOpoWorkingTimeInForceEnum>,
4896 #[builder(setter(into), default)]
4900 #[serde(rename = "workingStrategyId", default)]
4901 pub working_strategy_id: Option<i64>,
4902 #[builder(setter(into), default)]
4906 #[serde(rename = "workingStrategyType", default)]
4907 pub working_strategy_type: Option<i32>,
4908 #[builder(setter(into), default)]
4912 #[serde(rename = "workingPegPriceType", default)]
4913 pub working_peg_price_type: Option<OrderListPlaceOpoWorkingPegPriceTypeEnum>,
4914 #[builder(setter(into), default)]
4919 #[serde(rename = "workingPegOffsetType", default)]
4920 pub working_peg_offset_type: Option<OrderListPlaceOpoWorkingPegOffsetTypeEnum>,
4921 #[builder(setter(into), default)]
4926 #[serde(rename = "workingPegOffsetValue", default)]
4927 pub working_peg_offset_value: Option<i32>,
4928 #[builder(setter(into), default)]
4932 #[serde(rename = "pendingClientOrderId", default)]
4933 pub pending_client_order_id: Option<String>,
4934 #[builder(setter(into), default)]
4938 #[serde(rename = "pendingPrice", default)]
4939 pub pending_price: Option<rust_decimal::Decimal>,
4940 #[builder(setter(into), default)]
4944 #[serde(rename = "pendingStopPrice", default)]
4945 pub pending_stop_price: Option<rust_decimal::Decimal>,
4946 #[builder(setter(into), default)]
4950 #[serde(rename = "pendingTrailingDelta", default)]
4951 pub pending_trailing_delta: Option<rust_decimal::Decimal>,
4952 #[builder(setter(into), default)]
4956 #[serde(rename = "pendingIcebergQty", default)]
4957 pub pending_iceberg_qty: Option<rust_decimal::Decimal>,
4958 #[builder(setter(into), default)]
4962 #[serde(rename = "pendingTimeInForce", default)]
4963 pub pending_time_in_force: Option<OrderListPlaceOpoPendingTimeInForceEnum>,
4964 #[builder(setter(into), default)]
4968 #[serde(rename = "pendingStrategyId", default)]
4969 pub pending_strategy_id: Option<i64>,
4970 #[builder(setter(into), default)]
4974 #[serde(rename = "pendingStrategyType", default)]
4975 pub pending_strategy_type: Option<i32>,
4976 #[builder(setter(into), default)]
4980 #[serde(rename = "pendingPegPriceType", default)]
4981 pub pending_peg_price_type: Option<OrderListPlaceOpoPendingPegPriceTypeEnum>,
4982 #[builder(setter(into), default)]
4987 #[serde(rename = "pendingPegOffsetType", default)]
4988 pub pending_peg_offset_type: Option<OrderListPlaceOpoPendingPegOffsetTypeEnum>,
4989 #[builder(setter(into), default)]
4994 #[serde(rename = "pendingPegOffsetValue", default)]
4995 pub pending_peg_offset_value: Option<i32>,
4996 #[builder(setter(into), default)]
5000 #[serde(rename = "recvWindow", default)]
5001 pub recv_window: Option<rust_decimal::Decimal>,
5002}
5003
5004impl OrderListPlaceOpoParams {
5005 #[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#[derive(Clone, Debug, Builder, Deserialize)]
5042#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
5043pub struct OrderListPlaceOpocoParams {
5044 #[builder(setter(into))]
5049 #[serde(rename = "symbol")]
5050 pub symbol: String,
5051 #[builder(setter(into))]
5056 #[serde(rename = "workingType")]
5057 pub working_type: OrderListPlaceOpocoWorkingTypeEnum,
5058 #[builder(setter(into))]
5062 #[serde(rename = "workingSide")]
5063 pub working_side: OrderListPlaceOpocoWorkingSideEnum,
5064 #[builder(setter(into))]
5068 #[serde(rename = "workingPrice")]
5069 pub working_price: rust_decimal::Decimal,
5070 #[builder(setter(into))]
5074 #[serde(rename = "workingQuantity")]
5075 pub working_quantity: rust_decimal::Decimal,
5076 #[builder(setter(into))]
5080 #[serde(rename = "pendingSide")]
5081 pub pending_side: OrderListPlaceOpocoPendingSideEnum,
5082 #[builder(setter(into))]
5086 #[serde(rename = "pendingAboveType")]
5087 pub pending_above_type: OrderListPlaceOpocoPendingAboveTypeEnum,
5088 #[builder(setter(into), default)]
5092 #[serde(rename = "id", default)]
5093 pub id: Option<String>,
5094 #[builder(setter(into), default)]
5098 #[serde(rename = "listClientOrderId", default)]
5099 pub list_client_order_id: Option<String>,
5100 #[builder(setter(into), default)]
5104 #[serde(rename = "newOrderRespType", default)]
5105 pub new_order_resp_type: Option<OrderListPlaceOpocoNewOrderRespTypeEnum>,
5106 #[builder(setter(into), default)]
5110 #[serde(rename = "selfTradePreventionMode", default)]
5111 pub self_trade_prevention_mode: Option<OrderListPlaceOpocoSelfTradePreventionModeEnum>,
5112 #[builder(setter(into), default)]
5116 #[serde(rename = "workingClientOrderId", default)]
5117 pub working_client_order_id: Option<String>,
5118 #[builder(setter(into), default)]
5122 #[serde(rename = "workingIcebergQty", default)]
5123 pub working_iceberg_qty: Option<rust_decimal::Decimal>,
5124 #[builder(setter(into), default)]
5128 #[serde(rename = "workingTimeInForce", default)]
5129 pub working_time_in_force: Option<OrderListPlaceOpocoWorkingTimeInForceEnum>,
5130 #[builder(setter(into), default)]
5134 #[serde(rename = "workingStrategyId", default)]
5135 pub working_strategy_id: Option<i64>,
5136 #[builder(setter(into), default)]
5140 #[serde(rename = "workingStrategyType", default)]
5141 pub working_strategy_type: Option<i32>,
5142 #[builder(setter(into), default)]
5146 #[serde(rename = "workingPegPriceType", default)]
5147 pub working_peg_price_type: Option<OrderListPlaceOpocoWorkingPegPriceTypeEnum>,
5148 #[builder(setter(into), default)]
5152 #[serde(rename = "workingPegOffsetType", default)]
5153 pub working_peg_offset_type: Option<OrderListPlaceOpocoWorkingPegOffsetTypeEnum>,
5154 #[builder(setter(into), default)]
5158 #[serde(rename = "workingPegOffsetValue", default)]
5159 pub working_peg_offset_value: Option<i32>,
5160 #[builder(setter(into), default)]
5164 #[serde(rename = "pendingAboveClientOrderId", default)]
5165 pub pending_above_client_order_id: Option<String>,
5166 #[builder(setter(into), default)]
5170 #[serde(rename = "pendingAbovePrice", default)]
5171 pub pending_above_price: Option<rust_decimal::Decimal>,
5172 #[builder(setter(into), default)]
5176 #[serde(rename = "pendingAboveStopPrice", default)]
5177 pub pending_above_stop_price: Option<rust_decimal::Decimal>,
5178 #[builder(setter(into), default)]
5182 #[serde(rename = "pendingAboveTrailingDelta", default)]
5183 pub pending_above_trailing_delta: Option<rust_decimal::Decimal>,
5184 #[builder(setter(into), default)]
5188 #[serde(rename = "pendingAboveIcebergQty", default)]
5189 pub pending_above_iceberg_qty: Option<rust_decimal::Decimal>,
5190 #[builder(setter(into), default)]
5194 #[serde(rename = "pendingAboveTimeInForce", default)]
5195 pub pending_above_time_in_force: Option<OrderListPlaceOpocoPendingAboveTimeInForceEnum>,
5196 #[builder(setter(into), default)]
5200 #[serde(rename = "pendingAboveStrategyId", default)]
5201 pub pending_above_strategy_id: Option<i64>,
5202 #[builder(setter(into), default)]
5206 #[serde(rename = "pendingAboveStrategyType", default)]
5207 pub pending_above_strategy_type: Option<i32>,
5208 #[builder(setter(into), default)]
5212 #[serde(rename = "pendingAbovePegPriceType", default)]
5213 pub pending_above_peg_price_type: Option<OrderListPlaceOpocoPendingAbovePegPriceTypeEnum>,
5214 #[builder(setter(into), default)]
5218 #[serde(rename = "pendingAbovePegOffsetType", default)]
5219 pub pending_above_peg_offset_type: Option<OrderListPlaceOpocoPendingAbovePegOffsetTypeEnum>,
5220 #[builder(setter(into), default)]
5224 #[serde(rename = "pendingAbovePegOffsetValue", default)]
5225 pub pending_above_peg_offset_value: Option<i32>,
5226 #[builder(setter(into), default)]
5230 #[serde(rename = "pendingBelowType", default)]
5231 pub pending_below_type: Option<OrderListPlaceOpocoPendingBelowTypeEnum>,
5232 #[builder(setter(into), default)]
5236 #[serde(rename = "pendingBelowClientOrderId", default)]
5237 pub pending_below_client_order_id: Option<String>,
5238 #[builder(setter(into), default)]
5242 #[serde(rename = "pendingBelowPrice", default)]
5243 pub pending_below_price: Option<rust_decimal::Decimal>,
5244 #[builder(setter(into), default)]
5248 #[serde(rename = "pendingBelowStopPrice", default)]
5249 pub pending_below_stop_price: Option<rust_decimal::Decimal>,
5250 #[builder(setter(into), default)]
5254 #[serde(rename = "pendingBelowTrailingDelta", default)]
5255 pub pending_below_trailing_delta: Option<rust_decimal::Decimal>,
5256 #[builder(setter(into), default)]
5260 #[serde(rename = "pendingBelowIcebergQty", default)]
5261 pub pending_below_iceberg_qty: Option<rust_decimal::Decimal>,
5262 #[builder(setter(into), default)]
5266 #[serde(rename = "pendingBelowTimeInForce", default)]
5267 pub pending_below_time_in_force: Option<OrderListPlaceOpocoPendingBelowTimeInForceEnum>,
5268 #[builder(setter(into), default)]
5272 #[serde(rename = "pendingBelowStrategyId", default)]
5273 pub pending_below_strategy_id: Option<i64>,
5274 #[builder(setter(into), default)]
5278 #[serde(rename = "pendingBelowStrategyType", default)]
5279 pub pending_below_strategy_type: Option<i32>,
5280 #[builder(setter(into), default)]
5284 #[serde(rename = "pendingBelowPegPriceType", default)]
5285 pub pending_below_peg_price_type: Option<OrderListPlaceOpocoPendingBelowPegPriceTypeEnum>,
5286 #[builder(setter(into), default)]
5291 #[serde(rename = "pendingBelowPegOffsetType", default)]
5292 pub pending_below_peg_offset_type: Option<OrderListPlaceOpocoPendingBelowPegOffsetTypeEnum>,
5293 #[builder(setter(into), default)]
5298 #[serde(rename = "pendingBelowPegOffsetValue", default)]
5299 pub pending_below_peg_offset_value: Option<i32>,
5300 #[builder(setter(into), default)]
5304 #[serde(rename = "recvWindow", default)]
5305 pub recv_window: Option<rust_decimal::Decimal>,
5306}
5307
5308impl OrderListPlaceOpocoParams {
5309 #[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#[derive(Clone, Debug, Builder, Deserialize)]
5346#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
5347pub struct OrderListPlaceOtoParams {
5348 #[builder(setter(into))]
5353 #[serde(rename = "symbol")]
5354 pub symbol: String,
5355 #[builder(setter(into))]
5359 #[serde(rename = "workingType")]
5360 pub working_type: OrderListPlaceOtoWorkingTypeEnum,
5361 #[builder(setter(into))]
5365 #[serde(rename = "workingSide")]
5366 pub working_side: OrderListPlaceOtoWorkingSideEnum,
5367 #[builder(setter(into))]
5372 #[serde(rename = "workingPrice")]
5373 pub working_price: rust_decimal::Decimal,
5374 #[builder(setter(into))]
5378 #[serde(rename = "workingQuantity")]
5379 pub working_quantity: rust_decimal::Decimal,
5380 #[builder(setter(into))]
5384 #[serde(rename = "pendingType")]
5385 pub pending_type: OrderListPlaceOtoPendingTypeEnum,
5386 #[builder(setter(into))]
5390 #[serde(rename = "pendingSide")]
5391 pub pending_side: OrderListPlaceOtoPendingSideEnum,
5392 #[builder(setter(into))]
5396 #[serde(rename = "pendingQuantity")]
5397 pub pending_quantity: rust_decimal::Decimal,
5398 #[builder(setter(into), default)]
5402 #[serde(rename = "id", default)]
5403 pub id: Option<String>,
5404 #[builder(setter(into), default)]
5408 #[serde(rename = "listClientOrderId", default)]
5409 pub list_client_order_id: Option<String>,
5410 #[builder(setter(into), default)]
5414 #[serde(rename = "newOrderRespType", default)]
5415 pub new_order_resp_type: Option<OrderListPlaceOtoNewOrderRespTypeEnum>,
5416 #[builder(setter(into), default)]
5420 #[serde(rename = "selfTradePreventionMode", default)]
5421 pub self_trade_prevention_mode: Option<OrderListPlaceOtoSelfTradePreventionModeEnum>,
5422 #[builder(setter(into), default)]
5426 #[serde(rename = "workingClientOrderId", default)]
5427 pub working_client_order_id: Option<String>,
5428 #[builder(setter(into), default)]
5432 #[serde(rename = "workingIcebergQty", default)]
5433 pub working_iceberg_qty: Option<rust_decimal::Decimal>,
5434 #[builder(setter(into), default)]
5438 #[serde(rename = "workingTimeInForce", default)]
5439 pub working_time_in_force: Option<OrderListPlaceOtoWorkingTimeInForceEnum>,
5440 #[builder(setter(into), default)]
5444 #[serde(rename = "workingStrategyId", default)]
5445 pub working_strategy_id: Option<i64>,
5446 #[builder(setter(into), default)]
5450 #[serde(rename = "workingStrategyType", default)]
5451 pub working_strategy_type: Option<i32>,
5452 #[builder(setter(into), default)]
5456 #[serde(rename = "workingPegPriceType", default)]
5457 pub working_peg_price_type: Option<OrderListPlaceOtoWorkingPegPriceTypeEnum>,
5458 #[builder(setter(into), default)]
5463 #[serde(rename = "workingPegOffsetType", default)]
5464 pub working_peg_offset_type: Option<OrderListPlaceOtoWorkingPegOffsetTypeEnum>,
5465 #[builder(setter(into), default)]
5470 #[serde(rename = "workingPegOffsetValue", default)]
5471 pub working_peg_offset_value: Option<i32>,
5472 #[builder(setter(into), default)]
5476 #[serde(rename = "pendingClientOrderId", default)]
5477 pub pending_client_order_id: Option<String>,
5478 #[builder(setter(into), default)]
5483 #[serde(rename = "pendingPrice", default)]
5484 pub pending_price: Option<rust_decimal::Decimal>,
5485 #[builder(setter(into), default)]
5490 #[serde(rename = "pendingStopPrice", default)]
5491 pub pending_stop_price: Option<rust_decimal::Decimal>,
5492 #[builder(setter(into), default)]
5497 #[serde(rename = "pendingTrailingDelta", default)]
5498 pub pending_trailing_delta: Option<rust_decimal::Decimal>,
5499 #[builder(setter(into), default)]
5503 #[serde(rename = "pendingIcebergQty", default)]
5504 pub pending_iceberg_qty: Option<rust_decimal::Decimal>,
5505 #[builder(setter(into), default)]
5509 #[serde(rename = "pendingTimeInForce", default)]
5510 pub pending_time_in_force: Option<OrderListPlaceOtoPendingTimeInForceEnum>,
5511 #[builder(setter(into), default)]
5515 #[serde(rename = "pendingStrategyId", default)]
5516 pub pending_strategy_id: Option<i64>,
5517 #[builder(setter(into), default)]
5521 #[serde(rename = "pendingStrategyType", default)]
5522 pub pending_strategy_type: Option<i32>,
5523 #[builder(setter(into), default)]
5528 #[serde(rename = "pendingPegOffsetType", default)]
5529 pub pending_peg_offset_type: Option<OrderListPlaceOtoPendingPegOffsetTypeEnum>,
5530 #[builder(setter(into), default)]
5534 #[serde(rename = "pendingPegPriceType", default)]
5535 pub pending_peg_price_type: Option<OrderListPlaceOtoPendingPegPriceTypeEnum>,
5536 #[builder(setter(into), default)]
5541 #[serde(rename = "pendingPegOffsetValue", default)]
5542 pub pending_peg_offset_value: Option<i32>,
5543 #[builder(setter(into), default)]
5547 #[serde(rename = "recvWindow", default)]
5548 pub recv_window: Option<rust_decimal::Decimal>,
5549}
5550
5551impl OrderListPlaceOtoParams {
5552 #[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#[derive(Clone, Debug, Builder, Deserialize)]
5592#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
5593pub struct OrderListPlaceOtocoParams {
5594 #[builder(setter(into))]
5599 #[serde(rename = "symbol")]
5600 pub symbol: String,
5601 #[builder(setter(into))]
5605 #[serde(rename = "workingType")]
5606 pub working_type: OrderListPlaceOtocoWorkingTypeEnum,
5607 #[builder(setter(into))]
5611 #[serde(rename = "workingSide")]
5612 pub working_side: OrderListPlaceOtocoWorkingSideEnum,
5613 #[builder(setter(into))]
5618 #[serde(rename = "workingPrice")]
5619 pub working_price: rust_decimal::Decimal,
5620 #[builder(setter(into))]
5624 #[serde(rename = "workingQuantity")]
5625 pub working_quantity: rust_decimal::Decimal,
5626 #[builder(setter(into))]
5630 #[serde(rename = "pendingSide")]
5631 pub pending_side: OrderListPlaceOtocoPendingSideEnum,
5632 #[builder(setter(into))]
5636 #[serde(rename = "pendingQuantity")]
5637 pub pending_quantity: rust_decimal::Decimal,
5638 #[builder(setter(into))]
5642 #[serde(rename = "pendingAboveType")]
5643 pub pending_above_type: OrderListPlaceOtocoPendingAboveTypeEnum,
5644 #[builder(setter(into), default)]
5648 #[serde(rename = "id", default)]
5649 pub id: Option<String>,
5650 #[builder(setter(into), default)]
5654 #[serde(rename = "listClientOrderId", default)]
5655 pub list_client_order_id: Option<String>,
5656 #[builder(setter(into), default)]
5660 #[serde(rename = "newOrderRespType", default)]
5661 pub new_order_resp_type: Option<OrderListPlaceOtocoNewOrderRespTypeEnum>,
5662 #[builder(setter(into), default)]
5666 #[serde(rename = "selfTradePreventionMode", default)]
5667 pub self_trade_prevention_mode: Option<OrderListPlaceOtocoSelfTradePreventionModeEnum>,
5668 #[builder(setter(into), default)]
5672 #[serde(rename = "workingClientOrderId", default)]
5673 pub working_client_order_id: Option<String>,
5674 #[builder(setter(into), default)]
5678 #[serde(rename = "workingIcebergQty", default)]
5679 pub working_iceberg_qty: Option<rust_decimal::Decimal>,
5680 #[builder(setter(into), default)]
5684 #[serde(rename = "workingTimeInForce", default)]
5685 pub working_time_in_force: Option<OrderListPlaceOtocoWorkingTimeInForceEnum>,
5686 #[builder(setter(into), default)]
5690 #[serde(rename = "workingStrategyId", default)]
5691 pub working_strategy_id: Option<i64>,
5692 #[builder(setter(into), default)]
5696 #[serde(rename = "workingStrategyType", default)]
5697 pub working_strategy_type: Option<i32>,
5698 #[builder(setter(into), default)]
5702 #[serde(rename = "workingPegPriceType", default)]
5703 pub working_peg_price_type: Option<OrderListPlaceOtocoWorkingPegPriceTypeEnum>,
5704 #[builder(setter(into), default)]
5709 #[serde(rename = "workingPegOffsetType", default)]
5710 pub working_peg_offset_type: Option<OrderListPlaceOtocoWorkingPegOffsetTypeEnum>,
5711 #[builder(setter(into), default)]
5716 #[serde(rename = "workingPegOffsetValue", default)]
5717 pub working_peg_offset_value: Option<i32>,
5718 #[builder(setter(into), default)]
5722 #[serde(rename = "pendingAboveClientOrderId", default)]
5723 pub pending_above_client_order_id: Option<String>,
5724 #[builder(setter(into), default)]
5728 #[serde(rename = "pendingAbovePrice", default)]
5729 pub pending_above_price: Option<rust_decimal::Decimal>,
5730 #[builder(setter(into), default)]
5734 #[serde(rename = "pendingAboveStopPrice", default)]
5735 pub pending_above_stop_price: Option<rust_decimal::Decimal>,
5736 #[builder(setter(into), default)]
5740 #[serde(rename = "pendingAboveTrailingDelta", default)]
5741 pub pending_above_trailing_delta: Option<rust_decimal::Decimal>,
5742 #[builder(setter(into), default)]
5746 #[serde(rename = "pendingAboveIcebergQty", default)]
5747 pub pending_above_iceberg_qty: Option<rust_decimal::Decimal>,
5748 #[builder(setter(into), default)]
5752 #[serde(rename = "pendingAboveTimeInForce", default)]
5753 pub pending_above_time_in_force: Option<OrderListPlaceOtocoPendingAboveTimeInForceEnum>,
5754 #[builder(setter(into), default)]
5758 #[serde(rename = "pendingAboveStrategyId", default)]
5759 pub pending_above_strategy_id: Option<i64>,
5760 #[builder(setter(into), default)]
5764 #[serde(rename = "pendingAboveStrategyType", default)]
5765 pub pending_above_strategy_type: Option<i32>,
5766 #[builder(setter(into), default)]
5770 #[serde(rename = "pendingAbovePegPriceType", default)]
5771 pub pending_above_peg_price_type: Option<OrderListPlaceOtocoPendingAbovePegPriceTypeEnum>,
5772 #[builder(setter(into), default)]
5777 #[serde(rename = "pendingAbovePegOffsetType", default)]
5778 pub pending_above_peg_offset_type: Option<OrderListPlaceOtocoPendingAbovePegOffsetTypeEnum>,
5779 #[builder(setter(into), default)]
5784 #[serde(rename = "pendingAbovePegOffsetValue", default)]
5785 pub pending_above_peg_offset_value: Option<i32>,
5786 #[builder(setter(into), default)]
5790 #[serde(rename = "pendingBelowType", default)]
5791 pub pending_below_type: Option<OrderListPlaceOtocoPendingBelowTypeEnum>,
5792 #[builder(setter(into), default)]
5796 #[serde(rename = "pendingBelowClientOrderId", default)]
5797 pub pending_below_client_order_id: Option<String>,
5798 #[builder(setter(into), default)]
5802 #[serde(rename = "pendingBelowPrice", default)]
5803 pub pending_below_price: Option<rust_decimal::Decimal>,
5804 #[builder(setter(into), default)]
5808 #[serde(rename = "pendingBelowStopPrice", default)]
5809 pub pending_below_stop_price: Option<rust_decimal::Decimal>,
5810 #[builder(setter(into), default)]
5814 #[serde(rename = "pendingBelowTrailingDelta", default)]
5815 pub pending_below_trailing_delta: Option<rust_decimal::Decimal>,
5816 #[builder(setter(into), default)]
5820 #[serde(rename = "pendingBelowIcebergQty", default)]
5821 pub pending_below_iceberg_qty: Option<rust_decimal::Decimal>,
5822 #[builder(setter(into), default)]
5826 #[serde(rename = "pendingBelowTimeInForce", default)]
5827 pub pending_below_time_in_force: Option<OrderListPlaceOtocoPendingBelowTimeInForceEnum>,
5828 #[builder(setter(into), default)]
5832 #[serde(rename = "pendingBelowStrategyId", default)]
5833 pub pending_below_strategy_id: Option<i64>,
5834 #[builder(setter(into), default)]
5838 #[serde(rename = "pendingBelowStrategyType", default)]
5839 pub pending_below_strategy_type: Option<i32>,
5840 #[builder(setter(into), default)]
5844 #[serde(rename = "pendingBelowPegPriceType", default)]
5845 pub pending_below_peg_price_type: Option<OrderListPlaceOtocoPendingBelowPegPriceTypeEnum>,
5846 #[builder(setter(into), default)]
5851 #[serde(rename = "pendingBelowPegOffsetType", default)]
5852 pub pending_below_peg_offset_type: Option<OrderListPlaceOtocoPendingBelowPegOffsetTypeEnum>,
5853 #[builder(setter(into), default)]
5858 #[serde(rename = "pendingBelowPegOffsetValue", default)]
5859 pub pending_below_peg_offset_value: Option<i32>,
5860 #[builder(setter(into), default)]
5864 #[serde(rename = "recvWindow", default)]
5865 pub recv_window: Option<rust_decimal::Decimal>,
5866}
5867
5868impl OrderListPlaceOtocoParams {
5869 #[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#[derive(Clone, Debug, Builder, Deserialize)]
5909#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
5910pub struct OrderPlaceParams {
5911 #[builder(setter(into))]
5916 #[serde(rename = "symbol")]
5917 pub symbol: String,
5918 #[builder(setter(into))]
5922 #[serde(rename = "side")]
5923 pub side: OrderPlaceSideEnum,
5924 #[builder(setter(into))]
5928 #[serde(rename = "type")]
5929 pub r#type: OrderPlaceTypeEnum,
5930 #[builder(setter(into), default)]
5934 #[serde(rename = "id", default)]
5935 pub id: Option<String>,
5936 #[builder(setter(into), default)]
5940 #[serde(rename = "timeInForce", default)]
5941 pub time_in_force: Option<OrderPlaceTimeInForceEnum>,
5942 #[builder(setter(into), default)]
5947 #[serde(rename = "price", default)]
5948 pub price: Option<rust_decimal::Decimal>,
5949 #[builder(setter(into), default)]
5954 #[serde(rename = "quantity", default)]
5955 pub quantity: Option<rust_decimal::Decimal>,
5956 #[builder(setter(into), default)]
5961 #[serde(rename = "quoteOrderQty", default)]
5962 pub quote_order_qty: Option<rust_decimal::Decimal>,
5963 #[builder(setter(into), default)]
5967 #[serde(rename = "newClientOrderId", default)]
5968 pub new_client_order_id: Option<String>,
5969 #[builder(setter(into), default)]
5973 #[serde(rename = "newOrderRespType", default)]
5974 pub new_order_resp_type: Option<OrderPlaceNewOrderRespTypeEnum>,
5975 #[builder(setter(into), default)]
5979 #[serde(rename = "stopPrice", default)]
5980 pub stop_price: Option<rust_decimal::Decimal>,
5981 #[builder(setter(into), default)]
5985 #[serde(rename = "trailingDelta", default)]
5986 pub trailing_delta: Option<i32>,
5987 #[builder(setter(into), default)]
5991 #[serde(rename = "icebergQty", default)]
5992 pub iceberg_qty: Option<rust_decimal::Decimal>,
5993 #[builder(setter(into), default)]
5998 #[serde(rename = "strategyId", default)]
5999 pub strategy_id: Option<i64>,
6000 #[builder(setter(into), default)]
6004 #[serde(rename = "strategyType", default)]
6005 pub strategy_type: Option<i32>,
6006 #[builder(setter(into), default)]
6010 #[serde(rename = "selfTradePreventionMode", default)]
6011 pub self_trade_prevention_mode: Option<OrderPlaceSelfTradePreventionModeEnum>,
6012 #[builder(setter(into), default)]
6016 #[serde(rename = "pegPriceType", default)]
6017 pub peg_price_type: Option<OrderPlacePegPriceTypeEnum>,
6018 #[builder(setter(into), default)]
6022 #[serde(rename = "pegOffsetValue", default)]
6023 pub peg_offset_value: Option<i32>,
6024 #[builder(setter(into), default)]
6028 #[serde(rename = "pegOffsetType", default)]
6029 pub peg_offset_type: Option<OrderPlacePegOffsetTypeEnum>,
6030 #[builder(setter(into), default)]
6034 #[serde(rename = "recvWindow", default)]
6035 pub recv_window: Option<rust_decimal::Decimal>,
6036}
6037
6038impl OrderPlaceParams {
6039 #[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#[derive(Clone, Debug, Builder, Deserialize)]
6064#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
6065pub struct OrderTestParams {
6066 #[builder(setter(into))]
6071 #[serde(rename = "symbol")]
6072 pub symbol: String,
6073 #[builder(setter(into))]
6077 #[serde(rename = "side")]
6078 pub side: OrderTestSideEnum,
6079 #[builder(setter(into))]
6083 #[serde(rename = "type")]
6084 pub r#type: OrderTestTypeEnum,
6085 #[builder(setter(into), default)]
6089 #[serde(rename = "id", default)]
6090 pub id: Option<String>,
6091 #[builder(setter(into), default)]
6095 #[serde(rename = "computeCommissionRates", default)]
6096 pub compute_commission_rates: Option<bool>,
6097 #[builder(setter(into), default)]
6101 #[serde(rename = "timeInForce", default)]
6102 pub time_in_force: Option<OrderTestTimeInForceEnum>,
6103 #[builder(setter(into), default)]
6108 #[serde(rename = "price", default)]
6109 pub price: Option<rust_decimal::Decimal>,
6110 #[builder(setter(into), default)]
6115 #[serde(rename = "quantity", default)]
6116 pub quantity: Option<rust_decimal::Decimal>,
6117 #[builder(setter(into), default)]
6122 #[serde(rename = "quoteOrderQty", default)]
6123 pub quote_order_qty: Option<rust_decimal::Decimal>,
6124 #[builder(setter(into), default)]
6128 #[serde(rename = "newClientOrderId", default)]
6129 pub new_client_order_id: Option<String>,
6130 #[builder(setter(into), default)]
6134 #[serde(rename = "newOrderRespType", default)]
6135 pub new_order_resp_type: Option<OrderTestNewOrderRespTypeEnum>,
6136 #[builder(setter(into), default)]
6140 #[serde(rename = "stopPrice", default)]
6141 pub stop_price: Option<rust_decimal::Decimal>,
6142 #[builder(setter(into), default)]
6146 #[serde(rename = "trailingDelta", default)]
6147 pub trailing_delta: Option<i32>,
6148 #[builder(setter(into), default)]
6152 #[serde(rename = "icebergQty", default)]
6153 pub iceberg_qty: Option<rust_decimal::Decimal>,
6154 #[builder(setter(into), default)]
6159 #[serde(rename = "strategyId", default)]
6160 pub strategy_id: Option<i64>,
6161 #[builder(setter(into), default)]
6165 #[serde(rename = "strategyType", default)]
6166 pub strategy_type: Option<i32>,
6167 #[builder(setter(into), default)]
6171 #[serde(rename = "selfTradePreventionMode", default)]
6172 pub self_trade_prevention_mode: Option<OrderTestSelfTradePreventionModeEnum>,
6173 #[builder(setter(into), default)]
6177 #[serde(rename = "pegPriceType", default)]
6178 pub peg_price_type: Option<OrderTestPegPriceTypeEnum>,
6179 #[builder(setter(into), default)]
6183 #[serde(rename = "pegOffsetValue", default)]
6184 pub peg_offset_value: Option<i32>,
6185 #[builder(setter(into), default)]
6189 #[serde(rename = "pegOffsetType", default)]
6190 pub peg_offset_type: Option<OrderTestPegOffsetTypeEnum>,
6191 #[builder(setter(into), default)]
6195 #[serde(rename = "recvWindow", default)]
6196 pub recv_window: Option<rust_decimal::Decimal>,
6197}
6198
6199impl OrderTestParams {
6200 #[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#[derive(Clone, Debug, Builder, Deserialize)]
6225#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
6226pub struct SorOrderPlaceParams {
6227 #[builder(setter(into))]
6232 #[serde(rename = "symbol")]
6233 pub symbol: String,
6234 #[builder(setter(into))]
6238 #[serde(rename = "side")]
6239 pub side: SorOrderPlaceSideEnum,
6240 #[builder(setter(into))]
6244 #[serde(rename = "type")]
6245 pub r#type: SorOrderPlaceTypeEnum,
6246 #[builder(setter(into))]
6251 #[serde(rename = "quantity")]
6252 pub quantity: rust_decimal::Decimal,
6253 #[builder(setter(into), default)]
6257 #[serde(rename = "id", default)]
6258 pub id: Option<String>,
6259 #[builder(setter(into), default)]
6263 #[serde(rename = "timeInForce", default)]
6264 pub time_in_force: Option<SorOrderPlaceTimeInForceEnum>,
6265 #[builder(setter(into), default)]
6270 #[serde(rename = "price", default)]
6271 pub price: Option<rust_decimal::Decimal>,
6272 #[builder(setter(into), default)]
6276 #[serde(rename = "newClientOrderId", default)]
6277 pub new_client_order_id: Option<String>,
6278 #[builder(setter(into), default)]
6282 #[serde(rename = "newOrderRespType", default)]
6283 pub new_order_resp_type: Option<SorOrderPlaceNewOrderRespTypeEnum>,
6284 #[builder(setter(into), default)]
6288 #[serde(rename = "icebergQty", default)]
6289 pub iceberg_qty: Option<rust_decimal::Decimal>,
6290 #[builder(setter(into), default)]
6295 #[serde(rename = "strategyId", default)]
6296 pub strategy_id: Option<i64>,
6297 #[builder(setter(into), default)]
6301 #[serde(rename = "strategyType", default)]
6302 pub strategy_type: Option<i32>,
6303 #[builder(setter(into), default)]
6307 #[serde(rename = "selfTradePreventionMode", default)]
6308 pub self_trade_prevention_mode: Option<SorOrderPlaceSelfTradePreventionModeEnum>,
6309 #[builder(setter(into), default)]
6313 #[serde(rename = "recvWindow", default)]
6314 pub recv_window: Option<rust_decimal::Decimal>,
6315}
6316
6317impl SorOrderPlaceParams {
6318 #[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#[derive(Clone, Debug, Builder, Deserialize)]
6346#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
6347pub struct SorOrderTestParams {
6348 #[builder(setter(into))]
6353 #[serde(rename = "symbol")]
6354 pub symbol: String,
6355 #[builder(setter(into))]
6359 #[serde(rename = "side")]
6360 pub side: SorOrderTestSideEnum,
6361 #[builder(setter(into))]
6365 #[serde(rename = "type")]
6366 pub r#type: SorOrderTestTypeEnum,
6367 #[builder(setter(into))]
6372 #[serde(rename = "quantity")]
6373 pub quantity: rust_decimal::Decimal,
6374 #[builder(setter(into), default)]
6378 #[serde(rename = "id", default)]
6379 pub id: Option<String>,
6380 #[builder(setter(into), default)]
6384 #[serde(rename = "computeCommissionRates", default)]
6385 pub compute_commission_rates: Option<bool>,
6386 #[builder(setter(into), default)]
6390 #[serde(rename = "timeInForce", default)]
6391 pub time_in_force: Option<SorOrderTestTimeInForceEnum>,
6392 #[builder(setter(into), default)]
6397 #[serde(rename = "price", default)]
6398 pub price: Option<rust_decimal::Decimal>,
6399 #[builder(setter(into), default)]
6403 #[serde(rename = "newClientOrderId", default)]
6404 pub new_client_order_id: Option<String>,
6405 #[builder(setter(into), default)]
6409 #[serde(rename = "newOrderRespType", default)]
6410 pub new_order_resp_type: Option<SorOrderTestNewOrderRespTypeEnum>,
6411 #[builder(setter(into), default)]
6415 #[serde(rename = "icebergQty", default)]
6416 pub iceberg_qty: Option<rust_decimal::Decimal>,
6417 #[builder(setter(into), default)]
6422 #[serde(rename = "strategyId", default)]
6423 pub strategy_id: Option<i64>,
6424 #[builder(setter(into), default)]
6428 #[serde(rename = "strategyType", default)]
6429 pub strategy_type: Option<i32>,
6430 #[builder(setter(into), default)]
6434 #[serde(rename = "selfTradePreventionMode", default)]
6435 pub self_trade_prevention_mode: Option<SorOrderTestSelfTradePreventionModeEnum>,
6436 #[builder(setter(into), default)]
6440 #[serde(rename = "recvWindow", default)]
6441 pub recv_window: Option<rust_decimal::Decimal>,
6442}
6443
6444impl SorOrderTestParams {
6445 #[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}