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