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::staking::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait SolStakingApi: Send + Sync {
34 async fn claim_boost_rewards(
35 &self,
36 params: ClaimBoostRewardsParams,
37 ) -> anyhow::Result<RestApiResponse<models::ClaimBoostRewardsResponse>>;
38 async fn get_bnsol_rate_history(
39 &self,
40 params: GetBnsolRateHistoryParams,
41 ) -> anyhow::Result<RestApiResponse<models::GetBnsolRateHistoryResponse>>;
42 async fn get_bnsol_rewards_history(
43 &self,
44 params: GetBnsolRewardsHistoryParams,
45 ) -> anyhow::Result<RestApiResponse<models::GetBnsolRewardsHistoryResponse>>;
46 async fn get_boost_rewards_history(
47 &self,
48 params: GetBoostRewardsHistoryParams,
49 ) -> anyhow::Result<RestApiResponse<models::GetBoostRewardsHistoryResponse>>;
50 async fn get_sol_redemption_history(
51 &self,
52 params: GetSolRedemptionHistoryParams,
53 ) -> anyhow::Result<RestApiResponse<models::GetSolRedemptionHistoryResponse>>;
54 async fn get_sol_staking_history(
55 &self,
56 params: GetSolStakingHistoryParams,
57 ) -> anyhow::Result<RestApiResponse<models::GetSolStakingHistoryResponse>>;
58 async fn get_sol_staking_quota_details(
59 &self,
60 params: GetSolStakingQuotaDetailsParams,
61 ) -> anyhow::Result<RestApiResponse<models::GetSolStakingQuotaDetailsResponse>>;
62 async fn get_unclaimed_rewards(
63 &self,
64 params: GetUnclaimedRewardsParams,
65 ) -> anyhow::Result<RestApiResponse<Vec<models::GetUnclaimedRewardsResponseInner>>>;
66 async fn redeem_sol(
67 &self,
68 params: RedeemSolParams,
69 ) -> anyhow::Result<RestApiResponse<models::RedeemSolResponse>>;
70 async fn sol_staking_account(
71 &self,
72 params: SolStakingAccountParams,
73 ) -> anyhow::Result<RestApiResponse<models::SolStakingAccountResponse>>;
74 async fn subscribe_sol_staking(
75 &self,
76 params: SubscribeSolStakingParams,
77 ) -> anyhow::Result<RestApiResponse<models::SubscribeSolStakingResponse>>;
78}
79
80#[derive(Debug, Clone)]
81pub struct SolStakingApiClient {
82 configuration: ConfigurationRestApi,
83}
84
85impl SolStakingApiClient {
86 pub fn new(configuration: ConfigurationRestApi) -> Self {
87 Self { configuration }
88 }
89}
90
91#[allow(non_camel_case_types)]
92#[derive(Debug, Clone, Serialize, Deserialize)]
93pub enum GetBoostRewardsHistoryTypeEnum {
94 #[serde(rename = "CLAIM")]
95 Claim,
96 #[serde(rename = "DISTRIBUTE")]
97 Distribute,
98}
99
100impl GetBoostRewardsHistoryTypeEnum {
101 #[must_use]
102 pub fn as_str(&self) -> &'static str {
103 match self {
104 Self::Claim => "CLAIM",
105 Self::Distribute => "DISTRIBUTE",
106 }
107 }
108}
109
110impl std::str::FromStr for GetBoostRewardsHistoryTypeEnum {
111 type Err = Box<dyn std::error::Error + Send + Sync>;
112
113 fn from_str(s: &str) -> Result<Self, Self::Err> {
114 match s {
115 "CLAIM" => Ok(Self::Claim),
116 "DISTRIBUTE" => Ok(Self::Distribute),
117 other => Err(format!("invalid GetBoostRewardsHistoryTypeEnum: {}", other).into()),
118 }
119 }
120}
121
122#[derive(Clone, Debug, Builder, Deserialize, Default)]
127#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
128pub struct ClaimBoostRewardsParams {
129 #[builder(setter(into), default)]
133 #[serde(rename = "recvWindow", default)]
134 pub recv_window: Option<i64>,
135}
136
137impl ClaimBoostRewardsParams {
138 #[must_use]
141 pub fn builder() -> ClaimBoostRewardsParamsBuilder {
142 ClaimBoostRewardsParamsBuilder::default()
143 }
144}
145#[derive(Clone, Debug, Builder, Deserialize, Default)]
150#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
151pub struct GetBnsolRateHistoryParams {
152 #[builder(setter(into), default)]
157 #[serde(rename = "startTime", default)]
158 pub start_time: Option<i64>,
159 #[builder(setter(into), default)]
164 #[serde(rename = "endTime", default)]
165 pub end_time: Option<i64>,
166 #[builder(setter(into), default)]
170 #[serde(rename = "current", default)]
171 pub current: Option<i64>,
172 #[builder(setter(into), default)]
177 #[serde(rename = "size", default)]
178 pub size: Option<i64>,
179 #[builder(setter(into), default)]
183 #[serde(rename = "recvWindow", default)]
184 pub recv_window: Option<i64>,
185}
186
187impl GetBnsolRateHistoryParams {
188 #[must_use]
191 pub fn builder() -> GetBnsolRateHistoryParamsBuilder {
192 GetBnsolRateHistoryParamsBuilder::default()
193 }
194}
195#[derive(Clone, Debug, Builder, Deserialize, Default)]
200#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
201pub struct GetBnsolRewardsHistoryParams {
202 #[builder(setter(into), default)]
207 #[serde(rename = "startTime", default)]
208 pub start_time: Option<i64>,
209 #[builder(setter(into), default)]
214 #[serde(rename = "endTime", default)]
215 pub end_time: Option<i64>,
216 #[builder(setter(into), default)]
220 #[serde(rename = "current", default)]
221 pub current: Option<i64>,
222 #[builder(setter(into), default)]
227 #[serde(rename = "size", default)]
228 pub size: Option<i64>,
229 #[builder(setter(into), default)]
233 #[serde(rename = "recvWindow", default)]
234 pub recv_window: Option<i64>,
235}
236
237impl GetBnsolRewardsHistoryParams {
238 #[must_use]
241 pub fn builder() -> GetBnsolRewardsHistoryParamsBuilder {
242 GetBnsolRewardsHistoryParamsBuilder::default()
243 }
244}
245#[derive(Clone, Debug, Builder, Deserialize)]
250#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
251pub struct GetBoostRewardsHistoryParams {
252 #[builder(setter(into))]
257 #[serde(rename = "type")]
258 pub r#type: GetBoostRewardsHistoryTypeEnum,
259 #[builder(setter(into), default)]
264 #[serde(rename = "startTime", default)]
265 pub start_time: Option<i64>,
266 #[builder(setter(into), default)]
271 #[serde(rename = "endTime", default)]
272 pub end_time: Option<i64>,
273 #[builder(setter(into), default)]
277 #[serde(rename = "current", default)]
278 pub current: Option<i64>,
279 #[builder(setter(into), default)]
284 #[serde(rename = "size", default)]
285 pub size: Option<i64>,
286 #[builder(setter(into), default)]
290 #[serde(rename = "recvWindow", default)]
291 pub recv_window: Option<i64>,
292}
293
294impl GetBoostRewardsHistoryParams {
295 #[must_use]
302 pub fn builder(r#type: GetBoostRewardsHistoryTypeEnum) -> GetBoostRewardsHistoryParamsBuilder {
303 GetBoostRewardsHistoryParamsBuilder::default().r#type(r#type)
304 }
305}
306#[derive(Clone, Debug, Builder, Deserialize, Default)]
311#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
312pub struct GetSolRedemptionHistoryParams {
313 #[builder(setter(into), default)]
318 #[serde(rename = "redeemId", default)]
319 pub redeem_id: Option<i64>,
320 #[builder(setter(into), default)]
325 #[serde(rename = "startTime", default)]
326 pub start_time: Option<i64>,
327 #[builder(setter(into), default)]
332 #[serde(rename = "endTime", default)]
333 pub end_time: Option<i64>,
334 #[builder(setter(into), default)]
338 #[serde(rename = "current", default)]
339 pub current: Option<i64>,
340 #[builder(setter(into), default)]
345 #[serde(rename = "size", default)]
346 pub size: Option<i64>,
347 #[builder(setter(into), default)]
351 #[serde(rename = "recvWindow", default)]
352 pub recv_window: Option<i64>,
353}
354
355impl GetSolRedemptionHistoryParams {
356 #[must_use]
359 pub fn builder() -> GetSolRedemptionHistoryParamsBuilder {
360 GetSolRedemptionHistoryParamsBuilder::default()
361 }
362}
363#[derive(Clone, Debug, Builder, Deserialize, Default)]
368#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
369pub struct GetSolStakingHistoryParams {
370 #[builder(setter(into), default)]
375 #[serde(rename = "purchaseId", default)]
376 pub purchase_id: Option<i64>,
377 #[builder(setter(into), default)]
382 #[serde(rename = "startTime", default)]
383 pub start_time: Option<i64>,
384 #[builder(setter(into), default)]
389 #[serde(rename = "endTime", default)]
390 pub end_time: Option<i64>,
391 #[builder(setter(into), default)]
395 #[serde(rename = "current", default)]
396 pub current: Option<i64>,
397 #[builder(setter(into), default)]
402 #[serde(rename = "size", default)]
403 pub size: Option<i64>,
404 #[builder(setter(into), default)]
408 #[serde(rename = "recvWindow", default)]
409 pub recv_window: Option<i64>,
410}
411
412impl GetSolStakingHistoryParams {
413 #[must_use]
416 pub fn builder() -> GetSolStakingHistoryParamsBuilder {
417 GetSolStakingHistoryParamsBuilder::default()
418 }
419}
420#[derive(Clone, Debug, Builder, Deserialize, Default)]
425#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
426pub struct GetSolStakingQuotaDetailsParams {
427 #[builder(setter(into), default)]
431 #[serde(rename = "recvWindow", default)]
432 pub recv_window: Option<i64>,
433}
434
435impl GetSolStakingQuotaDetailsParams {
436 #[must_use]
439 pub fn builder() -> GetSolStakingQuotaDetailsParamsBuilder {
440 GetSolStakingQuotaDetailsParamsBuilder::default()
441 }
442}
443#[derive(Clone, Debug, Builder, Deserialize, Default)]
448#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
449pub struct GetUnclaimedRewardsParams {
450 #[builder(setter(into), default)]
454 #[serde(rename = "recvWindow", default)]
455 pub recv_window: Option<i64>,
456}
457
458impl GetUnclaimedRewardsParams {
459 #[must_use]
462 pub fn builder() -> GetUnclaimedRewardsParamsBuilder {
463 GetUnclaimedRewardsParamsBuilder::default()
464 }
465}
466#[derive(Clone, Debug, Builder, Deserialize)]
471#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
472pub struct RedeemSolParams {
473 #[builder(setter(into))]
477 #[serde(rename = "amount")]
478 pub amount: rust_decimal::Decimal,
479 #[builder(setter(into), default)]
483 #[serde(rename = "recvWindow", default)]
484 pub recv_window: Option<i64>,
485}
486
487impl RedeemSolParams {
488 #[must_use]
495 pub fn builder(amount: rust_decimal::Decimal) -> RedeemSolParamsBuilder {
496 RedeemSolParamsBuilder::default().amount(amount)
497 }
498}
499#[derive(Clone, Debug, Builder, Deserialize, Default)]
504#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
505pub struct SolStakingAccountParams {
506 #[builder(setter(into), default)]
510 #[serde(rename = "recvWindow", default)]
511 pub recv_window: Option<i64>,
512}
513
514impl SolStakingAccountParams {
515 #[must_use]
518 pub fn builder() -> SolStakingAccountParamsBuilder {
519 SolStakingAccountParamsBuilder::default()
520 }
521}
522#[derive(Clone, Debug, Builder, Deserialize)]
527#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
528pub struct SubscribeSolStakingParams {
529 #[builder(setter(into))]
533 #[serde(rename = "amount")]
534 pub amount: rust_decimal::Decimal,
535 #[builder(setter(into), default)]
539 #[serde(rename = "recvWindow", default)]
540 pub recv_window: Option<i64>,
541}
542
543impl SubscribeSolStakingParams {
544 #[must_use]
551 pub fn builder(amount: rust_decimal::Decimal) -> SubscribeSolStakingParamsBuilder {
552 SubscribeSolStakingParamsBuilder::default().amount(amount)
553 }
554}
555
556#[async_trait]
557impl SolStakingApi for SolStakingApiClient {
558 async fn claim_boost_rewards(
559 &self,
560 params: ClaimBoostRewardsParams,
561 ) -> anyhow::Result<RestApiResponse<models::ClaimBoostRewardsResponse>> {
562 let ClaimBoostRewardsParams { recv_window } = params;
563
564 let mut query_params = BTreeMap::new();
565 let body_params = BTreeMap::new();
566
567 if let Some(rw) = recv_window {
568 query_params.insert("recvWindow".to_string(), json!(rw));
569 }
570
571 send_request::<models::ClaimBoostRewardsResponse>(
572 &self.configuration,
573 "/sapi/v1/sol-staking/sol/claim",
574 reqwest::Method::POST,
575 query_params,
576 body_params,
577 if HAS_TIME_UNIT {
578 self.configuration.time_unit
579 } else {
580 None
581 },
582 true,
583 )
584 .await
585 }
586
587 async fn get_bnsol_rate_history(
588 &self,
589 params: GetBnsolRateHistoryParams,
590 ) -> anyhow::Result<RestApiResponse<models::GetBnsolRateHistoryResponse>> {
591 let GetBnsolRateHistoryParams {
592 start_time,
593 end_time,
594 current,
595 size,
596 recv_window,
597 } = params;
598
599 let mut query_params = BTreeMap::new();
600 let body_params = BTreeMap::new();
601
602 if let Some(rw) = start_time {
603 query_params.insert("startTime".to_string(), json!(rw));
604 }
605
606 if let Some(rw) = end_time {
607 query_params.insert("endTime".to_string(), json!(rw));
608 }
609
610 if let Some(rw) = current {
611 query_params.insert("current".to_string(), json!(rw));
612 }
613
614 if let Some(rw) = size {
615 query_params.insert("size".to_string(), json!(rw));
616 }
617
618 if let Some(rw) = recv_window {
619 query_params.insert("recvWindow".to_string(), json!(rw));
620 }
621
622 send_request::<models::GetBnsolRateHistoryResponse>(
623 &self.configuration,
624 "/sapi/v1/sol-staking/sol/history/rateHistory",
625 reqwest::Method::GET,
626 query_params,
627 body_params,
628 if HAS_TIME_UNIT {
629 self.configuration.time_unit
630 } else {
631 None
632 },
633 true,
634 )
635 .await
636 }
637
638 async fn get_bnsol_rewards_history(
639 &self,
640 params: GetBnsolRewardsHistoryParams,
641 ) -> anyhow::Result<RestApiResponse<models::GetBnsolRewardsHistoryResponse>> {
642 let GetBnsolRewardsHistoryParams {
643 start_time,
644 end_time,
645 current,
646 size,
647 recv_window,
648 } = params;
649
650 let mut query_params = BTreeMap::new();
651 let body_params = BTreeMap::new();
652
653 if let Some(rw) = start_time {
654 query_params.insert("startTime".to_string(), json!(rw));
655 }
656
657 if let Some(rw) = end_time {
658 query_params.insert("endTime".to_string(), json!(rw));
659 }
660
661 if let Some(rw) = current {
662 query_params.insert("current".to_string(), json!(rw));
663 }
664
665 if let Some(rw) = size {
666 query_params.insert("size".to_string(), json!(rw));
667 }
668
669 if let Some(rw) = recv_window {
670 query_params.insert("recvWindow".to_string(), json!(rw));
671 }
672
673 send_request::<models::GetBnsolRewardsHistoryResponse>(
674 &self.configuration,
675 "/sapi/v1/sol-staking/sol/history/bnsolRewardsHistory",
676 reqwest::Method::GET,
677 query_params,
678 body_params,
679 if HAS_TIME_UNIT {
680 self.configuration.time_unit
681 } else {
682 None
683 },
684 true,
685 )
686 .await
687 }
688
689 async fn get_boost_rewards_history(
690 &self,
691 params: GetBoostRewardsHistoryParams,
692 ) -> anyhow::Result<RestApiResponse<models::GetBoostRewardsHistoryResponse>> {
693 let GetBoostRewardsHistoryParams {
694 r#type,
695 start_time,
696 end_time,
697 current,
698 size,
699 recv_window,
700 } = params;
701
702 let mut query_params = BTreeMap::new();
703 let body_params = BTreeMap::new();
704
705 query_params.insert("type".to_string(), json!(r#type));
706
707 if let Some(rw) = start_time {
708 query_params.insert("startTime".to_string(), json!(rw));
709 }
710
711 if let Some(rw) = end_time {
712 query_params.insert("endTime".to_string(), json!(rw));
713 }
714
715 if let Some(rw) = current {
716 query_params.insert("current".to_string(), json!(rw));
717 }
718
719 if let Some(rw) = size {
720 query_params.insert("size".to_string(), json!(rw));
721 }
722
723 if let Some(rw) = recv_window {
724 query_params.insert("recvWindow".to_string(), json!(rw));
725 }
726
727 send_request::<models::GetBoostRewardsHistoryResponse>(
728 &self.configuration,
729 "/sapi/v1/sol-staking/sol/history/boostRewardsHistory",
730 reqwest::Method::GET,
731 query_params,
732 body_params,
733 if HAS_TIME_UNIT {
734 self.configuration.time_unit
735 } else {
736 None
737 },
738 true,
739 )
740 .await
741 }
742
743 async fn get_sol_redemption_history(
744 &self,
745 params: GetSolRedemptionHistoryParams,
746 ) -> anyhow::Result<RestApiResponse<models::GetSolRedemptionHistoryResponse>> {
747 let GetSolRedemptionHistoryParams {
748 redeem_id,
749 start_time,
750 end_time,
751 current,
752 size,
753 recv_window,
754 } = params;
755
756 let mut query_params = BTreeMap::new();
757 let body_params = BTreeMap::new();
758
759 if let Some(rw) = redeem_id {
760 query_params.insert("redeemId".to_string(), json!(rw));
761 }
762
763 if let Some(rw) = start_time {
764 query_params.insert("startTime".to_string(), json!(rw));
765 }
766
767 if let Some(rw) = end_time {
768 query_params.insert("endTime".to_string(), json!(rw));
769 }
770
771 if let Some(rw) = current {
772 query_params.insert("current".to_string(), json!(rw));
773 }
774
775 if let Some(rw) = size {
776 query_params.insert("size".to_string(), json!(rw));
777 }
778
779 if let Some(rw) = recv_window {
780 query_params.insert("recvWindow".to_string(), json!(rw));
781 }
782
783 send_request::<models::GetSolRedemptionHistoryResponse>(
784 &self.configuration,
785 "/sapi/v1/sol-staking/sol/history/redemptionHistory",
786 reqwest::Method::GET,
787 query_params,
788 body_params,
789 if HAS_TIME_UNIT {
790 self.configuration.time_unit
791 } else {
792 None
793 },
794 true,
795 )
796 .await
797 }
798
799 async fn get_sol_staking_history(
800 &self,
801 params: GetSolStakingHistoryParams,
802 ) -> anyhow::Result<RestApiResponse<models::GetSolStakingHistoryResponse>> {
803 let GetSolStakingHistoryParams {
804 purchase_id,
805 start_time,
806 end_time,
807 current,
808 size,
809 recv_window,
810 } = params;
811
812 let mut query_params = BTreeMap::new();
813 let body_params = BTreeMap::new();
814
815 if let Some(rw) = purchase_id {
816 query_params.insert("purchaseId".to_string(), json!(rw));
817 }
818
819 if let Some(rw) = start_time {
820 query_params.insert("startTime".to_string(), json!(rw));
821 }
822
823 if let Some(rw) = end_time {
824 query_params.insert("endTime".to_string(), json!(rw));
825 }
826
827 if let Some(rw) = current {
828 query_params.insert("current".to_string(), json!(rw));
829 }
830
831 if let Some(rw) = size {
832 query_params.insert("size".to_string(), json!(rw));
833 }
834
835 if let Some(rw) = recv_window {
836 query_params.insert("recvWindow".to_string(), json!(rw));
837 }
838
839 send_request::<models::GetSolStakingHistoryResponse>(
840 &self.configuration,
841 "/sapi/v1/sol-staking/sol/history/stakingHistory",
842 reqwest::Method::GET,
843 query_params,
844 body_params,
845 if HAS_TIME_UNIT {
846 self.configuration.time_unit
847 } else {
848 None
849 },
850 true,
851 )
852 .await
853 }
854
855 async fn get_sol_staking_quota_details(
856 &self,
857 params: GetSolStakingQuotaDetailsParams,
858 ) -> anyhow::Result<RestApiResponse<models::GetSolStakingQuotaDetailsResponse>> {
859 let GetSolStakingQuotaDetailsParams { recv_window } = params;
860
861 let mut query_params = BTreeMap::new();
862 let body_params = BTreeMap::new();
863
864 if let Some(rw) = recv_window {
865 query_params.insert("recvWindow".to_string(), json!(rw));
866 }
867
868 send_request::<models::GetSolStakingQuotaDetailsResponse>(
869 &self.configuration,
870 "/sapi/v1/sol-staking/sol/quota",
871 reqwest::Method::GET,
872 query_params,
873 body_params,
874 if HAS_TIME_UNIT {
875 self.configuration.time_unit
876 } else {
877 None
878 },
879 true,
880 )
881 .await
882 }
883
884 async fn get_unclaimed_rewards(
885 &self,
886 params: GetUnclaimedRewardsParams,
887 ) -> anyhow::Result<RestApiResponse<Vec<models::GetUnclaimedRewardsResponseInner>>> {
888 let GetUnclaimedRewardsParams { recv_window } = params;
889
890 let mut query_params = BTreeMap::new();
891 let body_params = BTreeMap::new();
892
893 if let Some(rw) = recv_window {
894 query_params.insert("recvWindow".to_string(), json!(rw));
895 }
896
897 send_request::<Vec<models::GetUnclaimedRewardsResponseInner>>(
898 &self.configuration,
899 "/sapi/v1/sol-staking/sol/history/unclaimedRewards",
900 reqwest::Method::GET,
901 query_params,
902 body_params,
903 if HAS_TIME_UNIT {
904 self.configuration.time_unit
905 } else {
906 None
907 },
908 true,
909 )
910 .await
911 }
912
913 async fn redeem_sol(
914 &self,
915 params: RedeemSolParams,
916 ) -> anyhow::Result<RestApiResponse<models::RedeemSolResponse>> {
917 let RedeemSolParams {
918 amount,
919 recv_window,
920 } = params;
921
922 let mut query_params = BTreeMap::new();
923 let body_params = BTreeMap::new();
924
925 query_params.insert("amount".to_string(), json!(amount));
926
927 if let Some(rw) = recv_window {
928 query_params.insert("recvWindow".to_string(), json!(rw));
929 }
930
931 send_request::<models::RedeemSolResponse>(
932 &self.configuration,
933 "/sapi/v1/sol-staking/sol/redeem",
934 reqwest::Method::POST,
935 query_params,
936 body_params,
937 if HAS_TIME_UNIT {
938 self.configuration.time_unit
939 } else {
940 None
941 },
942 true,
943 )
944 .await
945 }
946
947 async fn sol_staking_account(
948 &self,
949 params: SolStakingAccountParams,
950 ) -> anyhow::Result<RestApiResponse<models::SolStakingAccountResponse>> {
951 let SolStakingAccountParams { recv_window } = params;
952
953 let mut query_params = BTreeMap::new();
954 let body_params = BTreeMap::new();
955
956 if let Some(rw) = recv_window {
957 query_params.insert("recvWindow".to_string(), json!(rw));
958 }
959
960 send_request::<models::SolStakingAccountResponse>(
961 &self.configuration,
962 "/sapi/v1/sol-staking/account",
963 reqwest::Method::GET,
964 query_params,
965 body_params,
966 if HAS_TIME_UNIT {
967 self.configuration.time_unit
968 } else {
969 None
970 },
971 true,
972 )
973 .await
974 }
975
976 async fn subscribe_sol_staking(
977 &self,
978 params: SubscribeSolStakingParams,
979 ) -> anyhow::Result<RestApiResponse<models::SubscribeSolStakingResponse>> {
980 let SubscribeSolStakingParams {
981 amount,
982 recv_window,
983 } = params;
984
985 let mut query_params = BTreeMap::new();
986 let body_params = BTreeMap::new();
987
988 query_params.insert("amount".to_string(), json!(amount));
989
990 if let Some(rw) = recv_window {
991 query_params.insert("recvWindow".to_string(), json!(rw));
992 }
993
994 send_request::<models::SubscribeSolStakingResponse>(
995 &self.configuration,
996 "/sapi/v1/sol-staking/sol/stake",
997 reqwest::Method::POST,
998 query_params,
999 body_params,
1000 if HAS_TIME_UNIT {
1001 self.configuration.time_unit
1002 } else {
1003 None
1004 },
1005 true,
1006 )
1007 .await
1008 }
1009}
1010
1011#[cfg(all(test, feature = "staking"))]
1012mod tests {
1013 use super::*;
1014 use crate::TOKIO_SHARED_RT;
1015 use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
1016 use async_trait::async_trait;
1017 use std::collections::HashMap;
1018
1019 struct DummyRestApiResponse<T> {
1020 inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
1021 status: u16,
1022 headers: HashMap<String, String>,
1023 rate_limits: Option<Vec<RestApiRateLimit>>,
1024 }
1025
1026 impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
1027 fn from(dummy: DummyRestApiResponse<T>) -> Self {
1028 Self {
1029 data_fn: dummy.inner,
1030 status: dummy.status,
1031 headers: dummy.headers,
1032 rate_limits: dummy.rate_limits,
1033 }
1034 }
1035 }
1036
1037 struct MockSolStakingApiClient {
1038 force_error: bool,
1039 }
1040
1041 #[async_trait]
1042 impl SolStakingApi for MockSolStakingApiClient {
1043 async fn claim_boost_rewards(
1044 &self,
1045 _params: ClaimBoostRewardsParams,
1046 ) -> anyhow::Result<RestApiResponse<models::ClaimBoostRewardsResponse>> {
1047 if self.force_error {
1048 return Err(ConnectorError::ConnectorClientError {
1049 msg: "ResponseError".to_string(),
1050 code: None,
1051 }
1052 .into());
1053 }
1054
1055 let resp_json: Value = serde_json::from_str(r#"{"success":true}"#)
1056 .unwrap_or_else(|_| serde_json::json!({}));
1057 let dummy_response: models::ClaimBoostRewardsResponse =
1058 serde_json::from_value(resp_json.clone())
1059 .expect("should parse into models::ClaimBoostRewardsResponse");
1060
1061 let dummy = DummyRestApiResponse {
1062 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1063 status: 200,
1064 headers: HashMap::new(),
1065 rate_limits: None,
1066 };
1067
1068 Ok(dummy.into())
1069 }
1070
1071 async fn get_bnsol_rate_history(
1072 &self,
1073 _params: GetBnsolRateHistoryParams,
1074 ) -> anyhow::Result<RestApiResponse<models::GetBnsolRateHistoryResponse>> {
1075 if self.force_error {
1076 return Err(ConnectorError::ConnectorClientError {
1077 msg: "ResponseError".to_string(),
1078 code: None,
1079 }
1080 .into());
1081 }
1082
1083 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"annualPercentageRate":"0.00006408","exchangeRate":"1.001212343432","boostRewards":[{"boostAPR":"0.12000000","rewardsAsset":"SOL"}],"time":1577233578000}],"total":"1"}"#).unwrap_or_else(|_| serde_json::json!({}));
1084 let dummy_response: models::GetBnsolRateHistoryResponse =
1085 serde_json::from_value(resp_json.clone())
1086 .expect("should parse into models::GetBnsolRateHistoryResponse");
1087
1088 let dummy = DummyRestApiResponse {
1089 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1090 status: 200,
1091 headers: HashMap::new(),
1092 rate_limits: None,
1093 };
1094
1095 Ok(dummy.into())
1096 }
1097
1098 async fn get_bnsol_rewards_history(
1099 &self,
1100 _params: GetBnsolRewardsHistoryParams,
1101 ) -> anyhow::Result<RestApiResponse<models::GetBnsolRewardsHistoryResponse>> {
1102 if self.force_error {
1103 return Err(ConnectorError::ConnectorClientError {
1104 msg: "ResponseError".to_string(),
1105 code: None,
1106 }
1107 .into());
1108 }
1109
1110 let resp_json: Value = serde_json::from_str(r#"{"estRewardsInSOL":"1.23230920","rows":[{"time":1575018510000,"amountInSOL":"0.23223","holding":"2.3223","holdingInSOL":"2.4231","annualPercentageRate":"0.5"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1111 let dummy_response: models::GetBnsolRewardsHistoryResponse =
1112 serde_json::from_value(resp_json.clone())
1113 .expect("should parse into models::GetBnsolRewardsHistoryResponse");
1114
1115 let dummy = DummyRestApiResponse {
1116 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1117 status: 200,
1118 headers: HashMap::new(),
1119 rate_limits: None,
1120 };
1121
1122 Ok(dummy.into())
1123 }
1124
1125 async fn get_boost_rewards_history(
1126 &self,
1127 _params: GetBoostRewardsHistoryParams,
1128 ) -> anyhow::Result<RestApiResponse<models::GetBoostRewardsHistoryResponse>> {
1129 if self.force_error {
1130 return Err(ConnectorError::ConnectorClientError {
1131 msg: "ResponseError".to_string(),
1132 code: None,
1133 }
1134 .into());
1135 }
1136
1137 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1729520680,"token":"SOL","amount":"1.20291028","bnsolHolding":"2.0928798","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1138 let dummy_response: models::GetBoostRewardsHistoryResponse =
1139 serde_json::from_value(resp_json.clone())
1140 .expect("should parse into models::GetBoostRewardsHistoryResponse");
1141
1142 let dummy = DummyRestApiResponse {
1143 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1144 status: 200,
1145 headers: HashMap::new(),
1146 rate_limits: None,
1147 };
1148
1149 Ok(dummy.into())
1150 }
1151
1152 async fn get_sol_redemption_history(
1153 &self,
1154 _params: GetSolRedemptionHistoryParams,
1155 ) -> anyhow::Result<RestApiResponse<models::GetSolRedemptionHistoryResponse>> {
1156 if self.force_error {
1157 return Err(ConnectorError::ConnectorClientError {
1158 msg: "ResponseError".to_string(),
1159 code: None,
1160 }
1161 .into());
1162 }
1163
1164 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"arrivalTime":1575018510000,"asset":"BNSOL","amount":"21312.23223","distributeAsset":"SOL","distributeAmount":"21338.0699","exchangeRate":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1165 let dummy_response: models::GetSolRedemptionHistoryResponse =
1166 serde_json::from_value(resp_json.clone())
1167 .expect("should parse into models::GetSolRedemptionHistoryResponse");
1168
1169 let dummy = DummyRestApiResponse {
1170 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1171 status: 200,
1172 headers: HashMap::new(),
1173 rate_limits: None,
1174 };
1175
1176 Ok(dummy.into())
1177 }
1178
1179 async fn get_sol_staking_history(
1180 &self,
1181 _params: GetSolStakingHistoryParams,
1182 ) -> anyhow::Result<RestApiResponse<models::GetSolStakingHistoryResponse>> {
1183 if self.force_error {
1184 return Err(ConnectorError::ConnectorClientError {
1185 msg: "ResponseError".to_string(),
1186 code: None,
1187 }
1188 .into());
1189 }
1190
1191 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"asset":"SOL","amount":"21312.23223","distributeAsset":"BNSOL","distributeAmount":"21286.42584","exchangeRate":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1192 let dummy_response: models::GetSolStakingHistoryResponse =
1193 serde_json::from_value(resp_json.clone())
1194 .expect("should parse into models::GetSolStakingHistoryResponse");
1195
1196 let dummy = DummyRestApiResponse {
1197 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1198 status: 200,
1199 headers: HashMap::new(),
1200 rate_limits: None,
1201 };
1202
1203 Ok(dummy.into())
1204 }
1205
1206 async fn get_sol_staking_quota_details(
1207 &self,
1208 _params: GetSolStakingQuotaDetailsParams,
1209 ) -> anyhow::Result<RestApiResponse<models::GetSolStakingQuotaDetailsResponse>> {
1210 if self.force_error {
1211 return Err(ConnectorError::ConnectorClientError {
1212 msg: "ResponseError".to_string(),
1213 code: None,
1214 }
1215 .into());
1216 }
1217
1218 let resp_json: Value = serde_json::from_str(r#"{"leftStakingPersonalQuota":"1000","leftRedemptionPersonalQuota":"1000","minStakeAmount":"0.01000000","minRedeemAmount":"0.00000001","redeemPeriod":4,"stakeable":true,"redeemable":true,"soldOut":false,"commissionFee":"0.25000000","nextEpochTime":725993969475,"calculating":false}"#).unwrap_or_else(|_| serde_json::json!({}));
1219 let dummy_response: models::GetSolStakingQuotaDetailsResponse =
1220 serde_json::from_value(resp_json.clone())
1221 .expect("should parse into models::GetSolStakingQuotaDetailsResponse");
1222
1223 let dummy = DummyRestApiResponse {
1224 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1225 status: 200,
1226 headers: HashMap::new(),
1227 rate_limits: None,
1228 };
1229
1230 Ok(dummy.into())
1231 }
1232
1233 async fn get_unclaimed_rewards(
1234 &self,
1235 _params: GetUnclaimedRewardsParams,
1236 ) -> anyhow::Result<RestApiResponse<Vec<models::GetUnclaimedRewardsResponseInner>>>
1237 {
1238 if self.force_error {
1239 return Err(ConnectorError::ConnectorClientError {
1240 msg: "ResponseError".to_string(),
1241 code: None,
1242 }
1243 .into());
1244 }
1245
1246 let resp_json: Value =
1247 serde_json::from_str(r#"[{"amount":"1.00000011","rewardsAsset":"SOL"}]"#)
1248 .unwrap_or_else(|_| serde_json::json!({}));
1249 let dummy_response: Vec<models::GetUnclaimedRewardsResponseInner> =
1250 serde_json::from_value(resp_json.clone())
1251 .expect("should parse into Vec<models::GetUnclaimedRewardsResponseInner>");
1252
1253 let dummy = DummyRestApiResponse {
1254 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1255 status: 200,
1256 headers: HashMap::new(),
1257 rate_limits: None,
1258 };
1259
1260 Ok(dummy.into())
1261 }
1262
1263 async fn redeem_sol(
1264 &self,
1265 _params: RedeemSolParams,
1266 ) -> anyhow::Result<RestApiResponse<models::RedeemSolResponse>> {
1267 if self.force_error {
1268 return Err(ConnectorError::ConnectorClientError {
1269 msg: "ResponseError".to_string(),
1270 code: None,
1271 }
1272 .into());
1273 }
1274
1275 let resp_json: Value = serde_json::from_str(r#"{"success":true,"solAmount":"0.23092091","redeemId":1234567,"exchangeRate":"1.00121234","arrivalTime":1575018510000}"#).unwrap_or_else(|_| serde_json::json!({}));
1276 let dummy_response: models::RedeemSolResponse =
1277 serde_json::from_value(resp_json.clone())
1278 .expect("should parse into models::RedeemSolResponse");
1279
1280 let dummy = DummyRestApiResponse {
1281 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1282 status: 200,
1283 headers: HashMap::new(),
1284 rate_limits: None,
1285 };
1286
1287 Ok(dummy.into())
1288 }
1289
1290 async fn sol_staking_account(
1291 &self,
1292 _params: SolStakingAccountParams,
1293 ) -> anyhow::Result<RestApiResponse<models::SolStakingAccountResponse>> {
1294 if self.force_error {
1295 return Err(ConnectorError::ConnectorClientError {
1296 msg: "ResponseError".to_string(),
1297 code: None,
1298 }
1299 .into());
1300 }
1301
1302 let resp_json: Value = serde_json::from_str(r#"{"bnsolAmount":"1.10928781","holdingInSOL":"1.22330928","thirtyDaysProfitInSOL":"0.22330928"}"#).unwrap_or_else(|_| serde_json::json!({}));
1303 let dummy_response: models::SolStakingAccountResponse =
1304 serde_json::from_value(resp_json.clone())
1305 .expect("should parse into models::SolStakingAccountResponse");
1306
1307 let dummy = DummyRestApiResponse {
1308 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1309 status: 200,
1310 headers: HashMap::new(),
1311 rate_limits: None,
1312 };
1313
1314 Ok(dummy.into())
1315 }
1316
1317 async fn subscribe_sol_staking(
1318 &self,
1319 _params: SubscribeSolStakingParams,
1320 ) -> anyhow::Result<RestApiResponse<models::SubscribeSolStakingResponse>> {
1321 if self.force_error {
1322 return Err(ConnectorError::ConnectorClientError {
1323 msg: "ResponseError".to_string(),
1324 code: None,
1325 }
1326 .into());
1327 }
1328
1329 let resp_json: Value = serde_json::from_str(r#"{"success":true,"bnsolAmount":"0.23092091","purchaseId":1234567,"exchangeRate":"1.001212342342"}"#).unwrap_or_else(|_| serde_json::json!({}));
1330 let dummy_response: models::SubscribeSolStakingResponse =
1331 serde_json::from_value(resp_json.clone())
1332 .expect("should parse into models::SubscribeSolStakingResponse");
1333
1334 let dummy = DummyRestApiResponse {
1335 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1336 status: 200,
1337 headers: HashMap::new(),
1338 rate_limits: None,
1339 };
1340
1341 Ok(dummy.into())
1342 }
1343 }
1344
1345 #[test]
1346 fn claim_boost_rewards_required_params_success() {
1347 TOKIO_SHARED_RT.block_on(async {
1348 let client = MockSolStakingApiClient { force_error: false };
1349
1350 let params = ClaimBoostRewardsParams::builder().build().unwrap();
1351
1352 let resp_json: Value = serde_json::from_str(r#"{"success":true}"#)
1353 .unwrap_or_else(|_| serde_json::json!({}));
1354 let expected_response: models::ClaimBoostRewardsResponse =
1355 serde_json::from_value(resp_json.clone())
1356 .expect("should parse into models::ClaimBoostRewardsResponse");
1357
1358 let resp = client
1359 .claim_boost_rewards(params)
1360 .await
1361 .expect("Expected a response");
1362 let data_future = resp.data();
1363 let actual_response = data_future.await.unwrap();
1364 assert_eq!(actual_response, expected_response);
1365 });
1366 }
1367
1368 #[test]
1369 fn claim_boost_rewards_optional_params_success() {
1370 TOKIO_SHARED_RT.block_on(async {
1371 let client = MockSolStakingApiClient { force_error: false };
1372
1373 let params = ClaimBoostRewardsParams::builder()
1374 .recv_window(5000)
1375 .build()
1376 .unwrap();
1377
1378 let resp_json: Value = serde_json::from_str(r#"{"success":true}"#)
1379 .unwrap_or_else(|_| serde_json::json!({}));
1380 let expected_response: models::ClaimBoostRewardsResponse =
1381 serde_json::from_value(resp_json.clone())
1382 .expect("should parse into models::ClaimBoostRewardsResponse");
1383
1384 let resp = client
1385 .claim_boost_rewards(params)
1386 .await
1387 .expect("Expected a response");
1388 let data_future = resp.data();
1389 let actual_response = data_future.await.unwrap();
1390 assert_eq!(actual_response, expected_response);
1391 });
1392 }
1393
1394 #[test]
1395 fn claim_boost_rewards_response_error() {
1396 TOKIO_SHARED_RT.block_on(async {
1397 let client = MockSolStakingApiClient { force_error: true };
1398
1399 let params = ClaimBoostRewardsParams::builder().build().unwrap();
1400
1401 match client.claim_boost_rewards(params).await {
1402 Ok(_) => panic!("Expected an error"),
1403 Err(err) => {
1404 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1405 }
1406 }
1407 });
1408 }
1409
1410 #[test]
1411 fn get_bnsol_rate_history_required_params_success() {
1412 TOKIO_SHARED_RT.block_on(async {
1413 let client = MockSolStakingApiClient { force_error: false };
1414
1415 let params = GetBnsolRateHistoryParams::builder().build().unwrap();
1416
1417 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"annualPercentageRate":"0.00006408","exchangeRate":"1.001212343432","boostRewards":[{"boostAPR":"0.12000000","rewardsAsset":"SOL"}],"time":1577233578000}],"total":"1"}"#).unwrap_or_else(|_| serde_json::json!({}));
1418 let expected_response : models::GetBnsolRateHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetBnsolRateHistoryResponse");
1419
1420 let resp = client.get_bnsol_rate_history(params).await.expect("Expected a response");
1421 let data_future = resp.data();
1422 let actual_response = data_future.await.unwrap();
1423 assert_eq!(actual_response, expected_response);
1424 });
1425 }
1426
1427 #[test]
1428 fn get_bnsol_rate_history_optional_params_success() {
1429 TOKIO_SHARED_RT.block_on(async {
1430 let client = MockSolStakingApiClient { force_error: false };
1431
1432 let params = GetBnsolRateHistoryParams::builder().start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();
1433
1434 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"annualPercentageRate":"0.00006408","exchangeRate":"1.001212343432","boostRewards":[{"boostAPR":"0.12000000","rewardsAsset":"SOL"}],"time":1577233578000}],"total":"1"}"#).unwrap_or_else(|_| serde_json::json!({}));
1435 let expected_response : models::GetBnsolRateHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetBnsolRateHistoryResponse");
1436
1437 let resp = client.get_bnsol_rate_history(params).await.expect("Expected a response");
1438 let data_future = resp.data();
1439 let actual_response = data_future.await.unwrap();
1440 assert_eq!(actual_response, expected_response);
1441 });
1442 }
1443
1444 #[test]
1445 fn get_bnsol_rate_history_response_error() {
1446 TOKIO_SHARED_RT.block_on(async {
1447 let client = MockSolStakingApiClient { force_error: true };
1448
1449 let params = GetBnsolRateHistoryParams::builder().build().unwrap();
1450
1451 match client.get_bnsol_rate_history(params).await {
1452 Ok(_) => panic!("Expected an error"),
1453 Err(err) => {
1454 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1455 }
1456 }
1457 });
1458 }
1459
1460 #[test]
1461 fn get_bnsol_rewards_history_required_params_success() {
1462 TOKIO_SHARED_RT.block_on(async {
1463 let client = MockSolStakingApiClient { force_error: false };
1464
1465 let params = GetBnsolRewardsHistoryParams::builder().build().unwrap();
1466
1467 let resp_json: Value = serde_json::from_str(r#"{"estRewardsInSOL":"1.23230920","rows":[{"time":1575018510000,"amountInSOL":"0.23223","holding":"2.3223","holdingInSOL":"2.4231","annualPercentageRate":"0.5"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1468 let expected_response : models::GetBnsolRewardsHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetBnsolRewardsHistoryResponse");
1469
1470 let resp = client.get_bnsol_rewards_history(params).await.expect("Expected a response");
1471 let data_future = resp.data();
1472 let actual_response = data_future.await.unwrap();
1473 assert_eq!(actual_response, expected_response);
1474 });
1475 }
1476
1477 #[test]
1478 fn get_bnsol_rewards_history_optional_params_success() {
1479 TOKIO_SHARED_RT.block_on(async {
1480 let client = MockSolStakingApiClient { force_error: false };
1481
1482 let params = GetBnsolRewardsHistoryParams::builder().start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();
1483
1484 let resp_json: Value = serde_json::from_str(r#"{"estRewardsInSOL":"1.23230920","rows":[{"time":1575018510000,"amountInSOL":"0.23223","holding":"2.3223","holdingInSOL":"2.4231","annualPercentageRate":"0.5"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1485 let expected_response : models::GetBnsolRewardsHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetBnsolRewardsHistoryResponse");
1486
1487 let resp = client.get_bnsol_rewards_history(params).await.expect("Expected a response");
1488 let data_future = resp.data();
1489 let actual_response = data_future.await.unwrap();
1490 assert_eq!(actual_response, expected_response);
1491 });
1492 }
1493
1494 #[test]
1495 fn get_bnsol_rewards_history_response_error() {
1496 TOKIO_SHARED_RT.block_on(async {
1497 let client = MockSolStakingApiClient { force_error: true };
1498
1499 let params = GetBnsolRewardsHistoryParams::builder().build().unwrap();
1500
1501 match client.get_bnsol_rewards_history(params).await {
1502 Ok(_) => panic!("Expected an error"),
1503 Err(err) => {
1504 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1505 }
1506 }
1507 });
1508 }
1509
1510 #[test]
1511 fn get_boost_rewards_history_required_params_success() {
1512 TOKIO_SHARED_RT.block_on(async {
1513 let client = MockSolStakingApiClient { force_error: false };
1514
1515 let params = GetBoostRewardsHistoryParams::builder(GetBoostRewardsHistoryTypeEnum::Claim,).build().unwrap();
1516
1517 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1729520680,"token":"SOL","amount":"1.20291028","bnsolHolding":"2.0928798","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1518 let expected_response : models::GetBoostRewardsHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetBoostRewardsHistoryResponse");
1519
1520 let resp = client.get_boost_rewards_history(params).await.expect("Expected a response");
1521 let data_future = resp.data();
1522 let actual_response = data_future.await.unwrap();
1523 assert_eq!(actual_response, expected_response);
1524 });
1525 }
1526
1527 #[test]
1528 fn get_boost_rewards_history_optional_params_success() {
1529 TOKIO_SHARED_RT.block_on(async {
1530 let client = MockSolStakingApiClient { force_error: false };
1531
1532 let params = GetBoostRewardsHistoryParams::builder(GetBoostRewardsHistoryTypeEnum::Claim,).start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();
1533
1534 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1729520680,"token":"SOL","amount":"1.20291028","bnsolHolding":"2.0928798","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1535 let expected_response : models::GetBoostRewardsHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetBoostRewardsHistoryResponse");
1536
1537 let resp = client.get_boost_rewards_history(params).await.expect("Expected a response");
1538 let data_future = resp.data();
1539 let actual_response = data_future.await.unwrap();
1540 assert_eq!(actual_response, expected_response);
1541 });
1542 }
1543
1544 #[test]
1545 fn get_boost_rewards_history_response_error() {
1546 TOKIO_SHARED_RT.block_on(async {
1547 let client = MockSolStakingApiClient { force_error: true };
1548
1549 let params =
1550 GetBoostRewardsHistoryParams::builder(GetBoostRewardsHistoryTypeEnum::Claim)
1551 .build()
1552 .unwrap();
1553
1554 match client.get_boost_rewards_history(params).await {
1555 Ok(_) => panic!("Expected an error"),
1556 Err(err) => {
1557 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1558 }
1559 }
1560 });
1561 }
1562
1563 #[test]
1564 fn get_sol_redemption_history_required_params_success() {
1565 TOKIO_SHARED_RT.block_on(async {
1566 let client = MockSolStakingApiClient { force_error: false };
1567
1568 let params = GetSolRedemptionHistoryParams::builder().build().unwrap();
1569
1570 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"arrivalTime":1575018510000,"asset":"BNSOL","amount":"21312.23223","distributeAsset":"SOL","distributeAmount":"21338.0699","exchangeRate":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1571 let expected_response : models::GetSolRedemptionHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSolRedemptionHistoryResponse");
1572
1573 let resp = client.get_sol_redemption_history(params).await.expect("Expected a response");
1574 let data_future = resp.data();
1575 let actual_response = data_future.await.unwrap();
1576 assert_eq!(actual_response, expected_response);
1577 });
1578 }
1579
1580 #[test]
1581 fn get_sol_redemption_history_optional_params_success() {
1582 TOKIO_SHARED_RT.block_on(async {
1583 let client = MockSolStakingApiClient { force_error: false };
1584
1585 let params = GetSolRedemptionHistoryParams::builder().redeem_id(1234567).start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();
1586
1587 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"arrivalTime":1575018510000,"asset":"BNSOL","amount":"21312.23223","distributeAsset":"SOL","distributeAmount":"21338.0699","exchangeRate":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1588 let expected_response : models::GetSolRedemptionHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSolRedemptionHistoryResponse");
1589
1590 let resp = client.get_sol_redemption_history(params).await.expect("Expected a response");
1591 let data_future = resp.data();
1592 let actual_response = data_future.await.unwrap();
1593 assert_eq!(actual_response, expected_response);
1594 });
1595 }
1596
1597 #[test]
1598 fn get_sol_redemption_history_response_error() {
1599 TOKIO_SHARED_RT.block_on(async {
1600 let client = MockSolStakingApiClient { force_error: true };
1601
1602 let params = GetSolRedemptionHistoryParams::builder().build().unwrap();
1603
1604 match client.get_sol_redemption_history(params).await {
1605 Ok(_) => panic!("Expected an error"),
1606 Err(err) => {
1607 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1608 }
1609 }
1610 });
1611 }
1612
1613 #[test]
1614 fn get_sol_staking_history_required_params_success() {
1615 TOKIO_SHARED_RT.block_on(async {
1616 let client = MockSolStakingApiClient { force_error: false };
1617
1618 let params = GetSolStakingHistoryParams::builder().build().unwrap();
1619
1620 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"asset":"SOL","amount":"21312.23223","distributeAsset":"BNSOL","distributeAmount":"21286.42584","exchangeRate":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1621 let expected_response : models::GetSolStakingHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSolStakingHistoryResponse");
1622
1623 let resp = client.get_sol_staking_history(params).await.expect("Expected a response");
1624 let data_future = resp.data();
1625 let actual_response = data_future.await.unwrap();
1626 assert_eq!(actual_response, expected_response);
1627 });
1628 }
1629
1630 #[test]
1631 fn get_sol_staking_history_optional_params_success() {
1632 TOKIO_SHARED_RT.block_on(async {
1633 let client = MockSolStakingApiClient { force_error: false };
1634
1635 let params = GetSolStakingHistoryParams::builder().purchase_id(1234567).start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();
1636
1637 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"asset":"SOL","amount":"21312.23223","distributeAsset":"BNSOL","distributeAmount":"21286.42584","exchangeRate":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1638 let expected_response : models::GetSolStakingHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSolStakingHistoryResponse");
1639
1640 let resp = client.get_sol_staking_history(params).await.expect("Expected a response");
1641 let data_future = resp.data();
1642 let actual_response = data_future.await.unwrap();
1643 assert_eq!(actual_response, expected_response);
1644 });
1645 }
1646
1647 #[test]
1648 fn get_sol_staking_history_response_error() {
1649 TOKIO_SHARED_RT.block_on(async {
1650 let client = MockSolStakingApiClient { force_error: true };
1651
1652 let params = GetSolStakingHistoryParams::builder().build().unwrap();
1653
1654 match client.get_sol_staking_history(params).await {
1655 Ok(_) => panic!("Expected an error"),
1656 Err(err) => {
1657 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1658 }
1659 }
1660 });
1661 }
1662
1663 #[test]
1664 fn get_sol_staking_quota_details_required_params_success() {
1665 TOKIO_SHARED_RT.block_on(async {
1666 let client = MockSolStakingApiClient { force_error: false };
1667
1668 let params = GetSolStakingQuotaDetailsParams::builder().build().unwrap();
1669
1670 let resp_json: Value = serde_json::from_str(r#"{"leftStakingPersonalQuota":"1000","leftRedemptionPersonalQuota":"1000","minStakeAmount":"0.01000000","minRedeemAmount":"0.00000001","redeemPeriod":4,"stakeable":true,"redeemable":true,"soldOut":false,"commissionFee":"0.25000000","nextEpochTime":725993969475,"calculating":false}"#).unwrap_or_else(|_| serde_json::json!({}));
1671 let expected_response : models::GetSolStakingQuotaDetailsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSolStakingQuotaDetailsResponse");
1672
1673 let resp = client.get_sol_staking_quota_details(params).await.expect("Expected a response");
1674 let data_future = resp.data();
1675 let actual_response = data_future.await.unwrap();
1676 assert_eq!(actual_response, expected_response);
1677 });
1678 }
1679
1680 #[test]
1681 fn get_sol_staking_quota_details_optional_params_success() {
1682 TOKIO_SHARED_RT.block_on(async {
1683 let client = MockSolStakingApiClient { force_error: false };
1684
1685 let params = GetSolStakingQuotaDetailsParams::builder().recv_window(5000).build().unwrap();
1686
1687 let resp_json: Value = serde_json::from_str(r#"{"leftStakingPersonalQuota":"1000","leftRedemptionPersonalQuota":"1000","minStakeAmount":"0.01000000","minRedeemAmount":"0.00000001","redeemPeriod":4,"stakeable":true,"redeemable":true,"soldOut":false,"commissionFee":"0.25000000","nextEpochTime":725993969475,"calculating":false}"#).unwrap_or_else(|_| serde_json::json!({}));
1688 let expected_response : models::GetSolStakingQuotaDetailsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSolStakingQuotaDetailsResponse");
1689
1690 let resp = client.get_sol_staking_quota_details(params).await.expect("Expected a response");
1691 let data_future = resp.data();
1692 let actual_response = data_future.await.unwrap();
1693 assert_eq!(actual_response, expected_response);
1694 });
1695 }
1696
1697 #[test]
1698 fn get_sol_staking_quota_details_response_error() {
1699 TOKIO_SHARED_RT.block_on(async {
1700 let client = MockSolStakingApiClient { force_error: true };
1701
1702 let params = GetSolStakingQuotaDetailsParams::builder().build().unwrap();
1703
1704 match client.get_sol_staking_quota_details(params).await {
1705 Ok(_) => panic!("Expected an error"),
1706 Err(err) => {
1707 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1708 }
1709 }
1710 });
1711 }
1712
1713 #[test]
1714 fn get_unclaimed_rewards_required_params_success() {
1715 TOKIO_SHARED_RT.block_on(async {
1716 let client = MockSolStakingApiClient { force_error: false };
1717
1718 let params = GetUnclaimedRewardsParams::builder().build().unwrap();
1719
1720 let resp_json: Value =
1721 serde_json::from_str(r#"[{"amount":"1.00000011","rewardsAsset":"SOL"}]"#)
1722 .unwrap_or_else(|_| serde_json::json!({}));
1723 let expected_response: Vec<models::GetUnclaimedRewardsResponseInner> =
1724 serde_json::from_value(resp_json.clone())
1725 .expect("should parse into Vec<models::GetUnclaimedRewardsResponseInner>");
1726
1727 let resp = client
1728 .get_unclaimed_rewards(params)
1729 .await
1730 .expect("Expected a response");
1731 let data_future = resp.data();
1732 let actual_response = data_future.await.unwrap();
1733 assert_eq!(actual_response, expected_response);
1734 });
1735 }
1736
1737 #[test]
1738 fn get_unclaimed_rewards_optional_params_success() {
1739 TOKIO_SHARED_RT.block_on(async {
1740 let client = MockSolStakingApiClient { force_error: false };
1741
1742 let params = GetUnclaimedRewardsParams::builder()
1743 .recv_window(5000)
1744 .build()
1745 .unwrap();
1746
1747 let resp_json: Value =
1748 serde_json::from_str(r#"[{"amount":"1.00000011","rewardsAsset":"SOL"}]"#)
1749 .unwrap_or_else(|_| serde_json::json!({}));
1750 let expected_response: Vec<models::GetUnclaimedRewardsResponseInner> =
1751 serde_json::from_value(resp_json.clone())
1752 .expect("should parse into Vec<models::GetUnclaimedRewardsResponseInner>");
1753
1754 let resp = client
1755 .get_unclaimed_rewards(params)
1756 .await
1757 .expect("Expected a response");
1758 let data_future = resp.data();
1759 let actual_response = data_future.await.unwrap();
1760 assert_eq!(actual_response, expected_response);
1761 });
1762 }
1763
1764 #[test]
1765 fn get_unclaimed_rewards_response_error() {
1766 TOKIO_SHARED_RT.block_on(async {
1767 let client = MockSolStakingApiClient { force_error: true };
1768
1769 let params = GetUnclaimedRewardsParams::builder().build().unwrap();
1770
1771 match client.get_unclaimed_rewards(params).await {
1772 Ok(_) => panic!("Expected an error"),
1773 Err(err) => {
1774 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1775 }
1776 }
1777 });
1778 }
1779
1780 #[test]
1781 fn redeem_sol_required_params_success() {
1782 TOKIO_SHARED_RT.block_on(async {
1783 let client = MockSolStakingApiClient { force_error: false };
1784
1785 let params = RedeemSolParams::builder(dec!(1.0),).build().unwrap();
1786
1787 let resp_json: Value = serde_json::from_str(r#"{"success":true,"solAmount":"0.23092091","redeemId":1234567,"exchangeRate":"1.00121234","arrivalTime":1575018510000}"#).unwrap_or_else(|_| serde_json::json!({}));
1788 let expected_response : models::RedeemSolResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RedeemSolResponse");
1789
1790 let resp = client.redeem_sol(params).await.expect("Expected a response");
1791 let data_future = resp.data();
1792 let actual_response = data_future.await.unwrap();
1793 assert_eq!(actual_response, expected_response);
1794 });
1795 }
1796
1797 #[test]
1798 fn redeem_sol_optional_params_success() {
1799 TOKIO_SHARED_RT.block_on(async {
1800 let client = MockSolStakingApiClient { force_error: false };
1801
1802 let params = RedeemSolParams::builder(dec!(1.0),).recv_window(5000).build().unwrap();
1803
1804 let resp_json: Value = serde_json::from_str(r#"{"success":true,"solAmount":"0.23092091","redeemId":1234567,"exchangeRate":"1.00121234","arrivalTime":1575018510000}"#).unwrap_or_else(|_| serde_json::json!({}));
1805 let expected_response : models::RedeemSolResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RedeemSolResponse");
1806
1807 let resp = client.redeem_sol(params).await.expect("Expected a response");
1808 let data_future = resp.data();
1809 let actual_response = data_future.await.unwrap();
1810 assert_eq!(actual_response, expected_response);
1811 });
1812 }
1813
1814 #[test]
1815 fn redeem_sol_response_error() {
1816 TOKIO_SHARED_RT.block_on(async {
1817 let client = MockSolStakingApiClient { force_error: true };
1818
1819 let params = RedeemSolParams::builder(dec!(1.0)).build().unwrap();
1820
1821 match client.redeem_sol(params).await {
1822 Ok(_) => panic!("Expected an error"),
1823 Err(err) => {
1824 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1825 }
1826 }
1827 });
1828 }
1829
1830 #[test]
1831 fn sol_staking_account_required_params_success() {
1832 TOKIO_SHARED_RT.block_on(async {
1833 let client = MockSolStakingApiClient { force_error: false };
1834
1835 let params = SolStakingAccountParams::builder().build().unwrap();
1836
1837 let resp_json: Value = serde_json::from_str(r#"{"bnsolAmount":"1.10928781","holdingInSOL":"1.22330928","thirtyDaysProfitInSOL":"0.22330928"}"#).unwrap_or_else(|_| serde_json::json!({}));
1838 let expected_response : models::SolStakingAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::SolStakingAccountResponse");
1839
1840 let resp = client.sol_staking_account(params).await.expect("Expected a response");
1841 let data_future = resp.data();
1842 let actual_response = data_future.await.unwrap();
1843 assert_eq!(actual_response, expected_response);
1844 });
1845 }
1846
1847 #[test]
1848 fn sol_staking_account_optional_params_success() {
1849 TOKIO_SHARED_RT.block_on(async {
1850 let client = MockSolStakingApiClient { force_error: false };
1851
1852 let params = SolStakingAccountParams::builder().recv_window(5000).build().unwrap();
1853
1854 let resp_json: Value = serde_json::from_str(r#"{"bnsolAmount":"1.10928781","holdingInSOL":"1.22330928","thirtyDaysProfitInSOL":"0.22330928"}"#).unwrap_or_else(|_| serde_json::json!({}));
1855 let expected_response : models::SolStakingAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::SolStakingAccountResponse");
1856
1857 let resp = client.sol_staking_account(params).await.expect("Expected a response");
1858 let data_future = resp.data();
1859 let actual_response = data_future.await.unwrap();
1860 assert_eq!(actual_response, expected_response);
1861 });
1862 }
1863
1864 #[test]
1865 fn sol_staking_account_response_error() {
1866 TOKIO_SHARED_RT.block_on(async {
1867 let client = MockSolStakingApiClient { force_error: true };
1868
1869 let params = SolStakingAccountParams::builder().build().unwrap();
1870
1871 match client.sol_staking_account(params).await {
1872 Ok(_) => panic!("Expected an error"),
1873 Err(err) => {
1874 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1875 }
1876 }
1877 });
1878 }
1879
1880 #[test]
1881 fn subscribe_sol_staking_required_params_success() {
1882 TOKIO_SHARED_RT.block_on(async {
1883 let client = MockSolStakingApiClient { force_error: false };
1884
1885 let params = SubscribeSolStakingParams::builder(dec!(1.0),).build().unwrap();
1886
1887 let resp_json: Value = serde_json::from_str(r#"{"success":true,"bnsolAmount":"0.23092091","purchaseId":1234567,"exchangeRate":"1.001212342342"}"#).unwrap_or_else(|_| serde_json::json!({}));
1888 let expected_response : models::SubscribeSolStakingResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::SubscribeSolStakingResponse");
1889
1890 let resp = client.subscribe_sol_staking(params).await.expect("Expected a response");
1891 let data_future = resp.data();
1892 let actual_response = data_future.await.unwrap();
1893 assert_eq!(actual_response, expected_response);
1894 });
1895 }
1896
1897 #[test]
1898 fn subscribe_sol_staking_optional_params_success() {
1899 TOKIO_SHARED_RT.block_on(async {
1900 let client = MockSolStakingApiClient { force_error: false };
1901
1902 let params = SubscribeSolStakingParams::builder(dec!(1.0),).recv_window(5000).build().unwrap();
1903
1904 let resp_json: Value = serde_json::from_str(r#"{"success":true,"bnsolAmount":"0.23092091","purchaseId":1234567,"exchangeRate":"1.001212342342"}"#).unwrap_or_else(|_| serde_json::json!({}));
1905 let expected_response : models::SubscribeSolStakingResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::SubscribeSolStakingResponse");
1906
1907 let resp = client.subscribe_sol_staking(params).await.expect("Expected a response");
1908 let data_future = resp.data();
1909 let actual_response = data_future.await.unwrap();
1910 assert_eq!(actual_response, expected_response);
1911 });
1912 }
1913
1914 #[test]
1915 fn subscribe_sol_staking_response_error() {
1916 TOKIO_SHARED_RT.block_on(async {
1917 let client = MockSolStakingApiClient { force_error: true };
1918
1919 let params = SubscribeSolStakingParams::builder(dec!(1.0))
1920 .build()
1921 .unwrap();
1922
1923 match client.subscribe_sol_staking(params).await {
1924 Ok(_) => panic!("Expected an error"),
1925 Err(err) => {
1926 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1927 }
1928 }
1929 });
1930 }
1931}