1use serde::{Deserialize, Serialize};
4
5use crate::types::{
6 Category, OrderStatus, OrderType, PositionIdx, Side, StopOrderType, TimeInForce, TriggerBy,
7};
8
9
10#[derive(Debug, Clone, Serialize)]
12#[serde(rename_all = "camelCase")]
13pub struct OrderParams {
14 pub category: Category,
16 pub symbol: String,
18 pub side: Side,
20 pub order_type: OrderType,
22 pub qty: String,
24 #[serde(skip_serializing_if = "Option::is_none")]
26 pub is_leverage: Option<i32>,
27 #[serde(skip_serializing_if = "Option::is_none")]
29 pub market_unit: Option<String>,
30 #[serde(skip_serializing_if = "Option::is_none")]
32 pub price: Option<String>,
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub trigger_direction: Option<i32>,
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub order_filter: Option<String>,
39 #[serde(skip_serializing_if = "Option::is_none")]
41 pub trigger_price: Option<String>,
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub trigger_by: Option<TriggerBy>,
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub order_iv: Option<String>,
48 #[serde(skip_serializing_if = "Option::is_none")]
50 pub time_in_force: Option<TimeInForce>,
51 #[serde(skip_serializing_if = "Option::is_none")]
53 pub position_idx: Option<PositionIdx>,
54 #[serde(skip_serializing_if = "Option::is_none")]
56 pub order_link_id: Option<String>,
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub take_profit: Option<String>,
60 #[serde(skip_serializing_if = "Option::is_none")]
62 pub stop_loss: Option<String>,
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub tp_trigger_by: Option<TriggerBy>,
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub sl_trigger_by: Option<TriggerBy>,
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub reduce_only: Option<bool>,
72 #[serde(skip_serializing_if = "Option::is_none")]
74 pub close_on_trigger: Option<bool>,
75 #[serde(skip_serializing_if = "Option::is_none")]
77 pub smp_type: Option<String>,
78 #[serde(skip_serializing_if = "Option::is_none")]
80 pub mmp: Option<bool>,
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub tpsl_mode: Option<String>,
84 #[serde(skip_serializing_if = "Option::is_none")]
86 pub tp_limit_price: Option<String>,
87 #[serde(skip_serializing_if = "Option::is_none")]
89 pub sl_limit_price: Option<String>,
90 #[serde(skip_serializing_if = "Option::is_none")]
92 pub tp_order_type: Option<OrderType>,
93 #[serde(skip_serializing_if = "Option::is_none")]
95 pub sl_order_type: Option<OrderType>,
96}
97
98impl OrderParams {
99 pub fn new(
101 category: Category,
102 symbol: impl Into<String>,
103 side: Side,
104 order_type: OrderType,
105 qty: impl Into<String>,
106 ) -> Self {
107 Self {
108 category,
109 symbol: symbol.into(),
110 side,
111 order_type,
112 qty: qty.into(),
113 is_leverage: None,
114 market_unit: None,
115 price: None,
116 trigger_direction: None,
117 order_filter: None,
118 trigger_price: None,
119 trigger_by: None,
120 order_iv: None,
121 time_in_force: None,
122 position_idx: None,
123 order_link_id: None,
124 take_profit: None,
125 stop_loss: None,
126 tp_trigger_by: None,
127 sl_trigger_by: None,
128 reduce_only: None,
129 close_on_trigger: None,
130 smp_type: None,
131 mmp: None,
132 tpsl_mode: None,
133 tp_limit_price: None,
134 sl_limit_price: None,
135 tp_order_type: None,
136 sl_order_type: None,
137 }
138 }
139
140 pub fn market(
142 category: Category,
143 symbol: impl Into<String>,
144 side: Side,
145 qty: impl Into<String>,
146 ) -> Self {
147 Self::new(category, symbol, side, OrderType::Market, qty)
148 }
149
150 pub fn limit(
152 category: Category,
153 symbol: impl Into<String>,
154 side: Side,
155 qty: impl Into<String>,
156 price: impl Into<String>,
157 ) -> Self {
158 Self::new(category, symbol, side, OrderType::Limit, qty).price(price)
159 }
160
161 pub fn price(mut self, price: impl Into<String>) -> Self {
163 self.price = Some(price.into());
164 self
165 }
166
167 pub fn time_in_force(mut self, tif: TimeInForce) -> Self {
169 self.time_in_force = Some(tif);
170 self
171 }
172
173 pub fn order_link_id(mut self, id: impl Into<String>) -> Self {
175 self.order_link_id = Some(id.into());
176 self
177 }
178
179 pub fn take_profit(mut self, tp: impl Into<String>) -> Self {
181 self.take_profit = Some(tp.into());
182 self
183 }
184
185 pub fn stop_loss(mut self, sl: impl Into<String>) -> Self {
187 self.stop_loss = Some(sl.into());
188 self
189 }
190
191 pub fn reduce_only(mut self, reduce: bool) -> Self {
193 self.reduce_only = Some(reduce);
194 self
195 }
196
197 pub fn position_idx(mut self, idx: PositionIdx) -> Self {
199 self.position_idx = Some(idx);
200 self
201 }
202
203 pub fn leverage(mut self, enabled: bool) -> Self {
205 self.is_leverage = Some(if enabled { 1 } else { 0 });
206 self
207 }
208
209 pub fn trigger_price(mut self, price: impl Into<String>) -> Self {
211 self.trigger_price = Some(price.into());
212 self
213 }
214
215 pub fn trigger_by(mut self, by: TriggerBy) -> Self {
217 self.trigger_by = Some(by);
218 self
219 }
220
221 pub fn close_on_trigger(mut self, close: bool) -> Self {
223 self.close_on_trigger = Some(close);
224 self
225 }
226
227 pub fn tpsl_mode(mut self, mode: impl Into<String>) -> Self {
229 self.tpsl_mode = Some(mode.into());
230 self
231 }
232}
233
234
235#[derive(Debug, Clone, Serialize)]
237#[serde(rename_all = "camelCase")]
238pub struct AmendOrderParams {
239 pub category: Category,
241 pub symbol: String,
243 #[serde(skip_serializing_if = "Option::is_none")]
245 pub order_id: Option<String>,
246 #[serde(skip_serializing_if = "Option::is_none")]
248 pub order_link_id: Option<String>,
249 #[serde(skip_serializing_if = "Option::is_none")]
251 pub order_iv: Option<String>,
252 #[serde(skip_serializing_if = "Option::is_none")]
254 pub trigger_price: Option<String>,
255 #[serde(skip_serializing_if = "Option::is_none")]
257 pub qty: Option<String>,
258 #[serde(skip_serializing_if = "Option::is_none")]
260 pub price: Option<String>,
261 #[serde(skip_serializing_if = "Option::is_none")]
263 pub tpsl_mode: Option<String>,
264 #[serde(skip_serializing_if = "Option::is_none")]
266 pub take_profit: Option<String>,
267 #[serde(skip_serializing_if = "Option::is_none")]
269 pub stop_loss: Option<String>,
270 #[serde(skip_serializing_if = "Option::is_none")]
272 pub tp_trigger_by: Option<TriggerBy>,
273 #[serde(skip_serializing_if = "Option::is_none")]
275 pub sl_trigger_by: Option<TriggerBy>,
276 #[serde(skip_serializing_if = "Option::is_none")]
278 pub trigger_by: Option<TriggerBy>,
279 #[serde(skip_serializing_if = "Option::is_none")]
281 pub tp_limit_price: Option<String>,
282 #[serde(skip_serializing_if = "Option::is_none")]
284 pub sl_limit_price: Option<String>,
285}
286
287impl AmendOrderParams {
288 pub fn by_order_id(
290 category: Category,
291 symbol: impl Into<String>,
292 order_id: impl Into<String>,
293 ) -> Self {
294 Self {
295 category,
296 symbol: symbol.into(),
297 order_id: Some(order_id.into()),
298 order_link_id: None,
299 order_iv: None,
300 trigger_price: None,
301 qty: None,
302 price: None,
303 tpsl_mode: None,
304 take_profit: None,
305 stop_loss: None,
306 tp_trigger_by: None,
307 sl_trigger_by: None,
308 trigger_by: None,
309 tp_limit_price: None,
310 sl_limit_price: None,
311 }
312 }
313
314 pub fn by_order_link_id(
316 category: Category,
317 symbol: impl Into<String>,
318 order_link_id: impl Into<String>,
319 ) -> Self {
320 Self {
321 category,
322 symbol: symbol.into(),
323 order_id: None,
324 order_link_id: Some(order_link_id.into()),
325 order_iv: None,
326 trigger_price: None,
327 qty: None,
328 price: None,
329 tpsl_mode: None,
330 take_profit: None,
331 stop_loss: None,
332 tp_trigger_by: None,
333 sl_trigger_by: None,
334 trigger_by: None,
335 tp_limit_price: None,
336 sl_limit_price: None,
337 }
338 }
339
340 pub fn qty(mut self, qty: impl Into<String>) -> Self {
342 self.qty = Some(qty.into());
343 self
344 }
345
346 pub fn price(mut self, price: impl Into<String>) -> Self {
348 self.price = Some(price.into());
349 self
350 }
351
352 pub fn take_profit(mut self, tp: impl Into<String>) -> Self {
354 self.take_profit = Some(tp.into());
355 self
356 }
357
358 pub fn stop_loss(mut self, sl: impl Into<String>) -> Self {
360 self.stop_loss = Some(sl.into());
361 self
362 }
363
364 pub fn trigger_price(mut self, price: impl Into<String>) -> Self {
366 self.trigger_price = Some(price.into());
367 self
368 }
369}
370
371
372#[derive(Debug, Clone, Serialize)]
374#[serde(rename_all = "camelCase")]
375pub struct CancelOrderParams {
376 pub category: Category,
378 pub symbol: String,
380 #[serde(skip_serializing_if = "Option::is_none")]
382 pub order_id: Option<String>,
383 #[serde(skip_serializing_if = "Option::is_none")]
385 pub order_link_id: Option<String>,
386 #[serde(skip_serializing_if = "Option::is_none")]
388 pub order_filter: Option<String>,
389}
390
391impl CancelOrderParams {
392 pub fn by_order_id(
394 category: Category,
395 symbol: impl Into<String>,
396 order_id: impl Into<String>,
397 ) -> Self {
398 Self {
399 category,
400 symbol: symbol.into(),
401 order_id: Some(order_id.into()),
402 order_link_id: None,
403 order_filter: None,
404 }
405 }
406
407 pub fn by_order_link_id(
409 category: Category,
410 symbol: impl Into<String>,
411 order_link_id: impl Into<String>,
412 ) -> Self {
413 Self {
414 category,
415 symbol: symbol.into(),
416 order_id: None,
417 order_link_id: Some(order_link_id.into()),
418 order_filter: None,
419 }
420 }
421
422 pub fn order_filter(mut self, filter: impl Into<String>) -> Self {
424 self.order_filter = Some(filter.into());
425 self
426 }
427}
428
429
430#[derive(Debug, Clone, Serialize)]
432#[serde(rename_all = "camelCase")]
433pub struct CancelAllOrdersParams {
434 pub category: Category,
436 #[serde(skip_serializing_if = "Option::is_none")]
438 pub symbol: Option<String>,
439 #[serde(skip_serializing_if = "Option::is_none")]
441 pub base_coin: Option<String>,
442 #[serde(skip_serializing_if = "Option::is_none")]
444 pub settle_coin: Option<String>,
445 #[serde(skip_serializing_if = "Option::is_none")]
447 pub order_filter: Option<String>,
448 #[serde(skip_serializing_if = "Option::is_none")]
450 pub stop_order_type: Option<StopOrderType>,
451}
452
453impl CancelAllOrdersParams {
454 pub fn new(category: Category) -> Self {
456 Self {
457 category,
458 symbol: None,
459 base_coin: None,
460 settle_coin: None,
461 order_filter: None,
462 stop_order_type: None,
463 }
464 }
465
466 pub fn symbol(mut self, symbol: impl Into<String>) -> Self {
468 self.symbol = Some(symbol.into());
469 self
470 }
471
472 pub fn base_coin(mut self, coin: impl Into<String>) -> Self {
474 self.base_coin = Some(coin.into());
475 self
476 }
477
478 pub fn settle_coin(mut self, coin: impl Into<String>) -> Self {
480 self.settle_coin = Some(coin.into());
481 self
482 }
483}
484
485
486#[derive(Debug, Clone, Serialize)]
488#[serde(rename_all = "camelCase")]
489pub struct GetOpenOrdersParams {
490 pub category: Category,
492 #[serde(skip_serializing_if = "Option::is_none")]
494 pub symbol: Option<String>,
495 #[serde(skip_serializing_if = "Option::is_none")]
497 pub base_coin: Option<String>,
498 #[serde(skip_serializing_if = "Option::is_none")]
500 pub settle_coin: Option<String>,
501 #[serde(skip_serializing_if = "Option::is_none")]
503 pub order_id: Option<String>,
504 #[serde(skip_serializing_if = "Option::is_none")]
506 pub order_link_id: Option<String>,
507 #[serde(skip_serializing_if = "Option::is_none")]
509 pub open_only: Option<i32>,
510 #[serde(skip_serializing_if = "Option::is_none")]
512 pub order_filter: Option<String>,
513 #[serde(skip_serializing_if = "Option::is_none")]
515 pub limit: Option<u32>,
516 #[serde(skip_serializing_if = "Option::is_none")]
518 pub cursor: Option<String>,
519}
520
521impl GetOpenOrdersParams {
522 pub fn new(category: Category) -> Self {
524 Self {
525 category,
526 symbol: None,
527 base_coin: None,
528 settle_coin: None,
529 order_id: None,
530 order_link_id: None,
531 open_only: None,
532 order_filter: None,
533 limit: None,
534 cursor: None,
535 }
536 }
537
538 pub fn symbol(mut self, symbol: impl Into<String>) -> Self {
540 self.symbol = Some(symbol.into());
541 self
542 }
543
544 pub fn base_coin(mut self, coin: impl Into<String>) -> Self {
546 self.base_coin = Some(coin.into());
547 self
548 }
549
550 pub fn settle_coin(mut self, coin: impl Into<String>) -> Self {
552 self.settle_coin = Some(coin.into());
553 self
554 }
555
556 pub fn order_id(mut self, id: impl Into<String>) -> Self {
558 self.order_id = Some(id.into());
559 self
560 }
561
562 pub fn order_link_id(mut self, id: impl Into<String>) -> Self {
564 self.order_link_id = Some(id.into());
565 self
566 }
567
568 pub fn limit(mut self, limit: u32) -> Self {
570 self.limit = Some(limit);
571 self
572 }
573
574 pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
576 self.cursor = Some(cursor.into());
577 self
578 }
579}
580
581#[derive(Debug, Clone, Serialize)]
583#[serde(rename_all = "camelCase")]
584pub struct GetOrderHistoryParams {
585 pub category: Category,
587 #[serde(skip_serializing_if = "Option::is_none")]
589 pub symbol: Option<String>,
590 #[serde(skip_serializing_if = "Option::is_none")]
592 pub base_coin: Option<String>,
593 #[serde(skip_serializing_if = "Option::is_none")]
595 pub settle_coin: Option<String>,
596 #[serde(skip_serializing_if = "Option::is_none")]
598 pub order_id: Option<String>,
599 #[serde(skip_serializing_if = "Option::is_none")]
601 pub order_link_id: Option<String>,
602 #[serde(skip_serializing_if = "Option::is_none")]
604 pub order_filter: Option<String>,
605 #[serde(skip_serializing_if = "Option::is_none")]
607 pub order_status: Option<OrderStatus>,
608 #[serde(skip_serializing_if = "Option::is_none")]
610 pub start_time: Option<u64>,
611 #[serde(skip_serializing_if = "Option::is_none")]
613 pub end_time: Option<u64>,
614 #[serde(skip_serializing_if = "Option::is_none")]
616 pub limit: Option<u32>,
617 #[serde(skip_serializing_if = "Option::is_none")]
619 pub cursor: Option<String>,
620}
621
622impl GetOrderHistoryParams {
623 pub fn new(category: Category) -> Self {
625 Self {
626 category,
627 symbol: None,
628 base_coin: None,
629 settle_coin: None,
630 order_id: None,
631 order_link_id: None,
632 order_filter: None,
633 order_status: None,
634 start_time: None,
635 end_time: None,
636 limit: None,
637 cursor: None,
638 }
639 }
640
641 pub fn symbol(mut self, symbol: impl Into<String>) -> Self {
643 self.symbol = Some(symbol.into());
644 self
645 }
646
647 pub fn base_coin(mut self, coin: impl Into<String>) -> Self {
649 self.base_coin = Some(coin.into());
650 self
651 }
652
653 pub fn order_status(mut self, status: OrderStatus) -> Self {
655 self.order_status = Some(status);
656 self
657 }
658
659 pub fn start_time(mut self, start: u64) -> Self {
661 self.start_time = Some(start);
662 self
663 }
664
665 pub fn end_time(mut self, end: u64) -> Self {
667 self.end_time = Some(end);
668 self
669 }
670
671 pub fn limit(mut self, limit: u32) -> Self {
673 self.limit = Some(limit);
674 self
675 }
676
677 pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
679 self.cursor = Some(cursor.into());
680 self
681 }
682}
683
684#[derive(Debug, Clone, Serialize)]
686#[serde(rename_all = "camelCase")]
687pub struct GetExecutionListParams {
688 pub category: Category,
690 #[serde(skip_serializing_if = "Option::is_none")]
692 pub symbol: Option<String>,
693 #[serde(skip_serializing_if = "Option::is_none")]
695 pub order_id: Option<String>,
696 #[serde(skip_serializing_if = "Option::is_none")]
698 pub order_link_id: Option<String>,
699 #[serde(skip_serializing_if = "Option::is_none")]
701 pub base_coin: Option<String>,
702 #[serde(skip_serializing_if = "Option::is_none")]
704 pub start_time: Option<u64>,
705 #[serde(skip_serializing_if = "Option::is_none")]
707 pub end_time: Option<u64>,
708 #[serde(skip_serializing_if = "Option::is_none")]
710 pub exec_type: Option<String>,
711 #[serde(skip_serializing_if = "Option::is_none")]
713 pub limit: Option<u32>,
714 #[serde(skip_serializing_if = "Option::is_none")]
716 pub cursor: Option<String>,
717}
718
719impl GetExecutionListParams {
720 pub fn new(category: Category) -> Self {
722 Self {
723 category,
724 symbol: None,
725 order_id: None,
726 order_link_id: None,
727 base_coin: None,
728 start_time: None,
729 end_time: None,
730 exec_type: None,
731 limit: None,
732 cursor: None,
733 }
734 }
735
736 pub fn symbol(mut self, symbol: impl Into<String>) -> Self {
738 self.symbol = Some(symbol.into());
739 self
740 }
741
742 pub fn order_id(mut self, id: impl Into<String>) -> Self {
744 self.order_id = Some(id.into());
745 self
746 }
747
748 pub fn base_coin(mut self, coin: impl Into<String>) -> Self {
750 self.base_coin = Some(coin.into());
751 self
752 }
753
754 pub fn start_time(mut self, start: u64) -> Self {
756 self.start_time = Some(start);
757 self
758 }
759
760 pub fn end_time(mut self, end: u64) -> Self {
762 self.end_time = Some(end);
763 self
764 }
765
766 pub fn limit(mut self, limit: u32) -> Self {
768 self.limit = Some(limit);
769 self
770 }
771
772 pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
774 self.cursor = Some(cursor.into());
775 self
776 }
777}
778
779#[derive(Debug, Clone, Serialize)]
781#[serde(rename_all = "camelCase")]
782pub struct GetBorrowQuotaParams {
783 pub category: Category,
785 pub symbol: String,
787 pub side: Side,
789}
790
791impl GetBorrowQuotaParams {
792 pub fn new(symbol: impl Into<String>, side: Side) -> Self {
794 Self {
795 category: Category::Spot,
796 symbol: symbol.into(),
797 side,
798 }
799 }
800}
801
802
803#[derive(Debug, Clone, Serialize)]
805#[serde(rename_all = "camelCase")]
806pub struct BatchOrderParams {
807 pub symbol: String,
809 pub side: Side,
811 pub order_type: OrderType,
813 pub qty: String,
815 #[serde(skip_serializing_if = "Option::is_none")]
817 pub is_leverage: Option<i32>,
818 #[serde(skip_serializing_if = "Option::is_none")]
820 pub price: Option<String>,
821 #[serde(skip_serializing_if = "Option::is_none")]
823 pub trigger_direction: Option<i32>,
824 #[serde(skip_serializing_if = "Option::is_none")]
826 pub trigger_by: Option<TriggerBy>,
827 #[serde(skip_serializing_if = "Option::is_none")]
829 pub order_iv: Option<String>,
830 #[serde(skip_serializing_if = "Option::is_none")]
832 pub time_in_force: Option<TimeInForce>,
833 #[serde(skip_serializing_if = "Option::is_none")]
835 pub position_idx: Option<PositionIdx>,
836 #[serde(skip_serializing_if = "Option::is_none")]
838 pub order_link_id: Option<String>,
839 #[serde(skip_serializing_if = "Option::is_none")]
841 pub take_profit: Option<String>,
842 #[serde(skip_serializing_if = "Option::is_none")]
844 pub stop_loss: Option<String>,
845 #[serde(skip_serializing_if = "Option::is_none")]
847 pub tp_trigger_by: Option<TriggerBy>,
848 #[serde(skip_serializing_if = "Option::is_none")]
850 pub sl_trigger_by: Option<TriggerBy>,
851 #[serde(skip_serializing_if = "Option::is_none")]
853 pub reduce_only: Option<bool>,
854 #[serde(skip_serializing_if = "Option::is_none")]
856 pub close_on_trigger: Option<bool>,
857 #[serde(skip_serializing_if = "Option::is_none")]
859 pub smp_type: Option<String>,
860 #[serde(skip_serializing_if = "Option::is_none")]
862 pub mmp: Option<bool>,
863 #[serde(skip_serializing_if = "Option::is_none")]
865 pub tpsl_mode: Option<String>,
866 #[serde(skip_serializing_if = "Option::is_none")]
868 pub tp_limit_price: Option<String>,
869 #[serde(skip_serializing_if = "Option::is_none")]
871 pub sl_limit_price: Option<String>,
872 #[serde(skip_serializing_if = "Option::is_none")]
874 pub tp_order_type: Option<OrderType>,
875 #[serde(skip_serializing_if = "Option::is_none")]
877 pub sl_order_type: Option<OrderType>,
878}
879
880impl BatchOrderParams {
881 pub fn new(
883 symbol: impl Into<String>,
884 side: Side,
885 order_type: OrderType,
886 qty: impl Into<String>,
887 ) -> Self {
888 Self {
889 symbol: symbol.into(),
890 side,
891 order_type,
892 qty: qty.into(),
893 is_leverage: None,
894 price: None,
895 trigger_direction: None,
896 trigger_by: None,
897 order_iv: None,
898 time_in_force: None,
899 position_idx: None,
900 order_link_id: None,
901 take_profit: None,
902 stop_loss: None,
903 tp_trigger_by: None,
904 sl_trigger_by: None,
905 reduce_only: None,
906 close_on_trigger: None,
907 smp_type: None,
908 mmp: None,
909 tpsl_mode: None,
910 tp_limit_price: None,
911 sl_limit_price: None,
912 tp_order_type: None,
913 sl_order_type: None,
914 }
915 }
916
917 pub fn market(symbol: impl Into<String>, side: Side, qty: impl Into<String>) -> Self {
919 Self::new(symbol, side, OrderType::Market, qty)
920 }
921
922 pub fn limit(
924 symbol: impl Into<String>,
925 side: Side,
926 qty: impl Into<String>,
927 price: impl Into<String>,
928 ) -> Self {
929 Self::new(symbol, side, OrderType::Limit, qty).price(price)
930 }
931
932 pub fn price(mut self, price: impl Into<String>) -> Self {
934 self.price = Some(price.into());
935 self
936 }
937
938 pub fn time_in_force(mut self, tif: TimeInForce) -> Self {
940 self.time_in_force = Some(tif);
941 self
942 }
943
944 pub fn order_link_id(mut self, id: impl Into<String>) -> Self {
946 self.order_link_id = Some(id.into());
947 self
948 }
949
950 pub fn reduce_only(mut self, reduce: bool) -> Self {
952 self.reduce_only = Some(reduce);
953 self
954 }
955
956 pub fn position_idx(mut self, idx: PositionIdx) -> Self {
958 self.position_idx = Some(idx);
959 self
960 }
961}
962
963#[derive(Debug, Clone, Serialize)]
965#[serde(rename_all = "camelCase")]
966pub struct BatchAmendOrderParams {
967 pub symbol: String,
969 #[serde(skip_serializing_if = "Option::is_none")]
971 pub order_id: Option<String>,
972 #[serde(skip_serializing_if = "Option::is_none")]
974 pub order_link_id: Option<String>,
975 #[serde(skip_serializing_if = "Option::is_none")]
977 pub order_iv: Option<String>,
978 #[serde(skip_serializing_if = "Option::is_none")]
980 pub trigger_price: Option<String>,
981 #[serde(skip_serializing_if = "Option::is_none")]
983 pub qty: Option<String>,
984 #[serde(skip_serializing_if = "Option::is_none")]
986 pub price: Option<String>,
987 #[serde(skip_serializing_if = "Option::is_none")]
989 pub tpsl_mode: Option<String>,
990 #[serde(skip_serializing_if = "Option::is_none")]
992 pub take_profit: Option<String>,
993 #[serde(skip_serializing_if = "Option::is_none")]
995 pub stop_loss: Option<String>,
996 #[serde(skip_serializing_if = "Option::is_none")]
998 pub tp_trigger_by: Option<TriggerBy>,
999 #[serde(skip_serializing_if = "Option::is_none")]
1001 pub sl_trigger_by: Option<TriggerBy>,
1002 #[serde(skip_serializing_if = "Option::is_none")]
1004 pub trigger_by: Option<TriggerBy>,
1005 #[serde(skip_serializing_if = "Option::is_none")]
1007 pub tp_limit_price: Option<String>,
1008 #[serde(skip_serializing_if = "Option::is_none")]
1010 pub sl_limit_price: Option<String>,
1011}
1012
1013impl BatchAmendOrderParams {
1014 pub fn by_order_id(symbol: impl Into<String>, order_id: impl Into<String>) -> Self {
1016 Self {
1017 symbol: symbol.into(),
1018 order_id: Some(order_id.into()),
1019 order_link_id: None,
1020 order_iv: None,
1021 trigger_price: None,
1022 qty: None,
1023 price: None,
1024 tpsl_mode: None,
1025 take_profit: None,
1026 stop_loss: None,
1027 tp_trigger_by: None,
1028 sl_trigger_by: None,
1029 trigger_by: None,
1030 tp_limit_price: None,
1031 sl_limit_price: None,
1032 }
1033 }
1034
1035 pub fn by_order_link_id(symbol: impl Into<String>, order_link_id: impl Into<String>) -> Self {
1037 Self {
1038 symbol: symbol.into(),
1039 order_id: None,
1040 order_link_id: Some(order_link_id.into()),
1041 order_iv: None,
1042 trigger_price: None,
1043 qty: None,
1044 price: None,
1045 tpsl_mode: None,
1046 take_profit: None,
1047 stop_loss: None,
1048 tp_trigger_by: None,
1049 sl_trigger_by: None,
1050 trigger_by: None,
1051 tp_limit_price: None,
1052 sl_limit_price: None,
1053 }
1054 }
1055
1056 pub fn qty(mut self, qty: impl Into<String>) -> Self {
1058 self.qty = Some(qty.into());
1059 self
1060 }
1061
1062 pub fn price(mut self, price: impl Into<String>) -> Self {
1064 self.price = Some(price.into());
1065 self
1066 }
1067}
1068
1069#[derive(Debug, Clone, Serialize)]
1071#[serde(rename_all = "camelCase")]
1072pub struct BatchCancelOrderParams {
1073 pub symbol: String,
1075 #[serde(skip_serializing_if = "Option::is_none")]
1077 pub order_id: Option<String>,
1078 #[serde(skip_serializing_if = "Option::is_none")]
1080 pub order_link_id: Option<String>,
1081}
1082
1083impl BatchCancelOrderParams {
1084 pub fn by_order_id(symbol: impl Into<String>, order_id: impl Into<String>) -> Self {
1086 Self {
1087 symbol: symbol.into(),
1088 order_id: Some(order_id.into()),
1089 order_link_id: None,
1090 }
1091 }
1092
1093 pub fn by_order_link_id(symbol: impl Into<String>, order_link_id: impl Into<String>) -> Self {
1095 Self {
1096 symbol: symbol.into(),
1097 order_id: None,
1098 order_link_id: Some(order_link_id.into()),
1099 }
1100 }
1101}
1102
1103
1104#[derive(Debug, Clone, Deserialize)]
1106#[serde(rename_all = "camelCase")]
1107pub struct OrderResult {
1108 pub order_id: String,
1110 pub order_link_id: String,
1112}
1113
1114#[derive(Debug, Clone, Deserialize)]
1116#[serde(rename_all = "camelCase")]
1117pub struct OrderInfo {
1118 pub order_id: String,
1120 pub order_link_id: String,
1122 #[serde(default)]
1124 pub block_trade_id: Option<String>,
1125 pub symbol: String,
1127 pub price: String,
1129 pub qty: String,
1131 pub side: Side,
1133 #[serde(default)]
1135 pub is_leverage: Option<String>,
1136 #[serde(default)]
1138 pub position_idx: Option<i32>,
1139 pub order_status: OrderStatus,
1141 #[serde(default)]
1143 pub create_type: Option<String>,
1144 #[serde(default)]
1146 pub cancel_type: Option<String>,
1147 #[serde(default)]
1149 pub reject_reason: Option<String>,
1150 #[serde(default)]
1152 pub avg_price: Option<String>,
1153 #[serde(default)]
1155 pub leaves_qty: Option<String>,
1156 #[serde(default)]
1158 pub leaves_value: Option<String>,
1159 pub cum_exec_qty: String,
1161 pub cum_exec_value: String,
1163 pub cum_exec_fee: String,
1165 #[serde(default)]
1167 pub time_in_force: Option<TimeInForce>,
1168 pub order_type: OrderType,
1170 #[serde(default)]
1172 pub stop_order_type: Option<String>,
1173 #[serde(default)]
1175 pub order_iv: Option<String>,
1176 #[serde(default)]
1178 pub market_unit: Option<String>,
1179 #[serde(default)]
1181 pub trigger_price: Option<String>,
1182 #[serde(default)]
1184 pub take_profit: Option<String>,
1185 #[serde(default)]
1187 pub stop_loss: Option<String>,
1188 #[serde(default)]
1190 pub tpsl_mode: Option<String>,
1191 #[serde(default)]
1193 pub tp_limit_price: Option<String>,
1194 #[serde(default)]
1196 pub sl_limit_price: Option<String>,
1197 #[serde(default)]
1199 pub tp_trigger_by: Option<String>,
1200 #[serde(default)]
1202 pub sl_trigger_by: Option<String>,
1203 #[serde(default)]
1205 pub trigger_direction: Option<i32>,
1206 #[serde(default)]
1208 pub trigger_by: Option<String>,
1209 #[serde(default)]
1211 pub last_price_on_created: Option<String>,
1212 #[serde(default)]
1214 pub reduce_only: Option<bool>,
1215 #[serde(default)]
1217 pub close_on_trigger: Option<bool>,
1218 #[serde(default)]
1220 pub smp_type: Option<String>,
1221 #[serde(default)]
1223 pub smp_group: Option<i32>,
1224 #[serde(default)]
1226 pub smp_order_id: Option<String>,
1227 pub created_time: String,
1229 pub updated_time: String,
1231}
1232
1233#[derive(Debug, Clone, Deserialize)]
1235#[serde(rename_all = "camelCase")]
1236pub struct OrderListResult {
1237 pub category: Category,
1239 pub list: Vec<OrderInfo>,
1241 #[serde(default)]
1243 pub next_page_cursor: Option<String>,
1244}
1245
1246#[derive(Debug, Clone, Deserialize)]
1248#[serde(rename_all = "camelCase")]
1249pub struct Execution {
1250 pub symbol: String,
1252 pub order_id: String,
1254 pub order_link_id: String,
1256 pub side: Side,
1258 pub order_price: String,
1260 pub order_qty: String,
1262 pub leaves_qty: String,
1264 pub order_type: OrderType,
1266 #[serde(default)]
1268 pub stop_order_type: Option<String>,
1269 pub exec_fee: String,
1271 pub exec_id: String,
1273 pub exec_price: String,
1275 pub exec_qty: String,
1277 pub exec_type: String,
1279 pub exec_value: String,
1281 pub exec_time: String,
1283 pub is_maker: bool,
1285 #[serde(default)]
1287 pub fee_rate: Option<String>,
1288 #[serde(default)]
1290 pub trade_iv: Option<String>,
1291 #[serde(default)]
1293 pub mark_iv: Option<String>,
1294 #[serde(default)]
1296 pub mark_price: Option<String>,
1297 #[serde(default)]
1299 pub index_price: Option<String>,
1300 #[serde(default)]
1302 pub underlying_price: Option<String>,
1303 #[serde(default)]
1305 pub block_trade_id: Option<String>,
1306 #[serde(default)]
1308 pub closed_size: Option<String>,
1309 #[serde(default)]
1311 pub seq: Option<i64>,
1312}
1313
1314#[derive(Debug, Clone, Deserialize)]
1316#[serde(rename_all = "camelCase")]
1317pub struct ExecutionListResult {
1318 pub category: Category,
1320 pub list: Vec<Execution>,
1322 #[serde(default)]
1324 pub next_page_cursor: Option<String>,
1325}
1326
1327#[derive(Debug, Clone, Deserialize)]
1329#[serde(rename_all = "camelCase")]
1330pub struct BorrowQuotaResult {
1331 pub symbol: String,
1333 pub side: Side,
1335 pub max_trade_qty: String,
1337 pub max_trade_amount: String,
1339 #[serde(default)]
1341 pub spot_max_trade_qty: Option<String>,
1342 #[serde(default)]
1344 pub spot_max_trade_amount: Option<String>,
1345 #[serde(default)]
1347 pub borrow_coin: Option<String>,
1348}
1349
1350#[derive(Debug, Clone, Deserialize)]
1352#[serde(rename_all = "camelCase")]
1353pub struct BatchOrderResult {
1354 pub category: Category,
1356 pub symbol: String,
1358 pub order_id: String,
1360 pub order_link_id: String,
1362 #[serde(default)]
1364 pub create_at: Option<String>,
1365}
1366
1367#[derive(Debug, Clone, Deserialize)]
1369#[serde(rename_all = "camelCase")]
1370pub struct BatchOperationResult {
1371 pub list: Vec<BatchOrderResult>,
1373 #[serde(default)]
1375 pub ret_ext_info: Option<BatchRetExtInfo>,
1376}
1377
1378#[derive(Debug, Clone, Deserialize)]
1380#[serde(rename_all = "camelCase")]
1381pub struct BatchRetExtInfo {
1382 pub list: Vec<BatchErrorInfo>,
1384}
1385
1386#[derive(Debug, Clone, Deserialize)]
1388#[serde(rename_all = "camelCase")]
1389pub struct BatchErrorInfo {
1390 pub code: i32,
1392 pub msg: String,
1394}
1395
1396#[derive(Debug, Clone, Deserialize)]
1398#[serde(rename_all = "camelCase")]
1399pub struct CancelAllResult {
1400 pub list: Vec<OrderResult>,
1402 #[serde(default)]
1404 pub success: Option<String>,
1405}
1406
1407#[cfg(test)]
1408mod tests {
1409 use super::*;
1410
1411 #[test]
1412 fn test_order_params_market() {
1413 let params = OrderParams::market(Category::Linear, "BTCUSDT", Side::Buy, "0.001");
1414 assert_eq!(params.category, Category::Linear);
1415 assert_eq!(params.symbol, "BTCUSDT");
1416 assert_eq!(params.side, Side::Buy);
1417 assert_eq!(params.order_type, OrderType::Market);
1418 assert_eq!(params.qty, "0.001");
1419 }
1420
1421 #[test]
1422 fn test_order_params_limit() {
1423 let params = OrderParams::limit(Category::Spot, "BTCUSDT", Side::Sell, "0.5", "50000")
1424 .time_in_force(TimeInForce::GTC)
1425 .order_link_id("my_order_123");
1426
1427 assert_eq!(params.order_type, OrderType::Limit);
1428 assert_eq!(params.price, Some("50000".to_string()));
1429 assert_eq!(params.time_in_force, Some(TimeInForce::GTC));
1430 assert_eq!(params.order_link_id, Some("my_order_123".to_string()));
1431 }
1432
1433 #[test]
1434 fn test_amend_order_params() {
1435 let params = AmendOrderParams::by_order_id(Category::Linear, "BTCUSDT", "order123")
1436 .price("51000")
1437 .qty("0.002");
1438
1439 assert_eq!(params.order_id, Some("order123".to_string()));
1440 assert_eq!(params.price, Some("51000".to_string()));
1441 assert_eq!(params.qty, Some("0.002".to_string()));
1442 }
1443
1444 #[test]
1445 fn test_cancel_order_params() {
1446 let params =
1447 CancelOrderParams::by_order_link_id(Category::Spot, "ETHUSDT", "my_order_456");
1448
1449 assert_eq!(params.order_link_id, Some("my_order_456".to_string()));
1450 assert!(params.order_id.is_none());
1451 }
1452
1453 #[test]
1454 fn test_batch_order_params() {
1455 let order1 = BatchOrderParams::limit("BTCUSDT", Side::Buy, "0.001", "50000")
1456 .order_link_id("batch_1");
1457 let order2 = BatchOrderParams::market("ETHUSDT", Side::Sell, "0.1")
1458 .reduce_only(true);
1459
1460 assert_eq!(order1.price, Some("50000".to_string()));
1461 assert_eq!(order2.reduce_only, Some(true));
1462 }
1463}