Skip to main content

binance_sdk/staking/rest_api/apis/
eth_staking_api.rs

1/*
2 * Staking REST API
3 *
4 * Subscribe to staking products, track positions, and query rewards via the Binance Staking API.
5 *
6 * The version of the OpenAPI document: 1.0.0
7 *
8 *
9 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
10 * https://openapi-generator.tech
11 * Do not edit the class manually.
12 */
13
14#![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 EthStakingApi: Send + Sync {
34    async fn eth_staking_account(
35        &self,
36        params: EthStakingAccountParams,
37    ) -> anyhow::Result<RestApiResponse<models::EthStakingAccountResponse>>;
38    async fn get_current_eth_staking_quota(
39        &self,
40        params: GetCurrentEthStakingQuotaParams,
41    ) -> anyhow::Result<RestApiResponse<models::GetCurrentEthStakingQuotaResponse>>;
42    async fn get_eth_redemption_history(
43        &self,
44        params: GetEthRedemptionHistoryParams,
45    ) -> anyhow::Result<RestApiResponse<models::GetEthRedemptionHistoryResponse>>;
46    async fn get_eth_staking_history(
47        &self,
48        params: GetEthStakingHistoryParams,
49    ) -> anyhow::Result<RestApiResponse<models::GetEthStakingHistoryResponse>>;
50    async fn get_wbeth_rate_history(
51        &self,
52        params: GetWbethRateHistoryParams,
53    ) -> anyhow::Result<RestApiResponse<models::GetWbethRateHistoryResponse>>;
54    async fn get_wbeth_rewards_history(
55        &self,
56        params: GetWbethRewardsHistoryParams,
57    ) -> anyhow::Result<RestApiResponse<models::GetWbethRewardsHistoryResponse>>;
58    async fn get_wbeth_unwrap_history(
59        &self,
60        params: GetWbethUnwrapHistoryParams,
61    ) -> anyhow::Result<RestApiResponse<models::GetWbethUnwrapHistoryResponse>>;
62    async fn get_wbeth_wrap_history(
63        &self,
64        params: GetWbethWrapHistoryParams,
65    ) -> anyhow::Result<RestApiResponse<models::GetWbethWrapHistoryResponse>>;
66    async fn redeem_eth(
67        &self,
68        params: RedeemEthParams,
69    ) -> anyhow::Result<RestApiResponse<models::RedeemEthResponse>>;
70    async fn subscribe_eth_staking(
71        &self,
72        params: SubscribeEthStakingParams,
73    ) -> anyhow::Result<RestApiResponse<models::SubscribeEthStakingResponse>>;
74    async fn wrap_beth(
75        &self,
76        params: WrapBethParams,
77    ) -> anyhow::Result<RestApiResponse<models::WrapBethResponse>>;
78}
79
80#[derive(Debug, Clone)]
81pub struct EthStakingApiClient {
82    configuration: ConfigurationRestApi,
83}
84
85impl EthStakingApiClient {
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 RedeemEthAssetEnum {
94    #[serde(rename = "WBETH")]
95    Wbeth,
96    #[serde(rename = "BETH")]
97    Beth,
98}
99
100impl RedeemEthAssetEnum {
101    #[must_use]
102    pub fn as_str(&self) -> &'static str {
103        match self {
104            Self::Wbeth => "WBETH",
105            Self::Beth => "BETH",
106        }
107    }
108}
109
110impl std::str::FromStr for RedeemEthAssetEnum {
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            "WBETH" => Ok(Self::Wbeth),
116            "BETH" => Ok(Self::Beth),
117            other => Err(format!("invalid RedeemEthAssetEnum: {}", other).into()),
118        }
119    }
120}
121
122/// Request parameters for the [`eth_staking_account`] operation.
123///
124/// This struct holds all of the inputs you can pass when calling
125/// [`eth_staking_account`](#method.eth_staking_account).
126#[derive(Clone, Debug, Builder, Deserialize, Default)]
127#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
128pub struct EthStakingAccountParams {
129    /// Request validity window in milliseconds.
130    ///
131    /// This field is **optional.
132    #[builder(setter(into), default)]
133    #[serde(rename = "recvWindow", default)]
134    pub recv_window: Option<i64>,
135}
136
137impl EthStakingAccountParams {
138    /// Create a builder for [`eth_staking_account`].
139    ///
140    #[must_use]
141    pub fn builder() -> EthStakingAccountParamsBuilder {
142        EthStakingAccountParamsBuilder::default()
143    }
144}
145/// Request parameters for the [`get_current_eth_staking_quota`] operation.
146///
147/// This struct holds all of the inputs you can pass when calling
148/// [`get_current_eth_staking_quota`](#method.get_current_eth_staking_quota).
149#[derive(Clone, Debug, Builder, Deserialize, Default)]
150#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
151pub struct GetCurrentEthStakingQuotaParams {
152    /// Request validity window in milliseconds.
153    ///
154    /// This field is **optional.
155    #[builder(setter(into), default)]
156    #[serde(rename = "recvWindow", default)]
157    pub recv_window: Option<i64>,
158}
159
160impl GetCurrentEthStakingQuotaParams {
161    /// Create a builder for [`get_current_eth_staking_quota`].
162    ///
163    #[must_use]
164    pub fn builder() -> GetCurrentEthStakingQuotaParamsBuilder {
165        GetCurrentEthStakingQuotaParamsBuilder::default()
166    }
167}
168/// Request parameters for the [`get_eth_redemption_history`] operation.
169///
170/// This struct holds all of the inputs you can pass when calling
171/// [`get_eth_redemption_history`](#method.get_eth_redemption_history).
172#[derive(Clone, Debug, Builder, Deserialize, Default)]
173#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
174pub struct GetEthRedemptionHistoryParams {
175    ///
176    /// The `redeem_id` parameter.
177    ///
178    /// This field is **optional.
179    #[builder(setter(into), default)]
180    #[serde(rename = "redeemId", default)]
181    pub redeem_id: Option<i64>,
182    ///
183    /// The `start_time` parameter.
184    ///
185    /// This field is **optional.
186    #[builder(setter(into), default)]
187    #[serde(rename = "startTime", default)]
188    pub start_time: Option<i64>,
189    ///
190    /// The `end_time` parameter.
191    ///
192    /// This field is **optional.
193    #[builder(setter(into), default)]
194    #[serde(rename = "endTime", default)]
195    pub end_time: Option<i64>,
196    /// Currently querying page
197    ///
198    /// This field is **optional.
199    #[builder(setter(into), default)]
200    #[serde(rename = "current", default)]
201    pub current: Option<i64>,
202    ///
203    /// The `size` parameter.
204    ///
205    /// This field is **optional.
206    #[builder(setter(into), default)]
207    #[serde(rename = "size", default)]
208    pub size: Option<i64>,
209    /// Request validity window in milliseconds.
210    ///
211    /// This field is **optional.
212    #[builder(setter(into), default)]
213    #[serde(rename = "recvWindow", default)]
214    pub recv_window: Option<i64>,
215}
216
217impl GetEthRedemptionHistoryParams {
218    /// Create a builder for [`get_eth_redemption_history`].
219    ///
220    #[must_use]
221    pub fn builder() -> GetEthRedemptionHistoryParamsBuilder {
222        GetEthRedemptionHistoryParamsBuilder::default()
223    }
224}
225/// Request parameters for the [`get_eth_staking_history`] operation.
226///
227/// This struct holds all of the inputs you can pass when calling
228/// [`get_eth_staking_history`](#method.get_eth_staking_history).
229#[derive(Clone, Debug, Builder, Deserialize, Default)]
230#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
231pub struct GetEthStakingHistoryParams {
232    ///
233    /// The `purchase_id` parameter.
234    ///
235    /// This field is **optional.
236    #[builder(setter(into), default)]
237    #[serde(rename = "purchaseId", default)]
238    pub purchase_id: Option<i64>,
239    ///
240    /// The `start_time` parameter.
241    ///
242    /// This field is **optional.
243    #[builder(setter(into), default)]
244    #[serde(rename = "startTime", default)]
245    pub start_time: Option<i64>,
246    ///
247    /// The `end_time` parameter.
248    ///
249    /// This field is **optional.
250    #[builder(setter(into), default)]
251    #[serde(rename = "endTime", default)]
252    pub end_time: Option<i64>,
253    /// Currently querying page
254    ///
255    /// This field is **optional.
256    #[builder(setter(into), default)]
257    #[serde(rename = "current", default)]
258    pub current: Option<i64>,
259    ///
260    /// The `size` parameter.
261    ///
262    /// This field is **optional.
263    #[builder(setter(into), default)]
264    #[serde(rename = "size", default)]
265    pub size: Option<i64>,
266    /// Request validity window in milliseconds.
267    ///
268    /// This field is **optional.
269    #[builder(setter(into), default)]
270    #[serde(rename = "recvWindow", default)]
271    pub recv_window: Option<i64>,
272}
273
274impl GetEthStakingHistoryParams {
275    /// Create a builder for [`get_eth_staking_history`].
276    ///
277    #[must_use]
278    pub fn builder() -> GetEthStakingHistoryParamsBuilder {
279        GetEthStakingHistoryParamsBuilder::default()
280    }
281}
282/// Request parameters for the [`get_wbeth_rate_history`] operation.
283///
284/// This struct holds all of the inputs you can pass when calling
285/// [`get_wbeth_rate_history`](#method.get_wbeth_rate_history).
286#[derive(Clone, Debug, Builder, Deserialize, Default)]
287#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
288pub struct GetWbethRateHistoryParams {
289    ///
290    /// The `start_time` parameter.
291    ///
292    /// This field is **optional.
293    #[builder(setter(into), default)]
294    #[serde(rename = "startTime", default)]
295    pub start_time: Option<i64>,
296    ///
297    /// The `end_time` parameter.
298    ///
299    /// This field is **optional.
300    #[builder(setter(into), default)]
301    #[serde(rename = "endTime", default)]
302    pub end_time: Option<i64>,
303    /// Currently querying page
304    ///
305    /// This field is **optional.
306    #[builder(setter(into), default)]
307    #[serde(rename = "current", default)]
308    pub current: Option<i64>,
309    ///
310    /// The `size` parameter.
311    ///
312    /// This field is **optional.
313    #[builder(setter(into), default)]
314    #[serde(rename = "size", default)]
315    pub size: Option<i64>,
316    /// Request validity window in milliseconds.
317    ///
318    /// This field is **optional.
319    #[builder(setter(into), default)]
320    #[serde(rename = "recvWindow", default)]
321    pub recv_window: Option<i64>,
322}
323
324impl GetWbethRateHistoryParams {
325    /// Create a builder for [`get_wbeth_rate_history`].
326    ///
327    #[must_use]
328    pub fn builder() -> GetWbethRateHistoryParamsBuilder {
329        GetWbethRateHistoryParamsBuilder::default()
330    }
331}
332/// Request parameters for the [`get_wbeth_rewards_history`] operation.
333///
334/// This struct holds all of the inputs you can pass when calling
335/// [`get_wbeth_rewards_history`](#method.get_wbeth_rewards_history).
336#[derive(Clone, Debug, Builder, Deserialize, Default)]
337#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
338pub struct GetWbethRewardsHistoryParams {
339    ///
340    /// The `start_time` parameter.
341    ///
342    /// This field is **optional.
343    #[builder(setter(into), default)]
344    #[serde(rename = "startTime", default)]
345    pub start_time: Option<i64>,
346    ///
347    /// The `end_time` parameter.
348    ///
349    /// This field is **optional.
350    #[builder(setter(into), default)]
351    #[serde(rename = "endTime", default)]
352    pub end_time: Option<i64>,
353    /// Currently querying page
354    ///
355    /// This field is **optional.
356    #[builder(setter(into), default)]
357    #[serde(rename = "current", default)]
358    pub current: Option<i64>,
359    ///
360    /// The `size` parameter.
361    ///
362    /// This field is **optional.
363    #[builder(setter(into), default)]
364    #[serde(rename = "size", default)]
365    pub size: Option<i64>,
366    /// Request validity window in milliseconds.
367    ///
368    /// This field is **optional.
369    #[builder(setter(into), default)]
370    #[serde(rename = "recvWindow", default)]
371    pub recv_window: Option<i64>,
372}
373
374impl GetWbethRewardsHistoryParams {
375    /// Create a builder for [`get_wbeth_rewards_history`].
376    ///
377    #[must_use]
378    pub fn builder() -> GetWbethRewardsHistoryParamsBuilder {
379        GetWbethRewardsHistoryParamsBuilder::default()
380    }
381}
382/// Request parameters for the [`get_wbeth_unwrap_history`] operation.
383///
384/// This struct holds all of the inputs you can pass when calling
385/// [`get_wbeth_unwrap_history`](#method.get_wbeth_unwrap_history).
386#[derive(Clone, Debug, Builder, Deserialize, Default)]
387#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
388pub struct GetWbethUnwrapHistoryParams {
389    ///
390    /// The `start_time` parameter.
391    ///
392    /// This field is **optional.
393    #[builder(setter(into), default)]
394    #[serde(rename = "startTime", default)]
395    pub start_time: Option<i64>,
396    ///
397    /// The `end_time` parameter.
398    ///
399    /// This field is **optional.
400    #[builder(setter(into), default)]
401    #[serde(rename = "endTime", default)]
402    pub end_time: Option<i64>,
403    /// Currently querying page
404    ///
405    /// This field is **optional.
406    #[builder(setter(into), default)]
407    #[serde(rename = "current", default)]
408    pub current: Option<i64>,
409    ///
410    /// The `size` parameter.
411    ///
412    /// This field is **optional.
413    #[builder(setter(into), default)]
414    #[serde(rename = "size", default)]
415    pub size: Option<i64>,
416    /// Request validity window in milliseconds.
417    ///
418    /// This field is **optional.
419    #[builder(setter(into), default)]
420    #[serde(rename = "recvWindow", default)]
421    pub recv_window: Option<i64>,
422}
423
424impl GetWbethUnwrapHistoryParams {
425    /// Create a builder for [`get_wbeth_unwrap_history`].
426    ///
427    #[must_use]
428    pub fn builder() -> GetWbethUnwrapHistoryParamsBuilder {
429        GetWbethUnwrapHistoryParamsBuilder::default()
430    }
431}
432/// Request parameters for the [`get_wbeth_wrap_history`] operation.
433///
434/// This struct holds all of the inputs you can pass when calling
435/// [`get_wbeth_wrap_history`](#method.get_wbeth_wrap_history).
436#[derive(Clone, Debug, Builder, Deserialize, Default)]
437#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
438pub struct GetWbethWrapHistoryParams {
439    ///
440    /// The `start_time` parameter.
441    ///
442    /// This field is **optional.
443    #[builder(setter(into), default)]
444    #[serde(rename = "startTime", default)]
445    pub start_time: Option<i64>,
446    ///
447    /// The `end_time` parameter.
448    ///
449    /// This field is **optional.
450    #[builder(setter(into), default)]
451    #[serde(rename = "endTime", default)]
452    pub end_time: Option<i64>,
453    /// Currently querying page
454    ///
455    /// This field is **optional.
456    #[builder(setter(into), default)]
457    #[serde(rename = "current", default)]
458    pub current: Option<i64>,
459    ///
460    /// The `size` parameter.
461    ///
462    /// This field is **optional.
463    #[builder(setter(into), default)]
464    #[serde(rename = "size", default)]
465    pub size: Option<i64>,
466    /// Request validity window in milliseconds.
467    ///
468    /// This field is **optional.
469    #[builder(setter(into), default)]
470    #[serde(rename = "recvWindow", default)]
471    pub recv_window: Option<i64>,
472}
473
474impl GetWbethWrapHistoryParams {
475    /// Create a builder for [`get_wbeth_wrap_history`].
476    ///
477    #[must_use]
478    pub fn builder() -> GetWbethWrapHistoryParamsBuilder {
479        GetWbethWrapHistoryParamsBuilder::default()
480    }
481}
482/// Request parameters for the [`redeem_eth`] operation.
483///
484/// This struct holds all of the inputs you can pass when calling
485/// [`redeem_eth`](#method.redeem_eth).
486#[derive(Clone, Debug, Builder, Deserialize)]
487#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
488pub struct RedeemEthParams {
489    /// Amount in BETH, limit 8 decimals
490    ///
491    /// This field is **required.
492    #[builder(setter(into))]
493    #[serde(rename = "amount")]
494    pub amount: rust_decimal::Decimal,
495    ///
496    /// The `asset` parameter.
497    ///
498    /// This field is **optional.
499    #[builder(setter(into), default)]
500    #[serde(rename = "asset", default)]
501    pub asset: Option<RedeemEthAssetEnum>,
502    /// Request validity window in milliseconds.
503    ///
504    /// This field is **optional.
505    #[builder(setter(into), default)]
506    #[serde(rename = "recvWindow", default)]
507    pub recv_window: Option<i64>,
508}
509
510impl RedeemEthParams {
511    /// Create a builder for [`redeem_eth`].
512    ///
513    /// Required parameters:
514    ///
515    /// * `amount` — Amount in BETH, limit 8 decimals
516    ///
517    #[must_use]
518    pub fn builder(amount: rust_decimal::Decimal) -> RedeemEthParamsBuilder {
519        RedeemEthParamsBuilder::default().amount(amount)
520    }
521}
522/// Request parameters for the [`subscribe_eth_staking`] operation.
523///
524/// This struct holds all of the inputs you can pass when calling
525/// [`subscribe_eth_staking`](#method.subscribe_eth_staking).
526#[derive(Clone, Debug, Builder, Deserialize)]
527#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
528pub struct SubscribeEthStakingParams {
529    /// Amount in ETH, limit 4 decimals
530    ///
531    /// This field is **required.
532    #[builder(setter(into))]
533    #[serde(rename = "amount")]
534    pub amount: rust_decimal::Decimal,
535    /// Request validity window in milliseconds.
536    ///
537    /// This field is **optional.
538    #[builder(setter(into), default)]
539    #[serde(rename = "recvWindow", default)]
540    pub recv_window: Option<i64>,
541}
542
543impl SubscribeEthStakingParams {
544    /// Create a builder for [`subscribe_eth_staking`].
545    ///
546    /// Required parameters:
547    ///
548    /// * `amount` — Amount in ETH, limit 4 decimals
549    ///
550    #[must_use]
551    pub fn builder(amount: rust_decimal::Decimal) -> SubscribeEthStakingParamsBuilder {
552        SubscribeEthStakingParamsBuilder::default().amount(amount)
553    }
554}
555/// Request parameters for the [`wrap_beth`] operation.
556///
557/// This struct holds all of the inputs you can pass when calling
558/// [`wrap_beth`](#method.wrap_beth).
559#[derive(Clone, Debug, Builder, Deserialize)]
560#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
561pub struct WrapBethParams {
562    /// Amount in BETH, limit 4 decimals
563    ///
564    /// This field is **required.
565    #[builder(setter(into))]
566    #[serde(rename = "amount")]
567    pub amount: rust_decimal::Decimal,
568    /// Request validity window in milliseconds.
569    ///
570    /// This field is **optional.
571    #[builder(setter(into), default)]
572    #[serde(rename = "recvWindow", default)]
573    pub recv_window: Option<i64>,
574}
575
576impl WrapBethParams {
577    /// Create a builder for [`wrap_beth`].
578    ///
579    /// Required parameters:
580    ///
581    /// * `amount` — Amount in BETH, limit 4 decimals
582    ///
583    #[must_use]
584    pub fn builder(amount: rust_decimal::Decimal) -> WrapBethParamsBuilder {
585        WrapBethParamsBuilder::default().amount(amount)
586    }
587}
588
589#[async_trait]
590impl EthStakingApi for EthStakingApiClient {
591    async fn eth_staking_account(
592        &self,
593        params: EthStakingAccountParams,
594    ) -> anyhow::Result<RestApiResponse<models::EthStakingAccountResponse>> {
595        let EthStakingAccountParams { recv_window } = params;
596
597        let mut query_params = BTreeMap::new();
598        let body_params = BTreeMap::new();
599
600        if let Some(rw) = recv_window {
601            query_params.insert("recvWindow".to_string(), json!(rw));
602        }
603
604        send_request::<models::EthStakingAccountResponse>(
605            &self.configuration,
606            "/sapi/v2/eth-staking/account",
607            reqwest::Method::GET,
608            query_params,
609            body_params,
610            if HAS_TIME_UNIT {
611                self.configuration.time_unit
612            } else {
613                None
614            },
615            true,
616        )
617        .await
618    }
619
620    async fn get_current_eth_staking_quota(
621        &self,
622        params: GetCurrentEthStakingQuotaParams,
623    ) -> anyhow::Result<RestApiResponse<models::GetCurrentEthStakingQuotaResponse>> {
624        let GetCurrentEthStakingQuotaParams { recv_window } = params;
625
626        let mut query_params = BTreeMap::new();
627        let body_params = BTreeMap::new();
628
629        if let Some(rw) = recv_window {
630            query_params.insert("recvWindow".to_string(), json!(rw));
631        }
632
633        send_request::<models::GetCurrentEthStakingQuotaResponse>(
634            &self.configuration,
635            "/sapi/v1/eth-staking/eth/quota",
636            reqwest::Method::GET,
637            query_params,
638            body_params,
639            if HAS_TIME_UNIT {
640                self.configuration.time_unit
641            } else {
642                None
643            },
644            true,
645        )
646        .await
647    }
648
649    async fn get_eth_redemption_history(
650        &self,
651        params: GetEthRedemptionHistoryParams,
652    ) -> anyhow::Result<RestApiResponse<models::GetEthRedemptionHistoryResponse>> {
653        let GetEthRedemptionHistoryParams {
654            redeem_id,
655            start_time,
656            end_time,
657            current,
658            size,
659            recv_window,
660        } = params;
661
662        let mut query_params = BTreeMap::new();
663        let body_params = BTreeMap::new();
664
665        if let Some(rw) = redeem_id {
666            query_params.insert("redeemId".to_string(), json!(rw));
667        }
668
669        if let Some(rw) = start_time {
670            query_params.insert("startTime".to_string(), json!(rw));
671        }
672
673        if let Some(rw) = end_time {
674            query_params.insert("endTime".to_string(), json!(rw));
675        }
676
677        if let Some(rw) = current {
678            query_params.insert("current".to_string(), json!(rw));
679        }
680
681        if let Some(rw) = size {
682            query_params.insert("size".to_string(), json!(rw));
683        }
684
685        if let Some(rw) = recv_window {
686            query_params.insert("recvWindow".to_string(), json!(rw));
687        }
688
689        send_request::<models::GetEthRedemptionHistoryResponse>(
690            &self.configuration,
691            "/sapi/v1/eth-staking/eth/history/redemptionHistory",
692            reqwest::Method::GET,
693            query_params,
694            body_params,
695            if HAS_TIME_UNIT {
696                self.configuration.time_unit
697            } else {
698                None
699            },
700            true,
701        )
702        .await
703    }
704
705    async fn get_eth_staking_history(
706        &self,
707        params: GetEthStakingHistoryParams,
708    ) -> anyhow::Result<RestApiResponse<models::GetEthStakingHistoryResponse>> {
709        let GetEthStakingHistoryParams {
710            purchase_id,
711            start_time,
712            end_time,
713            current,
714            size,
715            recv_window,
716        } = params;
717
718        let mut query_params = BTreeMap::new();
719        let body_params = BTreeMap::new();
720
721        if let Some(rw) = purchase_id {
722            query_params.insert("purchaseId".to_string(), json!(rw));
723        }
724
725        if let Some(rw) = start_time {
726            query_params.insert("startTime".to_string(), json!(rw));
727        }
728
729        if let Some(rw) = end_time {
730            query_params.insert("endTime".to_string(), json!(rw));
731        }
732
733        if let Some(rw) = current {
734            query_params.insert("current".to_string(), json!(rw));
735        }
736
737        if let Some(rw) = size {
738            query_params.insert("size".to_string(), json!(rw));
739        }
740
741        if let Some(rw) = recv_window {
742            query_params.insert("recvWindow".to_string(), json!(rw));
743        }
744
745        send_request::<models::GetEthStakingHistoryResponse>(
746            &self.configuration,
747            "/sapi/v1/eth-staking/eth/history/stakingHistory",
748            reqwest::Method::GET,
749            query_params,
750            body_params,
751            if HAS_TIME_UNIT {
752                self.configuration.time_unit
753            } else {
754                None
755            },
756            true,
757        )
758        .await
759    }
760
761    async fn get_wbeth_rate_history(
762        &self,
763        params: GetWbethRateHistoryParams,
764    ) -> anyhow::Result<RestApiResponse<models::GetWbethRateHistoryResponse>> {
765        let GetWbethRateHistoryParams {
766            start_time,
767            end_time,
768            current,
769            size,
770            recv_window,
771        } = params;
772
773        let mut query_params = BTreeMap::new();
774        let body_params = BTreeMap::new();
775
776        if let Some(rw) = start_time {
777            query_params.insert("startTime".to_string(), json!(rw));
778        }
779
780        if let Some(rw) = end_time {
781            query_params.insert("endTime".to_string(), json!(rw));
782        }
783
784        if let Some(rw) = current {
785            query_params.insert("current".to_string(), json!(rw));
786        }
787
788        if let Some(rw) = size {
789            query_params.insert("size".to_string(), json!(rw));
790        }
791
792        if let Some(rw) = recv_window {
793            query_params.insert("recvWindow".to_string(), json!(rw));
794        }
795
796        send_request::<models::GetWbethRateHistoryResponse>(
797            &self.configuration,
798            "/sapi/v1/eth-staking/eth/history/rateHistory",
799            reqwest::Method::GET,
800            query_params,
801            body_params,
802            if HAS_TIME_UNIT {
803                self.configuration.time_unit
804            } else {
805                None
806            },
807            true,
808        )
809        .await
810    }
811
812    async fn get_wbeth_rewards_history(
813        &self,
814        params: GetWbethRewardsHistoryParams,
815    ) -> anyhow::Result<RestApiResponse<models::GetWbethRewardsHistoryResponse>> {
816        let GetWbethRewardsHistoryParams {
817            start_time,
818            end_time,
819            current,
820            size,
821            recv_window,
822        } = params;
823
824        let mut query_params = BTreeMap::new();
825        let body_params = BTreeMap::new();
826
827        if let Some(rw) = start_time {
828            query_params.insert("startTime".to_string(), json!(rw));
829        }
830
831        if let Some(rw) = end_time {
832            query_params.insert("endTime".to_string(), json!(rw));
833        }
834
835        if let Some(rw) = current {
836            query_params.insert("current".to_string(), json!(rw));
837        }
838
839        if let Some(rw) = size {
840            query_params.insert("size".to_string(), json!(rw));
841        }
842
843        if let Some(rw) = recv_window {
844            query_params.insert("recvWindow".to_string(), json!(rw));
845        }
846
847        send_request::<models::GetWbethRewardsHistoryResponse>(
848            &self.configuration,
849            "/sapi/v1/eth-staking/eth/history/wbethRewardsHistory",
850            reqwest::Method::GET,
851            query_params,
852            body_params,
853            if HAS_TIME_UNIT {
854                self.configuration.time_unit
855            } else {
856                None
857            },
858            true,
859        )
860        .await
861    }
862
863    async fn get_wbeth_unwrap_history(
864        &self,
865        params: GetWbethUnwrapHistoryParams,
866    ) -> anyhow::Result<RestApiResponse<models::GetWbethUnwrapHistoryResponse>> {
867        let GetWbethUnwrapHistoryParams {
868            start_time,
869            end_time,
870            current,
871            size,
872            recv_window,
873        } = params;
874
875        let mut query_params = BTreeMap::new();
876        let body_params = BTreeMap::new();
877
878        if let Some(rw) = start_time {
879            query_params.insert("startTime".to_string(), json!(rw));
880        }
881
882        if let Some(rw) = end_time {
883            query_params.insert("endTime".to_string(), json!(rw));
884        }
885
886        if let Some(rw) = current {
887            query_params.insert("current".to_string(), json!(rw));
888        }
889
890        if let Some(rw) = size {
891            query_params.insert("size".to_string(), json!(rw));
892        }
893
894        if let Some(rw) = recv_window {
895            query_params.insert("recvWindow".to_string(), json!(rw));
896        }
897
898        send_request::<models::GetWbethUnwrapHistoryResponse>(
899            &self.configuration,
900            "/sapi/v1/eth-staking/wbeth/history/unwrapHistory",
901            reqwest::Method::GET,
902            query_params,
903            body_params,
904            if HAS_TIME_UNIT {
905                self.configuration.time_unit
906            } else {
907                None
908            },
909            true,
910        )
911        .await
912    }
913
914    async fn get_wbeth_wrap_history(
915        &self,
916        params: GetWbethWrapHistoryParams,
917    ) -> anyhow::Result<RestApiResponse<models::GetWbethWrapHistoryResponse>> {
918        let GetWbethWrapHistoryParams {
919            start_time,
920            end_time,
921            current,
922            size,
923            recv_window,
924        } = params;
925
926        let mut query_params = BTreeMap::new();
927        let body_params = BTreeMap::new();
928
929        if let Some(rw) = start_time {
930            query_params.insert("startTime".to_string(), json!(rw));
931        }
932
933        if let Some(rw) = end_time {
934            query_params.insert("endTime".to_string(), json!(rw));
935        }
936
937        if let Some(rw) = current {
938            query_params.insert("current".to_string(), json!(rw));
939        }
940
941        if let Some(rw) = size {
942            query_params.insert("size".to_string(), json!(rw));
943        }
944
945        if let Some(rw) = recv_window {
946            query_params.insert("recvWindow".to_string(), json!(rw));
947        }
948
949        send_request::<models::GetWbethWrapHistoryResponse>(
950            &self.configuration,
951            "/sapi/v1/eth-staking/wbeth/history/wrapHistory",
952            reqwest::Method::GET,
953            query_params,
954            body_params,
955            if HAS_TIME_UNIT {
956                self.configuration.time_unit
957            } else {
958                None
959            },
960            true,
961        )
962        .await
963    }
964
965    async fn redeem_eth(
966        &self,
967        params: RedeemEthParams,
968    ) -> anyhow::Result<RestApiResponse<models::RedeemEthResponse>> {
969        let RedeemEthParams {
970            amount,
971            asset,
972            recv_window,
973        } = params;
974
975        let mut query_params = BTreeMap::new();
976        let body_params = BTreeMap::new();
977
978        query_params.insert("amount".to_string(), json!(amount));
979
980        if let Some(rw) = asset {
981            query_params.insert("asset".to_string(), json!(rw));
982        }
983
984        if let Some(rw) = recv_window {
985            query_params.insert("recvWindow".to_string(), json!(rw));
986        }
987
988        send_request::<models::RedeemEthResponse>(
989            &self.configuration,
990            "/sapi/v1/eth-staking/eth/redeem",
991            reqwest::Method::POST,
992            query_params,
993            body_params,
994            if HAS_TIME_UNIT {
995                self.configuration.time_unit
996            } else {
997                None
998            },
999            true,
1000        )
1001        .await
1002    }
1003
1004    async fn subscribe_eth_staking(
1005        &self,
1006        params: SubscribeEthStakingParams,
1007    ) -> anyhow::Result<RestApiResponse<models::SubscribeEthStakingResponse>> {
1008        let SubscribeEthStakingParams {
1009            amount,
1010            recv_window,
1011        } = params;
1012
1013        let mut query_params = BTreeMap::new();
1014        let body_params = BTreeMap::new();
1015
1016        query_params.insert("amount".to_string(), json!(amount));
1017
1018        if let Some(rw) = recv_window {
1019            query_params.insert("recvWindow".to_string(), json!(rw));
1020        }
1021
1022        send_request::<models::SubscribeEthStakingResponse>(
1023            &self.configuration,
1024            "/sapi/v2/eth-staking/eth/stake",
1025            reqwest::Method::POST,
1026            query_params,
1027            body_params,
1028            if HAS_TIME_UNIT {
1029                self.configuration.time_unit
1030            } else {
1031                None
1032            },
1033            true,
1034        )
1035        .await
1036    }
1037
1038    async fn wrap_beth(
1039        &self,
1040        params: WrapBethParams,
1041    ) -> anyhow::Result<RestApiResponse<models::WrapBethResponse>> {
1042        let WrapBethParams {
1043            amount,
1044            recv_window,
1045        } = params;
1046
1047        let mut query_params = BTreeMap::new();
1048        let body_params = BTreeMap::new();
1049
1050        query_params.insert("amount".to_string(), json!(amount));
1051
1052        if let Some(rw) = recv_window {
1053            query_params.insert("recvWindow".to_string(), json!(rw));
1054        }
1055
1056        send_request::<models::WrapBethResponse>(
1057            &self.configuration,
1058            "/sapi/v1/eth-staking/wbeth/wrap",
1059            reqwest::Method::POST,
1060            query_params,
1061            body_params,
1062            if HAS_TIME_UNIT {
1063                self.configuration.time_unit
1064            } else {
1065                None
1066            },
1067            true,
1068        )
1069        .await
1070    }
1071}
1072
1073#[cfg(all(test, feature = "staking"))]
1074mod tests {
1075    use super::*;
1076    use crate::TOKIO_SHARED_RT;
1077    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
1078    use async_trait::async_trait;
1079    use std::collections::HashMap;
1080
1081    struct DummyRestApiResponse<T> {
1082        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
1083        status: u16,
1084        headers: HashMap<String, String>,
1085        rate_limits: Option<Vec<RestApiRateLimit>>,
1086    }
1087
1088    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
1089        fn from(dummy: DummyRestApiResponse<T>) -> Self {
1090            Self {
1091                data_fn: dummy.inner,
1092                status: dummy.status,
1093                headers: dummy.headers,
1094                rate_limits: dummy.rate_limits,
1095            }
1096        }
1097    }
1098
1099    struct MockEthStakingApiClient {
1100        force_error: bool,
1101    }
1102
1103    #[async_trait]
1104    impl EthStakingApi for MockEthStakingApiClient {
1105        async fn eth_staking_account(
1106            &self,
1107            _params: EthStakingAccountParams,
1108        ) -> anyhow::Result<RestApiResponse<models::EthStakingAccountResponse>> {
1109            if self.force_error {
1110                return Err(ConnectorError::ConnectorClientError {
1111                    msg: "ResponseError".to_string(),
1112                    code: None,
1113                }
1114                .into());
1115            }
1116
1117            let resp_json: Value = serde_json::from_str(r#"{"holdingInETH":"1.22330928","holdings":{"wbethAmount":"1.10928781","bethAmount":"1.90002112"},"thirtyDaysProfitInETH":"0.22330928","profit":{"amountFromWBETH":"0.12330928","amountFromBETH":"0.1"}}"#).unwrap_or_else(|_| serde_json::json!({}));
1118            let dummy_response: models::EthStakingAccountResponse =
1119                serde_json::from_value(resp_json.clone())
1120                    .expect("should parse into models::EthStakingAccountResponse");
1121
1122            let dummy = DummyRestApiResponse {
1123                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1124                status: 200,
1125                headers: HashMap::new(),
1126                rate_limits: None,
1127            };
1128
1129            Ok(dummy.into())
1130        }
1131
1132        async fn get_current_eth_staking_quota(
1133            &self,
1134            _params: GetCurrentEthStakingQuotaParams,
1135        ) -> anyhow::Result<RestApiResponse<models::GetCurrentEthStakingQuotaResponse>> {
1136            if self.force_error {
1137                return Err(ConnectorError::ConnectorClientError {
1138                    msg: "ResponseError".to_string(),
1139                    code: None,
1140                }
1141                .into());
1142            }
1143
1144            let resp_json: Value = serde_json::from_str(r#"{"leftStakingPersonalQuota":"1000","leftRedemptionPersonalQuota":"1000","minStakeAmount":"0.00010000","minRedeemAmount":"0.00000001","redeemPeriod":20,"stakeable":true,"redeemable":true,"commissionFee":"0.05000000","calculating":false}"#).unwrap_or_else(|_| serde_json::json!({}));
1145            let dummy_response: models::GetCurrentEthStakingQuotaResponse =
1146                serde_json::from_value(resp_json.clone())
1147                    .expect("should parse into models::GetCurrentEthStakingQuotaResponse");
1148
1149            let dummy = DummyRestApiResponse {
1150                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1151                status: 200,
1152                headers: HashMap::new(),
1153                rate_limits: None,
1154            };
1155
1156            Ok(dummy.into())
1157        }
1158
1159        async fn get_eth_redemption_history(
1160            &self,
1161            _params: GetEthRedemptionHistoryParams,
1162        ) -> anyhow::Result<RestApiResponse<models::GetEthRedemptionHistoryResponse>> {
1163            if self.force_error {
1164                return Err(ConnectorError::ConnectorClientError {
1165                    msg: "ResponseError".to_string(),
1166                    code: None,
1167                }
1168                .into());
1169            }
1170
1171            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"arrivalTime":1575018510000,"asset":"WBETH","amount":"21312.23223","distributeAsset":"ETH","distributeAmount":"21338.0699","conversionRatio":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1172            let dummy_response: models::GetEthRedemptionHistoryResponse =
1173                serde_json::from_value(resp_json.clone())
1174                    .expect("should parse into models::GetEthRedemptionHistoryResponse");
1175
1176            let dummy = DummyRestApiResponse {
1177                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1178                status: 200,
1179                headers: HashMap::new(),
1180                rate_limits: None,
1181            };
1182
1183            Ok(dummy.into())
1184        }
1185
1186        async fn get_eth_staking_history(
1187            &self,
1188            _params: GetEthStakingHistoryParams,
1189        ) -> anyhow::Result<RestApiResponse<models::GetEthStakingHistoryResponse>> {
1190            if self.force_error {
1191                return Err(ConnectorError::ConnectorClientError {
1192                    msg: "ResponseError".to_string(),
1193                    code: None,
1194                }
1195                .into());
1196            }
1197
1198            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"asset":"ETH","amount":"21312.23223","distributeAsset":"WBETH","distributeAmount":"21286.42584","conversionRatio":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1199            let dummy_response: models::GetEthStakingHistoryResponse =
1200                serde_json::from_value(resp_json.clone())
1201                    .expect("should parse into models::GetEthStakingHistoryResponse");
1202
1203            let dummy = DummyRestApiResponse {
1204                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1205                status: 200,
1206                headers: HashMap::new(),
1207                rate_limits: None,
1208            };
1209
1210            Ok(dummy.into())
1211        }
1212
1213        async fn get_wbeth_rate_history(
1214            &self,
1215            _params: GetWbethRateHistoryParams,
1216        ) -> anyhow::Result<RestApiResponse<models::GetWbethRateHistoryResponse>> {
1217            if self.force_error {
1218                return Err(ConnectorError::ConnectorClientError {
1219                    msg: "ResponseError".to_string(),
1220                    code: None,
1221                }
1222                .into());
1223            }
1224
1225            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"annualPercentageRate":"0.00006408","exchangeRate":"1.00121234","time":1577233578000}],"total":"1"}"#).unwrap_or_else(|_| serde_json::json!({}));
1226            let dummy_response: models::GetWbethRateHistoryResponse =
1227                serde_json::from_value(resp_json.clone())
1228                    .expect("should parse into models::GetWbethRateHistoryResponse");
1229
1230            let dummy = DummyRestApiResponse {
1231                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1232                status: 200,
1233                headers: HashMap::new(),
1234                rate_limits: None,
1235            };
1236
1237            Ok(dummy.into())
1238        }
1239
1240        async fn get_wbeth_rewards_history(
1241            &self,
1242            _params: GetWbethRewardsHistoryParams,
1243        ) -> anyhow::Result<RestApiResponse<models::GetWbethRewardsHistoryResponse>> {
1244            if self.force_error {
1245                return Err(ConnectorError::ConnectorClientError {
1246                    msg: "ResponseError".to_string(),
1247                    code: None,
1248                }
1249                .into());
1250            }
1251
1252            let resp_json: Value = serde_json::from_str(r#"{"estRewardsInETH":"1.23230920","rows":[{"time":1575018510000,"amountInETH":"0.23223","holding":"2.3223","holdingInETH":"2.4231","annualPercentageRate":"0.5"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1253            let dummy_response: models::GetWbethRewardsHistoryResponse =
1254                serde_json::from_value(resp_json.clone())
1255                    .expect("should parse into models::GetWbethRewardsHistoryResponse");
1256
1257            let dummy = DummyRestApiResponse {
1258                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1259                status: 200,
1260                headers: HashMap::new(),
1261                rate_limits: None,
1262            };
1263
1264            Ok(dummy.into())
1265        }
1266
1267        async fn get_wbeth_unwrap_history(
1268            &self,
1269            _params: GetWbethUnwrapHistoryParams,
1270        ) -> anyhow::Result<RestApiResponse<models::GetWbethUnwrapHistoryResponse>> {
1271            if self.force_error {
1272                return Err(ConnectorError::ConnectorClientError {
1273                    msg: "ResponseError".to_string(),
1274                    code: None,
1275                }
1276                .into());
1277            }
1278
1279            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"fromAsset":"WBETH","fromAmount":"21312.23223","toAsset":"BETH","toAmount":"21312.23223","exchangeRate":"1.01243253","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1280            let dummy_response: models::GetWbethUnwrapHistoryResponse =
1281                serde_json::from_value(resp_json.clone())
1282                    .expect("should parse into models::GetWbethUnwrapHistoryResponse");
1283
1284            let dummy = DummyRestApiResponse {
1285                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1286                status: 200,
1287                headers: HashMap::new(),
1288                rate_limits: None,
1289            };
1290
1291            Ok(dummy.into())
1292        }
1293
1294        async fn get_wbeth_wrap_history(
1295            &self,
1296            _params: GetWbethWrapHistoryParams,
1297        ) -> anyhow::Result<RestApiResponse<models::GetWbethWrapHistoryResponse>> {
1298            if self.force_error {
1299                return Err(ConnectorError::ConnectorClientError {
1300                    msg: "ResponseError".to_string(),
1301                    code: None,
1302                }
1303                .into());
1304            }
1305
1306            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"fromAsset":"BETH","fromAmount":"21312.23223","toAsset":"WBETH","toAmount":"21312.23223","exchangeRate":"1.01243253","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1307            let dummy_response: models::GetWbethWrapHistoryResponse =
1308                serde_json::from_value(resp_json.clone())
1309                    .expect("should parse into models::GetWbethWrapHistoryResponse");
1310
1311            let dummy = DummyRestApiResponse {
1312                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1313                status: 200,
1314                headers: HashMap::new(),
1315                rate_limits: None,
1316            };
1317
1318            Ok(dummy.into())
1319        }
1320
1321        async fn redeem_eth(
1322            &self,
1323            _params: RedeemEthParams,
1324        ) -> anyhow::Result<RestApiResponse<models::RedeemEthResponse>> {
1325            if self.force_error {
1326                return Err(ConnectorError::ConnectorClientError {
1327                    msg: "ResponseError".to_string(),
1328                    code: None,
1329                }
1330                .into());
1331            }
1332
1333            let resp_json: Value = serde_json::from_str(r#"{"success":true,"ethAmount":"0.23092091","redeemId":1234567,"conversionRatio":"1.00121234","arrivalTime":1575018510000}"#).unwrap_or_else(|_| serde_json::json!({}));
1334            let dummy_response: models::RedeemEthResponse =
1335                serde_json::from_value(resp_json.clone())
1336                    .expect("should parse into models::RedeemEthResponse");
1337
1338            let dummy = DummyRestApiResponse {
1339                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1340                status: 200,
1341                headers: HashMap::new(),
1342                rate_limits: None,
1343            };
1344
1345            Ok(dummy.into())
1346        }
1347
1348        async fn subscribe_eth_staking(
1349            &self,
1350            _params: SubscribeEthStakingParams,
1351        ) -> anyhow::Result<RestApiResponse<models::SubscribeEthStakingResponse>> {
1352            if self.force_error {
1353                return Err(ConnectorError::ConnectorClientError {
1354                    msg: "ResponseError".to_string(),
1355                    code: None,
1356                }
1357                .into());
1358            }
1359
1360            let resp_json: Value = serde_json::from_str(r#"{"success":true,"wbethAmount":"0.23092091","purchaseId":1234567,"conversionRatio":"1.001212342342"}"#).unwrap_or_else(|_| serde_json::json!({}));
1361            let dummy_response: models::SubscribeEthStakingResponse =
1362                serde_json::from_value(resp_json.clone())
1363                    .expect("should parse into models::SubscribeEthStakingResponse");
1364
1365            let dummy = DummyRestApiResponse {
1366                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1367                status: 200,
1368                headers: HashMap::new(),
1369                rate_limits: None,
1370            };
1371
1372            Ok(dummy.into())
1373        }
1374
1375        async fn wrap_beth(
1376            &self,
1377            _params: WrapBethParams,
1378        ) -> anyhow::Result<RestApiResponse<models::WrapBethResponse>> {
1379            if self.force_error {
1380                return Err(ConnectorError::ConnectorClientError {
1381                    msg: "ResponseError".to_string(),
1382                    code: None,
1383                }
1384                .into());
1385            }
1386
1387            let resp_json: Value = serde_json::from_str(
1388                r#"{"success":true,"wbethAmount":"0.23092091","exchangeRate":"1.001212343432"}"#,
1389            )
1390            .unwrap_or_else(|_| serde_json::json!({}));
1391            let dummy_response: models::WrapBethResponse =
1392                serde_json::from_value(resp_json.clone())
1393                    .expect("should parse into models::WrapBethResponse");
1394
1395            let dummy = DummyRestApiResponse {
1396                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1397                status: 200,
1398                headers: HashMap::new(),
1399                rate_limits: None,
1400            };
1401
1402            Ok(dummy.into())
1403        }
1404    }
1405
1406    #[test]
1407    fn eth_staking_account_required_params_success() {
1408        TOKIO_SHARED_RT.block_on(async {
1409            let client = MockEthStakingApiClient { force_error: false };
1410
1411            let params = EthStakingAccountParams::builder().build().unwrap();
1412
1413            let resp_json: Value = serde_json::from_str(r#"{"holdingInETH":"1.22330928","holdings":{"wbethAmount":"1.10928781","bethAmount":"1.90002112"},"thirtyDaysProfitInETH":"0.22330928","profit":{"amountFromWBETH":"0.12330928","amountFromBETH":"0.1"}}"#).unwrap_or_else(|_| serde_json::json!({}));
1414            let expected_response : models::EthStakingAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::EthStakingAccountResponse");
1415
1416            let resp = client.eth_staking_account(params).await.expect("Expected a response");
1417            let data_future = resp.data();
1418            let actual_response = data_future.await.unwrap();
1419            assert_eq!(actual_response, expected_response);
1420        });
1421    }
1422
1423    #[test]
1424    fn eth_staking_account_optional_params_success() {
1425        TOKIO_SHARED_RT.block_on(async {
1426            let client = MockEthStakingApiClient { force_error: false };
1427
1428            let params = EthStakingAccountParams::builder().recv_window(5000).build().unwrap();
1429
1430            let resp_json: Value = serde_json::from_str(r#"{"holdingInETH":"1.22330928","holdings":{"wbethAmount":"1.10928781","bethAmount":"1.90002112"},"thirtyDaysProfitInETH":"0.22330928","profit":{"amountFromWBETH":"0.12330928","amountFromBETH":"0.1"}}"#).unwrap_or_else(|_| serde_json::json!({}));
1431            let expected_response : models::EthStakingAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::EthStakingAccountResponse");
1432
1433            let resp = client.eth_staking_account(params).await.expect("Expected a response");
1434            let data_future = resp.data();
1435            let actual_response = data_future.await.unwrap();
1436            assert_eq!(actual_response, expected_response);
1437        });
1438    }
1439
1440    #[test]
1441    fn eth_staking_account_response_error() {
1442        TOKIO_SHARED_RT.block_on(async {
1443            let client = MockEthStakingApiClient { force_error: true };
1444
1445            let params = EthStakingAccountParams::builder().build().unwrap();
1446
1447            match client.eth_staking_account(params).await {
1448                Ok(_) => panic!("Expected an error"),
1449                Err(err) => {
1450                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1451                }
1452            }
1453        });
1454    }
1455
1456    #[test]
1457    fn get_current_eth_staking_quota_required_params_success() {
1458        TOKIO_SHARED_RT.block_on(async {
1459            let client = MockEthStakingApiClient { force_error: false };
1460
1461            let params = GetCurrentEthStakingQuotaParams::builder().build().unwrap();
1462
1463            let resp_json: Value = serde_json::from_str(r#"{"leftStakingPersonalQuota":"1000","leftRedemptionPersonalQuota":"1000","minStakeAmount":"0.00010000","minRedeemAmount":"0.00000001","redeemPeriod":20,"stakeable":true,"redeemable":true,"commissionFee":"0.05000000","calculating":false}"#).unwrap_or_else(|_| serde_json::json!({}));
1464            let expected_response : models::GetCurrentEthStakingQuotaResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetCurrentEthStakingQuotaResponse");
1465
1466            let resp = client.get_current_eth_staking_quota(params).await.expect("Expected a response");
1467            let data_future = resp.data();
1468            let actual_response = data_future.await.unwrap();
1469            assert_eq!(actual_response, expected_response);
1470        });
1471    }
1472
1473    #[test]
1474    fn get_current_eth_staking_quota_optional_params_success() {
1475        TOKIO_SHARED_RT.block_on(async {
1476            let client = MockEthStakingApiClient { force_error: false };
1477
1478            let params = GetCurrentEthStakingQuotaParams::builder().recv_window(5000).build().unwrap();
1479
1480            let resp_json: Value = serde_json::from_str(r#"{"leftStakingPersonalQuota":"1000","leftRedemptionPersonalQuota":"1000","minStakeAmount":"0.00010000","minRedeemAmount":"0.00000001","redeemPeriod":20,"stakeable":true,"redeemable":true,"commissionFee":"0.05000000","calculating":false}"#).unwrap_or_else(|_| serde_json::json!({}));
1481            let expected_response : models::GetCurrentEthStakingQuotaResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetCurrentEthStakingQuotaResponse");
1482
1483            let resp = client.get_current_eth_staking_quota(params).await.expect("Expected a response");
1484            let data_future = resp.data();
1485            let actual_response = data_future.await.unwrap();
1486            assert_eq!(actual_response, expected_response);
1487        });
1488    }
1489
1490    #[test]
1491    fn get_current_eth_staking_quota_response_error() {
1492        TOKIO_SHARED_RT.block_on(async {
1493            let client = MockEthStakingApiClient { force_error: true };
1494
1495            let params = GetCurrentEthStakingQuotaParams::builder().build().unwrap();
1496
1497            match client.get_current_eth_staking_quota(params).await {
1498                Ok(_) => panic!("Expected an error"),
1499                Err(err) => {
1500                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1501                }
1502            }
1503        });
1504    }
1505
1506    #[test]
1507    fn get_eth_redemption_history_required_params_success() {
1508        TOKIO_SHARED_RT.block_on(async {
1509            let client = MockEthStakingApiClient { force_error: false };
1510
1511            let params = GetEthRedemptionHistoryParams::builder().build().unwrap();
1512
1513            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"arrivalTime":1575018510000,"asset":"WBETH","amount":"21312.23223","distributeAsset":"ETH","distributeAmount":"21338.0699","conversionRatio":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1514            let expected_response : models::GetEthRedemptionHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetEthRedemptionHistoryResponse");
1515
1516            let resp = client.get_eth_redemption_history(params).await.expect("Expected a response");
1517            let data_future = resp.data();
1518            let actual_response = data_future.await.unwrap();
1519            assert_eq!(actual_response, expected_response);
1520        });
1521    }
1522
1523    #[test]
1524    fn get_eth_redemption_history_optional_params_success() {
1525        TOKIO_SHARED_RT.block_on(async {
1526            let client = MockEthStakingApiClient { force_error: false };
1527
1528            let params = GetEthRedemptionHistoryParams::builder().redeem_id(1234567).start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();
1529
1530            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"arrivalTime":1575018510000,"asset":"WBETH","amount":"21312.23223","distributeAsset":"ETH","distributeAmount":"21338.0699","conversionRatio":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1531            let expected_response : models::GetEthRedemptionHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetEthRedemptionHistoryResponse");
1532
1533            let resp = client.get_eth_redemption_history(params).await.expect("Expected a response");
1534            let data_future = resp.data();
1535            let actual_response = data_future.await.unwrap();
1536            assert_eq!(actual_response, expected_response);
1537        });
1538    }
1539
1540    #[test]
1541    fn get_eth_redemption_history_response_error() {
1542        TOKIO_SHARED_RT.block_on(async {
1543            let client = MockEthStakingApiClient { force_error: true };
1544
1545            let params = GetEthRedemptionHistoryParams::builder().build().unwrap();
1546
1547            match client.get_eth_redemption_history(params).await {
1548                Ok(_) => panic!("Expected an error"),
1549                Err(err) => {
1550                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1551                }
1552            }
1553        });
1554    }
1555
1556    #[test]
1557    fn get_eth_staking_history_required_params_success() {
1558        TOKIO_SHARED_RT.block_on(async {
1559            let client = MockEthStakingApiClient { force_error: false };
1560
1561            let params = GetEthStakingHistoryParams::builder().build().unwrap();
1562
1563            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"asset":"ETH","amount":"21312.23223","distributeAsset":"WBETH","distributeAmount":"21286.42584","conversionRatio":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1564            let expected_response : models::GetEthStakingHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetEthStakingHistoryResponse");
1565
1566            let resp = client.get_eth_staking_history(params).await.expect("Expected a response");
1567            let data_future = resp.data();
1568            let actual_response = data_future.await.unwrap();
1569            assert_eq!(actual_response, expected_response);
1570        });
1571    }
1572
1573    #[test]
1574    fn get_eth_staking_history_optional_params_success() {
1575        TOKIO_SHARED_RT.block_on(async {
1576            let client = MockEthStakingApiClient { force_error: false };
1577
1578            let params = GetEthStakingHistoryParams::builder().purchase_id(1234567).start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();
1579
1580            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"asset":"ETH","amount":"21312.23223","distributeAsset":"WBETH","distributeAmount":"21286.42584","conversionRatio":"1.00121234","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1581            let expected_response : models::GetEthStakingHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetEthStakingHistoryResponse");
1582
1583            let resp = client.get_eth_staking_history(params).await.expect("Expected a response");
1584            let data_future = resp.data();
1585            let actual_response = data_future.await.unwrap();
1586            assert_eq!(actual_response, expected_response);
1587        });
1588    }
1589
1590    #[test]
1591    fn get_eth_staking_history_response_error() {
1592        TOKIO_SHARED_RT.block_on(async {
1593            let client = MockEthStakingApiClient { force_error: true };
1594
1595            let params = GetEthStakingHistoryParams::builder().build().unwrap();
1596
1597            match client.get_eth_staking_history(params).await {
1598                Ok(_) => panic!("Expected an error"),
1599                Err(err) => {
1600                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1601                }
1602            }
1603        });
1604    }
1605
1606    #[test]
1607    fn get_wbeth_rate_history_required_params_success() {
1608        TOKIO_SHARED_RT.block_on(async {
1609            let client = MockEthStakingApiClient { force_error: false };
1610
1611            let params = GetWbethRateHistoryParams::builder().build().unwrap();
1612
1613            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"annualPercentageRate":"0.00006408","exchangeRate":"1.00121234","time":1577233578000}],"total":"1"}"#).unwrap_or_else(|_| serde_json::json!({}));
1614            let expected_response : models::GetWbethRateHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetWbethRateHistoryResponse");
1615
1616            let resp = client.get_wbeth_rate_history(params).await.expect("Expected a response");
1617            let data_future = resp.data();
1618            let actual_response = data_future.await.unwrap();
1619            assert_eq!(actual_response, expected_response);
1620        });
1621    }
1622
1623    #[test]
1624    fn get_wbeth_rate_history_optional_params_success() {
1625        TOKIO_SHARED_RT.block_on(async {
1626            let client = MockEthStakingApiClient { force_error: false };
1627
1628            let params = GetWbethRateHistoryParams::builder().start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();
1629
1630            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"annualPercentageRate":"0.00006408","exchangeRate":"1.00121234","time":1577233578000}],"total":"1"}"#).unwrap_or_else(|_| serde_json::json!({}));
1631            let expected_response : models::GetWbethRateHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetWbethRateHistoryResponse");
1632
1633            let resp = client.get_wbeth_rate_history(params).await.expect("Expected a response");
1634            let data_future = resp.data();
1635            let actual_response = data_future.await.unwrap();
1636            assert_eq!(actual_response, expected_response);
1637        });
1638    }
1639
1640    #[test]
1641    fn get_wbeth_rate_history_response_error() {
1642        TOKIO_SHARED_RT.block_on(async {
1643            let client = MockEthStakingApiClient { force_error: true };
1644
1645            let params = GetWbethRateHistoryParams::builder().build().unwrap();
1646
1647            match client.get_wbeth_rate_history(params).await {
1648                Ok(_) => panic!("Expected an error"),
1649                Err(err) => {
1650                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1651                }
1652            }
1653        });
1654    }
1655
1656    #[test]
1657    fn get_wbeth_rewards_history_required_params_success() {
1658        TOKIO_SHARED_RT.block_on(async {
1659            let client = MockEthStakingApiClient { force_error: false };
1660
1661            let params = GetWbethRewardsHistoryParams::builder().build().unwrap();
1662
1663            let resp_json: Value = serde_json::from_str(r#"{"estRewardsInETH":"1.23230920","rows":[{"time":1575018510000,"amountInETH":"0.23223","holding":"2.3223","holdingInETH":"2.4231","annualPercentageRate":"0.5"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1664            let expected_response : models::GetWbethRewardsHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetWbethRewardsHistoryResponse");
1665
1666            let resp = client.get_wbeth_rewards_history(params).await.expect("Expected a response");
1667            let data_future = resp.data();
1668            let actual_response = data_future.await.unwrap();
1669            assert_eq!(actual_response, expected_response);
1670        });
1671    }
1672
1673    #[test]
1674    fn get_wbeth_rewards_history_optional_params_success() {
1675        TOKIO_SHARED_RT.block_on(async {
1676            let client = MockEthStakingApiClient { force_error: false };
1677
1678            let params = GetWbethRewardsHistoryParams::builder().start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();
1679
1680            let resp_json: Value = serde_json::from_str(r#"{"estRewardsInETH":"1.23230920","rows":[{"time":1575018510000,"amountInETH":"0.23223","holding":"2.3223","holdingInETH":"2.4231","annualPercentageRate":"0.5"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1681            let expected_response : models::GetWbethRewardsHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetWbethRewardsHistoryResponse");
1682
1683            let resp = client.get_wbeth_rewards_history(params).await.expect("Expected a response");
1684            let data_future = resp.data();
1685            let actual_response = data_future.await.unwrap();
1686            assert_eq!(actual_response, expected_response);
1687        });
1688    }
1689
1690    #[test]
1691    fn get_wbeth_rewards_history_response_error() {
1692        TOKIO_SHARED_RT.block_on(async {
1693            let client = MockEthStakingApiClient { force_error: true };
1694
1695            let params = GetWbethRewardsHistoryParams::builder().build().unwrap();
1696
1697            match client.get_wbeth_rewards_history(params).await {
1698                Ok(_) => panic!("Expected an error"),
1699                Err(err) => {
1700                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1701                }
1702            }
1703        });
1704    }
1705
1706    #[test]
1707    fn get_wbeth_unwrap_history_required_params_success() {
1708        TOKIO_SHARED_RT.block_on(async {
1709            let client = MockEthStakingApiClient { force_error: false };
1710
1711            let params = GetWbethUnwrapHistoryParams::builder().build().unwrap();
1712
1713            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"fromAsset":"WBETH","fromAmount":"21312.23223","toAsset":"BETH","toAmount":"21312.23223","exchangeRate":"1.01243253","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1714            let expected_response : models::GetWbethUnwrapHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetWbethUnwrapHistoryResponse");
1715
1716            let resp = client.get_wbeth_unwrap_history(params).await.expect("Expected a response");
1717            let data_future = resp.data();
1718            let actual_response = data_future.await.unwrap();
1719            assert_eq!(actual_response, expected_response);
1720        });
1721    }
1722
1723    #[test]
1724    fn get_wbeth_unwrap_history_optional_params_success() {
1725        TOKIO_SHARED_RT.block_on(async {
1726            let client = MockEthStakingApiClient { force_error: false };
1727
1728            let params = GetWbethUnwrapHistoryParams::builder().start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();
1729
1730            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"fromAsset":"WBETH","fromAmount":"21312.23223","toAsset":"BETH","toAmount":"21312.23223","exchangeRate":"1.01243253","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1731            let expected_response : models::GetWbethUnwrapHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetWbethUnwrapHistoryResponse");
1732
1733            let resp = client.get_wbeth_unwrap_history(params).await.expect("Expected a response");
1734            let data_future = resp.data();
1735            let actual_response = data_future.await.unwrap();
1736            assert_eq!(actual_response, expected_response);
1737        });
1738    }
1739
1740    #[test]
1741    fn get_wbeth_unwrap_history_response_error() {
1742        TOKIO_SHARED_RT.block_on(async {
1743            let client = MockEthStakingApiClient { force_error: true };
1744
1745            let params = GetWbethUnwrapHistoryParams::builder().build().unwrap();
1746
1747            match client.get_wbeth_unwrap_history(params).await {
1748                Ok(_) => panic!("Expected an error"),
1749                Err(err) => {
1750                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1751                }
1752            }
1753        });
1754    }
1755
1756    #[test]
1757    fn get_wbeth_wrap_history_required_params_success() {
1758        TOKIO_SHARED_RT.block_on(async {
1759            let client = MockEthStakingApiClient { force_error: false };
1760
1761            let params = GetWbethWrapHistoryParams::builder().build().unwrap();
1762
1763            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"fromAsset":"BETH","fromAmount":"21312.23223","toAsset":"WBETH","toAmount":"21312.23223","exchangeRate":"1.01243253","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1764            let expected_response : models::GetWbethWrapHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetWbethWrapHistoryResponse");
1765
1766            let resp = client.get_wbeth_wrap_history(params).await.expect("Expected a response");
1767            let data_future = resp.data();
1768            let actual_response = data_future.await.unwrap();
1769            assert_eq!(actual_response, expected_response);
1770        });
1771    }
1772
1773    #[test]
1774    fn get_wbeth_wrap_history_optional_params_success() {
1775        TOKIO_SHARED_RT.block_on(async {
1776            let client = MockEthStakingApiClient { force_error: false };
1777
1778            let params = GetWbethWrapHistoryParams::builder().start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();
1779
1780            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"time":1575018510000,"fromAsset":"BETH","fromAmount":"21312.23223","toAsset":"WBETH","toAmount":"21312.23223","exchangeRate":"1.01243253","status":"SUCCESS"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
1781            let expected_response : models::GetWbethWrapHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetWbethWrapHistoryResponse");
1782
1783            let resp = client.get_wbeth_wrap_history(params).await.expect("Expected a response");
1784            let data_future = resp.data();
1785            let actual_response = data_future.await.unwrap();
1786            assert_eq!(actual_response, expected_response);
1787        });
1788    }
1789
1790    #[test]
1791    fn get_wbeth_wrap_history_response_error() {
1792        TOKIO_SHARED_RT.block_on(async {
1793            let client = MockEthStakingApiClient { force_error: true };
1794
1795            let params = GetWbethWrapHistoryParams::builder().build().unwrap();
1796
1797            match client.get_wbeth_wrap_history(params).await {
1798                Ok(_) => panic!("Expected an error"),
1799                Err(err) => {
1800                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1801                }
1802            }
1803        });
1804    }
1805
1806    #[test]
1807    fn redeem_eth_required_params_success() {
1808        TOKIO_SHARED_RT.block_on(async {
1809            let client = MockEthStakingApiClient { force_error: false };
1810
1811            let params = RedeemEthParams::builder(dec!(1.0),).build().unwrap();
1812
1813            let resp_json: Value = serde_json::from_str(r#"{"success":true,"ethAmount":"0.23092091","redeemId":1234567,"conversionRatio":"1.00121234","arrivalTime":1575018510000}"#).unwrap_or_else(|_| serde_json::json!({}));
1814            let expected_response : models::RedeemEthResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RedeemEthResponse");
1815
1816            let resp = client.redeem_eth(params).await.expect("Expected a response");
1817            let data_future = resp.data();
1818            let actual_response = data_future.await.unwrap();
1819            assert_eq!(actual_response, expected_response);
1820        });
1821    }
1822
1823    #[test]
1824    fn redeem_eth_optional_params_success() {
1825        TOKIO_SHARED_RT.block_on(async {
1826            let client = MockEthStakingApiClient { force_error: false };
1827
1828            let params = RedeemEthParams::builder(dec!(1.0),).asset(RedeemEthAssetEnum::Wbeth).recv_window(5000).build().unwrap();
1829
1830            let resp_json: Value = serde_json::from_str(r#"{"success":true,"ethAmount":"0.23092091","redeemId":1234567,"conversionRatio":"1.00121234","arrivalTime":1575018510000}"#).unwrap_or_else(|_| serde_json::json!({}));
1831            let expected_response : models::RedeemEthResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RedeemEthResponse");
1832
1833            let resp = client.redeem_eth(params).await.expect("Expected a response");
1834            let data_future = resp.data();
1835            let actual_response = data_future.await.unwrap();
1836            assert_eq!(actual_response, expected_response);
1837        });
1838    }
1839
1840    #[test]
1841    fn redeem_eth_response_error() {
1842        TOKIO_SHARED_RT.block_on(async {
1843            let client = MockEthStakingApiClient { force_error: true };
1844
1845            let params = RedeemEthParams::builder(dec!(1.0)).build().unwrap();
1846
1847            match client.redeem_eth(params).await {
1848                Ok(_) => panic!("Expected an error"),
1849                Err(err) => {
1850                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1851                }
1852            }
1853        });
1854    }
1855
1856    #[test]
1857    fn subscribe_eth_staking_required_params_success() {
1858        TOKIO_SHARED_RT.block_on(async {
1859            let client = MockEthStakingApiClient { force_error: false };
1860
1861            let params = SubscribeEthStakingParams::builder(dec!(1.0),).build().unwrap();
1862
1863            let resp_json: Value = serde_json::from_str(r#"{"success":true,"wbethAmount":"0.23092091","purchaseId":1234567,"conversionRatio":"1.001212342342"}"#).unwrap_or_else(|_| serde_json::json!({}));
1864            let expected_response : models::SubscribeEthStakingResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::SubscribeEthStakingResponse");
1865
1866            let resp = client.subscribe_eth_staking(params).await.expect("Expected a response");
1867            let data_future = resp.data();
1868            let actual_response = data_future.await.unwrap();
1869            assert_eq!(actual_response, expected_response);
1870        });
1871    }
1872
1873    #[test]
1874    fn subscribe_eth_staking_optional_params_success() {
1875        TOKIO_SHARED_RT.block_on(async {
1876            let client = MockEthStakingApiClient { force_error: false };
1877
1878            let params = SubscribeEthStakingParams::builder(dec!(1.0),).recv_window(5000).build().unwrap();
1879
1880            let resp_json: Value = serde_json::from_str(r#"{"success":true,"wbethAmount":"0.23092091","purchaseId":1234567,"conversionRatio":"1.001212342342"}"#).unwrap_or_else(|_| serde_json::json!({}));
1881            let expected_response : models::SubscribeEthStakingResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::SubscribeEthStakingResponse");
1882
1883            let resp = client.subscribe_eth_staking(params).await.expect("Expected a response");
1884            let data_future = resp.data();
1885            let actual_response = data_future.await.unwrap();
1886            assert_eq!(actual_response, expected_response);
1887        });
1888    }
1889
1890    #[test]
1891    fn subscribe_eth_staking_response_error() {
1892        TOKIO_SHARED_RT.block_on(async {
1893            let client = MockEthStakingApiClient { force_error: true };
1894
1895            let params = SubscribeEthStakingParams::builder(dec!(1.0))
1896                .build()
1897                .unwrap();
1898
1899            match client.subscribe_eth_staking(params).await {
1900                Ok(_) => panic!("Expected an error"),
1901                Err(err) => {
1902                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1903                }
1904            }
1905        });
1906    }
1907
1908    #[test]
1909    fn wrap_beth_required_params_success() {
1910        TOKIO_SHARED_RT.block_on(async {
1911            let client = MockEthStakingApiClient { force_error: false };
1912
1913            let params = WrapBethParams::builder(dec!(1.0)).build().unwrap();
1914
1915            let resp_json: Value = serde_json::from_str(
1916                r#"{"success":true,"wbethAmount":"0.23092091","exchangeRate":"1.001212343432"}"#,
1917            )
1918            .unwrap_or_else(|_| serde_json::json!({}));
1919            let expected_response: models::WrapBethResponse =
1920                serde_json::from_value(resp_json.clone())
1921                    .expect("should parse into models::WrapBethResponse");
1922
1923            let resp = client.wrap_beth(params).await.expect("Expected a response");
1924            let data_future = resp.data();
1925            let actual_response = data_future.await.unwrap();
1926            assert_eq!(actual_response, expected_response);
1927        });
1928    }
1929
1930    #[test]
1931    fn wrap_beth_optional_params_success() {
1932        TOKIO_SHARED_RT.block_on(async {
1933            let client = MockEthStakingApiClient { force_error: false };
1934
1935            let params = WrapBethParams::builder(dec!(1.0))
1936                .recv_window(5000)
1937                .build()
1938                .unwrap();
1939
1940            let resp_json: Value = serde_json::from_str(
1941                r#"{"success":true,"wbethAmount":"0.23092091","exchangeRate":"1.001212343432"}"#,
1942            )
1943            .unwrap_or_else(|_| serde_json::json!({}));
1944            let expected_response: models::WrapBethResponse =
1945                serde_json::from_value(resp_json.clone())
1946                    .expect("should parse into models::WrapBethResponse");
1947
1948            let resp = client.wrap_beth(params).await.expect("Expected a response");
1949            let data_future = resp.data();
1950            let actual_response = data_future.await.unwrap();
1951            assert_eq!(actual_response, expected_response);
1952        });
1953    }
1954
1955    #[test]
1956    fn wrap_beth_response_error() {
1957        TOKIO_SHARED_RT.block_on(async {
1958            let client = MockEthStakingApiClient { force_error: true };
1959
1960            let params = WrapBethParams::builder(dec!(1.0)).build().unwrap();
1961
1962            match client.wrap_beth(params).await {
1963                Ok(_) => panic!("Expected an error"),
1964                Err(err) => {
1965                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1966                }
1967            }
1968        });
1969    }
1970}