/*
 * Binance Staking REST API
 *
 * OpenAPI Specification for the Binance Staking REST API
 *
 * The version of the OpenAPI document: 1.0.0
 *
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

#![allow(unused_imports)]
use async_trait::async_trait;
use derive_builder::Builder;
use reqwest;
use rust_decimal::prelude::*;
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use std::collections::BTreeMap;

use crate::common::{
    config::ConfigurationRestApi,
    models::{ParamBuildError, RestApiResponse},
    utils::send_request,
};
use crate::staking::rest_api::models;

const HAS_TIME_UNIT: bool = false;

#[async_trait]
pub trait OnChainYieldsApi: Send + Sync {
    async fn get_on_chain_yields_locked_personal_left_quota(
        &self,
        params: GetOnChainYieldsLockedPersonalLeftQuotaParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedPersonalLeftQuotaResponse>>;
    async fn get_on_chain_yields_locked_product_list(
        &self,
        params: GetOnChainYieldsLockedProductListParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedProductListResponse>>;
    async fn get_on_chain_yields_locked_product_position(
        &self,
        params: GetOnChainYieldsLockedProductPositionParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedProductPositionResponse>>;
    async fn get_on_chain_yields_locked_redemption_record(
        &self,
        params: GetOnChainYieldsLockedRedemptionRecordParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedRedemptionRecordResponse>>;
    async fn get_on_chain_yields_locked_rewards_history(
        &self,
        params: GetOnChainYieldsLockedRewardsHistoryParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedRewardsHistoryResponse>>;
    async fn get_on_chain_yields_locked_subscription_preview(
        &self,
        params: GetOnChainYieldsLockedSubscriptionPreviewParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedSubscriptionPreviewResponse>>;
    async fn get_on_chain_yields_locked_subscription_record(
        &self,
        params: GetOnChainYieldsLockedSubscriptionRecordParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedSubscriptionRecordResponse>>;
    async fn on_chain_yields_account(
        &self,
        params: OnChainYieldsAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::OnChainYieldsAccountResponse>>;
    async fn redeem_on_chain_yields_locked_product(
        &self,
        params: RedeemOnChainYieldsLockedProductParams,
    ) -> anyhow::Result<RestApiResponse<models::RedeemOnChainYieldsLockedProductResponse>>;
    async fn set_on_chain_yields_locked_auto_subscribe(
        &self,
        params: SetOnChainYieldsLockedAutoSubscribeParams,
    ) -> anyhow::Result<RestApiResponse<models::SetOnChainYieldsLockedAutoSubscribeResponse>>;
    async fn set_on_chain_yields_locked_product_redeem_option(
        &self,
        params: SetOnChainYieldsLockedProductRedeemOptionParams,
    ) -> anyhow::Result<RestApiResponse<models::SetOnChainYieldsLockedProductRedeemOptionResponse>>;
    async fn subscribe_on_chain_yields_locked_product(
        &self,
        params: SubscribeOnChainYieldsLockedProductParams,
    ) -> anyhow::Result<RestApiResponse<models::SubscribeOnChainYieldsLockedProductResponse>>;
}

#[derive(Debug, Clone)]
pub struct OnChainYieldsApiClient {
    configuration: ConfigurationRestApi,
}

impl OnChainYieldsApiClient {
    pub fn new(configuration: ConfigurationRestApi) -> Self {
        Self { configuration }
    }
}

/// Request parameters for the [`get_on_chain_yields_locked_personal_left_quota`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_on_chain_yields_locked_personal_left_quota`](#method.get_on_chain_yields_locked_personal_left_quota).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetOnChainYieldsLockedPersonalLeftQuotaParams {
    ///
    /// The `project_id` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub project_id: String,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetOnChainYieldsLockedPersonalLeftQuotaParams {
    /// Create a builder for [`get_on_chain_yields_locked_personal_left_quota`].
    ///
    /// Required parameters:
    ///
    /// * `project_id` — String
    ///
    #[must_use]
    pub fn builder(project_id: String) -> GetOnChainYieldsLockedPersonalLeftQuotaParamsBuilder {
        GetOnChainYieldsLockedPersonalLeftQuotaParamsBuilder::default().project_id(project_id)
    }
}
/// Request parameters for the [`get_on_chain_yields_locked_product_list`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_on_chain_yields_locked_product_list`](#method.get_on_chain_yields_locked_product_list).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetOnChainYieldsLockedProductListParams {
    /// WBETH or BETH, default to BETH
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub asset: Option<String>,
    /// Currently querying page. Start from 1. Default:1
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub current: Option<i64>,
    /// Default:10, Max:100
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub size: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetOnChainYieldsLockedProductListParams {
    /// Create a builder for [`get_on_chain_yields_locked_product_list`].
    ///
    #[must_use]
    pub fn builder() -> GetOnChainYieldsLockedProductListParamsBuilder {
        GetOnChainYieldsLockedProductListParamsBuilder::default()
    }
}
/// Request parameters for the [`get_on_chain_yields_locked_product_position`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_on_chain_yields_locked_product_position`](#method.get_on_chain_yields_locked_product_position).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetOnChainYieldsLockedProductPositionParams {
    /// WBETH or BETH, default to BETH
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub asset: Option<String>,
    ///
    /// The `position_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub position_id: Option<i64>,
    ///
    /// The `project_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub project_id: Option<String>,
    /// Currently querying page. Start from 1. Default:1
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub current: Option<i64>,
    /// Default:10, Max:100
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub size: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetOnChainYieldsLockedProductPositionParams {
    /// Create a builder for [`get_on_chain_yields_locked_product_position`].
    ///
    #[must_use]
    pub fn builder() -> GetOnChainYieldsLockedProductPositionParamsBuilder {
        GetOnChainYieldsLockedProductPositionParamsBuilder::default()
    }
}
/// Request parameters for the [`get_on_chain_yields_locked_redemption_record`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_on_chain_yields_locked_redemption_record`](#method.get_on_chain_yields_locked_redemption_record).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetOnChainYieldsLockedRedemptionRecordParams {
    ///
    /// The `position_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub position_id: Option<i64>,
    ///
    /// The `redeem_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub redeem_id: Option<String>,
    /// WBETH or BETH, default to BETH
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub asset: Option<String>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Currently querying page. Start from 1. Default:1
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub current: Option<i64>,
    /// Default:10, Max:100
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub size: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetOnChainYieldsLockedRedemptionRecordParams {
    /// Create a builder for [`get_on_chain_yields_locked_redemption_record`].
    ///
    #[must_use]
    pub fn builder() -> GetOnChainYieldsLockedRedemptionRecordParamsBuilder {
        GetOnChainYieldsLockedRedemptionRecordParamsBuilder::default()
    }
}
/// Request parameters for the [`get_on_chain_yields_locked_rewards_history`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_on_chain_yields_locked_rewards_history`](#method.get_on_chain_yields_locked_rewards_history).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetOnChainYieldsLockedRewardsHistoryParams {
    ///
    /// The `position_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub position_id: Option<String>,
    /// WBETH or BETH, default to BETH
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub asset: Option<String>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Currently querying page. Start from 1. Default:1
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub current: Option<i64>,
    /// Default:10, Max:100
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub size: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetOnChainYieldsLockedRewardsHistoryParams {
    /// Create a builder for [`get_on_chain_yields_locked_rewards_history`].
    ///
    #[must_use]
    pub fn builder() -> GetOnChainYieldsLockedRewardsHistoryParamsBuilder {
        GetOnChainYieldsLockedRewardsHistoryParamsBuilder::default()
    }
}
/// Request parameters for the [`get_on_chain_yields_locked_subscription_preview`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_on_chain_yields_locked_subscription_preview`](#method.get_on_chain_yields_locked_subscription_preview).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetOnChainYieldsLockedSubscriptionPreviewParams {
    ///
    /// The `project_id` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub project_id: String,
    /// Amount in SOL.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub amount: rust_decimal::Decimal,
    /// true or false, default true.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub auto_subscribe: Option<bool>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetOnChainYieldsLockedSubscriptionPreviewParams {
    /// Create a builder for [`get_on_chain_yields_locked_subscription_preview`].
    ///
    /// Required parameters:
    ///
    /// * `project_id` — String
    /// * `amount` — Amount in SOL.
    ///
    #[must_use]
    pub fn builder(
        project_id: String,
        amount: rust_decimal::Decimal,
    ) -> GetOnChainYieldsLockedSubscriptionPreviewParamsBuilder {
        GetOnChainYieldsLockedSubscriptionPreviewParamsBuilder::default()
            .project_id(project_id)
            .amount(amount)
    }
}
/// Request parameters for the [`get_on_chain_yields_locked_subscription_record`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_on_chain_yields_locked_subscription_record`](#method.get_on_chain_yields_locked_subscription_record).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetOnChainYieldsLockedSubscriptionRecordParams {
    ///
    /// The `purchase_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub purchase_id: Option<String>,
    ///
    /// The `client_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub client_id: Option<String>,
    /// WBETH or BETH, default to BETH
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub asset: Option<String>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Currently querying page. Start from 1. Default:1
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub current: Option<i64>,
    /// Default:10, Max:100
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub size: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetOnChainYieldsLockedSubscriptionRecordParams {
    /// Create a builder for [`get_on_chain_yields_locked_subscription_record`].
    ///
    #[must_use]
    pub fn builder() -> GetOnChainYieldsLockedSubscriptionRecordParamsBuilder {
        GetOnChainYieldsLockedSubscriptionRecordParamsBuilder::default()
    }
}
/// Request parameters for the [`on_chain_yields_account`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`on_chain_yields_account`](#method.on_chain_yields_account).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct OnChainYieldsAccountParams {
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl OnChainYieldsAccountParams {
    /// Create a builder for [`on_chain_yields_account`].
    ///
    #[must_use]
    pub fn builder() -> OnChainYieldsAccountParamsBuilder {
        OnChainYieldsAccountParamsBuilder::default()
    }
}
/// Request parameters for the [`redeem_on_chain_yields_locked_product`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`redeem_on_chain_yields_locked_product`](#method.redeem_on_chain_yields_locked_product).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct RedeemOnChainYieldsLockedProductParams {
    ///
    /// The `position_id` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub position_id: String,
    ///
    /// The `channel_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub channel_id: Option<String>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl RedeemOnChainYieldsLockedProductParams {
    /// Create a builder for [`redeem_on_chain_yields_locked_product`].
    ///
    /// Required parameters:
    ///
    /// * `position_id` — String
    ///
    #[must_use]
    pub fn builder(position_id: String) -> RedeemOnChainYieldsLockedProductParamsBuilder {
        RedeemOnChainYieldsLockedProductParamsBuilder::default().position_id(position_id)
    }
}
/// Request parameters for the [`set_on_chain_yields_locked_auto_subscribe`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`set_on_chain_yields_locked_auto_subscribe`](#method.set_on_chain_yields_locked_auto_subscribe).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct SetOnChainYieldsLockedAutoSubscribeParams {
    ///
    /// The `position_id` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub position_id: String,
    /// true or false
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub auto_subscribe: bool,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl SetOnChainYieldsLockedAutoSubscribeParams {
    /// Create a builder for [`set_on_chain_yields_locked_auto_subscribe`].
    ///
    /// Required parameters:
    ///
    /// * `position_id` — String
    /// * `auto_subscribe` — true or false
    ///
    #[must_use]
    pub fn builder(
        position_id: String,
        auto_subscribe: bool,
    ) -> SetOnChainYieldsLockedAutoSubscribeParamsBuilder {
        SetOnChainYieldsLockedAutoSubscribeParamsBuilder::default()
            .position_id(position_id)
            .auto_subscribe(auto_subscribe)
    }
}
/// Request parameters for the [`set_on_chain_yields_locked_product_redeem_option`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`set_on_chain_yields_locked_product_redeem_option`](#method.set_on_chain_yields_locked_product_redeem_option).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct SetOnChainYieldsLockedProductRedeemOptionParams {
    ///
    /// The `position_id` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub position_id: String,
    /// 'SPOT','FLEXIBLE'
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub redeem_to: String,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl SetOnChainYieldsLockedProductRedeemOptionParams {
    /// Create a builder for [`set_on_chain_yields_locked_product_redeem_option`].
    ///
    /// Required parameters:
    ///
    /// * `position_id` — String
    /// * `redeem_to` — 'SPOT','FLEXIBLE'
    ///
    #[must_use]
    pub fn builder(
        position_id: String,
        redeem_to: String,
    ) -> SetOnChainYieldsLockedProductRedeemOptionParamsBuilder {
        SetOnChainYieldsLockedProductRedeemOptionParamsBuilder::default()
            .position_id(position_id)
            .redeem_to(redeem_to)
    }
}
/// Request parameters for the [`subscribe_on_chain_yields_locked_product`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`subscribe_on_chain_yields_locked_product`](#method.subscribe_on_chain_yields_locked_product).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct SubscribeOnChainYieldsLockedProductParams {
    ///
    /// The `project_id` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub project_id: String,
    /// Amount in SOL.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub amount: rust_decimal::Decimal,
    /// true or false, default true.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub auto_subscribe: Option<bool>,
    /// `SPOT`,`FUND`,`ALL`, default `SPOT`
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub source_account: Option<String>,
    /// `SPOT`,`FLEXIBLE`, default `FLEXIBLE` Takes effect when Auto Subscribe is false
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub redeem_to: Option<String>,
    ///
    /// The `channel_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub channel_id: Option<String>,
    ///
    /// The `client_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub client_id: Option<String>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl SubscribeOnChainYieldsLockedProductParams {
    /// Create a builder for [`subscribe_on_chain_yields_locked_product`].
    ///
    /// Required parameters:
    ///
    /// * `project_id` — String
    /// * `amount` — Amount in SOL.
    ///
    #[must_use]
    pub fn builder(
        project_id: String,
        amount: rust_decimal::Decimal,
    ) -> SubscribeOnChainYieldsLockedProductParamsBuilder {
        SubscribeOnChainYieldsLockedProductParamsBuilder::default()
            .project_id(project_id)
            .amount(amount)
    }
}

#[async_trait]
impl OnChainYieldsApi for OnChainYieldsApiClient {
    async fn get_on_chain_yields_locked_personal_left_quota(
        &self,
        params: GetOnChainYieldsLockedPersonalLeftQuotaParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedPersonalLeftQuotaResponse>>
    {
        let GetOnChainYieldsLockedPersonalLeftQuotaParams {
            project_id,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("projectId".to_string(), json!(project_id));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetOnChainYieldsLockedPersonalLeftQuotaResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/locked/personalLeftQuota",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_on_chain_yields_locked_product_list(
        &self,
        params: GetOnChainYieldsLockedProductListParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedProductListResponse>> {
        let GetOnChainYieldsLockedProductListParams {
            asset,
            current,
            size,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = asset {
            query_params.insert("asset".to_string(), json!(rw));
        }

        if let Some(rw) = current {
            query_params.insert("current".to_string(), json!(rw));
        }

        if let Some(rw) = size {
            query_params.insert("size".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetOnChainYieldsLockedProductListResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/locked/list",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_on_chain_yields_locked_product_position(
        &self,
        params: GetOnChainYieldsLockedProductPositionParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedProductPositionResponse>>
    {
        let GetOnChainYieldsLockedProductPositionParams {
            asset,
            position_id,
            project_id,
            current,
            size,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = asset {
            query_params.insert("asset".to_string(), json!(rw));
        }

        if let Some(rw) = position_id {
            query_params.insert("positionId".to_string(), json!(rw));
        }

        if let Some(rw) = project_id {
            query_params.insert("projectId".to_string(), json!(rw));
        }

        if let Some(rw) = current {
            query_params.insert("current".to_string(), json!(rw));
        }

        if let Some(rw) = size {
            query_params.insert("size".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetOnChainYieldsLockedProductPositionResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/locked/position",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_on_chain_yields_locked_redemption_record(
        &self,
        params: GetOnChainYieldsLockedRedemptionRecordParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedRedemptionRecordResponse>>
    {
        let GetOnChainYieldsLockedRedemptionRecordParams {
            position_id,
            redeem_id,
            asset,
            start_time,
            end_time,
            current,
            size,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = position_id {
            query_params.insert("positionId".to_string(), json!(rw));
        }

        if let Some(rw) = redeem_id {
            query_params.insert("redeemId".to_string(), json!(rw));
        }

        if let Some(rw) = asset {
            query_params.insert("asset".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = current {
            query_params.insert("current".to_string(), json!(rw));
        }

        if let Some(rw) = size {
            query_params.insert("size".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetOnChainYieldsLockedRedemptionRecordResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/locked/history/redemptionRecord",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_on_chain_yields_locked_rewards_history(
        &self,
        params: GetOnChainYieldsLockedRewardsHistoryParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedRewardsHistoryResponse>> {
        let GetOnChainYieldsLockedRewardsHistoryParams {
            position_id,
            asset,
            start_time,
            end_time,
            current,
            size,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = position_id {
            query_params.insert("positionId".to_string(), json!(rw));
        }

        if let Some(rw) = asset {
            query_params.insert("asset".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = current {
            query_params.insert("current".to_string(), json!(rw));
        }

        if let Some(rw) = size {
            query_params.insert("size".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetOnChainYieldsLockedRewardsHistoryResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/locked/history/rewardsRecord",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_on_chain_yields_locked_subscription_preview(
        &self,
        params: GetOnChainYieldsLockedSubscriptionPreviewParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedSubscriptionPreviewResponse>>
    {
        let GetOnChainYieldsLockedSubscriptionPreviewParams {
            project_id,
            amount,
            auto_subscribe,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("projectId".to_string(), json!(project_id));

        query_params.insert("amount".to_string(), json!(amount));

        if let Some(rw) = auto_subscribe {
            query_params.insert("autoSubscribe".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetOnChainYieldsLockedSubscriptionPreviewResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/locked/subscriptionPreview",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_on_chain_yields_locked_subscription_record(
        &self,
        params: GetOnChainYieldsLockedSubscriptionRecordParams,
    ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedSubscriptionRecordResponse>>
    {
        let GetOnChainYieldsLockedSubscriptionRecordParams {
            purchase_id,
            client_id,
            asset,
            start_time,
            end_time,
            current,
            size,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = purchase_id {
            query_params.insert("purchaseId".to_string(), json!(rw));
        }

        if let Some(rw) = client_id {
            query_params.insert("clientId".to_string(), json!(rw));
        }

        if let Some(rw) = asset {
            query_params.insert("asset".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = current {
            query_params.insert("current".to_string(), json!(rw));
        }

        if let Some(rw) = size {
            query_params.insert("size".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetOnChainYieldsLockedSubscriptionRecordResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/locked/history/subscriptionRecord",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn on_chain_yields_account(
        &self,
        params: OnChainYieldsAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::OnChainYieldsAccountResponse>> {
        let OnChainYieldsAccountParams { recv_window } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::OnChainYieldsAccountResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/account",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn redeem_on_chain_yields_locked_product(
        &self,
        params: RedeemOnChainYieldsLockedProductParams,
    ) -> anyhow::Result<RestApiResponse<models::RedeemOnChainYieldsLockedProductResponse>> {
        let RedeemOnChainYieldsLockedProductParams {
            position_id,
            channel_id,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("positionId".to_string(), json!(position_id));

        if let Some(rw) = channel_id {
            query_params.insert("channelId".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::RedeemOnChainYieldsLockedProductResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/locked/redeem",
            reqwest::Method::POST,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn set_on_chain_yields_locked_auto_subscribe(
        &self,
        params: SetOnChainYieldsLockedAutoSubscribeParams,
    ) -> anyhow::Result<RestApiResponse<models::SetOnChainYieldsLockedAutoSubscribeResponse>> {
        let SetOnChainYieldsLockedAutoSubscribeParams {
            position_id,
            auto_subscribe,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("positionId".to_string(), json!(position_id));

        query_params.insert("autoSubscribe".to_string(), json!(auto_subscribe));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::SetOnChainYieldsLockedAutoSubscribeResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/locked/setAutoSubscribe",
            reqwest::Method::POST,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn set_on_chain_yields_locked_product_redeem_option(
        &self,
        params: SetOnChainYieldsLockedProductRedeemOptionParams,
    ) -> anyhow::Result<RestApiResponse<models::SetOnChainYieldsLockedProductRedeemOptionResponse>>
    {
        let SetOnChainYieldsLockedProductRedeemOptionParams {
            position_id,
            redeem_to,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("positionId".to_string(), json!(position_id));

        query_params.insert("redeemTo".to_string(), json!(redeem_to));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::SetOnChainYieldsLockedProductRedeemOptionResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/locked/setRedeemOption",
            reqwest::Method::POST,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn subscribe_on_chain_yields_locked_product(
        &self,
        params: SubscribeOnChainYieldsLockedProductParams,
    ) -> anyhow::Result<RestApiResponse<models::SubscribeOnChainYieldsLockedProductResponse>> {
        let SubscribeOnChainYieldsLockedProductParams {
            project_id,
            amount,
            auto_subscribe,
            source_account,
            redeem_to,
            channel_id,
            client_id,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("projectId".to_string(), json!(project_id));

        query_params.insert("amount".to_string(), json!(amount));

        if let Some(rw) = auto_subscribe {
            query_params.insert("autoSubscribe".to_string(), json!(rw));
        }

        if let Some(rw) = source_account {
            query_params.insert("sourceAccount".to_string(), json!(rw));
        }

        if let Some(rw) = redeem_to {
            query_params.insert("redeemTo".to_string(), json!(rw));
        }

        if let Some(rw) = channel_id {
            query_params.insert("channelId".to_string(), json!(rw));
        }

        if let Some(rw) = client_id {
            query_params.insert("clientId".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::SubscribeOnChainYieldsLockedProductResponse>(
            &self.configuration,
            "/sapi/v1/onchain-yields/locked/subscribe",
            reqwest::Method::POST,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }
}

#[cfg(all(test, feature = "staking"))]
mod tests {
    use super::*;
    use crate::TOKIO_SHARED_RT;
    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
    use async_trait::async_trait;
    use std::collections::HashMap;

    struct DummyRestApiResponse<T> {
        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
        status: u16,
        headers: HashMap<String, String>,
        rate_limits: Option<Vec<RestApiRateLimit>>,
    }

    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
        fn from(dummy: DummyRestApiResponse<T>) -> Self {
            Self {
                data_fn: dummy.inner,
                status: dummy.status,
                headers: dummy.headers,
                rate_limits: dummy.rate_limits,
            }
        }
    }

    struct MockOnChainYieldsApiClient {
        force_error: bool,
    }

    #[async_trait]
    impl OnChainYieldsApi for MockOnChainYieldsApiClient {
        async fn get_on_chain_yields_locked_personal_left_quota(
            &self,
            _params: GetOnChainYieldsLockedPersonalLeftQuotaParams,
        ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedPersonalLeftQuotaResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"leftPersonalQuota":"1000"}"#).unwrap();
            let dummy_response: models::GetOnChainYieldsLockedPersonalLeftQuotaResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetOnChainYieldsLockedPersonalLeftQuotaResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_on_chain_yields_locked_product_list(
            &self,
            _params: GetOnChainYieldsLockedProductListParams,
        ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedProductListResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"projectId":"Solv-60d","detail":{"asset":"BTC","rewardAsset":"SOLV","duration":60,"renewable":true,"isSoldOut":true,"apr":"0.039","status":"PREHEATING","subscriptionStartTime":1646182276000,"canRedeemToFlex":true},"quota":{"totalPersonalQuota":"2","minimum":"0.001"}}],"total":1}"#).unwrap();
            let dummy_response: models::GetOnChainYieldsLockedProductListResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::GetOnChainYieldsLockedProductListResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_on_chain_yields_locked_product_position(
            &self,
            _params: GetOnChainYieldsLockedProductPositionParams,
        ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedProductPositionResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","projectId":"Solv-60d","asset":"BTC","amount":"122.09202928","purchaseTime":"1646182276000","duration":"60","accrualDays":"4","rewardAsset":"SOLV","APY":"0.039","rewardAmt":"5.17181528","nextPay":"1.29295383","nextPayDate":"1646697600000","payPeriod":"1","rewardsPayDate":"1646697600000","rewardsEndDate":"1651449600000","deliverDate":"1651536000000","nextSubscriptionDate":"1651536000000","redeemingAmt":"232.2323","redeemTo":"FLEXIBLE","canRedeemEarly":true,"autoSubscribe":true,"type":"AUTO","status":"HOLDING"}],"total":1}"#).unwrap();
            let dummy_response: models::GetOnChainYieldsLockedProductPositionResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetOnChainYieldsLockedProductPositionResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_on_chain_yields_locked_redemption_record(
            &self,
            _params: GetOnChainYieldsLockedRedemptionRecordParams,
        ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedRedemptionRecordResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","redeemId":40607,"time":1575018510000,"asset":"BTC","lockPeriod":"30","amount":"21312.23223","originalAmount":"21312.23223","type":"NORMAL","deliverDate":"1575018510000","lossAmount":"0.00001232","isComplete":true,"rewardAsset":"SOLV","rewardAmt":"5.17181528","status":"PAID"}],"total":1}"#).unwrap();
            let dummy_response: models::GetOnChainYieldsLockedRedemptionRecordResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetOnChainYieldsLockedRedemptionRecordResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_on_chain_yields_locked_rewards_history(
            &self,
            _params: GetOnChainYieldsLockedRewardsHistoryParams,
        ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedRewardsHistoryResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","time":1575018510000,"asset":"BNB","lockPeriod":"30","amount":"21312.23223"}],"total":1}"#).unwrap();
            let dummy_response: models::GetOnChainYieldsLockedRewardsHistoryResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetOnChainYieldsLockedRewardsHistoryResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_on_chain_yields_locked_subscription_preview(
            &self,
            _params: GetOnChainYieldsLockedSubscriptionPreviewParams,
        ) -> anyhow::Result<
            RestApiResponse<models::GetOnChainYieldsLockedSubscriptionPreviewResponse>,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"rewardAsset":"SOLV","totalRewardAmt":"5.17181528","nextPay":"1.29295383","nextPayDate":"1646697600000","rewardsPayDate":"1646697600000","valueDate":"1646697600000","rewardsEndDate":"1651449600000","deliverDate":"1651536000000","nextSubscriptionDate":"1651536000000"}"#).unwrap();
            let dummy_response: models::GetOnChainYieldsLockedSubscriptionPreviewResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetOnChainYieldsLockedSubscriptionPreviewResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_on_chain_yields_locked_subscription_record(
            &self,
            _params: GetOnChainYieldsLockedSubscriptionRecordParams,
        ) -> anyhow::Result<RestApiResponse<models::GetOnChainYieldsLockedSubscriptionRecordResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","purchaseId":"26055","projectId":"Solv-60d","clientId":"ABC","time":1575018510000,"asset":"BTC","amount":"21312.23223","lockPeriod":"30","type":"AUTO","sourceAccount":"SPOT","amtFromSpot":"30","amtFromFunding":"70","status":"SUCCESS"}],"total":1}"#).unwrap();
            let dummy_response: models::GetOnChainYieldsLockedSubscriptionRecordResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetOnChainYieldsLockedSubscriptionRecordResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn on_chain_yields_account(
            &self,
            _params: OnChainYieldsAccountParams,
        ) -> anyhow::Result<RestApiResponse<models::OnChainYieldsAccountResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"totalAmountInBTC":"0.01067982","totalAmountInUSDT":"77.13289230","totalFlexibleAmountInBTC":"0.00000000","totalFlexibleAmountInUSDT":"0.00000000","totalLockedInBTC":"0.01067982","totalLockedInUSDT":"77.13289230"}"#).unwrap();
            let dummy_response: models::OnChainYieldsAccountResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::OnChainYieldsAccountResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn redeem_on_chain_yields_locked_product(
            &self,
            _params: RedeemOnChainYieldsLockedProductParams,
        ) -> anyhow::Result<RestApiResponse<models::RedeemOnChainYieldsLockedProductResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value =
                serde_json::from_str(r#"{"redeemId":40607,"success":true}"#).unwrap();
            let dummy_response: models::RedeemOnChainYieldsLockedProductResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::RedeemOnChainYieldsLockedProductResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn set_on_chain_yields_locked_auto_subscribe(
            &self,
            _params: SetOnChainYieldsLockedAutoSubscribeParams,
        ) -> anyhow::Result<RestApiResponse<models::SetOnChainYieldsLockedAutoSubscribeResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"success":true}"#).unwrap();
            let dummy_response: models::SetOnChainYieldsLockedAutoSubscribeResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::SetOnChainYieldsLockedAutoSubscribeResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn set_on_chain_yields_locked_product_redeem_option(
            &self,
            _params: SetOnChainYieldsLockedProductRedeemOptionParams,
        ) -> anyhow::Result<
            RestApiResponse<models::SetOnChainYieldsLockedProductRedeemOptionResponse>,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"success":true}"#).unwrap();
            let dummy_response: models::SetOnChainYieldsLockedProductRedeemOptionResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::SetOnChainYieldsLockedProductRedeemOptionResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn subscribe_on_chain_yields_locked_product(
            &self,
            _params: SubscribeOnChainYieldsLockedProductParams,
        ) -> anyhow::Result<RestApiResponse<models::SubscribeOnChainYieldsLockedProductResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"purchaseId":40607,"positionId":"12345","amount":"75.46000000","success":true}"#).unwrap();
            let dummy_response: models::SubscribeOnChainYieldsLockedProductResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::SubscribeOnChainYieldsLockedProductResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }
    }

    #[test]
    fn get_on_chain_yields_locked_personal_left_quota_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedPersonalLeftQuotaParams::builder("1".to_string())
                .build()
                .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"leftPersonalQuota":"1000"}"#).unwrap();
            let expected_response: models::GetOnChainYieldsLockedPersonalLeftQuotaResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetOnChainYieldsLockedPersonalLeftQuotaResponse",
                );

            let resp = client
                .get_on_chain_yields_locked_personal_left_quota(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_personal_left_quota_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedPersonalLeftQuotaParams::builder("1".to_string())
                .recv_window(5000)
                .build()
                .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"leftPersonalQuota":"1000"}"#).unwrap();
            let expected_response: models::GetOnChainYieldsLockedPersonalLeftQuotaResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetOnChainYieldsLockedPersonalLeftQuotaResponse",
                );

            let resp = client
                .get_on_chain_yields_locked_personal_left_quota(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_personal_left_quota_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params = GetOnChainYieldsLockedPersonalLeftQuotaParams::builder("1".to_string())
                .build()
                .unwrap();

            match client
                .get_on_chain_yields_locked_personal_left_quota(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_on_chain_yields_locked_product_list_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedProductListParams::builder().build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"projectId":"Solv-60d","detail":{"asset":"BTC","rewardAsset":"SOLV","duration":60,"renewable":true,"isSoldOut":true,"apr":"0.039","status":"PREHEATING","subscriptionStartTime":1646182276000,"canRedeemToFlex":true},"quota":{"totalPersonalQuota":"2","minimum":"0.001"}}],"total":1}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedProductListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedProductListResponse");

            let resp = client.get_on_chain_yields_locked_product_list(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_product_list_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedProductListParams::builder().asset("BETH".to_string()).current(1).size(10).recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"projectId":"Solv-60d","detail":{"asset":"BTC","rewardAsset":"SOLV","duration":60,"renewable":true,"isSoldOut":true,"apr":"0.039","status":"PREHEATING","subscriptionStartTime":1646182276000,"canRedeemToFlex":true},"quota":{"totalPersonalQuota":"2","minimum":"0.001"}}],"total":1}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedProductListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedProductListResponse");

            let resp = client.get_on_chain_yields_locked_product_list(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_product_list_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params = GetOnChainYieldsLockedProductListParams::builder()
                .build()
                .unwrap();

            match client.get_on_chain_yields_locked_product_list(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_on_chain_yields_locked_product_position_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedProductPositionParams::builder().build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","projectId":"Solv-60d","asset":"BTC","amount":"122.09202928","purchaseTime":"1646182276000","duration":"60","accrualDays":"4","rewardAsset":"SOLV","APY":"0.039","rewardAmt":"5.17181528","nextPay":"1.29295383","nextPayDate":"1646697600000","payPeriod":"1","rewardsPayDate":"1646697600000","rewardsEndDate":"1651449600000","deliverDate":"1651536000000","nextSubscriptionDate":"1651536000000","redeemingAmt":"232.2323","redeemTo":"FLEXIBLE","canRedeemEarly":true,"autoSubscribe":true,"type":"AUTO","status":"HOLDING"}],"total":1}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedProductPositionResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedProductPositionResponse");

            let resp = client.get_on_chain_yields_locked_product_position(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_product_position_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedProductPositionParams::builder().asset("BETH".to_string()).position_id(1).project_id("1".to_string()).current(1).size(10).recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","projectId":"Solv-60d","asset":"BTC","amount":"122.09202928","purchaseTime":"1646182276000","duration":"60","accrualDays":"4","rewardAsset":"SOLV","APY":"0.039","rewardAmt":"5.17181528","nextPay":"1.29295383","nextPayDate":"1646697600000","payPeriod":"1","rewardsPayDate":"1646697600000","rewardsEndDate":"1651449600000","deliverDate":"1651536000000","nextSubscriptionDate":"1651536000000","redeemingAmt":"232.2323","redeemTo":"FLEXIBLE","canRedeemEarly":true,"autoSubscribe":true,"type":"AUTO","status":"HOLDING"}],"total":1}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedProductPositionResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedProductPositionResponse");

            let resp = client.get_on_chain_yields_locked_product_position(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_product_position_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params = GetOnChainYieldsLockedProductPositionParams::builder()
                .build()
                .unwrap();

            match client
                .get_on_chain_yields_locked_product_position(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_on_chain_yields_locked_redemption_record_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedRedemptionRecordParams::builder().build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","redeemId":40607,"time":1575018510000,"asset":"BTC","lockPeriod":"30","amount":"21312.23223","originalAmount":"21312.23223","type":"NORMAL","deliverDate":"1575018510000","lossAmount":"0.00001232","isComplete":true,"rewardAsset":"SOLV","rewardAmt":"5.17181528","status":"PAID"}],"total":1}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedRedemptionRecordResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedRedemptionRecordResponse");

            let resp = client.get_on_chain_yields_locked_redemption_record(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_redemption_record_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedRedemptionRecordParams::builder().position_id(1).redeem_id("1".to_string()).asset("BETH".to_string()).start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","redeemId":40607,"time":1575018510000,"asset":"BTC","lockPeriod":"30","amount":"21312.23223","originalAmount":"21312.23223","type":"NORMAL","deliverDate":"1575018510000","lossAmount":"0.00001232","isComplete":true,"rewardAsset":"SOLV","rewardAmt":"5.17181528","status":"PAID"}],"total":1}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedRedemptionRecordResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedRedemptionRecordResponse");

            let resp = client.get_on_chain_yields_locked_redemption_record(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_redemption_record_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params = GetOnChainYieldsLockedRedemptionRecordParams::builder()
                .build()
                .unwrap();

            match client
                .get_on_chain_yields_locked_redemption_record(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_on_chain_yields_locked_rewards_history_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedRewardsHistoryParams::builder().build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","time":1575018510000,"asset":"BNB","lockPeriod":"30","amount":"21312.23223"}],"total":1}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedRewardsHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedRewardsHistoryResponse");

            let resp = client.get_on_chain_yields_locked_rewards_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_rewards_history_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedRewardsHistoryParams::builder().position_id("1".to_string()).asset("BETH".to_string()).start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","time":1575018510000,"asset":"BNB","lockPeriod":"30","amount":"21312.23223"}],"total":1}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedRewardsHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedRewardsHistoryResponse");

            let resp = client.get_on_chain_yields_locked_rewards_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_rewards_history_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params = GetOnChainYieldsLockedRewardsHistoryParams::builder()
                .build()
                .unwrap();

            match client
                .get_on_chain_yields_locked_rewards_history(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_on_chain_yields_locked_subscription_preview_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedSubscriptionPreviewParams::builder("1".to_string(),dec!(1.0),).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rewardAsset":"SOLV","totalRewardAmt":"5.17181528","nextPay":"1.29295383","nextPayDate":"1646697600000","rewardsPayDate":"1646697600000","valueDate":"1646697600000","rewardsEndDate":"1651449600000","deliverDate":"1651536000000","nextSubscriptionDate":"1651536000000"}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedSubscriptionPreviewResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedSubscriptionPreviewResponse");

            let resp = client.get_on_chain_yields_locked_subscription_preview(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_subscription_preview_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedSubscriptionPreviewParams::builder("1".to_string(),dec!(1.0),).auto_subscribe(true).recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rewardAsset":"SOLV","totalRewardAmt":"5.17181528","nextPay":"1.29295383","nextPayDate":"1646697600000","rewardsPayDate":"1646697600000","valueDate":"1646697600000","rewardsEndDate":"1651449600000","deliverDate":"1651536000000","nextSubscriptionDate":"1651536000000"}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedSubscriptionPreviewResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedSubscriptionPreviewResponse");

            let resp = client.get_on_chain_yields_locked_subscription_preview(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_subscription_preview_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params = GetOnChainYieldsLockedSubscriptionPreviewParams::builder(
                "1".to_string(),
                dec!(1.0),
            )
            .build()
            .unwrap();

            match client
                .get_on_chain_yields_locked_subscription_preview(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_on_chain_yields_locked_subscription_record_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedSubscriptionRecordParams::builder().build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","purchaseId":"26055","projectId":"Solv-60d","clientId":"ABC","time":1575018510000,"asset":"BTC","amount":"21312.23223","lockPeriod":"30","type":"AUTO","sourceAccount":"SPOT","amtFromSpot":"30","amtFromFunding":"70","status":"SUCCESS"}],"total":1}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedSubscriptionRecordResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedSubscriptionRecordResponse");

            let resp = client.get_on_chain_yields_locked_subscription_record(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_subscription_record_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = GetOnChainYieldsLockedSubscriptionRecordParams::builder().purchase_id("1".to_string()).client_id("1".to_string()).asset("BETH".to_string()).start_time(1623319461670).end_time(1641782889000).current(1).size(10).recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"positionId":"123123","purchaseId":"26055","projectId":"Solv-60d","clientId":"ABC","time":1575018510000,"asset":"BTC","amount":"21312.23223","lockPeriod":"30","type":"AUTO","sourceAccount":"SPOT","amtFromSpot":"30","amtFromFunding":"70","status":"SUCCESS"}],"total":1}"#).unwrap();
            let expected_response : models::GetOnChainYieldsLockedSubscriptionRecordResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetOnChainYieldsLockedSubscriptionRecordResponse");

            let resp = client.get_on_chain_yields_locked_subscription_record(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_on_chain_yields_locked_subscription_record_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params = GetOnChainYieldsLockedSubscriptionRecordParams::builder()
                .build()
                .unwrap();

            match client
                .get_on_chain_yields_locked_subscription_record(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn on_chain_yields_account_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = OnChainYieldsAccountParams::builder().build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"totalAmountInBTC":"0.01067982","totalAmountInUSDT":"77.13289230","totalFlexibleAmountInBTC":"0.00000000","totalFlexibleAmountInUSDT":"0.00000000","totalLockedInBTC":"0.01067982","totalLockedInUSDT":"77.13289230"}"#).unwrap();
            let expected_response : models::OnChainYieldsAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::OnChainYieldsAccountResponse");

            let resp = client.on_chain_yields_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn on_chain_yields_account_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = OnChainYieldsAccountParams::builder().recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"totalAmountInBTC":"0.01067982","totalAmountInUSDT":"77.13289230","totalFlexibleAmountInBTC":"0.00000000","totalFlexibleAmountInUSDT":"0.00000000","totalLockedInBTC":"0.01067982","totalLockedInUSDT":"77.13289230"}"#).unwrap();
            let expected_response : models::OnChainYieldsAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::OnChainYieldsAccountResponse");

            let resp = client.on_chain_yields_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn on_chain_yields_account_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params = OnChainYieldsAccountParams::builder().build().unwrap();

            match client.on_chain_yields_account(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn redeem_on_chain_yields_locked_product_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = RedeemOnChainYieldsLockedProductParams::builder("1".to_string())
                .build()
                .unwrap();

            let resp_json: Value =
                serde_json::from_str(r#"{"redeemId":40607,"success":true}"#).unwrap();
            let expected_response: models::RedeemOnChainYieldsLockedProductResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::RedeemOnChainYieldsLockedProductResponse");

            let resp = client
                .redeem_on_chain_yields_locked_product(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn redeem_on_chain_yields_locked_product_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = RedeemOnChainYieldsLockedProductParams::builder("1".to_string())
                .channel_id("1".to_string())
                .recv_window(5000)
                .build()
                .unwrap();

            let resp_json: Value =
                serde_json::from_str(r#"{"redeemId":40607,"success":true}"#).unwrap();
            let expected_response: models::RedeemOnChainYieldsLockedProductResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::RedeemOnChainYieldsLockedProductResponse");

            let resp = client
                .redeem_on_chain_yields_locked_product(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn redeem_on_chain_yields_locked_product_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params = RedeemOnChainYieldsLockedProductParams::builder("1".to_string())
                .build()
                .unwrap();

            match client.redeem_on_chain_yields_locked_product(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn set_on_chain_yields_locked_auto_subscribe_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = SetOnChainYieldsLockedAutoSubscribeParams::builder("1".to_string(), true)
                .build()
                .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"success":true}"#).unwrap();
            let expected_response: models::SetOnChainYieldsLockedAutoSubscribeResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::SetOnChainYieldsLockedAutoSubscribeResponse",
                );

            let resp = client
                .set_on_chain_yields_locked_auto_subscribe(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn set_on_chain_yields_locked_auto_subscribe_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = SetOnChainYieldsLockedAutoSubscribeParams::builder("1".to_string(), true)
                .recv_window(5000)
                .build()
                .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"success":true}"#).unwrap();
            let expected_response: models::SetOnChainYieldsLockedAutoSubscribeResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::SetOnChainYieldsLockedAutoSubscribeResponse",
                );

            let resp = client
                .set_on_chain_yields_locked_auto_subscribe(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn set_on_chain_yields_locked_auto_subscribe_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params = SetOnChainYieldsLockedAutoSubscribeParams::builder("1".to_string(), true)
                .build()
                .unwrap();

            match client
                .set_on_chain_yields_locked_auto_subscribe(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn set_on_chain_yields_locked_product_redeem_option_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = SetOnChainYieldsLockedProductRedeemOptionParams::builder(
                "1".to_string(),
                "redeem_to_example".to_string(),
            )
            .build()
            .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"success":true}"#).unwrap();
            let expected_response: models::SetOnChainYieldsLockedProductRedeemOptionResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::SetOnChainYieldsLockedProductRedeemOptionResponse",
                );

            let resp = client
                .set_on_chain_yields_locked_product_redeem_option(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn set_on_chain_yields_locked_product_redeem_option_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = SetOnChainYieldsLockedProductRedeemOptionParams::builder(
                "1".to_string(),
                "redeem_to_example".to_string(),
            )
            .recv_window(5000)
            .build()
            .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"success":true}"#).unwrap();
            let expected_response: models::SetOnChainYieldsLockedProductRedeemOptionResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::SetOnChainYieldsLockedProductRedeemOptionResponse",
                );

            let resp = client
                .set_on_chain_yields_locked_product_redeem_option(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn set_on_chain_yields_locked_product_redeem_option_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params = SetOnChainYieldsLockedProductRedeemOptionParams::builder(
                "1".to_string(),
                "redeem_to_example".to_string(),
            )
            .build()
            .unwrap();

            match client
                .set_on_chain_yields_locked_product_redeem_option(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn subscribe_on_chain_yields_locked_product_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = SubscribeOnChainYieldsLockedProductParams::builder("1".to_string(),dec!(1.0),).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"purchaseId":40607,"positionId":"12345","amount":"75.46000000","success":true}"#).unwrap();
            let expected_response : models::SubscribeOnChainYieldsLockedProductResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::SubscribeOnChainYieldsLockedProductResponse");

            let resp = client.subscribe_on_chain_yields_locked_product(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn subscribe_on_chain_yields_locked_product_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: false };

            let params = SubscribeOnChainYieldsLockedProductParams::builder("1".to_string(),dec!(1.0),).auto_subscribe(true).source_account("SPOT".to_string()).redeem_to(String::new()).channel_id("1".to_string()).client_id("1".to_string()).recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"purchaseId":40607,"positionId":"12345","amount":"75.46000000","success":true}"#).unwrap();
            let expected_response : models::SubscribeOnChainYieldsLockedProductResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::SubscribeOnChainYieldsLockedProductResponse");

            let resp = client.subscribe_on_chain_yields_locked_product(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn subscribe_on_chain_yields_locked_product_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockOnChainYieldsApiClient { force_error: true };

            let params =
                SubscribeOnChainYieldsLockedProductParams::builder("1".to_string(), dec!(1.0))
                    .build()
                    .unwrap();

            match client
                .subscribe_on_chain_yields_locked_product(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }
}
