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::sub_account::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait AccountManagementApi: Send + Sync {
34 async fn create_a_virtual_sub_account(
35 &self,
36 params: CreateAVirtualSubAccountParams,
37 ) -> anyhow::Result<RestApiResponse<models::CreateAVirtualSubAccountResponse>>;
38 async fn enable_futures_for_sub_account(
39 &self,
40 params: EnableFuturesForSubAccountParams,
41 ) -> anyhow::Result<RestApiResponse<models::EnableFuturesForSubAccountResponse>>;
42 async fn enable_options_for_sub_account(
43 &self,
44 params: EnableOptionsForSubAccountParams,
45 ) -> anyhow::Result<RestApiResponse<models::EnableOptionsForSubAccountResponse>>;
46 async fn get_futures_position_risk_of_sub_account(
47 &self,
48 params: GetFuturesPositionRiskOfSubAccountParams,
49 ) -> anyhow::Result<RestApiResponse<Vec<models::GetFuturesPositionRiskOfSubAccountResponseInner>>>;
50 async fn get_futures_position_risk_of_sub_account_v2(
51 &self,
52 params: GetFuturesPositionRiskOfSubAccountV2Params,
53 ) -> anyhow::Result<RestApiResponse<models::GetFuturesPositionRiskOfSubAccountV2Response>>;
54 async fn get_sub_accounts_status_on_margin_or_futures(
55 &self,
56 params: GetSubAccountsStatusOnMarginOrFuturesParams,
57 ) -> anyhow::Result<
58 RestApiResponse<Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>>,
59 >;
60 async fn query_sub_account_list(
61 &self,
62 params: QuerySubAccountListParams,
63 ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountListResponse>>;
64 async fn query_sub_account_transaction_statistics(
65 &self,
66 params: QuerySubAccountTransactionStatisticsParams,
67 ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountTransactionStatisticsResponse>>;
68}
69
70#[derive(Debug, Clone)]
71pub struct AccountManagementApiClient {
72 configuration: ConfigurationRestApi,
73}
74
75impl AccountManagementApiClient {
76 pub fn new(configuration: ConfigurationRestApi) -> Self {
77 Self { configuration }
78 }
79}
80
81#[derive(Clone, Debug, Builder, Deserialize)]
86#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
87pub struct CreateAVirtualSubAccountParams {
88 #[builder(setter(into))]
92 #[serde(rename = "subAccountString")]
93 pub sub_account_string: String,
94 #[builder(setter(into), default)]
99 #[serde(rename = "recvWindow", default)]
100 pub recv_window: Option<i64>,
101}
102
103impl CreateAVirtualSubAccountParams {
104 #[must_use]
111 pub fn builder(sub_account_string: String) -> CreateAVirtualSubAccountParamsBuilder {
112 CreateAVirtualSubAccountParamsBuilder::default().sub_account_string(sub_account_string)
113 }
114}
115#[derive(Clone, Debug, Builder, Deserialize)]
120#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
121pub struct EnableFuturesForSubAccountParams {
122 #[builder(setter(into))]
127 #[serde(rename = "email")]
128 pub email: String,
129 #[builder(setter(into), default)]
134 #[serde(rename = "recvWindow", default)]
135 pub recv_window: Option<i64>,
136}
137
138impl EnableFuturesForSubAccountParams {
139 #[must_use]
146 pub fn builder(email: String) -> EnableFuturesForSubAccountParamsBuilder {
147 EnableFuturesForSubAccountParamsBuilder::default().email(email)
148 }
149}
150#[derive(Clone, Debug, Builder, Deserialize)]
155#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
156pub struct EnableOptionsForSubAccountParams {
157 #[builder(setter(into))]
162 #[serde(rename = "email")]
163 pub email: String,
164 #[builder(setter(into), default)]
169 #[serde(rename = "recvWindow", default)]
170 pub recv_window: Option<i64>,
171}
172
173impl EnableOptionsForSubAccountParams {
174 #[must_use]
181 pub fn builder(email: String) -> EnableOptionsForSubAccountParamsBuilder {
182 EnableOptionsForSubAccountParamsBuilder::default().email(email)
183 }
184}
185#[derive(Clone, Debug, Builder, Deserialize)]
190#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
191pub struct GetFuturesPositionRiskOfSubAccountParams {
192 #[builder(setter(into))]
197 #[serde(rename = "email")]
198 pub email: String,
199 #[builder(setter(into), default)]
204 #[serde(rename = "recvWindow", default)]
205 pub recv_window: Option<i64>,
206}
207
208impl GetFuturesPositionRiskOfSubAccountParams {
209 #[must_use]
216 pub fn builder(email: String) -> GetFuturesPositionRiskOfSubAccountParamsBuilder {
217 GetFuturesPositionRiskOfSubAccountParamsBuilder::default().email(email)
218 }
219}
220#[derive(Clone, Debug, Builder, Deserialize)]
225#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
226pub struct GetFuturesPositionRiskOfSubAccountV2Params {
227 #[builder(setter(into))]
232 #[serde(rename = "email")]
233 pub email: String,
234 #[builder(setter(into))]
238 #[serde(rename = "futuresType")]
239 pub futures_type: i64,
240 #[builder(setter(into), default)]
245 #[serde(rename = "recvWindow", default)]
246 pub recv_window: Option<i64>,
247}
248
249impl GetFuturesPositionRiskOfSubAccountV2Params {
250 #[must_use]
258 pub fn builder(
259 email: String,
260 futures_type: i64,
261 ) -> GetFuturesPositionRiskOfSubAccountV2ParamsBuilder {
262 GetFuturesPositionRiskOfSubAccountV2ParamsBuilder::default()
263 .email(email)
264 .futures_type(futures_type)
265 }
266}
267#[derive(Clone, Debug, Builder, Deserialize, Default)]
272#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
273pub struct GetSubAccountsStatusOnMarginOrFuturesParams {
274 #[builder(setter(into), default)]
279 #[serde(rename = "email", default)]
280 pub email: Option<String>,
281 #[builder(setter(into), default)]
286 #[serde(rename = "recvWindow", default)]
287 pub recv_window: Option<i64>,
288}
289
290impl GetSubAccountsStatusOnMarginOrFuturesParams {
291 #[must_use]
294 pub fn builder() -> GetSubAccountsStatusOnMarginOrFuturesParamsBuilder {
295 GetSubAccountsStatusOnMarginOrFuturesParamsBuilder::default()
296 }
297}
298#[derive(Clone, Debug, Builder, Deserialize, Default)]
303#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
304pub struct QuerySubAccountListParams {
305 #[builder(setter(into), default)]
310 #[serde(rename = "email", default)]
311 pub email: Option<String>,
312 #[builder(setter(into), default)]
317 #[serde(rename = "isFreeze", default)]
318 pub is_freeze: Option<String>,
319 #[builder(setter(into), default)]
324 #[serde(rename = "page", default)]
325 pub page: Option<i64>,
326 #[builder(setter(into), default)]
331 #[serde(rename = "limit", default)]
332 pub limit: Option<i64>,
333 #[builder(setter(into), default)]
338 #[serde(rename = "recvWindow", default)]
339 pub recv_window: Option<i64>,
340}
341
342impl QuerySubAccountListParams {
343 #[must_use]
346 pub fn builder() -> QuerySubAccountListParamsBuilder {
347 QuerySubAccountListParamsBuilder::default()
348 }
349}
350#[derive(Clone, Debug, Builder, Deserialize, Default)]
355#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
356pub struct QuerySubAccountTransactionStatisticsParams {
357 #[builder(setter(into), default)]
361 #[serde(rename = "email", default)]
362 pub email: Option<String>,
363 #[builder(setter(into), default)]
368 #[serde(rename = "recvWindow", default)]
369 pub recv_window: Option<i64>,
370}
371
372impl QuerySubAccountTransactionStatisticsParams {
373 #[must_use]
376 pub fn builder() -> QuerySubAccountTransactionStatisticsParamsBuilder {
377 QuerySubAccountTransactionStatisticsParamsBuilder::default()
378 }
379}
380
381#[async_trait]
382impl AccountManagementApi for AccountManagementApiClient {
383 async fn create_a_virtual_sub_account(
384 &self,
385 params: CreateAVirtualSubAccountParams,
386 ) -> anyhow::Result<RestApiResponse<models::CreateAVirtualSubAccountResponse>> {
387 let CreateAVirtualSubAccountParams {
388 sub_account_string,
389 recv_window,
390 } = params;
391
392 let mut query_params = BTreeMap::new();
393 let body_params = BTreeMap::new();
394
395 query_params.insert("subAccountString".to_string(), json!(sub_account_string));
396
397 if let Some(rw) = recv_window {
398 query_params.insert("recvWindow".to_string(), json!(rw));
399 }
400
401 send_request::<models::CreateAVirtualSubAccountResponse>(
402 &self.configuration,
403 "/sapi/v1/sub-account/virtualSubAccount",
404 reqwest::Method::POST,
405 query_params,
406 body_params,
407 if HAS_TIME_UNIT {
408 self.configuration.time_unit
409 } else {
410 None
411 },
412 true,
413 )
414 .await
415 }
416
417 async fn enable_futures_for_sub_account(
418 &self,
419 params: EnableFuturesForSubAccountParams,
420 ) -> anyhow::Result<RestApiResponse<models::EnableFuturesForSubAccountResponse>> {
421 let EnableFuturesForSubAccountParams { email, recv_window } = params;
422
423 let mut query_params = BTreeMap::new();
424 let body_params = BTreeMap::new();
425
426 query_params.insert("email".to_string(), json!(email));
427
428 if let Some(rw) = recv_window {
429 query_params.insert("recvWindow".to_string(), json!(rw));
430 }
431
432 send_request::<models::EnableFuturesForSubAccountResponse>(
433 &self.configuration,
434 "/sapi/v1/sub-account/futures/enable",
435 reqwest::Method::POST,
436 query_params,
437 body_params,
438 if HAS_TIME_UNIT {
439 self.configuration.time_unit
440 } else {
441 None
442 },
443 true,
444 )
445 .await
446 }
447
448 async fn enable_options_for_sub_account(
449 &self,
450 params: EnableOptionsForSubAccountParams,
451 ) -> anyhow::Result<RestApiResponse<models::EnableOptionsForSubAccountResponse>> {
452 let EnableOptionsForSubAccountParams { email, recv_window } = params;
453
454 let mut query_params = BTreeMap::new();
455 let body_params = BTreeMap::new();
456
457 query_params.insert("email".to_string(), json!(email));
458
459 if let Some(rw) = recv_window {
460 query_params.insert("recvWindow".to_string(), json!(rw));
461 }
462
463 send_request::<models::EnableOptionsForSubAccountResponse>(
464 &self.configuration,
465 "/sapi/v1/sub-account/eoptions/enable",
466 reqwest::Method::POST,
467 query_params,
468 body_params,
469 if HAS_TIME_UNIT {
470 self.configuration.time_unit
471 } else {
472 None
473 },
474 true,
475 )
476 .await
477 }
478
479 async fn get_futures_position_risk_of_sub_account(
480 &self,
481 params: GetFuturesPositionRiskOfSubAccountParams,
482 ) -> anyhow::Result<RestApiResponse<Vec<models::GetFuturesPositionRiskOfSubAccountResponseInner>>>
483 {
484 let GetFuturesPositionRiskOfSubAccountParams { email, recv_window } = params;
485
486 let mut query_params = BTreeMap::new();
487 let body_params = BTreeMap::new();
488
489 query_params.insert("email".to_string(), json!(email));
490
491 if let Some(rw) = recv_window {
492 query_params.insert("recvWindow".to_string(), json!(rw));
493 }
494
495 send_request::<Vec<models::GetFuturesPositionRiskOfSubAccountResponseInner>>(
496 &self.configuration,
497 "/sapi/v1/sub-account/futures/positionRisk",
498 reqwest::Method::GET,
499 query_params,
500 body_params,
501 if HAS_TIME_UNIT {
502 self.configuration.time_unit
503 } else {
504 None
505 },
506 true,
507 )
508 .await
509 }
510
511 async fn get_futures_position_risk_of_sub_account_v2(
512 &self,
513 params: GetFuturesPositionRiskOfSubAccountV2Params,
514 ) -> anyhow::Result<RestApiResponse<models::GetFuturesPositionRiskOfSubAccountV2Response>> {
515 let GetFuturesPositionRiskOfSubAccountV2Params {
516 email,
517 futures_type,
518 recv_window,
519 } = params;
520
521 let mut query_params = BTreeMap::new();
522 let body_params = BTreeMap::new();
523
524 query_params.insert("email".to_string(), json!(email));
525
526 query_params.insert("futuresType".to_string(), json!(futures_type));
527
528 if let Some(rw) = recv_window {
529 query_params.insert("recvWindow".to_string(), json!(rw));
530 }
531
532 send_request::<models::GetFuturesPositionRiskOfSubAccountV2Response>(
533 &self.configuration,
534 "/sapi/v2/sub-account/futures/positionRisk",
535 reqwest::Method::GET,
536 query_params,
537 body_params,
538 if HAS_TIME_UNIT {
539 self.configuration.time_unit
540 } else {
541 None
542 },
543 true,
544 )
545 .await
546 }
547
548 async fn get_sub_accounts_status_on_margin_or_futures(
549 &self,
550 params: GetSubAccountsStatusOnMarginOrFuturesParams,
551 ) -> anyhow::Result<
552 RestApiResponse<Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>>,
553 > {
554 let GetSubAccountsStatusOnMarginOrFuturesParams { email, recv_window } = params;
555
556 let mut query_params = BTreeMap::new();
557 let body_params = BTreeMap::new();
558
559 if let Some(rw) = email {
560 query_params.insert("email".to_string(), json!(rw));
561 }
562
563 if let Some(rw) = recv_window {
564 query_params.insert("recvWindow".to_string(), json!(rw));
565 }
566
567 send_request::<Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>>(
568 &self.configuration,
569 "/sapi/v1/sub-account/status",
570 reqwest::Method::GET,
571 query_params,
572 body_params,
573 if HAS_TIME_UNIT {
574 self.configuration.time_unit
575 } else {
576 None
577 },
578 true,
579 )
580 .await
581 }
582
583 async fn query_sub_account_list(
584 &self,
585 params: QuerySubAccountListParams,
586 ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountListResponse>> {
587 let QuerySubAccountListParams {
588 email,
589 is_freeze,
590 page,
591 limit,
592 recv_window,
593 } = params;
594
595 let mut query_params = BTreeMap::new();
596 let body_params = BTreeMap::new();
597
598 if let Some(rw) = email {
599 query_params.insert("email".to_string(), json!(rw));
600 }
601
602 if let Some(rw) = is_freeze {
603 query_params.insert("isFreeze".to_string(), json!(rw));
604 }
605
606 if let Some(rw) = page {
607 query_params.insert("page".to_string(), json!(rw));
608 }
609
610 if let Some(rw) = limit {
611 query_params.insert("limit".to_string(), json!(rw));
612 }
613
614 if let Some(rw) = recv_window {
615 query_params.insert("recvWindow".to_string(), json!(rw));
616 }
617
618 send_request::<models::QuerySubAccountListResponse>(
619 &self.configuration,
620 "/sapi/v1/sub-account/list",
621 reqwest::Method::GET,
622 query_params,
623 body_params,
624 if HAS_TIME_UNIT {
625 self.configuration.time_unit
626 } else {
627 None
628 },
629 true,
630 )
631 .await
632 }
633
634 async fn query_sub_account_transaction_statistics(
635 &self,
636 params: QuerySubAccountTransactionStatisticsParams,
637 ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountTransactionStatisticsResponse>> {
638 let QuerySubAccountTransactionStatisticsParams { email, recv_window } = params;
639
640 let mut query_params = BTreeMap::new();
641 let body_params = BTreeMap::new();
642
643 if let Some(rw) = email {
644 query_params.insert("email".to_string(), json!(rw));
645 }
646
647 if let Some(rw) = recv_window {
648 query_params.insert("recvWindow".to_string(), json!(rw));
649 }
650
651 send_request::<models::QuerySubAccountTransactionStatisticsResponse>(
652 &self.configuration,
653 "/sapi/v1/sub-account/transaction-statistics",
654 reqwest::Method::GET,
655 query_params,
656 body_params,
657 if HAS_TIME_UNIT {
658 self.configuration.time_unit
659 } else {
660 None
661 },
662 true,
663 )
664 .await
665 }
666}
667
668#[cfg(all(test, feature = "sub_account"))]
669mod tests {
670 use super::*;
671 use crate::TOKIO_SHARED_RT;
672 use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
673 use async_trait::async_trait;
674 use std::collections::HashMap;
675
676 struct DummyRestApiResponse<T> {
677 inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
678 status: u16,
679 headers: HashMap<String, String>,
680 rate_limits: Option<Vec<RestApiRateLimit>>,
681 }
682
683 impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
684 fn from(dummy: DummyRestApiResponse<T>) -> Self {
685 Self {
686 data_fn: dummy.inner,
687 status: dummy.status,
688 headers: dummy.headers,
689 rate_limits: dummy.rate_limits,
690 }
691 }
692 }
693
694 struct MockAccountManagementApiClient {
695 force_error: bool,
696 }
697
698 #[async_trait]
699 impl AccountManagementApi for MockAccountManagementApiClient {
700 async fn create_a_virtual_sub_account(
701 &self,
702 _params: CreateAVirtualSubAccountParams,
703 ) -> anyhow::Result<RestApiResponse<models::CreateAVirtualSubAccountResponse>> {
704 if self.force_error {
705 return Err(ConnectorError::ConnectorClientError {
706 msg: "ResponseError".to_string(),
707 code: None,
708 }
709 .into());
710 }
711
712 let resp_json: Value =
713 serde_json::from_str(r#"{"email":"addsdd_virtual@aasaixwqnoemail.com"}"#)
714 .unwrap_or_else(|_| serde_json::json!({}));
715 let dummy_response: models::CreateAVirtualSubAccountResponse =
716 serde_json::from_value(resp_json.clone())
717 .expect("should parse into models::CreateAVirtualSubAccountResponse");
718
719 let dummy = DummyRestApiResponse {
720 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
721 status: 200,
722 headers: HashMap::new(),
723 rate_limits: None,
724 };
725
726 Ok(dummy.into())
727 }
728
729 async fn enable_futures_for_sub_account(
730 &self,
731 _params: EnableFuturesForSubAccountParams,
732 ) -> anyhow::Result<RestApiResponse<models::EnableFuturesForSubAccountResponse>> {
733 if self.force_error {
734 return Err(ConnectorError::ConnectorClientError {
735 msg: "ResponseError".to_string(),
736 code: None,
737 }
738 .into());
739 }
740
741 let resp_json: Value =
742 serde_json::from_str(r#"{"email":"123@test.com","isFuturesEnabled":true}"#)
743 .unwrap_or_else(|_| serde_json::json!({}));
744 let dummy_response: models::EnableFuturesForSubAccountResponse =
745 serde_json::from_value(resp_json.clone())
746 .expect("should parse into models::EnableFuturesForSubAccountResponse");
747
748 let dummy = DummyRestApiResponse {
749 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
750 status: 200,
751 headers: HashMap::new(),
752 rate_limits: None,
753 };
754
755 Ok(dummy.into())
756 }
757
758 async fn enable_options_for_sub_account(
759 &self,
760 _params: EnableOptionsForSubAccountParams,
761 ) -> anyhow::Result<RestApiResponse<models::EnableOptionsForSubAccountResponse>> {
762 if self.force_error {
763 return Err(ConnectorError::ConnectorClientError {
764 msg: "ResponseError".to_string(),
765 code: None,
766 }
767 .into());
768 }
769
770 let resp_json: Value =
771 serde_json::from_str(r#"{"email":"123@test.com","isEOptionsEnabled":true}"#)
772 .unwrap_or_else(|_| serde_json::json!({}));
773 let dummy_response: models::EnableOptionsForSubAccountResponse =
774 serde_json::from_value(resp_json.clone())
775 .expect("should parse into models::EnableOptionsForSubAccountResponse");
776
777 let dummy = DummyRestApiResponse {
778 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
779 status: 200,
780 headers: HashMap::new(),
781 rate_limits: None,
782 };
783
784 Ok(dummy.into())
785 }
786
787 async fn get_futures_position_risk_of_sub_account(
788 &self,
789 _params: GetFuturesPositionRiskOfSubAccountParams,
790 ) -> anyhow::Result<
791 RestApiResponse<Vec<models::GetFuturesPositionRiskOfSubAccountResponseInner>>,
792 > {
793 if self.force_error {
794 return Err(ConnectorError::ConnectorClientError {
795 msg: "ResponseError".to_string(),
796 code: None,
797 }
798 .into());
799 }
800
801 let resp_json: Value = serde_json::from_str(r#"[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}]"#).unwrap_or_else(|_| serde_json::json!({}));
802 let dummy_response : Vec<models::GetFuturesPositionRiskOfSubAccountResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetFuturesPositionRiskOfSubAccountResponseInner>");
803
804 let dummy = DummyRestApiResponse {
805 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
806 status: 200,
807 headers: HashMap::new(),
808 rate_limits: None,
809 };
810
811 Ok(dummy.into())
812 }
813
814 async fn get_futures_position_risk_of_sub_account_v2(
815 &self,
816 _params: GetFuturesPositionRiskOfSubAccountV2Params,
817 ) -> anyhow::Result<RestApiResponse<models::GetFuturesPositionRiskOfSubAccountV2Response>>
818 {
819 if self.force_error {
820 return Err(ConnectorError::ConnectorClientError {
821 msg: "ResponseError".to_string(),
822 code: None,
823 }
824 .into());
825 }
826
827 let resp_json: Value = serde_json::from_str(r#"{"futurePositionRiskVos":[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}],"deliveryPositionRiskVos":[{"entryPrice":"9975.12000","markPrice":"9973.50770517","leverage":"20","isolated":"false","isolatedWallet":"9973.50770517","isolatedMargin":"0.00000000","isAutoAddMargin":"false","positionSide":"BOTH","positionAmount":"1.230","symbol":"BTCUSD_201225","unrealizedProfit":"-0.01612295"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
828 let dummy_response: models::GetFuturesPositionRiskOfSubAccountV2Response =
829 serde_json::from_value(resp_json.clone()).expect(
830 "should parse into models::GetFuturesPositionRiskOfSubAccountV2Response",
831 );
832
833 let dummy = DummyRestApiResponse {
834 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
835 status: 200,
836 headers: HashMap::new(),
837 rate_limits: None,
838 };
839
840 Ok(dummy.into())
841 }
842
843 async fn get_sub_accounts_status_on_margin_or_futures(
844 &self,
845 _params: GetSubAccountsStatusOnMarginOrFuturesParams,
846 ) -> anyhow::Result<
847 RestApiResponse<Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>>,
848 > {
849 if self.force_error {
850 return Err(ConnectorError::ConnectorClientError {
851 msg: "ResponseError".to_string(),
852 code: None,
853 }
854 .into());
855 }
856
857 let resp_json: Value = serde_json::from_str(r#"[{"email":"123@test.com","isSubUserEnabled":true,"isUserActive":true,"insertTime":1570791523523,"isMarginEnabled":true,"isFutureEnabled":true,"mobile":1570791523523}]"#).unwrap_or_else(|_| serde_json::json!({}));
858 let dummy_response : Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>");
859
860 let dummy = DummyRestApiResponse {
861 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
862 status: 200,
863 headers: HashMap::new(),
864 rate_limits: None,
865 };
866
867 Ok(dummy.into())
868 }
869
870 async fn query_sub_account_list(
871 &self,
872 _params: QuerySubAccountListParams,
873 ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountListResponse>> {
874 if self.force_error {
875 return Err(ConnectorError::ConnectorClientError {
876 msg: "ResponseError".to_string(),
877 code: None,
878 }
879 .into());
880 }
881
882 let resp_json: Value = serde_json::from_str(r#"{"subAccounts":[{"subUserId":123456,"email":"testsub@gmail.com","remark":"remark","isFreeze":false,"createTime":1544433328000,"isManagedSubAccount":false,"isAssetManagementSubAccount":false}]}"#).unwrap_or_else(|_| serde_json::json!({}));
883 let dummy_response: models::QuerySubAccountListResponse =
884 serde_json::from_value(resp_json.clone())
885 .expect("should parse into models::QuerySubAccountListResponse");
886
887 let dummy = DummyRestApiResponse {
888 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
889 status: 200,
890 headers: HashMap::new(),
891 rate_limits: None,
892 };
893
894 Ok(dummy.into())
895 }
896
897 async fn query_sub_account_transaction_statistics(
898 &self,
899 _params: QuerySubAccountTransactionStatisticsParams,
900 ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountTransactionStatisticsResponse>>
901 {
902 if self.force_error {
903 return Err(ConnectorError::ConnectorClientError {
904 msg: "ResponseError".to_string(),
905 code: None,
906 }
907 .into());
908 }
909
910 let resp_json: Value = serde_json::from_str(r#"{"recent30BtcTotal":"0","recent30BtcFuturesTotal":"0","recent30BtcMarginTotal":"0","recent30BusdTotal":"0","recent30BusdFuturesTotal":"0","recent30BusdMarginTotal":"0","tradeInfoVos":[{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1676851200000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
911 let dummy_response: models::QuerySubAccountTransactionStatisticsResponse =
912 serde_json::from_value(resp_json.clone()).expect(
913 "should parse into models::QuerySubAccountTransactionStatisticsResponse",
914 );
915
916 let dummy = DummyRestApiResponse {
917 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
918 status: 200,
919 headers: HashMap::new(),
920 rate_limits: None,
921 };
922
923 Ok(dummy.into())
924 }
925 }
926
927 #[test]
928 fn create_a_virtual_sub_account_required_params_success() {
929 TOKIO_SHARED_RT.block_on(async {
930 let client = MockAccountManagementApiClient { force_error: false };
931
932 let params = CreateAVirtualSubAccountParams::builder("testSubAccount".to_string())
933 .build()
934 .unwrap();
935
936 let resp_json: Value =
937 serde_json::from_str(r#"{"email":"addsdd_virtual@aasaixwqnoemail.com"}"#)
938 .unwrap_or_else(|_| serde_json::json!({}));
939 let expected_response: models::CreateAVirtualSubAccountResponse =
940 serde_json::from_value(resp_json.clone())
941 .expect("should parse into models::CreateAVirtualSubAccountResponse");
942
943 let resp = client
944 .create_a_virtual_sub_account(params)
945 .await
946 .expect("Expected a response");
947 let data_future = resp.data();
948 let actual_response = data_future.await.unwrap();
949 assert_eq!(actual_response, expected_response);
950 });
951 }
952
953 #[test]
954 fn create_a_virtual_sub_account_optional_params_success() {
955 TOKIO_SHARED_RT.block_on(async {
956 let client = MockAccountManagementApiClient { force_error: false };
957
958 let params = CreateAVirtualSubAccountParams::builder("testSubAccount".to_string())
959 .recv_window(5000)
960 .build()
961 .unwrap();
962
963 let resp_json: Value =
964 serde_json::from_str(r#"{"email":"addsdd_virtual@aasaixwqnoemail.com"}"#)
965 .unwrap_or_else(|_| serde_json::json!({}));
966 let expected_response: models::CreateAVirtualSubAccountResponse =
967 serde_json::from_value(resp_json.clone())
968 .expect("should parse into models::CreateAVirtualSubAccountResponse");
969
970 let resp = client
971 .create_a_virtual_sub_account(params)
972 .await
973 .expect("Expected a response");
974 let data_future = resp.data();
975 let actual_response = data_future.await.unwrap();
976 assert_eq!(actual_response, expected_response);
977 });
978 }
979
980 #[test]
981 fn create_a_virtual_sub_account_response_error() {
982 TOKIO_SHARED_RT.block_on(async {
983 let client = MockAccountManagementApiClient { force_error: true };
984
985 let params = CreateAVirtualSubAccountParams::builder("testSubAccount".to_string())
986 .build()
987 .unwrap();
988
989 match client.create_a_virtual_sub_account(params).await {
990 Ok(_) => panic!("Expected an error"),
991 Err(err) => {
992 assert_eq!(err.to_string(), "Connector client error: ResponseError");
993 }
994 }
995 });
996 }
997
998 #[test]
999 fn enable_futures_for_sub_account_required_params_success() {
1000 TOKIO_SHARED_RT.block_on(async {
1001 let client = MockAccountManagementApiClient { force_error: false };
1002
1003 let params = EnableFuturesForSubAccountParams::builder("123@test.com".to_string())
1004 .build()
1005 .unwrap();
1006
1007 let resp_json: Value =
1008 serde_json::from_str(r#"{"email":"123@test.com","isFuturesEnabled":true}"#)
1009 .unwrap_or_else(|_| serde_json::json!({}));
1010 let expected_response: models::EnableFuturesForSubAccountResponse =
1011 serde_json::from_value(resp_json.clone())
1012 .expect("should parse into models::EnableFuturesForSubAccountResponse");
1013
1014 let resp = client
1015 .enable_futures_for_sub_account(params)
1016 .await
1017 .expect("Expected a response");
1018 let data_future = resp.data();
1019 let actual_response = data_future.await.unwrap();
1020 assert_eq!(actual_response, expected_response);
1021 });
1022 }
1023
1024 #[test]
1025 fn enable_futures_for_sub_account_optional_params_success() {
1026 TOKIO_SHARED_RT.block_on(async {
1027 let client = MockAccountManagementApiClient { force_error: false };
1028
1029 let params = EnableFuturesForSubAccountParams::builder("123@test.com".to_string())
1030 .recv_window(5000)
1031 .build()
1032 .unwrap();
1033
1034 let resp_json: Value =
1035 serde_json::from_str(r#"{"email":"123@test.com","isFuturesEnabled":true}"#)
1036 .unwrap_or_else(|_| serde_json::json!({}));
1037 let expected_response: models::EnableFuturesForSubAccountResponse =
1038 serde_json::from_value(resp_json.clone())
1039 .expect("should parse into models::EnableFuturesForSubAccountResponse");
1040
1041 let resp = client
1042 .enable_futures_for_sub_account(params)
1043 .await
1044 .expect("Expected a response");
1045 let data_future = resp.data();
1046 let actual_response = data_future.await.unwrap();
1047 assert_eq!(actual_response, expected_response);
1048 });
1049 }
1050
1051 #[test]
1052 fn enable_futures_for_sub_account_response_error() {
1053 TOKIO_SHARED_RT.block_on(async {
1054 let client = MockAccountManagementApiClient { force_error: true };
1055
1056 let params = EnableFuturesForSubAccountParams::builder("123@test.com".to_string())
1057 .build()
1058 .unwrap();
1059
1060 match client.enable_futures_for_sub_account(params).await {
1061 Ok(_) => panic!("Expected an error"),
1062 Err(err) => {
1063 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1064 }
1065 }
1066 });
1067 }
1068
1069 #[test]
1070 fn enable_options_for_sub_account_required_params_success() {
1071 TOKIO_SHARED_RT.block_on(async {
1072 let client = MockAccountManagementApiClient { force_error: false };
1073
1074 let params = EnableOptionsForSubAccountParams::builder("123@test.com".to_string())
1075 .build()
1076 .unwrap();
1077
1078 let resp_json: Value =
1079 serde_json::from_str(r#"{"email":"123@test.com","isEOptionsEnabled":true}"#)
1080 .unwrap_or_else(|_| serde_json::json!({}));
1081 let expected_response: models::EnableOptionsForSubAccountResponse =
1082 serde_json::from_value(resp_json.clone())
1083 .expect("should parse into models::EnableOptionsForSubAccountResponse");
1084
1085 let resp = client
1086 .enable_options_for_sub_account(params)
1087 .await
1088 .expect("Expected a response");
1089 let data_future = resp.data();
1090 let actual_response = data_future.await.unwrap();
1091 assert_eq!(actual_response, expected_response);
1092 });
1093 }
1094
1095 #[test]
1096 fn enable_options_for_sub_account_optional_params_success() {
1097 TOKIO_SHARED_RT.block_on(async {
1098 let client = MockAccountManagementApiClient { force_error: false };
1099
1100 let params = EnableOptionsForSubAccountParams::builder("123@test.com".to_string())
1101 .recv_window(5000)
1102 .build()
1103 .unwrap();
1104
1105 let resp_json: Value =
1106 serde_json::from_str(r#"{"email":"123@test.com","isEOptionsEnabled":true}"#)
1107 .unwrap_or_else(|_| serde_json::json!({}));
1108 let expected_response: models::EnableOptionsForSubAccountResponse =
1109 serde_json::from_value(resp_json.clone())
1110 .expect("should parse into models::EnableOptionsForSubAccountResponse");
1111
1112 let resp = client
1113 .enable_options_for_sub_account(params)
1114 .await
1115 .expect("Expected a response");
1116 let data_future = resp.data();
1117 let actual_response = data_future.await.unwrap();
1118 assert_eq!(actual_response, expected_response);
1119 });
1120 }
1121
1122 #[test]
1123 fn enable_options_for_sub_account_response_error() {
1124 TOKIO_SHARED_RT.block_on(async {
1125 let client = MockAccountManagementApiClient { force_error: true };
1126
1127 let params = EnableOptionsForSubAccountParams::builder("123@test.com".to_string())
1128 .build()
1129 .unwrap();
1130
1131 match client.enable_options_for_sub_account(params).await {
1132 Ok(_) => panic!("Expected an error"),
1133 Err(err) => {
1134 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1135 }
1136 }
1137 });
1138 }
1139
1140 #[test]
1141 fn get_futures_position_risk_of_sub_account_required_params_success() {
1142 TOKIO_SHARED_RT.block_on(async {
1143 let client = MockAccountManagementApiClient { force_error: false };
1144
1145 let params = GetFuturesPositionRiskOfSubAccountParams::builder("123@test.com".to_string(),).build().unwrap();
1146
1147 let resp_json: Value = serde_json::from_str(r#"[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}]"#).unwrap_or_else(|_| serde_json::json!({}));
1148 let expected_response : Vec<models::GetFuturesPositionRiskOfSubAccountResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetFuturesPositionRiskOfSubAccountResponseInner>");
1149
1150 let resp = client.get_futures_position_risk_of_sub_account(params).await.expect("Expected a response");
1151 let data_future = resp.data();
1152 let actual_response = data_future.await.unwrap();
1153 assert_eq!(actual_response, expected_response);
1154 });
1155 }
1156
1157 #[test]
1158 fn get_futures_position_risk_of_sub_account_optional_params_success() {
1159 TOKIO_SHARED_RT.block_on(async {
1160 let client = MockAccountManagementApiClient { force_error: false };
1161
1162 let params = GetFuturesPositionRiskOfSubAccountParams::builder("123@test.com".to_string(),).recv_window(5000).build().unwrap();
1163
1164 let resp_json: Value = serde_json::from_str(r#"[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}]"#).unwrap_or_else(|_| serde_json::json!({}));
1165 let expected_response : Vec<models::GetFuturesPositionRiskOfSubAccountResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetFuturesPositionRiskOfSubAccountResponseInner>");
1166
1167 let resp = client.get_futures_position_risk_of_sub_account(params).await.expect("Expected a response");
1168 let data_future = resp.data();
1169 let actual_response = data_future.await.unwrap();
1170 assert_eq!(actual_response, expected_response);
1171 });
1172 }
1173
1174 #[test]
1175 fn get_futures_position_risk_of_sub_account_response_error() {
1176 TOKIO_SHARED_RT.block_on(async {
1177 let client = MockAccountManagementApiClient { force_error: true };
1178
1179 let params =
1180 GetFuturesPositionRiskOfSubAccountParams::builder("123@test.com".to_string())
1181 .build()
1182 .unwrap();
1183
1184 match client
1185 .get_futures_position_risk_of_sub_account(params)
1186 .await
1187 {
1188 Ok(_) => panic!("Expected an error"),
1189 Err(err) => {
1190 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1191 }
1192 }
1193 });
1194 }
1195
1196 #[test]
1197 fn get_futures_position_risk_of_sub_account_v2_required_params_success() {
1198 TOKIO_SHARED_RT.block_on(async {
1199 let client = MockAccountManagementApiClient { force_error: false };
1200
1201 let params = GetFuturesPositionRiskOfSubAccountV2Params::builder("123@test.com".to_string(),1,).build().unwrap();
1202
1203 let resp_json: Value = serde_json::from_str(r#"{"futurePositionRiskVos":[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}],"deliveryPositionRiskVos":[{"entryPrice":"9975.12000","markPrice":"9973.50770517","leverage":"20","isolated":"false","isolatedWallet":"9973.50770517","isolatedMargin":"0.00000000","isAutoAddMargin":"false","positionSide":"BOTH","positionAmount":"1.230","symbol":"BTCUSD_201225","unrealizedProfit":"-0.01612295"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
1204 let expected_response : models::GetFuturesPositionRiskOfSubAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetFuturesPositionRiskOfSubAccountV2Response");
1205
1206 let resp = client.get_futures_position_risk_of_sub_account_v2(params).await.expect("Expected a response");
1207 let data_future = resp.data();
1208 let actual_response = data_future.await.unwrap();
1209 assert_eq!(actual_response, expected_response);
1210 });
1211 }
1212
1213 #[test]
1214 fn get_futures_position_risk_of_sub_account_v2_optional_params_success() {
1215 TOKIO_SHARED_RT.block_on(async {
1216 let client = MockAccountManagementApiClient { force_error: false };
1217
1218 let params = GetFuturesPositionRiskOfSubAccountV2Params::builder("123@test.com".to_string(),1,).recv_window(5000).build().unwrap();
1219
1220 let resp_json: Value = serde_json::from_str(r#"{"futurePositionRiskVos":[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}],"deliveryPositionRiskVos":[{"entryPrice":"9975.12000","markPrice":"9973.50770517","leverage":"20","isolated":"false","isolatedWallet":"9973.50770517","isolatedMargin":"0.00000000","isAutoAddMargin":"false","positionSide":"BOTH","positionAmount":"1.230","symbol":"BTCUSD_201225","unrealizedProfit":"-0.01612295"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
1221 let expected_response : models::GetFuturesPositionRiskOfSubAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetFuturesPositionRiskOfSubAccountV2Response");
1222
1223 let resp = client.get_futures_position_risk_of_sub_account_v2(params).await.expect("Expected a response");
1224 let data_future = resp.data();
1225 let actual_response = data_future.await.unwrap();
1226 assert_eq!(actual_response, expected_response);
1227 });
1228 }
1229
1230 #[test]
1231 fn get_futures_position_risk_of_sub_account_v2_response_error() {
1232 TOKIO_SHARED_RT.block_on(async {
1233 let client = MockAccountManagementApiClient { force_error: true };
1234
1235 let params =
1236 GetFuturesPositionRiskOfSubAccountV2Params::builder("123@test.com".to_string(), 1)
1237 .build()
1238 .unwrap();
1239
1240 match client
1241 .get_futures_position_risk_of_sub_account_v2(params)
1242 .await
1243 {
1244 Ok(_) => panic!("Expected an error"),
1245 Err(err) => {
1246 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1247 }
1248 }
1249 });
1250 }
1251
1252 #[test]
1253 fn get_sub_accounts_status_on_margin_or_futures_required_params_success() {
1254 TOKIO_SHARED_RT.block_on(async {
1255 let client = MockAccountManagementApiClient { force_error: false };
1256
1257 let params = GetSubAccountsStatusOnMarginOrFuturesParams::builder().build().unwrap();
1258
1259 let resp_json: Value = serde_json::from_str(r#"[{"email":"123@test.com","isSubUserEnabled":true,"isUserActive":true,"insertTime":1570791523523,"isMarginEnabled":true,"isFutureEnabled":true,"mobile":1570791523523}]"#).unwrap_or_else(|_| serde_json::json!({}));
1260 let expected_response : Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>");
1261
1262 let resp = client.get_sub_accounts_status_on_margin_or_futures(params).await.expect("Expected a response");
1263 let data_future = resp.data();
1264 let actual_response = data_future.await.unwrap();
1265 assert_eq!(actual_response, expected_response);
1266 });
1267 }
1268
1269 #[test]
1270 fn get_sub_accounts_status_on_margin_or_futures_optional_params_success() {
1271 TOKIO_SHARED_RT.block_on(async {
1272 let client = MockAccountManagementApiClient { force_error: false };
1273
1274 let params = GetSubAccountsStatusOnMarginOrFuturesParams::builder().email("123@test.com".to_string()).recv_window(5000).build().unwrap();
1275
1276 let resp_json: Value = serde_json::from_str(r#"[{"email":"123@test.com","isSubUserEnabled":true,"isUserActive":true,"insertTime":1570791523523,"isMarginEnabled":true,"isFutureEnabled":true,"mobile":1570791523523}]"#).unwrap_or_else(|_| serde_json::json!({}));
1277 let expected_response : Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>");
1278
1279 let resp = client.get_sub_accounts_status_on_margin_or_futures(params).await.expect("Expected a response");
1280 let data_future = resp.data();
1281 let actual_response = data_future.await.unwrap();
1282 assert_eq!(actual_response, expected_response);
1283 });
1284 }
1285
1286 #[test]
1287 fn get_sub_accounts_status_on_margin_or_futures_response_error() {
1288 TOKIO_SHARED_RT.block_on(async {
1289 let client = MockAccountManagementApiClient { force_error: true };
1290
1291 let params = GetSubAccountsStatusOnMarginOrFuturesParams::builder()
1292 .build()
1293 .unwrap();
1294
1295 match client
1296 .get_sub_accounts_status_on_margin_or_futures(params)
1297 .await
1298 {
1299 Ok(_) => panic!("Expected an error"),
1300 Err(err) => {
1301 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1302 }
1303 }
1304 });
1305 }
1306
1307 #[test]
1308 fn query_sub_account_list_required_params_success() {
1309 TOKIO_SHARED_RT.block_on(async {
1310 let client = MockAccountManagementApiClient { force_error: false };
1311
1312 let params = QuerySubAccountListParams::builder().build().unwrap();
1313
1314 let resp_json: Value = serde_json::from_str(r#"{"subAccounts":[{"subUserId":123456,"email":"testsub@gmail.com","remark":"remark","isFreeze":false,"createTime":1544433328000,"isManagedSubAccount":false,"isAssetManagementSubAccount":false}]}"#).unwrap_or_else(|_| serde_json::json!({}));
1315 let expected_response : models::QuerySubAccountListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountListResponse");
1316
1317 let resp = client.query_sub_account_list(params).await.expect("Expected a response");
1318 let data_future = resp.data();
1319 let actual_response = data_future.await.unwrap();
1320 assert_eq!(actual_response, expected_response);
1321 });
1322 }
1323
1324 #[test]
1325 fn query_sub_account_list_optional_params_success() {
1326 TOKIO_SHARED_RT.block_on(async {
1327 let client = MockAccountManagementApiClient { force_error: false };
1328
1329 let params = QuerySubAccountListParams::builder().email("123@test.com".to_string()).is_freeze("true".to_string()).page(1).limit(10).recv_window(5000).build().unwrap();
1330
1331 let resp_json: Value = serde_json::from_str(r#"{"subAccounts":[{"subUserId":123456,"email":"testsub@gmail.com","remark":"remark","isFreeze":false,"createTime":1544433328000,"isManagedSubAccount":false,"isAssetManagementSubAccount":false}]}"#).unwrap_or_else(|_| serde_json::json!({}));
1332 let expected_response : models::QuerySubAccountListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountListResponse");
1333
1334 let resp = client.query_sub_account_list(params).await.expect("Expected a response");
1335 let data_future = resp.data();
1336 let actual_response = data_future.await.unwrap();
1337 assert_eq!(actual_response, expected_response);
1338 });
1339 }
1340
1341 #[test]
1342 fn query_sub_account_list_response_error() {
1343 TOKIO_SHARED_RT.block_on(async {
1344 let client = MockAccountManagementApiClient { force_error: true };
1345
1346 let params = QuerySubAccountListParams::builder().build().unwrap();
1347
1348 match client.query_sub_account_list(params).await {
1349 Ok(_) => panic!("Expected an error"),
1350 Err(err) => {
1351 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1352 }
1353 }
1354 });
1355 }
1356
1357 #[test]
1358 fn query_sub_account_transaction_statistics_required_params_success() {
1359 TOKIO_SHARED_RT.block_on(async {
1360 let client = MockAccountManagementApiClient { force_error: false };
1361
1362 let params = QuerySubAccountTransactionStatisticsParams::builder().build().unwrap();
1363
1364 let resp_json: Value = serde_json::from_str(r#"{"recent30BtcTotal":"0","recent30BtcFuturesTotal":"0","recent30BtcMarginTotal":"0","recent30BusdTotal":"0","recent30BusdFuturesTotal":"0","recent30BusdMarginTotal":"0","tradeInfoVos":[{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1676851200000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
1365 let expected_response : models::QuerySubAccountTransactionStatisticsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountTransactionStatisticsResponse");
1366
1367 let resp = client.query_sub_account_transaction_statistics(params).await.expect("Expected a response");
1368 let data_future = resp.data();
1369 let actual_response = data_future.await.unwrap();
1370 assert_eq!(actual_response, expected_response);
1371 });
1372 }
1373
1374 #[test]
1375 fn query_sub_account_transaction_statistics_optional_params_success() {
1376 TOKIO_SHARED_RT.block_on(async {
1377 let client = MockAccountManagementApiClient { force_error: false };
1378
1379 let params = QuerySubAccountTransactionStatisticsParams::builder().email("abc@test.com".to_string()).recv_window(5000).build().unwrap();
1380
1381 let resp_json: Value = serde_json::from_str(r#"{"recent30BtcTotal":"0","recent30BtcFuturesTotal":"0","recent30BtcMarginTotal":"0","recent30BusdTotal":"0","recent30BusdFuturesTotal":"0","recent30BusdMarginTotal":"0","tradeInfoVos":[{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1676851200000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
1382 let expected_response : models::QuerySubAccountTransactionStatisticsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountTransactionStatisticsResponse");
1383
1384 let resp = client.query_sub_account_transaction_statistics(params).await.expect("Expected a response");
1385 let data_future = resp.data();
1386 let actual_response = data_future.await.unwrap();
1387 assert_eq!(actual_response, expected_response);
1388 });
1389 }
1390
1391 #[test]
1392 fn query_sub_account_transaction_statistics_response_error() {
1393 TOKIO_SHARED_RT.block_on(async {
1394 let client = MockAccountManagementApiClient { force_error: true };
1395
1396 let params = QuerySubAccountTransactionStatisticsParams::builder()
1397 .build()
1398 .unwrap();
1399
1400 match client
1401 .query_sub_account_transaction_statistics(params)
1402 .await
1403 {
1404 Ok(_) => panic!("Expected an error"),
1405 Err(err) => {
1406 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1407 }
1408 }
1409 });
1410 }
1411}