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