1#![allow(unused_imports)]
15use async_trait::async_trait;
16use derive_builder::Builder;
17use reqwest;
18use rust_decimal::prelude::*;
19use serde::{Deserialize, Serialize};
20use serde_json::{Value, json};
21use std::collections::BTreeMap;
22
23use crate::common::{
24 config::ConfigurationRestApi,
25 models::{ParamBuildError, RestApiResponse},
26 utils::send_request,
27};
28use crate::spot::rest_api::models;
29
30const HAS_TIME_UNIT: bool = true;
31
32#[async_trait]
33pub trait AccountApi: Send + Sync {
34 async fn account_commission(
35 &self,
36 params: AccountCommissionParams,
37 ) -> anyhow::Result<RestApiResponse<models::AccountCommissionResponse>>;
38 async fn all_order_list(
39 &self,
40 params: AllOrderListParams,
41 ) -> anyhow::Result<RestApiResponse<Vec<models::AllOrderListResponseInner>>>;
42 async fn all_orders(
43 &self,
44 params: AllOrdersParams,
45 ) -> anyhow::Result<RestApiResponse<Vec<models::AllOrdersResponseInner>>>;
46 async fn get_account(
47 &self,
48 params: GetAccountParams,
49 ) -> anyhow::Result<RestApiResponse<models::GetAccountResponse>>;
50 async fn get_open_orders(
51 &self,
52 params: GetOpenOrdersParams,
53 ) -> anyhow::Result<RestApiResponse<Vec<models::GetOpenOrdersResponseInner>>>;
54 async fn get_order(
55 &self,
56 params: GetOrderParams,
57 ) -> anyhow::Result<RestApiResponse<models::GetOrderResponse>>;
58 async fn get_order_list(
59 &self,
60 params: GetOrderListParams,
61 ) -> anyhow::Result<RestApiResponse<models::GetOrderListResponse>>;
62 async fn my_allocations(
63 &self,
64 params: MyAllocationsParams,
65 ) -> anyhow::Result<RestApiResponse<Vec<models::MyAllocationsResponseInner>>>;
66 async fn my_filters(
67 &self,
68 params: MyFiltersParams,
69 ) -> anyhow::Result<RestApiResponse<models::MyFiltersResponse>>;
70 async fn my_prevented_matches(
71 &self,
72 params: MyPreventedMatchesParams,
73 ) -> anyhow::Result<RestApiResponse<Vec<models::MyPreventedMatchesResponseInner>>>;
74 async fn my_trades(
75 &self,
76 params: MyTradesParams,
77 ) -> anyhow::Result<RestApiResponse<Vec<models::MyTradesResponseInner>>>;
78 async fn open_order_list(
79 &self,
80 params: OpenOrderListParams,
81 ) -> anyhow::Result<RestApiResponse<Vec<models::OpenOrderListResponseInner>>>;
82 async fn order_amendments(
83 &self,
84 params: OrderAmendmentsParams,
85 ) -> anyhow::Result<RestApiResponse<Vec<models::OrderAmendmentsResponseInner>>>;
86 async fn rate_limit_order(
87 &self,
88 params: RateLimitOrderParams,
89 ) -> anyhow::Result<RestApiResponse<Vec<models::RateLimitOrderResponseInner>>>;
90}
91
92#[derive(Debug, Clone)]
93pub struct AccountApiClient {
94 configuration: ConfigurationRestApi,
95}
96
97impl AccountApiClient {
98 pub fn new(configuration: ConfigurationRestApi) -> Self {
99 Self { configuration }
100 }
101}
102
103#[derive(Clone, Debug, Builder, Deserialize)]
108#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
109pub struct AccountCommissionParams {
110 #[builder(setter(into))]
115 #[serde(rename = "symbol")]
116 pub symbol: String,
117}
118
119impl AccountCommissionParams {
120 #[must_use]
127 pub fn builder(symbol: String) -> AccountCommissionParamsBuilder {
128 AccountCommissionParamsBuilder::default().symbol(symbol)
129 }
130}
131#[derive(Clone, Debug, Builder, Deserialize, Default)]
136#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
137pub struct AllOrderListParams {
138 #[builder(setter(into), default)]
142 #[serde(rename = "fromId", default)]
143 pub from_id: Option<i64>,
144 #[builder(setter(into), default)]
149 #[serde(rename = "startTime", default)]
150 pub start_time: Option<i64>,
151 #[builder(setter(into), default)]
156 #[serde(rename = "endTime", default)]
157 pub end_time: Option<i64>,
158 #[builder(setter(into), default)]
163 #[serde(rename = "limit", default)]
164 pub limit: Option<i32>,
165 #[builder(setter(into), default)]
169 #[serde(rename = "recvWindow", default)]
170 pub recv_window: Option<rust_decimal::Decimal>,
171}
172
173impl AllOrderListParams {
174 #[must_use]
177 pub fn builder() -> AllOrderListParamsBuilder {
178 AllOrderListParamsBuilder::default()
179 }
180}
181#[derive(Clone, Debug, Builder, Deserialize)]
186#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
187pub struct AllOrdersParams {
188 #[builder(setter(into))]
193 #[serde(rename = "symbol")]
194 pub symbol: String,
195 #[builder(setter(into), default)]
200 #[serde(rename = "orderId", default)]
201 pub order_id: Option<i64>,
202 #[builder(setter(into), default)]
207 #[serde(rename = "startTime", default)]
208 pub start_time: Option<i64>,
209 #[builder(setter(into), default)]
214 #[serde(rename = "endTime", default)]
215 pub end_time: Option<i64>,
216 #[builder(setter(into), default)]
221 #[serde(rename = "limit", default)]
222 pub limit: Option<i32>,
223 #[builder(setter(into), default)]
227 #[serde(rename = "recvWindow", default)]
228 pub recv_window: Option<rust_decimal::Decimal>,
229}
230
231impl AllOrdersParams {
232 #[must_use]
239 pub fn builder(symbol: String) -> AllOrdersParamsBuilder {
240 AllOrdersParamsBuilder::default().symbol(symbol)
241 }
242}
243#[derive(Clone, Debug, Builder, Deserialize, Default)]
248#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
249pub struct GetAccountParams {
250 #[builder(setter(into), default)]
254 #[serde(rename = "omitZeroBalances", default)]
255 pub omit_zero_balances: Option<bool>,
256 #[builder(setter(into), default)]
260 #[serde(rename = "recvWindow", default)]
261 pub recv_window: Option<rust_decimal::Decimal>,
262}
263
264impl GetAccountParams {
265 #[must_use]
268 pub fn builder() -> GetAccountParamsBuilder {
269 GetAccountParamsBuilder::default()
270 }
271}
272#[derive(Clone, Debug, Builder, Deserialize, Default)]
277#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
278pub struct GetOpenOrdersParams {
279 #[builder(setter(into), default)]
284 #[serde(rename = "symbol", default)]
285 pub symbol: Option<String>,
286 #[builder(setter(into), default)]
290 #[serde(rename = "recvWindow", default)]
291 pub recv_window: Option<rust_decimal::Decimal>,
292}
293
294impl GetOpenOrdersParams {
295 #[must_use]
298 pub fn builder() -> GetOpenOrdersParamsBuilder {
299 GetOpenOrdersParamsBuilder::default()
300 }
301}
302#[derive(Clone, Debug, Builder, Deserialize)]
307#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
308pub struct GetOrderParams {
309 #[builder(setter(into))]
314 #[serde(rename = "symbol")]
315 pub symbol: String,
316 #[builder(setter(into), default)]
321 #[serde(rename = "orderId", default)]
322 pub order_id: Option<i64>,
323 #[builder(setter(into), default)]
328 #[serde(rename = "origClientOrderId", default)]
329 pub orig_client_order_id: Option<String>,
330 #[builder(setter(into), default)]
334 #[serde(rename = "recvWindow", default)]
335 pub recv_window: Option<rust_decimal::Decimal>,
336}
337
338impl GetOrderParams {
339 #[must_use]
346 pub fn builder(symbol: String) -> GetOrderParamsBuilder {
347 GetOrderParamsBuilder::default().symbol(symbol)
348 }
349}
350#[derive(Clone, Debug, Builder, Deserialize, Default)]
355#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
356pub struct GetOrderListParams {
357 #[builder(setter(into), default)]
361 #[serde(rename = "orderListId", default)]
362 pub order_list_id: Option<i64>,
363 #[builder(setter(into), default)]
367 #[serde(rename = "origClientOrderId", default)]
368 pub orig_client_order_id: Option<String>,
369 #[builder(setter(into), default)]
373 #[serde(rename = "recvWindow", default)]
374 pub recv_window: Option<rust_decimal::Decimal>,
375}
376
377impl GetOrderListParams {
378 #[must_use]
381 pub fn builder() -> GetOrderListParamsBuilder {
382 GetOrderListParamsBuilder::default()
383 }
384}
385#[derive(Clone, Debug, Builder, Deserialize)]
390#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
391pub struct MyAllocationsParams {
392 #[builder(setter(into))]
397 #[serde(rename = "symbol")]
398 pub symbol: String,
399 #[builder(setter(into), default)]
404 #[serde(rename = "startTime", default)]
405 pub start_time: Option<i64>,
406 #[builder(setter(into), default)]
411 #[serde(rename = "endTime", default)]
412 pub end_time: Option<i64>,
413 #[builder(setter(into), default)]
418 #[serde(rename = "fromAllocationId", default)]
419 pub from_allocation_id: Option<i32>,
420 #[builder(setter(into), default)]
425 #[serde(rename = "limit", default)]
426 pub limit: Option<i32>,
427 #[builder(setter(into), default)]
432 #[serde(rename = "orderId", default)]
433 pub order_id: Option<i64>,
434 #[builder(setter(into), default)]
438 #[serde(rename = "recvWindow", default)]
439 pub recv_window: Option<rust_decimal::Decimal>,
440}
441
442impl MyAllocationsParams {
443 #[must_use]
450 pub fn builder(symbol: String) -> MyAllocationsParamsBuilder {
451 MyAllocationsParamsBuilder::default().symbol(symbol)
452 }
453}
454#[derive(Clone, Debug, Builder, Deserialize)]
459#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
460pub struct MyFiltersParams {
461 #[builder(setter(into))]
466 #[serde(rename = "symbol")]
467 pub symbol: String,
468 #[builder(setter(into), default)]
472 #[serde(rename = "recvWindow", default)]
473 pub recv_window: Option<rust_decimal::Decimal>,
474}
475
476impl MyFiltersParams {
477 #[must_use]
484 pub fn builder(symbol: String) -> MyFiltersParamsBuilder {
485 MyFiltersParamsBuilder::default().symbol(symbol)
486 }
487}
488#[derive(Clone, Debug, Builder, Deserialize)]
493#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
494pub struct MyPreventedMatchesParams {
495 #[builder(setter(into))]
500 #[serde(rename = "symbol")]
501 pub symbol: String,
502 #[builder(setter(into), default)]
507 #[serde(rename = "preventedMatchId", default)]
508 pub prevented_match_id: Option<i64>,
509 #[builder(setter(into), default)]
514 #[serde(rename = "orderId", default)]
515 pub order_id: Option<i64>,
516 #[builder(setter(into), default)]
521 #[serde(rename = "fromPreventedMatchId", default)]
522 pub from_prevented_match_id: Option<i64>,
523 #[builder(setter(into), default)]
528 #[serde(rename = "limit", default)]
529 pub limit: Option<i32>,
530 #[builder(setter(into), default)]
534 #[serde(rename = "recvWindow", default)]
535 pub recv_window: Option<rust_decimal::Decimal>,
536}
537
538impl MyPreventedMatchesParams {
539 #[must_use]
546 pub fn builder(symbol: String) -> MyPreventedMatchesParamsBuilder {
547 MyPreventedMatchesParamsBuilder::default().symbol(symbol)
548 }
549}
550#[derive(Clone, Debug, Builder, Deserialize)]
555#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
556pub struct MyTradesParams {
557 #[builder(setter(into))]
562 #[serde(rename = "symbol")]
563 pub symbol: String,
564 #[builder(setter(into), default)]
568 #[serde(rename = "orderId", default)]
569 pub order_id: Option<i64>,
570 #[builder(setter(into), default)]
575 #[serde(rename = "startTime", default)]
576 pub start_time: Option<i64>,
577 #[builder(setter(into), default)]
582 #[serde(rename = "endTime", default)]
583 pub end_time: Option<i64>,
584 #[builder(setter(into), default)]
588 #[serde(rename = "fromId", default)]
589 pub from_id: Option<i64>,
590 #[builder(setter(into), default)]
595 #[serde(rename = "limit", default)]
596 pub limit: Option<i32>,
597 #[builder(setter(into), default)]
601 #[serde(rename = "recvWindow", default)]
602 pub recv_window: Option<rust_decimal::Decimal>,
603}
604
605impl MyTradesParams {
606 #[must_use]
613 pub fn builder(symbol: String) -> MyTradesParamsBuilder {
614 MyTradesParamsBuilder::default().symbol(symbol)
615 }
616}
617#[derive(Clone, Debug, Builder, Deserialize, Default)]
622#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
623pub struct OpenOrderListParams {
624 #[builder(setter(into), default)]
628 #[serde(rename = "recvWindow", default)]
629 pub recv_window: Option<rust_decimal::Decimal>,
630}
631
632impl OpenOrderListParams {
633 #[must_use]
636 pub fn builder() -> OpenOrderListParamsBuilder {
637 OpenOrderListParamsBuilder::default()
638 }
639}
640#[derive(Clone, Debug, Builder, Deserialize)]
645#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
646pub struct OrderAmendmentsParams {
647 #[builder(setter(into))]
652 #[serde(rename = "symbol")]
653 pub symbol: String,
654 #[builder(setter(into))]
659 #[serde(rename = "orderId")]
660 pub order_id: i64,
661 #[builder(setter(into), default)]
666 #[serde(rename = "fromExecutionId", default)]
667 pub from_execution_id: Option<i64>,
668 #[builder(setter(into), default)]
673 #[serde(rename = "limit", default)]
674 pub limit: Option<i64>,
675 #[builder(setter(into), default)]
679 #[serde(rename = "recvWindow", default)]
680 pub recv_window: Option<rust_decimal::Decimal>,
681}
682
683impl OrderAmendmentsParams {
684 #[must_use]
692 pub fn builder(symbol: String, order_id: i64) -> OrderAmendmentsParamsBuilder {
693 OrderAmendmentsParamsBuilder::default()
694 .symbol(symbol)
695 .order_id(order_id)
696 }
697}
698#[derive(Clone, Debug, Builder, Deserialize, Default)]
703#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
704pub struct RateLimitOrderParams {
705 #[builder(setter(into), default)]
709 #[serde(rename = "recvWindow", default)]
710 pub recv_window: Option<rust_decimal::Decimal>,
711}
712
713impl RateLimitOrderParams {
714 #[must_use]
717 pub fn builder() -> RateLimitOrderParamsBuilder {
718 RateLimitOrderParamsBuilder::default()
719 }
720}
721
722#[async_trait]
723impl AccountApi for AccountApiClient {
724 async fn account_commission(
725 &self,
726 params: AccountCommissionParams,
727 ) -> anyhow::Result<RestApiResponse<models::AccountCommissionResponse>> {
728 let AccountCommissionParams { symbol } = params;
729
730 let mut query_params = BTreeMap::new();
731 let body_params = BTreeMap::new();
732
733 query_params.insert("symbol".to_string(), json!(symbol));
734
735 send_request::<models::AccountCommissionResponse>(
736 &self.configuration,
737 "/api/v3/account/commission",
738 reqwest::Method::GET,
739 query_params,
740 body_params,
741 if HAS_TIME_UNIT {
742 self.configuration.time_unit
743 } else {
744 None
745 },
746 true,
747 )
748 .await
749 }
750
751 async fn all_order_list(
752 &self,
753 params: AllOrderListParams,
754 ) -> anyhow::Result<RestApiResponse<Vec<models::AllOrderListResponseInner>>> {
755 let AllOrderListParams {
756 from_id,
757 start_time,
758 end_time,
759 limit,
760 recv_window,
761 } = params;
762
763 let mut query_params = BTreeMap::new();
764 let body_params = BTreeMap::new();
765
766 if let Some(rw) = from_id {
767 query_params.insert("fromId".to_string(), json!(rw));
768 }
769
770 if let Some(rw) = start_time {
771 query_params.insert("startTime".to_string(), json!(rw));
772 }
773
774 if let Some(rw) = end_time {
775 query_params.insert("endTime".to_string(), json!(rw));
776 }
777
778 if let Some(rw) = limit {
779 query_params.insert("limit".to_string(), json!(rw));
780 }
781
782 if let Some(rw) = recv_window {
783 query_params.insert("recvWindow".to_string(), json!(rw));
784 }
785
786 send_request::<Vec<models::AllOrderListResponseInner>>(
787 &self.configuration,
788 "/api/v3/allOrderList",
789 reqwest::Method::GET,
790 query_params,
791 body_params,
792 if HAS_TIME_UNIT {
793 self.configuration.time_unit
794 } else {
795 None
796 },
797 true,
798 )
799 .await
800 }
801
802 async fn all_orders(
803 &self,
804 params: AllOrdersParams,
805 ) -> anyhow::Result<RestApiResponse<Vec<models::AllOrdersResponseInner>>> {
806 let AllOrdersParams {
807 symbol,
808 order_id,
809 start_time,
810 end_time,
811 limit,
812 recv_window,
813 } = params;
814
815 let mut query_params = BTreeMap::new();
816 let body_params = BTreeMap::new();
817
818 query_params.insert("symbol".to_string(), json!(symbol));
819
820 if let Some(rw) = order_id {
821 query_params.insert("orderId".to_string(), json!(rw));
822 }
823
824 if let Some(rw) = start_time {
825 query_params.insert("startTime".to_string(), json!(rw));
826 }
827
828 if let Some(rw) = end_time {
829 query_params.insert("endTime".to_string(), json!(rw));
830 }
831
832 if let Some(rw) = limit {
833 query_params.insert("limit".to_string(), json!(rw));
834 }
835
836 if let Some(rw) = recv_window {
837 query_params.insert("recvWindow".to_string(), json!(rw));
838 }
839
840 send_request::<Vec<models::AllOrdersResponseInner>>(
841 &self.configuration,
842 "/api/v3/allOrders",
843 reqwest::Method::GET,
844 query_params,
845 body_params,
846 if HAS_TIME_UNIT {
847 self.configuration.time_unit
848 } else {
849 None
850 },
851 true,
852 )
853 .await
854 }
855
856 async fn get_account(
857 &self,
858 params: GetAccountParams,
859 ) -> anyhow::Result<RestApiResponse<models::GetAccountResponse>> {
860 let GetAccountParams {
861 omit_zero_balances,
862 recv_window,
863 } = params;
864
865 let mut query_params = BTreeMap::new();
866 let body_params = BTreeMap::new();
867
868 if let Some(rw) = omit_zero_balances {
869 query_params.insert("omitZeroBalances".to_string(), json!(rw));
870 }
871
872 if let Some(rw) = recv_window {
873 query_params.insert("recvWindow".to_string(), json!(rw));
874 }
875
876 send_request::<models::GetAccountResponse>(
877 &self.configuration,
878 "/api/v3/account",
879 reqwest::Method::GET,
880 query_params,
881 body_params,
882 if HAS_TIME_UNIT {
883 self.configuration.time_unit
884 } else {
885 None
886 },
887 true,
888 )
889 .await
890 }
891
892 async fn get_open_orders(
893 &self,
894 params: GetOpenOrdersParams,
895 ) -> anyhow::Result<RestApiResponse<Vec<models::GetOpenOrdersResponseInner>>> {
896 let GetOpenOrdersParams {
897 symbol,
898 recv_window,
899 } = params;
900
901 let mut query_params = BTreeMap::new();
902 let body_params = BTreeMap::new();
903
904 if let Some(rw) = symbol {
905 query_params.insert("symbol".to_string(), json!(rw));
906 }
907
908 if let Some(rw) = recv_window {
909 query_params.insert("recvWindow".to_string(), json!(rw));
910 }
911
912 send_request::<Vec<models::GetOpenOrdersResponseInner>>(
913 &self.configuration,
914 "/api/v3/openOrders",
915 reqwest::Method::GET,
916 query_params,
917 body_params,
918 if HAS_TIME_UNIT {
919 self.configuration.time_unit
920 } else {
921 None
922 },
923 true,
924 )
925 .await
926 }
927
928 async fn get_order(
929 &self,
930 params: GetOrderParams,
931 ) -> anyhow::Result<RestApiResponse<models::GetOrderResponse>> {
932 let GetOrderParams {
933 symbol,
934 order_id,
935 orig_client_order_id,
936 recv_window,
937 } = params;
938
939 let mut query_params = BTreeMap::new();
940 let body_params = BTreeMap::new();
941
942 query_params.insert("symbol".to_string(), json!(symbol));
943
944 if let Some(rw) = order_id {
945 query_params.insert("orderId".to_string(), json!(rw));
946 }
947
948 if let Some(rw) = orig_client_order_id {
949 query_params.insert("origClientOrderId".to_string(), json!(rw));
950 }
951
952 if let Some(rw) = recv_window {
953 query_params.insert("recvWindow".to_string(), json!(rw));
954 }
955
956 send_request::<models::GetOrderResponse>(
957 &self.configuration,
958 "/api/v3/order",
959 reqwest::Method::GET,
960 query_params,
961 body_params,
962 if HAS_TIME_UNIT {
963 self.configuration.time_unit
964 } else {
965 None
966 },
967 true,
968 )
969 .await
970 }
971
972 async fn get_order_list(
973 &self,
974 params: GetOrderListParams,
975 ) -> anyhow::Result<RestApiResponse<models::GetOrderListResponse>> {
976 let GetOrderListParams {
977 order_list_id,
978 orig_client_order_id,
979 recv_window,
980 } = params;
981
982 let mut query_params = BTreeMap::new();
983 let body_params = BTreeMap::new();
984
985 if let Some(rw) = order_list_id {
986 query_params.insert("orderListId".to_string(), json!(rw));
987 }
988
989 if let Some(rw) = orig_client_order_id {
990 query_params.insert("origClientOrderId".to_string(), json!(rw));
991 }
992
993 if let Some(rw) = recv_window {
994 query_params.insert("recvWindow".to_string(), json!(rw));
995 }
996
997 send_request::<models::GetOrderListResponse>(
998 &self.configuration,
999 "/api/v3/orderList",
1000 reqwest::Method::GET,
1001 query_params,
1002 body_params,
1003 if HAS_TIME_UNIT {
1004 self.configuration.time_unit
1005 } else {
1006 None
1007 },
1008 true,
1009 )
1010 .await
1011 }
1012
1013 async fn my_allocations(
1014 &self,
1015 params: MyAllocationsParams,
1016 ) -> anyhow::Result<RestApiResponse<Vec<models::MyAllocationsResponseInner>>> {
1017 let MyAllocationsParams {
1018 symbol,
1019 start_time,
1020 end_time,
1021 from_allocation_id,
1022 limit,
1023 order_id,
1024 recv_window,
1025 } = params;
1026
1027 let mut query_params = BTreeMap::new();
1028 let body_params = BTreeMap::new();
1029
1030 query_params.insert("symbol".to_string(), json!(symbol));
1031
1032 if let Some(rw) = start_time {
1033 query_params.insert("startTime".to_string(), json!(rw));
1034 }
1035
1036 if let Some(rw) = end_time {
1037 query_params.insert("endTime".to_string(), json!(rw));
1038 }
1039
1040 if let Some(rw) = from_allocation_id {
1041 query_params.insert("fromAllocationId".to_string(), json!(rw));
1042 }
1043
1044 if let Some(rw) = limit {
1045 query_params.insert("limit".to_string(), json!(rw));
1046 }
1047
1048 if let Some(rw) = order_id {
1049 query_params.insert("orderId".to_string(), json!(rw));
1050 }
1051
1052 if let Some(rw) = recv_window {
1053 query_params.insert("recvWindow".to_string(), json!(rw));
1054 }
1055
1056 send_request::<Vec<models::MyAllocationsResponseInner>>(
1057 &self.configuration,
1058 "/api/v3/myAllocations",
1059 reqwest::Method::GET,
1060 query_params,
1061 body_params,
1062 if HAS_TIME_UNIT {
1063 self.configuration.time_unit
1064 } else {
1065 None
1066 },
1067 true,
1068 )
1069 .await
1070 }
1071
1072 async fn my_filters(
1073 &self,
1074 params: MyFiltersParams,
1075 ) -> anyhow::Result<RestApiResponse<models::MyFiltersResponse>> {
1076 let MyFiltersParams {
1077 symbol,
1078 recv_window,
1079 } = params;
1080
1081 let mut query_params = BTreeMap::new();
1082 let body_params = BTreeMap::new();
1083
1084 query_params.insert("symbol".to_string(), json!(symbol));
1085
1086 if let Some(rw) = recv_window {
1087 query_params.insert("recvWindow".to_string(), json!(rw));
1088 }
1089
1090 send_request::<models::MyFiltersResponse>(
1091 &self.configuration,
1092 "/api/v3/myFilters",
1093 reqwest::Method::GET,
1094 query_params,
1095 body_params,
1096 if HAS_TIME_UNIT {
1097 self.configuration.time_unit
1098 } else {
1099 None
1100 },
1101 true,
1102 )
1103 .await
1104 }
1105
1106 async fn my_prevented_matches(
1107 &self,
1108 params: MyPreventedMatchesParams,
1109 ) -> anyhow::Result<RestApiResponse<Vec<models::MyPreventedMatchesResponseInner>>> {
1110 let MyPreventedMatchesParams {
1111 symbol,
1112 prevented_match_id,
1113 order_id,
1114 from_prevented_match_id,
1115 limit,
1116 recv_window,
1117 } = params;
1118
1119 let mut query_params = BTreeMap::new();
1120 let body_params = BTreeMap::new();
1121
1122 query_params.insert("symbol".to_string(), json!(symbol));
1123
1124 if let Some(rw) = prevented_match_id {
1125 query_params.insert("preventedMatchId".to_string(), json!(rw));
1126 }
1127
1128 if let Some(rw) = order_id {
1129 query_params.insert("orderId".to_string(), json!(rw));
1130 }
1131
1132 if let Some(rw) = from_prevented_match_id {
1133 query_params.insert("fromPreventedMatchId".to_string(), json!(rw));
1134 }
1135
1136 if let Some(rw) = limit {
1137 query_params.insert("limit".to_string(), json!(rw));
1138 }
1139
1140 if let Some(rw) = recv_window {
1141 query_params.insert("recvWindow".to_string(), json!(rw));
1142 }
1143
1144 send_request::<Vec<models::MyPreventedMatchesResponseInner>>(
1145 &self.configuration,
1146 "/api/v3/myPreventedMatches",
1147 reqwest::Method::GET,
1148 query_params,
1149 body_params,
1150 if HAS_TIME_UNIT {
1151 self.configuration.time_unit
1152 } else {
1153 None
1154 },
1155 true,
1156 )
1157 .await
1158 }
1159
1160 async fn my_trades(
1161 &self,
1162 params: MyTradesParams,
1163 ) -> anyhow::Result<RestApiResponse<Vec<models::MyTradesResponseInner>>> {
1164 let MyTradesParams {
1165 symbol,
1166 order_id,
1167 start_time,
1168 end_time,
1169 from_id,
1170 limit,
1171 recv_window,
1172 } = params;
1173
1174 let mut query_params = BTreeMap::new();
1175 let body_params = BTreeMap::new();
1176
1177 query_params.insert("symbol".to_string(), json!(symbol));
1178
1179 if let Some(rw) = order_id {
1180 query_params.insert("orderId".to_string(), json!(rw));
1181 }
1182
1183 if let Some(rw) = start_time {
1184 query_params.insert("startTime".to_string(), json!(rw));
1185 }
1186
1187 if let Some(rw) = end_time {
1188 query_params.insert("endTime".to_string(), json!(rw));
1189 }
1190
1191 if let Some(rw) = from_id {
1192 query_params.insert("fromId".to_string(), json!(rw));
1193 }
1194
1195 if let Some(rw) = limit {
1196 query_params.insert("limit".to_string(), json!(rw));
1197 }
1198
1199 if let Some(rw) = recv_window {
1200 query_params.insert("recvWindow".to_string(), json!(rw));
1201 }
1202
1203 send_request::<Vec<models::MyTradesResponseInner>>(
1204 &self.configuration,
1205 "/api/v3/myTrades",
1206 reqwest::Method::GET,
1207 query_params,
1208 body_params,
1209 if HAS_TIME_UNIT {
1210 self.configuration.time_unit
1211 } else {
1212 None
1213 },
1214 true,
1215 )
1216 .await
1217 }
1218
1219 async fn open_order_list(
1220 &self,
1221 params: OpenOrderListParams,
1222 ) -> anyhow::Result<RestApiResponse<Vec<models::OpenOrderListResponseInner>>> {
1223 let OpenOrderListParams { recv_window } = params;
1224
1225 let mut query_params = BTreeMap::new();
1226 let body_params = BTreeMap::new();
1227
1228 if let Some(rw) = recv_window {
1229 query_params.insert("recvWindow".to_string(), json!(rw));
1230 }
1231
1232 send_request::<Vec<models::OpenOrderListResponseInner>>(
1233 &self.configuration,
1234 "/api/v3/openOrderList",
1235 reqwest::Method::GET,
1236 query_params,
1237 body_params,
1238 if HAS_TIME_UNIT {
1239 self.configuration.time_unit
1240 } else {
1241 None
1242 },
1243 true,
1244 )
1245 .await
1246 }
1247
1248 async fn order_amendments(
1249 &self,
1250 params: OrderAmendmentsParams,
1251 ) -> anyhow::Result<RestApiResponse<Vec<models::OrderAmendmentsResponseInner>>> {
1252 let OrderAmendmentsParams {
1253 symbol,
1254 order_id,
1255 from_execution_id,
1256 limit,
1257 recv_window,
1258 } = params;
1259
1260 let mut query_params = BTreeMap::new();
1261 let body_params = BTreeMap::new();
1262
1263 query_params.insert("symbol".to_string(), json!(symbol));
1264
1265 query_params.insert("orderId".to_string(), json!(order_id));
1266
1267 if let Some(rw) = from_execution_id {
1268 query_params.insert("fromExecutionId".to_string(), json!(rw));
1269 }
1270
1271 if let Some(rw) = limit {
1272 query_params.insert("limit".to_string(), json!(rw));
1273 }
1274
1275 if let Some(rw) = recv_window {
1276 query_params.insert("recvWindow".to_string(), json!(rw));
1277 }
1278
1279 send_request::<Vec<models::OrderAmendmentsResponseInner>>(
1280 &self.configuration,
1281 "/api/v3/order/amendments",
1282 reqwest::Method::GET,
1283 query_params,
1284 body_params,
1285 if HAS_TIME_UNIT {
1286 self.configuration.time_unit
1287 } else {
1288 None
1289 },
1290 true,
1291 )
1292 .await
1293 }
1294
1295 async fn rate_limit_order(
1296 &self,
1297 params: RateLimitOrderParams,
1298 ) -> anyhow::Result<RestApiResponse<Vec<models::RateLimitOrderResponseInner>>> {
1299 let RateLimitOrderParams { recv_window } = params;
1300
1301 let mut query_params = BTreeMap::new();
1302 let body_params = BTreeMap::new();
1303
1304 if let Some(rw) = recv_window {
1305 query_params.insert("recvWindow".to_string(), json!(rw));
1306 }
1307
1308 send_request::<Vec<models::RateLimitOrderResponseInner>>(
1309 &self.configuration,
1310 "/api/v3/rateLimit/order",
1311 reqwest::Method::GET,
1312 query_params,
1313 body_params,
1314 if HAS_TIME_UNIT {
1315 self.configuration.time_unit
1316 } else {
1317 None
1318 },
1319 true,
1320 )
1321 .await
1322 }
1323}
1324
1325#[cfg(all(test, feature = "spot"))]
1326mod tests {
1327 use super::*;
1328 use crate::TOKIO_SHARED_RT;
1329 use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
1330 use async_trait::async_trait;
1331 use std::collections::HashMap;
1332
1333 struct DummyRestApiResponse<T> {
1334 inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
1335 status: u16,
1336 headers: HashMap<String, String>,
1337 rate_limits: Option<Vec<RestApiRateLimit>>,
1338 }
1339
1340 impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
1341 fn from(dummy: DummyRestApiResponse<T>) -> Self {
1342 Self {
1343 data_fn: dummy.inner,
1344 status: dummy.status,
1345 headers: dummy.headers,
1346 rate_limits: dummy.rate_limits,
1347 }
1348 }
1349 }
1350
1351 struct MockAccountApiClient {
1352 force_error: bool,
1353 }
1354
1355 #[async_trait]
1356 impl AccountApi for MockAccountApiClient {
1357 async fn account_commission(
1358 &self,
1359 _params: AccountCommissionParams,
1360 ) -> anyhow::Result<RestApiResponse<models::AccountCommissionResponse>> {
1361 if self.force_error {
1362 return Err(ConnectorError::ConnectorClientError {
1363 msg: "ResponseError".to_string(),
1364 code: None,
1365 }
1366 .into());
1367 }
1368
1369 let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSDT","standardCommission":{"maker":"0.00000010","taker":"0.00000020","buyer":"0.00000030","seller":"0.00000040"},"specialCommission":{"maker":"0.01000000","taker":"0.02000000","buyer":"0.03000000","seller":"0.04000000"},"taxCommission":{"maker":"0.00000112","taker":"0.00000114","buyer":"0.00000118","seller":"0.00000116"},"discount":{"enabledForAccount":true,"enabledForSymbol":true,"discountAsset":"BNB","discount":"0.75000000"}}"#).unwrap_or_else(|_| serde_json::json!({}));
1370 let dummy_response: models::AccountCommissionResponse =
1371 serde_json::from_value(resp_json.clone())
1372 .expect("should parse into models::AccountCommissionResponse");
1373
1374 let dummy = DummyRestApiResponse {
1375 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1376 status: 200,
1377 headers: HashMap::new(),
1378 rate_limits: None,
1379 };
1380
1381 Ok(dummy.into())
1382 }
1383
1384 async fn all_order_list(
1385 &self,
1386 _params: AllOrderListParams,
1387 ) -> anyhow::Result<RestApiResponse<Vec<models::AllOrderListResponseInner>>> {
1388 if self.force_error {
1389 return Err(ConnectorError::ConnectorClientError {
1390 msg: "ResponseError".to_string(),
1391 code: None,
1392 }
1393 .into());
1394 }
1395
1396 let resp_json: Value = serde_json::from_str(r#"[{"orderListId":29,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"amEEAXryFzFwYF1FeRpUoZ","transactionTime":1565245913483,"symbol":"LTCBTC","orders":[{"symbol":"LTCBTC","orderId":4,"clientOrderId":"oD7aesZqjEGlZrbtRpy5zB"}]}]"#).unwrap_or_else(|_| serde_json::json!({}));
1397 let dummy_response: Vec<models::AllOrderListResponseInner> =
1398 serde_json::from_value(resp_json.clone())
1399 .expect("should parse into Vec<models::AllOrderListResponseInner>");
1400
1401 let dummy = DummyRestApiResponse {
1402 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1403 status: 200,
1404 headers: HashMap::new(),
1405 rate_limits: None,
1406 };
1407
1408 Ok(dummy.into())
1409 }
1410
1411 async fn all_orders(
1412 &self,
1413 _params: AllOrdersParams,
1414 ) -> anyhow::Result<RestApiResponse<Vec<models::AllOrdersResponseInner>>> {
1415 if self.force_error {
1416 return Err(ConnectorError::ConnectorClientError {
1417 msg: "ResponseError".to_string(),
1418 code: None,
1419 }
1420 .into());
1421 }
1422
1423 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"LTCBTC","orderId":1,"orderListId":-1,"clientOrderId":"myOrder1","price":"0.1","origQty":"1.0","executedQty":"0.0","cummulativeQuoteQty":"0.0","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","stopPrice":"0.00000000","icebergQty":"0.00000000","time":1499827319559,"updateTime":1499827319559,"isWorking":true,"origQuoteOrderQty":"0.000000","workingTime":1499827319559,"selfTradePreventionMode":"NONE","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]"#).unwrap_or_else(|_| serde_json::json!({}));
1424 let dummy_response: Vec<models::AllOrdersResponseInner> =
1425 serde_json::from_value(resp_json.clone())
1426 .expect("should parse into Vec<models::AllOrdersResponseInner>");
1427
1428 let dummy = DummyRestApiResponse {
1429 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1430 status: 200,
1431 headers: HashMap::new(),
1432 rate_limits: None,
1433 };
1434
1435 Ok(dummy.into())
1436 }
1437
1438 async fn get_account(
1439 &self,
1440 _params: GetAccountParams,
1441 ) -> anyhow::Result<RestApiResponse<models::GetAccountResponse>> {
1442 if self.force_error {
1443 return Err(ConnectorError::ConnectorClientError {
1444 msg: "ResponseError".to_string(),
1445 code: None,
1446 }
1447 .into());
1448 }
1449
1450 let resp_json: Value = serde_json::from_str(r#"{"makerCommission":15,"takerCommission":15,"buyerCommission":0,"sellerCommission":0,"commissionRates":{"maker":"0.00150000","taker":"0.00150000","buyer":"0.00000000","seller":"0.00000000"},"canTrade":true,"canWithdraw":true,"canDeposit":true,"brokered":false,"requireSelfTradePrevention":false,"preventSor":false,"updateTime":123456789,"accountType":"SPOT","balances":[{"asset":"BTC","free":"4723846.89208129","locked":"0.00000000"}],"permissions":["SPOT"],"uid":354937868}"#).unwrap_or_else(|_| serde_json::json!({}));
1451 let dummy_response: models::GetAccountResponse =
1452 serde_json::from_value(resp_json.clone())
1453 .expect("should parse into models::GetAccountResponse");
1454
1455 let dummy = DummyRestApiResponse {
1456 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1457 status: 200,
1458 headers: HashMap::new(),
1459 rate_limits: None,
1460 };
1461
1462 Ok(dummy.into())
1463 }
1464
1465 async fn get_open_orders(
1466 &self,
1467 _params: GetOpenOrdersParams,
1468 ) -> anyhow::Result<RestApiResponse<Vec<models::GetOpenOrdersResponseInner>>> {
1469 if self.force_error {
1470 return Err(ConnectorError::ConnectorClientError {
1471 msg: "ResponseError".to_string(),
1472 code: None,
1473 }
1474 .into());
1475 }
1476
1477 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"LTCBTC","orderId":1,"orderListId":-1,"clientOrderId":"myOrder1","price":"0.1","origQty":"1.0","executedQty":"0.0","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.0","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","stopPrice":"0.00000000","icebergQty":"0.00000000","time":1499827319559,"updateTime":1499827319559,"isWorking":true,"workingTime":1499827319559,"selfTradePreventionMode":"NONE","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]"#).unwrap_or_else(|_| serde_json::json!({}));
1478 let dummy_response: Vec<models::GetOpenOrdersResponseInner> =
1479 serde_json::from_value(resp_json.clone())
1480 .expect("should parse into Vec<models::GetOpenOrdersResponseInner>");
1481
1482 let dummy = DummyRestApiResponse {
1483 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1484 status: 200,
1485 headers: HashMap::new(),
1486 rate_limits: None,
1487 };
1488
1489 Ok(dummy.into())
1490 }
1491
1492 async fn get_order(
1493 &self,
1494 _params: GetOrderParams,
1495 ) -> anyhow::Result<RestApiResponse<models::GetOrderResponse>> {
1496 if self.force_error {
1497 return Err(ConnectorError::ConnectorClientError {
1498 msg: "ResponseError".to_string(),
1499 code: None,
1500 }
1501 .into());
1502 }
1503
1504 let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC","orderId":1,"orderListId":-1,"clientOrderId":"myOrder1","price":"0.1","origQty":"1.0","executedQty":"0.0","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.0","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","stopPrice":"0.00000000","icebergQty":"0.00000000","time":1499827319559,"updateTime":1499827319559,"isWorking":true,"workingTime":1499827319559,"selfTradePreventionMode":"NONE","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}"#).unwrap_or_else(|_| serde_json::json!({}));
1505 let dummy_response: models::GetOrderResponse =
1506 serde_json::from_value(resp_json.clone())
1507 .expect("should parse into models::GetOrderResponse");
1508
1509 let dummy = DummyRestApiResponse {
1510 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1511 status: 200,
1512 headers: HashMap::new(),
1513 rate_limits: None,
1514 };
1515
1516 Ok(dummy.into())
1517 }
1518
1519 async fn get_order_list(
1520 &self,
1521 _params: GetOrderListParams,
1522 ) -> anyhow::Result<RestApiResponse<models::GetOrderListResponse>> {
1523 if self.force_error {
1524 return Err(ConnectorError::ConnectorClientError {
1525 msg: "ResponseError".to_string(),
1526 code: None,
1527 }
1528 .into());
1529 }
1530
1531 let resp_json: Value = serde_json::from_str(r#"{"orderListId":27,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"h2USkA5YQpaXHPIrkd96xE","transactionTime":1565245656253,"symbol":"LTCBTC","orders":[{"symbol":"LTCBTC","orderId":4,"clientOrderId":"qD1gy3kc3Gx0rihm9Y3xwS"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
1532 let dummy_response: models::GetOrderListResponse =
1533 serde_json::from_value(resp_json.clone())
1534 .expect("should parse into models::GetOrderListResponse");
1535
1536 let dummy = DummyRestApiResponse {
1537 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1538 status: 200,
1539 headers: HashMap::new(),
1540 rate_limits: None,
1541 };
1542
1543 Ok(dummy.into())
1544 }
1545
1546 async fn my_allocations(
1547 &self,
1548 _params: MyAllocationsParams,
1549 ) -> anyhow::Result<RestApiResponse<Vec<models::MyAllocationsResponseInner>>> {
1550 if self.force_error {
1551 return Err(ConnectorError::ConnectorClientError {
1552 msg: "ResponseError".to_string(),
1553 code: None,
1554 }
1555 .into());
1556 }
1557
1558 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSDT","allocationId":0,"allocationType":"SOR","orderId":1,"orderListId":-1,"price":"1.00000000","qty":"5.00000000","quoteQty":"5.00000000","commission":"0.00000000","commissionAsset":"BTC","time":1687506878118,"isBuyer":true,"isMaker":false,"isAllocator":false}]"#).unwrap_or_else(|_| serde_json::json!({}));
1559 let dummy_response: Vec<models::MyAllocationsResponseInner> =
1560 serde_json::from_value(resp_json.clone())
1561 .expect("should parse into Vec<models::MyAllocationsResponseInner>");
1562
1563 let dummy = DummyRestApiResponse {
1564 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1565 status: 200,
1566 headers: HashMap::new(),
1567 rate_limits: None,
1568 };
1569
1570 Ok(dummy.into())
1571 }
1572
1573 async fn my_filters(
1574 &self,
1575 _params: MyFiltersParams,
1576 ) -> anyhow::Result<RestApiResponse<models::MyFiltersResponse>> {
1577 if self.force_error {
1578 return Err(ConnectorError::ConnectorClientError {
1579 msg: "ResponseError".to_string(),
1580 code: None,
1581 }
1582 .into());
1583 }
1584
1585 let resp_json: Value = serde_json::from_str(r#"{"exchangeFilters":[{"filterType":"EXCHANGE_MAX_NUM_ORDERS","maxNumOrders":1000}],"symbolFilters":[{"filterType":"PRICE_FILTER","priceExponent":8,"minPrice":"0.00000100","maxPrice":"100000.00000000","tickSize":"0.00000100"}],"assetFilters":[{"filterType":"MAX_ASSET","qtyExponent":8,"limit":"100.00000000","asset":"BNB"}],"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
1586 let dummy_response: models::MyFiltersResponse =
1587 serde_json::from_value(resp_json.clone())
1588 .expect("should parse into models::MyFiltersResponse");
1589
1590 let dummy = DummyRestApiResponse {
1591 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1592 status: 200,
1593 headers: HashMap::new(),
1594 rate_limits: None,
1595 };
1596
1597 Ok(dummy.into())
1598 }
1599
1600 async fn my_prevented_matches(
1601 &self,
1602 _params: MyPreventedMatchesParams,
1603 ) -> anyhow::Result<RestApiResponse<Vec<models::MyPreventedMatchesResponseInner>>> {
1604 if self.force_error {
1605 return Err(ConnectorError::ConnectorClientError {
1606 msg: "ResponseError".to_string(),
1607 code: None,
1608 }
1609 .into());
1610 }
1611
1612 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSDT","preventedMatchId":1,"takerOrderId":5,"makerSymbol":"BTCUSDT","makerOrderId":3,"tradeGroupId":1,"selfTradePreventionMode":"EXPIRE_MAKER","price":"1.100000","makerPreventedQuantity":"1.300000","transactTime":1669101687094}]"#).unwrap_or_else(|_| serde_json::json!({}));
1613 let dummy_response: Vec<models::MyPreventedMatchesResponseInner> =
1614 serde_json::from_value(resp_json.clone())
1615 .expect("should parse into Vec<models::MyPreventedMatchesResponseInner>");
1616
1617 let dummy = DummyRestApiResponse {
1618 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1619 status: 200,
1620 headers: HashMap::new(),
1621 rate_limits: None,
1622 };
1623
1624 Ok(dummy.into())
1625 }
1626
1627 async fn my_trades(
1628 &self,
1629 _params: MyTradesParams,
1630 ) -> anyhow::Result<RestApiResponse<Vec<models::MyTradesResponseInner>>> {
1631 if self.force_error {
1632 return Err(ConnectorError::ConnectorClientError {
1633 msg: "ResponseError".to_string(),
1634 code: None,
1635 }
1636 .into());
1637 }
1638
1639 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BNBBTC","id":28457,"orderId":100234,"orderListId":-1,"price":"4.00000100","qty":"12.00000000","quoteQty":"48.000012","commission":"10.10000000","commissionAsset":"BNB","time":1499865549590,"isBuyer":true,"isMaker":false,"isBestMatch":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
1640 let dummy_response: Vec<models::MyTradesResponseInner> =
1641 serde_json::from_value(resp_json.clone())
1642 .expect("should parse into Vec<models::MyTradesResponseInner>");
1643
1644 let dummy = DummyRestApiResponse {
1645 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1646 status: 200,
1647 headers: HashMap::new(),
1648 rate_limits: None,
1649 };
1650
1651 Ok(dummy.into())
1652 }
1653
1654 async fn open_order_list(
1655 &self,
1656 _params: OpenOrderListParams,
1657 ) -> anyhow::Result<RestApiResponse<Vec<models::OpenOrderListResponseInner>>> {
1658 if self.force_error {
1659 return Err(ConnectorError::ConnectorClientError {
1660 msg: "ResponseError".to_string(),
1661 code: None,
1662 }
1663 .into());
1664 }
1665
1666 let resp_json: Value = serde_json::from_str(r#"[{"orderListId":31,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"wuB13fmulKj3YjdqWEcsnp","transactionTime":1565246080644,"symbol":"LTCBTC","orders":[{"symbol":"LTCBTC","orderId":4,"clientOrderId":"r3EH2N76dHfLoSZWIUw1bT"}]}]"#).unwrap_or_else(|_| serde_json::json!({}));
1667 let dummy_response: Vec<models::OpenOrderListResponseInner> =
1668 serde_json::from_value(resp_json.clone())
1669 .expect("should parse into Vec<models::OpenOrderListResponseInner>");
1670
1671 let dummy = DummyRestApiResponse {
1672 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1673 status: 200,
1674 headers: HashMap::new(),
1675 rate_limits: None,
1676 };
1677
1678 Ok(dummy.into())
1679 }
1680
1681 async fn order_amendments(
1682 &self,
1683 _params: OrderAmendmentsParams,
1684 ) -> anyhow::Result<RestApiResponse<Vec<models::OrderAmendmentsResponseInner>>> {
1685 if self.force_error {
1686 return Err(ConnectorError::ConnectorClientError {
1687 msg: "ResponseError".to_string(),
1688 code: None,
1689 }
1690 .into());
1691 }
1692
1693 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSDT","orderId":9,"executionId":22,"origClientOrderId":"W0fJ9fiLKHOJutovPK3oJp","newClientOrderId":"UQ1Np3bmQ71jJzsSDW9Vpi","origQty":"5.00000000","newQty":"4.00000000","time":1741669661670}]"#).unwrap_or_else(|_| serde_json::json!({}));
1694 let dummy_response: Vec<models::OrderAmendmentsResponseInner> =
1695 serde_json::from_value(resp_json.clone())
1696 .expect("should parse into Vec<models::OrderAmendmentsResponseInner>");
1697
1698 let dummy = DummyRestApiResponse {
1699 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1700 status: 200,
1701 headers: HashMap::new(),
1702 rate_limits: None,
1703 };
1704
1705 Ok(dummy.into())
1706 }
1707
1708 async fn rate_limit_order(
1709 &self,
1710 _params: RateLimitOrderParams,
1711 ) -> anyhow::Result<RestApiResponse<Vec<models::RateLimitOrderResponseInner>>> {
1712 if self.force_error {
1713 return Err(ConnectorError::ConnectorClientError {
1714 msg: "ResponseError".to_string(),
1715 code: None,
1716 }
1717 .into());
1718 }
1719
1720 let resp_json: Value = serde_json::from_str(r#"[{"rateLimitType":"ORDERS","interval":"SECOND","intervalNum":10,"limit":50,"count":0}]"#).unwrap_or_else(|_| serde_json::json!({}));
1721 let dummy_response: Vec<models::RateLimitOrderResponseInner> =
1722 serde_json::from_value(resp_json.clone())
1723 .expect("should parse into Vec<models::RateLimitOrderResponseInner>");
1724
1725 let dummy = DummyRestApiResponse {
1726 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1727 status: 200,
1728 headers: HashMap::new(),
1729 rate_limits: None,
1730 };
1731
1732 Ok(dummy.into())
1733 }
1734 }
1735
1736 #[test]
1737 fn account_commission_required_params_success() {
1738 TOKIO_SHARED_RT.block_on(async {
1739 let client = MockAccountApiClient { force_error: false };
1740
1741 let params = AccountCommissionParams::builder("BTCUSDT".to_string()).build().unwrap();
1742
1743 let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSDT","standardCommission":{"maker":"0.00000010","taker":"0.00000020","buyer":"0.00000030","seller":"0.00000040"},"specialCommission":{"maker":"0.01000000","taker":"0.02000000","buyer":"0.03000000","seller":"0.04000000"},"taxCommission":{"maker":"0.00000112","taker":"0.00000114","buyer":"0.00000118","seller":"0.00000116"},"discount":{"enabledForAccount":true,"enabledForSymbol":true,"discountAsset":"BNB","discount":"0.75000000"}}"#).unwrap_or_else(|_| serde_json::json!({}));
1744 let expected_response : models::AccountCommissionResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AccountCommissionResponse");
1745
1746 let resp = client.account_commission(params).await.expect("Expected a response");
1747 let data_future = resp.data();
1748 let actual_response = data_future.await.unwrap();
1749 assert_eq!(actual_response, expected_response);
1750 });
1751 }
1752
1753 #[test]
1754 fn account_commission_optional_params_success() {
1755 TOKIO_SHARED_RT.block_on(async {
1756 let client = MockAccountApiClient { force_error: false };
1757
1758 let params = AccountCommissionParams::builder("BTCUSDT".to_string()).build().unwrap();
1759
1760 let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSDT","standardCommission":{"maker":"0.00000010","taker":"0.00000020","buyer":"0.00000030","seller":"0.00000040"},"specialCommission":{"maker":"0.01000000","taker":"0.02000000","buyer":"0.03000000","seller":"0.04000000"},"taxCommission":{"maker":"0.00000112","taker":"0.00000114","buyer":"0.00000118","seller":"0.00000116"},"discount":{"enabledForAccount":true,"enabledForSymbol":true,"discountAsset":"BNB","discount":"0.75000000"}}"#).unwrap_or_else(|_| serde_json::json!({}));
1761 let expected_response : models::AccountCommissionResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AccountCommissionResponse");
1762
1763 let resp = client.account_commission(params).await.expect("Expected a response");
1764 let data_future = resp.data();
1765 let actual_response = data_future.await.unwrap();
1766 assert_eq!(actual_response, expected_response);
1767 });
1768 }
1769
1770 #[test]
1771 fn account_commission_response_error() {
1772 TOKIO_SHARED_RT.block_on(async {
1773 let client = MockAccountApiClient { force_error: true };
1774
1775 let params = AccountCommissionParams::builder("BTCUSDT".to_string())
1776 .build()
1777 .unwrap();
1778
1779 match client.account_commission(params).await {
1780 Ok(_) => panic!("Expected an error"),
1781 Err(err) => {
1782 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1783 }
1784 }
1785 });
1786 }
1787
1788 #[test]
1789 fn all_order_list_required_params_success() {
1790 TOKIO_SHARED_RT.block_on(async {
1791 let client = MockAccountApiClient { force_error: false };
1792
1793 let params = AllOrderListParams::builder().build().unwrap();
1794
1795 let resp_json: Value = serde_json::from_str(r#"[{"orderListId":29,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"amEEAXryFzFwYF1FeRpUoZ","transactionTime":1565245913483,"symbol":"LTCBTC","orders":[{"symbol":"LTCBTC","orderId":4,"clientOrderId":"oD7aesZqjEGlZrbtRpy5zB"}]}]"#).unwrap_or_else(|_| serde_json::json!({}));
1796 let expected_response : Vec<models::AllOrderListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::AllOrderListResponseInner>");
1797
1798 let resp = client.all_order_list(params).await.expect("Expected a response");
1799 let data_future = resp.data();
1800 let actual_response = data_future.await.unwrap();
1801 assert_eq!(actual_response, expected_response);
1802 });
1803 }
1804
1805 #[test]
1806 fn all_order_list_optional_params_success() {
1807 TOKIO_SHARED_RT.block_on(async {
1808 let client = MockAccountApiClient { force_error: false };
1809
1810 let params = AllOrderListParams::builder().from_id(1).start_time(1735693200000).end_time(1735693200000).limit(1).recv_window(dec!(5000)).build().unwrap();
1811
1812 let resp_json: Value = serde_json::from_str(r#"[{"orderListId":29,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"amEEAXryFzFwYF1FeRpUoZ","transactionTime":1565245913483,"symbol":"LTCBTC","orders":[{"symbol":"LTCBTC","orderId":4,"clientOrderId":"oD7aesZqjEGlZrbtRpy5zB"}]}]"#).unwrap_or_else(|_| serde_json::json!({}));
1813 let expected_response : Vec<models::AllOrderListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::AllOrderListResponseInner>");
1814
1815 let resp = client.all_order_list(params).await.expect("Expected a response");
1816 let data_future = resp.data();
1817 let actual_response = data_future.await.unwrap();
1818 assert_eq!(actual_response, expected_response);
1819 });
1820 }
1821
1822 #[test]
1823 fn all_order_list_response_error() {
1824 TOKIO_SHARED_RT.block_on(async {
1825 let client = MockAccountApiClient { force_error: true };
1826
1827 let params = AllOrderListParams::builder().build().unwrap();
1828
1829 match client.all_order_list(params).await {
1830 Ok(_) => panic!("Expected an error"),
1831 Err(err) => {
1832 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1833 }
1834 }
1835 });
1836 }
1837
1838 #[test]
1839 fn all_orders_required_params_success() {
1840 TOKIO_SHARED_RT.block_on(async {
1841 let client = MockAccountApiClient { force_error: false };
1842
1843 let params = AllOrdersParams::builder("LTCBTC".to_string(),).build().unwrap();
1844
1845 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"LTCBTC","orderId":1,"orderListId":-1,"clientOrderId":"myOrder1","price":"0.1","origQty":"1.0","executedQty":"0.0","cummulativeQuoteQty":"0.0","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","stopPrice":"0.00000000","icebergQty":"0.00000000","time":1499827319559,"updateTime":1499827319559,"isWorking":true,"origQuoteOrderQty":"0.000000","workingTime":1499827319559,"selfTradePreventionMode":"NONE","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]"#).unwrap_or_else(|_| serde_json::json!({}));
1846 let expected_response : Vec<models::AllOrdersResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::AllOrdersResponseInner>");
1847
1848 let resp = client.all_orders(params).await.expect("Expected a response");
1849 let data_future = resp.data();
1850 let actual_response = data_future.await.unwrap();
1851 assert_eq!(actual_response, expected_response);
1852 });
1853 }
1854
1855 #[test]
1856 fn all_orders_optional_params_success() {
1857 TOKIO_SHARED_RT.block_on(async {
1858 let client = MockAccountApiClient { force_error: false };
1859
1860 let params = AllOrdersParams::builder("LTCBTC".to_string(),).order_id(1).start_time(1735693200000).end_time(1735693200000).limit(1).recv_window(dec!(5000)).build().unwrap();
1861
1862 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"LTCBTC","orderId":1,"orderListId":-1,"clientOrderId":"myOrder1","price":"0.1","origQty":"1.0","executedQty":"0.0","cummulativeQuoteQty":"0.0","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","stopPrice":"0.00000000","icebergQty":"0.00000000","time":1499827319559,"updateTime":1499827319559,"isWorking":true,"origQuoteOrderQty":"0.000000","workingTime":1499827319559,"selfTradePreventionMode":"NONE","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]"#).unwrap_or_else(|_| serde_json::json!({}));
1863 let expected_response : Vec<models::AllOrdersResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::AllOrdersResponseInner>");
1864
1865 let resp = client.all_orders(params).await.expect("Expected a response");
1866 let data_future = resp.data();
1867 let actual_response = data_future.await.unwrap();
1868 assert_eq!(actual_response, expected_response);
1869 });
1870 }
1871
1872 #[test]
1873 fn all_orders_response_error() {
1874 TOKIO_SHARED_RT.block_on(async {
1875 let client = MockAccountApiClient { force_error: true };
1876
1877 let params = AllOrdersParams::builder("LTCBTC".to_string())
1878 .build()
1879 .unwrap();
1880
1881 match client.all_orders(params).await {
1882 Ok(_) => panic!("Expected an error"),
1883 Err(err) => {
1884 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1885 }
1886 }
1887 });
1888 }
1889
1890 #[test]
1891 fn get_account_required_params_success() {
1892 TOKIO_SHARED_RT.block_on(async {
1893 let client = MockAccountApiClient { force_error: false };
1894
1895 let params = GetAccountParams::builder().build().unwrap();
1896
1897 let resp_json: Value = serde_json::from_str(r#"{"makerCommission":15,"takerCommission":15,"buyerCommission":0,"sellerCommission":0,"commissionRates":{"maker":"0.00150000","taker":"0.00150000","buyer":"0.00000000","seller":"0.00000000"},"canTrade":true,"canWithdraw":true,"canDeposit":true,"brokered":false,"requireSelfTradePrevention":false,"preventSor":false,"updateTime":123456789,"accountType":"SPOT","balances":[{"asset":"BTC","free":"4723846.89208129","locked":"0.00000000"}],"permissions":["SPOT"],"uid":354937868}"#).unwrap_or_else(|_| serde_json::json!({}));
1898 let expected_response : models::GetAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetAccountResponse");
1899
1900 let resp = client.get_account(params).await.expect("Expected a response");
1901 let data_future = resp.data();
1902 let actual_response = data_future.await.unwrap();
1903 assert_eq!(actual_response, expected_response);
1904 });
1905 }
1906
1907 #[test]
1908 fn get_account_optional_params_success() {
1909 TOKIO_SHARED_RT.block_on(async {
1910 let client = MockAccountApiClient { force_error: false };
1911
1912 let params = GetAccountParams::builder().omit_zero_balances(false).recv_window(dec!(5000)).build().unwrap();
1913
1914 let resp_json: Value = serde_json::from_str(r#"{"makerCommission":15,"takerCommission":15,"buyerCommission":0,"sellerCommission":0,"commissionRates":{"maker":"0.00150000","taker":"0.00150000","buyer":"0.00000000","seller":"0.00000000"},"canTrade":true,"canWithdraw":true,"canDeposit":true,"brokered":false,"requireSelfTradePrevention":false,"preventSor":false,"updateTime":123456789,"accountType":"SPOT","balances":[{"asset":"BTC","free":"4723846.89208129","locked":"0.00000000"}],"permissions":["SPOT"],"uid":354937868}"#).unwrap_or_else(|_| serde_json::json!({}));
1915 let expected_response : models::GetAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetAccountResponse");
1916
1917 let resp = client.get_account(params).await.expect("Expected a response");
1918 let data_future = resp.data();
1919 let actual_response = data_future.await.unwrap();
1920 assert_eq!(actual_response, expected_response);
1921 });
1922 }
1923
1924 #[test]
1925 fn get_account_response_error() {
1926 TOKIO_SHARED_RT.block_on(async {
1927 let client = MockAccountApiClient { force_error: true };
1928
1929 let params = GetAccountParams::builder().build().unwrap();
1930
1931 match client.get_account(params).await {
1932 Ok(_) => panic!("Expected an error"),
1933 Err(err) => {
1934 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1935 }
1936 }
1937 });
1938 }
1939
1940 #[test]
1941 fn get_open_orders_required_params_success() {
1942 TOKIO_SHARED_RT.block_on(async {
1943 let client = MockAccountApiClient { force_error: false };
1944
1945 let params = GetOpenOrdersParams::builder().build().unwrap();
1946
1947 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"LTCBTC","orderId":1,"orderListId":-1,"clientOrderId":"myOrder1","price":"0.1","origQty":"1.0","executedQty":"0.0","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.0","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","stopPrice":"0.00000000","icebergQty":"0.00000000","time":1499827319559,"updateTime":1499827319559,"isWorking":true,"workingTime":1499827319559,"selfTradePreventionMode":"NONE","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]"#).unwrap_or_else(|_| serde_json::json!({}));
1948 let expected_response : Vec<models::GetOpenOrdersResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetOpenOrdersResponseInner>");
1949
1950 let resp = client.get_open_orders(params).await.expect("Expected a response");
1951 let data_future = resp.data();
1952 let actual_response = data_future.await.unwrap();
1953 assert_eq!(actual_response, expected_response);
1954 });
1955 }
1956
1957 #[test]
1958 fn get_open_orders_optional_params_success() {
1959 TOKIO_SHARED_RT.block_on(async {
1960 let client = MockAccountApiClient { force_error: false };
1961
1962 let params = GetOpenOrdersParams::builder().symbol("LTCBTC".to_string()).recv_window(dec!(5000)).build().unwrap();
1963
1964 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"LTCBTC","orderId":1,"orderListId":-1,"clientOrderId":"myOrder1","price":"0.1","origQty":"1.0","executedQty":"0.0","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.0","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","stopPrice":"0.00000000","icebergQty":"0.00000000","time":1499827319559,"updateTime":1499827319559,"isWorking":true,"workingTime":1499827319559,"selfTradePreventionMode":"NONE","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}]"#).unwrap_or_else(|_| serde_json::json!({}));
1965 let expected_response : Vec<models::GetOpenOrdersResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetOpenOrdersResponseInner>");
1966
1967 let resp = client.get_open_orders(params).await.expect("Expected a response");
1968 let data_future = resp.data();
1969 let actual_response = data_future.await.unwrap();
1970 assert_eq!(actual_response, expected_response);
1971 });
1972 }
1973
1974 #[test]
1975 fn get_open_orders_response_error() {
1976 TOKIO_SHARED_RT.block_on(async {
1977 let client = MockAccountApiClient { force_error: true };
1978
1979 let params = GetOpenOrdersParams::builder().build().unwrap();
1980
1981 match client.get_open_orders(params).await {
1982 Ok(_) => panic!("Expected an error"),
1983 Err(err) => {
1984 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1985 }
1986 }
1987 });
1988 }
1989
1990 #[test]
1991 fn get_order_required_params_success() {
1992 TOKIO_SHARED_RT.block_on(async {
1993 let client = MockAccountApiClient { force_error: false };
1994
1995 let params = GetOrderParams::builder("LTCBTC".to_string(),).build().unwrap();
1996
1997 let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC","orderId":1,"orderListId":-1,"clientOrderId":"myOrder1","price":"0.1","origQty":"1.0","executedQty":"0.0","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.0","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","stopPrice":"0.00000000","icebergQty":"0.00000000","time":1499827319559,"updateTime":1499827319559,"isWorking":true,"workingTime":1499827319559,"selfTradePreventionMode":"NONE","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}"#).unwrap_or_else(|_| serde_json::json!({}));
1998 let expected_response : models::GetOrderResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOrderResponse");
1999
2000 let resp = client.get_order(params).await.expect("Expected a response");
2001 let data_future = resp.data();
2002 let actual_response = data_future.await.unwrap();
2003 assert_eq!(actual_response, expected_response);
2004 });
2005 }
2006
2007 #[test]
2008 fn get_order_optional_params_success() {
2009 TOKIO_SHARED_RT.block_on(async {
2010 let client = MockAccountApiClient { force_error: false };
2011
2012 let params = GetOrderParams::builder("LTCBTC".to_string(),).order_id(1).orig_client_order_id("myOrder1".to_string()).recv_window(dec!(5000)).build().unwrap();
2013
2014 let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC","orderId":1,"orderListId":-1,"clientOrderId":"myOrder1","price":"0.1","origQty":"1.0","executedQty":"0.0","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.0","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","stopPrice":"0.00000000","icebergQty":"0.00000000","time":1499827319559,"updateTime":1499827319559,"isWorking":true,"workingTime":1499827319559,"selfTradePreventionMode":"NONE","preventedMatchId":0,"preventedQuantity":"1.200000","strategyId":1,"strategyType":1000000,"trailingDelta":10,"trailingTime":-1,"usedSor":true,"workingFloor":"SOR","pegPriceType":"PRIMARY_PEG","pegOffsetType":"PRICE_LEVEL","pegOffsetValue":5,"peggedPrice":"87523.83710000","expiryReason":"INSUFFICIENT_LIQUIDITY"}"#).unwrap_or_else(|_| serde_json::json!({}));
2015 let expected_response : models::GetOrderResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOrderResponse");
2016
2017 let resp = client.get_order(params).await.expect("Expected a response");
2018 let data_future = resp.data();
2019 let actual_response = data_future.await.unwrap();
2020 assert_eq!(actual_response, expected_response);
2021 });
2022 }
2023
2024 #[test]
2025 fn get_order_response_error() {
2026 TOKIO_SHARED_RT.block_on(async {
2027 let client = MockAccountApiClient { force_error: true };
2028
2029 let params = GetOrderParams::builder("LTCBTC".to_string())
2030 .build()
2031 .unwrap();
2032
2033 match client.get_order(params).await {
2034 Ok(_) => panic!("Expected an error"),
2035 Err(err) => {
2036 assert_eq!(err.to_string(), "Connector client error: ResponseError");
2037 }
2038 }
2039 });
2040 }
2041
2042 #[test]
2043 fn get_order_list_required_params_success() {
2044 TOKIO_SHARED_RT.block_on(async {
2045 let client = MockAccountApiClient { force_error: false };
2046
2047 let params = GetOrderListParams::builder().build().unwrap();
2048
2049 let resp_json: Value = serde_json::from_str(r#"{"orderListId":27,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"h2USkA5YQpaXHPIrkd96xE","transactionTime":1565245656253,"symbol":"LTCBTC","orders":[{"symbol":"LTCBTC","orderId":4,"clientOrderId":"qD1gy3kc3Gx0rihm9Y3xwS"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2050 let expected_response : models::GetOrderListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOrderListResponse");
2051
2052 let resp = client.get_order_list(params).await.expect("Expected a response");
2053 let data_future = resp.data();
2054 let actual_response = data_future.await.unwrap();
2055 assert_eq!(actual_response, expected_response);
2056 });
2057 }
2058
2059 #[test]
2060 fn get_order_list_optional_params_success() {
2061 TOKIO_SHARED_RT.block_on(async {
2062 let client = MockAccountApiClient { force_error: false };
2063
2064 let params = GetOrderListParams::builder().order_list_id(27).orig_client_order_id("1".to_string()).recv_window(dec!(5000)).build().unwrap();
2065
2066 let resp_json: Value = serde_json::from_str(r#"{"orderListId":27,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"h2USkA5YQpaXHPIrkd96xE","transactionTime":1565245656253,"symbol":"LTCBTC","orders":[{"symbol":"LTCBTC","orderId":4,"clientOrderId":"qD1gy3kc3Gx0rihm9Y3xwS"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2067 let expected_response : models::GetOrderListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOrderListResponse");
2068
2069 let resp = client.get_order_list(params).await.expect("Expected a response");
2070 let data_future = resp.data();
2071 let actual_response = data_future.await.unwrap();
2072 assert_eq!(actual_response, expected_response);
2073 });
2074 }
2075
2076 #[test]
2077 fn get_order_list_response_error() {
2078 TOKIO_SHARED_RT.block_on(async {
2079 let client = MockAccountApiClient { force_error: true };
2080
2081 let params = GetOrderListParams::builder().build().unwrap();
2082
2083 match client.get_order_list(params).await {
2084 Ok(_) => panic!("Expected an error"),
2085 Err(err) => {
2086 assert_eq!(err.to_string(), "Connector client error: ResponseError");
2087 }
2088 }
2089 });
2090 }
2091
2092 #[test]
2093 fn my_allocations_required_params_success() {
2094 TOKIO_SHARED_RT.block_on(async {
2095 let client = MockAccountApiClient { force_error: false };
2096
2097 let params = MyAllocationsParams::builder("BTCUSDT".to_string(),).build().unwrap();
2098
2099 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSDT","allocationId":0,"allocationType":"SOR","orderId":1,"orderListId":-1,"price":"1.00000000","qty":"5.00000000","quoteQty":"5.00000000","commission":"0.00000000","commissionAsset":"BTC","time":1687506878118,"isBuyer":true,"isMaker":false,"isAllocator":false}]"#).unwrap_or_else(|_| serde_json::json!({}));
2100 let expected_response : Vec<models::MyAllocationsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::MyAllocationsResponseInner>");
2101
2102 let resp = client.my_allocations(params).await.expect("Expected a response");
2103 let data_future = resp.data();
2104 let actual_response = data_future.await.unwrap();
2105 assert_eq!(actual_response, expected_response);
2106 });
2107 }
2108
2109 #[test]
2110 fn my_allocations_optional_params_success() {
2111 TOKIO_SHARED_RT.block_on(async {
2112 let client = MockAccountApiClient { force_error: false };
2113
2114 let params = MyAllocationsParams::builder("BTCUSDT".to_string(),).start_time(1735693200000).end_time(1735693200000).from_allocation_id(0).limit(1).order_id(1).recv_window(dec!(5000)).build().unwrap();
2115
2116 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSDT","allocationId":0,"allocationType":"SOR","orderId":1,"orderListId":-1,"price":"1.00000000","qty":"5.00000000","quoteQty":"5.00000000","commission":"0.00000000","commissionAsset":"BTC","time":1687506878118,"isBuyer":true,"isMaker":false,"isAllocator":false}]"#).unwrap_or_else(|_| serde_json::json!({}));
2117 let expected_response : Vec<models::MyAllocationsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::MyAllocationsResponseInner>");
2118
2119 let resp = client.my_allocations(params).await.expect("Expected a response");
2120 let data_future = resp.data();
2121 let actual_response = data_future.await.unwrap();
2122 assert_eq!(actual_response, expected_response);
2123 });
2124 }
2125
2126 #[test]
2127 fn my_allocations_response_error() {
2128 TOKIO_SHARED_RT.block_on(async {
2129 let client = MockAccountApiClient { force_error: true };
2130
2131 let params = MyAllocationsParams::builder("BTCUSDT".to_string())
2132 .build()
2133 .unwrap();
2134
2135 match client.my_allocations(params).await {
2136 Ok(_) => panic!("Expected an error"),
2137 Err(err) => {
2138 assert_eq!(err.to_string(), "Connector client error: ResponseError");
2139 }
2140 }
2141 });
2142 }
2143
2144 #[test]
2145 fn my_filters_required_params_success() {
2146 TOKIO_SHARED_RT.block_on(async {
2147 let client = MockAccountApiClient { force_error: false };
2148
2149 let params = MyFiltersParams::builder("BNBUSDT".to_string(),).build().unwrap();
2150
2151 let resp_json: Value = serde_json::from_str(r#"{"exchangeFilters":[{"filterType":"EXCHANGE_MAX_NUM_ORDERS","maxNumOrders":1000}],"symbolFilters":[{"filterType":"PRICE_FILTER","priceExponent":8,"minPrice":"0.00000100","maxPrice":"100000.00000000","tickSize":"0.00000100"}],"assetFilters":[{"filterType":"MAX_ASSET","qtyExponent":8,"limit":"100.00000000","asset":"BNB"}],"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2152 let expected_response : models::MyFiltersResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::MyFiltersResponse");
2153
2154 let resp = client.my_filters(params).await.expect("Expected a response");
2155 let data_future = resp.data();
2156 let actual_response = data_future.await.unwrap();
2157 assert_eq!(actual_response, expected_response);
2158 });
2159 }
2160
2161 #[test]
2162 fn my_filters_optional_params_success() {
2163 TOKIO_SHARED_RT.block_on(async {
2164 let client = MockAccountApiClient { force_error: false };
2165
2166 let params = MyFiltersParams::builder("BNBUSDT".to_string(),).recv_window(dec!(5000)).build().unwrap();
2167
2168 let resp_json: Value = serde_json::from_str(r#"{"exchangeFilters":[{"filterType":"EXCHANGE_MAX_NUM_ORDERS","maxNumOrders":1000}],"symbolFilters":[{"filterType":"PRICE_FILTER","priceExponent":8,"minPrice":"0.00000100","maxPrice":"100000.00000000","tickSize":"0.00000100"}],"assetFilters":[{"filterType":"MAX_ASSET","qtyExponent":8,"limit":"100.00000000","asset":"BNB"}],"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":321}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2169 let expected_response : models::MyFiltersResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::MyFiltersResponse");
2170
2171 let resp = client.my_filters(params).await.expect("Expected a response");
2172 let data_future = resp.data();
2173 let actual_response = data_future.await.unwrap();
2174 assert_eq!(actual_response, expected_response);
2175 });
2176 }
2177
2178 #[test]
2179 fn my_filters_response_error() {
2180 TOKIO_SHARED_RT.block_on(async {
2181 let client = MockAccountApiClient { force_error: true };
2182
2183 let params = MyFiltersParams::builder("BNBUSDT".to_string())
2184 .build()
2185 .unwrap();
2186
2187 match client.my_filters(params).await {
2188 Ok(_) => panic!("Expected an error"),
2189 Err(err) => {
2190 assert_eq!(err.to_string(), "Connector client error: ResponseError");
2191 }
2192 }
2193 });
2194 }
2195
2196 #[test]
2197 fn my_prevented_matches_required_params_success() {
2198 TOKIO_SHARED_RT.block_on(async {
2199 let client = MockAccountApiClient { force_error: false };
2200
2201 let params = MyPreventedMatchesParams::builder("BTCUSDT".to_string(),).build().unwrap();
2202
2203 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSDT","preventedMatchId":1,"takerOrderId":5,"makerSymbol":"BTCUSDT","makerOrderId":3,"tradeGroupId":1,"selfTradePreventionMode":"EXPIRE_MAKER","price":"1.100000","makerPreventedQuantity":"1.300000","transactTime":1669101687094}]"#).unwrap_or_else(|_| serde_json::json!({}));
2204 let expected_response : Vec<models::MyPreventedMatchesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::MyPreventedMatchesResponseInner>");
2205
2206 let resp = client.my_prevented_matches(params).await.expect("Expected a response");
2207 let data_future = resp.data();
2208 let actual_response = data_future.await.unwrap();
2209 assert_eq!(actual_response, expected_response);
2210 });
2211 }
2212
2213 #[test]
2214 fn my_prevented_matches_optional_params_success() {
2215 TOKIO_SHARED_RT.block_on(async {
2216 let client = MockAccountApiClient { force_error: false };
2217
2218 let params = MyPreventedMatchesParams::builder("BTCUSDT".to_string(),).prevented_match_id(1).order_id(1).from_prevented_match_id(1).limit(1).recv_window(dec!(5000)).build().unwrap();
2219
2220 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSDT","preventedMatchId":1,"takerOrderId":5,"makerSymbol":"BTCUSDT","makerOrderId":3,"tradeGroupId":1,"selfTradePreventionMode":"EXPIRE_MAKER","price":"1.100000","makerPreventedQuantity":"1.300000","transactTime":1669101687094}]"#).unwrap_or_else(|_| serde_json::json!({}));
2221 let expected_response : Vec<models::MyPreventedMatchesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::MyPreventedMatchesResponseInner>");
2222
2223 let resp = client.my_prevented_matches(params).await.expect("Expected a response");
2224 let data_future = resp.data();
2225 let actual_response = data_future.await.unwrap();
2226 assert_eq!(actual_response, expected_response);
2227 });
2228 }
2229
2230 #[test]
2231 fn my_prevented_matches_response_error() {
2232 TOKIO_SHARED_RT.block_on(async {
2233 let client = MockAccountApiClient { force_error: true };
2234
2235 let params = MyPreventedMatchesParams::builder("BTCUSDT".to_string())
2236 .build()
2237 .unwrap();
2238
2239 match client.my_prevented_matches(params).await {
2240 Ok(_) => panic!("Expected an error"),
2241 Err(err) => {
2242 assert_eq!(err.to_string(), "Connector client error: ResponseError");
2243 }
2244 }
2245 });
2246 }
2247
2248 #[test]
2249 fn my_trades_required_params_success() {
2250 TOKIO_SHARED_RT.block_on(async {
2251 let client = MockAccountApiClient { force_error: false };
2252
2253 let params = MyTradesParams::builder("BNBBTC".to_string(),).build().unwrap();
2254
2255 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BNBBTC","id":28457,"orderId":100234,"orderListId":-1,"price":"4.00000100","qty":"12.00000000","quoteQty":"48.000012","commission":"10.10000000","commissionAsset":"BNB","time":1499865549590,"isBuyer":true,"isMaker":false,"isBestMatch":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2256 let expected_response : Vec<models::MyTradesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::MyTradesResponseInner>");
2257
2258 let resp = client.my_trades(params).await.expect("Expected a response");
2259 let data_future = resp.data();
2260 let actual_response = data_future.await.unwrap();
2261 assert_eq!(actual_response, expected_response);
2262 });
2263 }
2264
2265 #[test]
2266 fn my_trades_optional_params_success() {
2267 TOKIO_SHARED_RT.block_on(async {
2268 let client = MockAccountApiClient { force_error: false };
2269
2270 let params = MyTradesParams::builder("BNBBTC".to_string(),).order_id(100234).start_time(1735693200000).end_time(1735693200000).from_id(1).limit(1).recv_window(dec!(5000)).build().unwrap();
2271
2272 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BNBBTC","id":28457,"orderId":100234,"orderListId":-1,"price":"4.00000100","qty":"12.00000000","quoteQty":"48.000012","commission":"10.10000000","commissionAsset":"BNB","time":1499865549590,"isBuyer":true,"isMaker":false,"isBestMatch":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2273 let expected_response : Vec<models::MyTradesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::MyTradesResponseInner>");
2274
2275 let resp = client.my_trades(params).await.expect("Expected a response");
2276 let data_future = resp.data();
2277 let actual_response = data_future.await.unwrap();
2278 assert_eq!(actual_response, expected_response);
2279 });
2280 }
2281
2282 #[test]
2283 fn my_trades_response_error() {
2284 TOKIO_SHARED_RT.block_on(async {
2285 let client = MockAccountApiClient { force_error: true };
2286
2287 let params = MyTradesParams::builder("BNBBTC".to_string())
2288 .build()
2289 .unwrap();
2290
2291 match client.my_trades(params).await {
2292 Ok(_) => panic!("Expected an error"),
2293 Err(err) => {
2294 assert_eq!(err.to_string(), "Connector client error: ResponseError");
2295 }
2296 }
2297 });
2298 }
2299
2300 #[test]
2301 fn open_order_list_required_params_success() {
2302 TOKIO_SHARED_RT.block_on(async {
2303 let client = MockAccountApiClient { force_error: false };
2304
2305 let params = OpenOrderListParams::builder().build().unwrap();
2306
2307 let resp_json: Value = serde_json::from_str(r#"[{"orderListId":31,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"wuB13fmulKj3YjdqWEcsnp","transactionTime":1565246080644,"symbol":"LTCBTC","orders":[{"symbol":"LTCBTC","orderId":4,"clientOrderId":"r3EH2N76dHfLoSZWIUw1bT"}]}]"#).unwrap_or_else(|_| serde_json::json!({}));
2308 let expected_response : Vec<models::OpenOrderListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::OpenOrderListResponseInner>");
2309
2310 let resp = client.open_order_list(params).await.expect("Expected a response");
2311 let data_future = resp.data();
2312 let actual_response = data_future.await.unwrap();
2313 assert_eq!(actual_response, expected_response);
2314 });
2315 }
2316
2317 #[test]
2318 fn open_order_list_optional_params_success() {
2319 TOKIO_SHARED_RT.block_on(async {
2320 let client = MockAccountApiClient { force_error: false };
2321
2322 let params = OpenOrderListParams::builder().recv_window(dec!(5000)).build().unwrap();
2323
2324 let resp_json: Value = serde_json::from_str(r#"[{"orderListId":31,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"wuB13fmulKj3YjdqWEcsnp","transactionTime":1565246080644,"symbol":"LTCBTC","orders":[{"symbol":"LTCBTC","orderId":4,"clientOrderId":"r3EH2N76dHfLoSZWIUw1bT"}]}]"#).unwrap_or_else(|_| serde_json::json!({}));
2325 let expected_response : Vec<models::OpenOrderListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::OpenOrderListResponseInner>");
2326
2327 let resp = client.open_order_list(params).await.expect("Expected a response");
2328 let data_future = resp.data();
2329 let actual_response = data_future.await.unwrap();
2330 assert_eq!(actual_response, expected_response);
2331 });
2332 }
2333
2334 #[test]
2335 fn open_order_list_response_error() {
2336 TOKIO_SHARED_RT.block_on(async {
2337 let client = MockAccountApiClient { force_error: true };
2338
2339 let params = OpenOrderListParams::builder().build().unwrap();
2340
2341 match client.open_order_list(params).await {
2342 Ok(_) => panic!("Expected an error"),
2343 Err(err) => {
2344 assert_eq!(err.to_string(), "Connector client error: ResponseError");
2345 }
2346 }
2347 });
2348 }
2349
2350 #[test]
2351 fn order_amendments_required_params_success() {
2352 TOKIO_SHARED_RT.block_on(async {
2353 let client = MockAccountApiClient { force_error: false };
2354
2355 let params = OrderAmendmentsParams::builder("BTCUSDT".to_string(),9,).build().unwrap();
2356
2357 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSDT","orderId":9,"executionId":22,"origClientOrderId":"W0fJ9fiLKHOJutovPK3oJp","newClientOrderId":"UQ1Np3bmQ71jJzsSDW9Vpi","origQty":"5.00000000","newQty":"4.00000000","time":1741669661670}]"#).unwrap_or_else(|_| serde_json::json!({}));
2358 let expected_response : Vec<models::OrderAmendmentsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::OrderAmendmentsResponseInner>");
2359
2360 let resp = client.order_amendments(params).await.expect("Expected a response");
2361 let data_future = resp.data();
2362 let actual_response = data_future.await.unwrap();
2363 assert_eq!(actual_response, expected_response);
2364 });
2365 }
2366
2367 #[test]
2368 fn order_amendments_optional_params_success() {
2369 TOKIO_SHARED_RT.block_on(async {
2370 let client = MockAccountApiClient { force_error: false };
2371
2372 let params = OrderAmendmentsParams::builder("BTCUSDT".to_string(),9,).from_execution_id(22).limit(1).recv_window(dec!(5000)).build().unwrap();
2373
2374 let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSDT","orderId":9,"executionId":22,"origClientOrderId":"W0fJ9fiLKHOJutovPK3oJp","newClientOrderId":"UQ1Np3bmQ71jJzsSDW9Vpi","origQty":"5.00000000","newQty":"4.00000000","time":1741669661670}]"#).unwrap_or_else(|_| serde_json::json!({}));
2375 let expected_response : Vec<models::OrderAmendmentsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::OrderAmendmentsResponseInner>");
2376
2377 let resp = client.order_amendments(params).await.expect("Expected a response");
2378 let data_future = resp.data();
2379 let actual_response = data_future.await.unwrap();
2380 assert_eq!(actual_response, expected_response);
2381 });
2382 }
2383
2384 #[test]
2385 fn order_amendments_response_error() {
2386 TOKIO_SHARED_RT.block_on(async {
2387 let client = MockAccountApiClient { force_error: true };
2388
2389 let params = OrderAmendmentsParams::builder("BTCUSDT".to_string(), 9)
2390 .build()
2391 .unwrap();
2392
2393 match client.order_amendments(params).await {
2394 Ok(_) => panic!("Expected an error"),
2395 Err(err) => {
2396 assert_eq!(err.to_string(), "Connector client error: ResponseError");
2397 }
2398 }
2399 });
2400 }
2401
2402 #[test]
2403 fn rate_limit_order_required_params_success() {
2404 TOKIO_SHARED_RT.block_on(async {
2405 let client = MockAccountApiClient { force_error: false };
2406
2407 let params = RateLimitOrderParams::builder().build().unwrap();
2408
2409 let resp_json: Value = serde_json::from_str(r#"[{"rateLimitType":"ORDERS","interval":"SECOND","intervalNum":10,"limit":50,"count":0}]"#).unwrap_or_else(|_| serde_json::json!({}));
2410 let expected_response : Vec<models::RateLimitOrderResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::RateLimitOrderResponseInner>");
2411
2412 let resp = client.rate_limit_order(params).await.expect("Expected a response");
2413 let data_future = resp.data();
2414 let actual_response = data_future.await.unwrap();
2415 assert_eq!(actual_response, expected_response);
2416 });
2417 }
2418
2419 #[test]
2420 fn rate_limit_order_optional_params_success() {
2421 TOKIO_SHARED_RT.block_on(async {
2422 let client = MockAccountApiClient { force_error: false };
2423
2424 let params = RateLimitOrderParams::builder().recv_window(dec!(5000)).build().unwrap();
2425
2426 let resp_json: Value = serde_json::from_str(r#"[{"rateLimitType":"ORDERS","interval":"SECOND","intervalNum":10,"limit":50,"count":0}]"#).unwrap_or_else(|_| serde_json::json!({}));
2427 let expected_response : Vec<models::RateLimitOrderResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::RateLimitOrderResponseInner>");
2428
2429 let resp = client.rate_limit_order(params).await.expect("Expected a response");
2430 let data_future = resp.data();
2431 let actual_response = data_future.await.unwrap();
2432 assert_eq!(actual_response, expected_response);
2433 });
2434 }
2435
2436 #[test]
2437 fn rate_limit_order_response_error() {
2438 TOKIO_SHARED_RT.block_on(async {
2439 let client = MockAccountApiClient { force_error: true };
2440
2441 let params = RateLimitOrderParams::builder().build().unwrap();
2442
2443 match client.rate_limit_order(params).await {
2444 Ok(_) => panic!("Expected an error"),
2445 Err(err) => {
2446 assert_eq!(err.to_string(), "Connector client error: ResponseError");
2447 }
2448 }
2449 });
2450 }
2451}