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