#![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::mining::rest_api::models;
const HAS_TIME_UNIT: bool = false;
#[async_trait]
pub trait Api: Send + Sync {
async fn account_list(
&self,
params: AccountListParams,
) -> anyhow::Result<RestApiResponse<models::AccountListResponse>>;
async fn acquiring_algorithm(
&self,
) -> anyhow::Result<RestApiResponse<models::AcquiringAlgorithmResponse>>;
async fn acquiring_coinname(
&self,
) -> anyhow::Result<RestApiResponse<models::AcquiringCoinnameResponse>>;
async fn cancel_hashrate_resale_configuration(
&self,
params: CancelHashrateResaleConfigurationParams,
) -> anyhow::Result<RestApiResponse<models::CancelHashrateResaleConfigurationResponse>>;
async fn earnings_list(
&self,
params: EarningsListParams,
) -> anyhow::Result<RestApiResponse<models::EarningsListResponse>>;
async fn extra_bonus_list(
&self,
params: ExtraBonusListParams,
) -> anyhow::Result<RestApiResponse<models::ExtraBonusListResponse>>;
async fn hashrate_resale_detail(
&self,
params: HashrateResaleDetailParams,
) -> anyhow::Result<RestApiResponse<models::HashrateResaleDetailResponse>>;
async fn hashrate_resale_list(
&self,
params: HashrateResaleListParams,
) -> anyhow::Result<RestApiResponse<models::HashrateResaleListResponse>>;
async fn hashrate_resale_request(
&self,
params: HashrateResaleRequestParams,
) -> anyhow::Result<RestApiResponse<models::HashrateResaleRequestResponse>>;
async fn mining_account_earning(
&self,
params: MiningAccountEarningParams,
) -> anyhow::Result<RestApiResponse<models::MiningAccountEarningResponse>>;
async fn request_for_detail_miner_list(
&self,
params: RequestForDetailMinerListParams,
) -> anyhow::Result<RestApiResponse<models::RequestForDetailMinerListResponse>>;
async fn request_for_miner_list(
&self,
params: RequestForMinerListParams,
) -> anyhow::Result<RestApiResponse<models::RequestForMinerListResponse>>;
async fn statistic_list(
&self,
params: StatisticListParams,
) -> anyhow::Result<RestApiResponse<models::StatisticListResponse>>;
}
#[derive(Debug, Clone)]
pub struct ApiClient {
configuration: ConfigurationRestApi,
}
impl ApiClient {
pub fn new(configuration: ConfigurationRestApi) -> Self {
Self { configuration }
}
}
#[derive(Clone, Debug, Builder, Deserialize)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct AccountListParams {
#[builder(setter(into))]
#[serde(rename = "algo")]
pub algo: String,
#[builder(setter(into))]
#[serde(rename = "userName")]
pub user_name: String,
#[builder(setter(into), default)]
#[serde(rename = "recvWindow", default)]
pub recv_window: Option<i64>,
}
impl AccountListParams {
#[must_use]
pub fn builder(algo: String, user_name: String) -> AccountListParamsBuilder {
AccountListParamsBuilder::default()
.algo(algo)
.user_name(user_name)
}
}
#[derive(Clone, Debug, Builder, Deserialize)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct CancelHashrateResaleConfigurationParams {
#[builder(setter(into))]
#[serde(rename = "configId")]
pub config_id: i64,
#[builder(setter(into))]
#[serde(rename = "userName")]
pub user_name: String,
#[builder(setter(into), default)]
#[serde(rename = "recvWindow", default)]
pub recv_window: Option<i64>,
}
impl CancelHashrateResaleConfigurationParams {
#[must_use]
pub fn builder(
config_id: i64,
user_name: String,
) -> CancelHashrateResaleConfigurationParamsBuilder {
CancelHashrateResaleConfigurationParamsBuilder::default()
.config_id(config_id)
.user_name(user_name)
}
}
#[derive(Clone, Debug, Builder, Deserialize)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct EarningsListParams {
#[builder(setter(into))]
#[serde(rename = "algo")]
pub algo: String,
#[builder(setter(into))]
#[serde(rename = "userName")]
pub user_name: String,
#[builder(setter(into), default)]
#[serde(rename = "coin", default)]
pub coin: Option<String>,
#[builder(setter(into), default)]
#[serde(rename = "startDate", default)]
pub start_date: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "endDate", default)]
pub end_date: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "pageIndex", default)]
pub page_index: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "pageSize", default)]
pub page_size: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "recvWindow", default)]
pub recv_window: Option<i64>,
}
impl EarningsListParams {
#[must_use]
pub fn builder(algo: String, user_name: String) -> EarningsListParamsBuilder {
EarningsListParamsBuilder::default()
.algo(algo)
.user_name(user_name)
}
}
#[derive(Clone, Debug, Builder, Deserialize)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct ExtraBonusListParams {
#[builder(setter(into))]
#[serde(rename = "algo")]
pub algo: String,
#[builder(setter(into))]
#[serde(rename = "userName")]
pub user_name: String,
#[builder(setter(into), default)]
#[serde(rename = "coin", default)]
pub coin: Option<String>,
#[builder(setter(into), default)]
#[serde(rename = "startDate", default)]
pub start_date: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "endDate", default)]
pub end_date: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "pageIndex", default)]
pub page_index: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "pageSize", default)]
pub page_size: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "recvWindow", default)]
pub recv_window: Option<i64>,
}
impl ExtraBonusListParams {
#[must_use]
pub fn builder(algo: String, user_name: String) -> ExtraBonusListParamsBuilder {
ExtraBonusListParamsBuilder::default()
.algo(algo)
.user_name(user_name)
}
}
#[derive(Clone, Debug, Builder, Deserialize)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct HashrateResaleDetailParams {
#[builder(setter(into))]
#[serde(rename = "configId")]
pub config_id: i64,
#[builder(setter(into), default)]
#[serde(rename = "pageIndex", default)]
pub page_index: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "pageSize", default)]
pub page_size: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "recvWindow", default)]
pub recv_window: Option<i64>,
}
impl HashrateResaleDetailParams {
#[must_use]
pub fn builder(config_id: i64) -> HashrateResaleDetailParamsBuilder {
HashrateResaleDetailParamsBuilder::default().config_id(config_id)
}
}
#[derive(Clone, Debug, Builder, Deserialize, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct HashrateResaleListParams {
#[builder(setter(into), default)]
#[serde(rename = "pageIndex", default)]
pub page_index: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "pageSize", default)]
pub page_size: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "recvWindow", default)]
pub recv_window: Option<i64>,
}
impl HashrateResaleListParams {
#[must_use]
pub fn builder() -> HashrateResaleListParamsBuilder {
HashrateResaleListParamsBuilder::default()
}
}
#[derive(Clone, Debug, Builder, Deserialize)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct HashrateResaleRequestParams {
#[builder(setter(into))]
#[serde(rename = "userName")]
pub user_name: String,
#[builder(setter(into))]
#[serde(rename = "algo")]
pub algo: String,
#[builder(setter(into))]
#[serde(rename = "endDate")]
pub end_date: i64,
#[builder(setter(into))]
#[serde(rename = "startDate")]
pub start_date: i64,
#[builder(setter(into))]
#[serde(rename = "toPoolUser")]
pub to_pool_user: String,
#[builder(setter(into))]
#[serde(rename = "hashRate")]
pub hash_rate: i64,
#[builder(setter(into), default)]
#[serde(rename = "recvWindow", default)]
pub recv_window: Option<i64>,
}
impl HashrateResaleRequestParams {
#[must_use]
pub fn builder(
user_name: String,
algo: String,
end_date: i64,
start_date: i64,
to_pool_user: String,
hash_rate: i64,
) -> HashrateResaleRequestParamsBuilder {
HashrateResaleRequestParamsBuilder::default()
.user_name(user_name)
.algo(algo)
.end_date(end_date)
.start_date(start_date)
.to_pool_user(to_pool_user)
.hash_rate(hash_rate)
}
}
#[derive(Clone, Debug, Builder, Deserialize)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct MiningAccountEarningParams {
#[builder(setter(into))]
#[serde(rename = "algo")]
pub algo: String,
#[builder(setter(into), default)]
#[serde(rename = "startDate", default)]
pub start_date: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "endDate", default)]
pub end_date: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "pageIndex", default)]
pub page_index: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "pageSize", default)]
pub page_size: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "recvWindow", default)]
pub recv_window: Option<i64>,
}
impl MiningAccountEarningParams {
#[must_use]
pub fn builder(algo: String) -> MiningAccountEarningParamsBuilder {
MiningAccountEarningParamsBuilder::default().algo(algo)
}
}
#[derive(Clone, Debug, Builder, Deserialize)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct RequestForDetailMinerListParams {
#[builder(setter(into))]
#[serde(rename = "algo")]
pub algo: String,
#[builder(setter(into))]
#[serde(rename = "userName")]
pub user_name: String,
#[builder(setter(into))]
#[serde(rename = "workerName")]
pub worker_name: String,
#[builder(setter(into), default)]
#[serde(rename = "recvWindow", default)]
pub recv_window: Option<i64>,
}
impl RequestForDetailMinerListParams {
#[must_use]
pub fn builder(
algo: String,
user_name: String,
worker_name: String,
) -> RequestForDetailMinerListParamsBuilder {
RequestForDetailMinerListParamsBuilder::default()
.algo(algo)
.user_name(user_name)
.worker_name(worker_name)
}
}
#[derive(Clone, Debug, Builder, Deserialize)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct RequestForMinerListParams {
#[builder(setter(into))]
#[serde(rename = "algo")]
pub algo: String,
#[builder(setter(into))]
#[serde(rename = "userName")]
pub user_name: String,
#[builder(setter(into), default)]
#[serde(rename = "pageIndex", default)]
pub page_index: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "sort", default)]
pub sort: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "sortColumn", default)]
pub sort_column: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "workerStatus", default)]
pub worker_status: Option<i64>,
#[builder(setter(into), default)]
#[serde(rename = "recvWindow", default)]
pub recv_window: Option<i64>,
}
impl RequestForMinerListParams {
#[must_use]
pub fn builder(algo: String, user_name: String) -> RequestForMinerListParamsBuilder {
RequestForMinerListParamsBuilder::default()
.algo(algo)
.user_name(user_name)
}
}
#[derive(Clone, Debug, Builder, Deserialize)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct StatisticListParams {
#[builder(setter(into))]
#[serde(rename = "algo")]
pub algo: String,
#[builder(setter(into))]
#[serde(rename = "userName")]
pub user_name: String,
#[builder(setter(into), default)]
#[serde(rename = "recvWindow", default)]
pub recv_window: Option<i64>,
}
impl StatisticListParams {
#[must_use]
pub fn builder(algo: String, user_name: String) -> StatisticListParamsBuilder {
StatisticListParamsBuilder::default()
.algo(algo)
.user_name(user_name)
}
}
#[async_trait]
impl Api for ApiClient {
async fn account_list(
&self,
params: AccountListParams,
) -> anyhow::Result<RestApiResponse<models::AccountListResponse>> {
let AccountListParams {
algo,
user_name,
recv_window,
} = params;
let mut query_params = BTreeMap::new();
let body_params = BTreeMap::new();
query_params.insert("algo".to_string(), json!(algo));
query_params.insert("userName".to_string(), json!(user_name));
if let Some(rw) = recv_window {
query_params.insert("recvWindow".to_string(), json!(rw));
}
send_request::<models::AccountListResponse>(
&self.configuration,
"/sapi/v1/mining/statistics/user/list",
reqwest::Method::GET,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
true,
)
.await
}
async fn acquiring_algorithm(
&self,
) -> anyhow::Result<RestApiResponse<models::AcquiringAlgorithmResponse>> {
let query_params = BTreeMap::new();
let body_params = BTreeMap::new();
send_request::<models::AcquiringAlgorithmResponse>(
&self.configuration,
"/sapi/v1/mining/pub/algoList",
reqwest::Method::GET,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
false,
)
.await
}
async fn acquiring_coinname(
&self,
) -> anyhow::Result<RestApiResponse<models::AcquiringCoinnameResponse>> {
let query_params = BTreeMap::new();
let body_params = BTreeMap::new();
send_request::<models::AcquiringCoinnameResponse>(
&self.configuration,
"/sapi/v1/mining/pub/coinList",
reqwest::Method::GET,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
false,
)
.await
}
async fn cancel_hashrate_resale_configuration(
&self,
params: CancelHashrateResaleConfigurationParams,
) -> anyhow::Result<RestApiResponse<models::CancelHashrateResaleConfigurationResponse>> {
let CancelHashrateResaleConfigurationParams {
config_id,
user_name,
recv_window,
} = params;
let mut query_params = BTreeMap::new();
let body_params = BTreeMap::new();
query_params.insert("configId".to_string(), json!(config_id));
query_params.insert("userName".to_string(), json!(user_name));
if let Some(rw) = recv_window {
query_params.insert("recvWindow".to_string(), json!(rw));
}
send_request::<models::CancelHashrateResaleConfigurationResponse>(
&self.configuration,
"/sapi/v1/mining/hash-transfer/config/cancel",
reqwest::Method::POST,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
true,
)
.await
}
async fn earnings_list(
&self,
params: EarningsListParams,
) -> anyhow::Result<RestApiResponse<models::EarningsListResponse>> {
let EarningsListParams {
algo,
user_name,
coin,
start_date,
end_date,
page_index,
page_size,
recv_window,
} = params;
let mut query_params = BTreeMap::new();
let body_params = BTreeMap::new();
query_params.insert("algo".to_string(), json!(algo));
query_params.insert("userName".to_string(), json!(user_name));
if let Some(rw) = coin {
query_params.insert("coin".to_string(), json!(rw));
}
if let Some(rw) = start_date {
query_params.insert("startDate".to_string(), json!(rw));
}
if let Some(rw) = end_date {
query_params.insert("endDate".to_string(), json!(rw));
}
if let Some(rw) = page_index {
query_params.insert("pageIndex".to_string(), json!(rw));
}
if let Some(rw) = page_size {
query_params.insert("pageSize".to_string(), json!(rw));
}
if let Some(rw) = recv_window {
query_params.insert("recvWindow".to_string(), json!(rw));
}
send_request::<models::EarningsListResponse>(
&self.configuration,
"/sapi/v1/mining/payment/list",
reqwest::Method::GET,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
true,
)
.await
}
async fn extra_bonus_list(
&self,
params: ExtraBonusListParams,
) -> anyhow::Result<RestApiResponse<models::ExtraBonusListResponse>> {
let ExtraBonusListParams {
algo,
user_name,
coin,
start_date,
end_date,
page_index,
page_size,
recv_window,
} = params;
let mut query_params = BTreeMap::new();
let body_params = BTreeMap::new();
query_params.insert("algo".to_string(), json!(algo));
query_params.insert("userName".to_string(), json!(user_name));
if let Some(rw) = coin {
query_params.insert("coin".to_string(), json!(rw));
}
if let Some(rw) = start_date {
query_params.insert("startDate".to_string(), json!(rw));
}
if let Some(rw) = end_date {
query_params.insert("endDate".to_string(), json!(rw));
}
if let Some(rw) = page_index {
query_params.insert("pageIndex".to_string(), json!(rw));
}
if let Some(rw) = page_size {
query_params.insert("pageSize".to_string(), json!(rw));
}
if let Some(rw) = recv_window {
query_params.insert("recvWindow".to_string(), json!(rw));
}
send_request::<models::ExtraBonusListResponse>(
&self.configuration,
"/sapi/v1/mining/payment/other",
reqwest::Method::GET,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
true,
)
.await
}
async fn hashrate_resale_detail(
&self,
params: HashrateResaleDetailParams,
) -> anyhow::Result<RestApiResponse<models::HashrateResaleDetailResponse>> {
let HashrateResaleDetailParams {
config_id,
page_index,
page_size,
recv_window,
} = params;
let mut query_params = BTreeMap::new();
let body_params = BTreeMap::new();
query_params.insert("configId".to_string(), json!(config_id));
if let Some(rw) = page_index {
query_params.insert("pageIndex".to_string(), json!(rw));
}
if let Some(rw) = page_size {
query_params.insert("pageSize".to_string(), json!(rw));
}
if let Some(rw) = recv_window {
query_params.insert("recvWindow".to_string(), json!(rw));
}
send_request::<models::HashrateResaleDetailResponse>(
&self.configuration,
"/sapi/v1/mining/hash-transfer/profit/details",
reqwest::Method::GET,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
true,
)
.await
}
async fn hashrate_resale_list(
&self,
params: HashrateResaleListParams,
) -> anyhow::Result<RestApiResponse<models::HashrateResaleListResponse>> {
let HashrateResaleListParams {
page_index,
page_size,
recv_window,
} = params;
let mut query_params = BTreeMap::new();
let body_params = BTreeMap::new();
if let Some(rw) = page_index {
query_params.insert("pageIndex".to_string(), json!(rw));
}
if let Some(rw) = page_size {
query_params.insert("pageSize".to_string(), json!(rw));
}
if let Some(rw) = recv_window {
query_params.insert("recvWindow".to_string(), json!(rw));
}
send_request::<models::HashrateResaleListResponse>(
&self.configuration,
"/sapi/v1/mining/hash-transfer/config/details/list",
reqwest::Method::GET,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
true,
)
.await
}
async fn hashrate_resale_request(
&self,
params: HashrateResaleRequestParams,
) -> anyhow::Result<RestApiResponse<models::HashrateResaleRequestResponse>> {
let HashrateResaleRequestParams {
user_name,
algo,
end_date,
start_date,
to_pool_user,
hash_rate,
recv_window,
} = params;
let mut query_params = BTreeMap::new();
let body_params = BTreeMap::new();
query_params.insert("userName".to_string(), json!(user_name));
query_params.insert("algo".to_string(), json!(algo));
query_params.insert("endDate".to_string(), json!(end_date));
query_params.insert("startDate".to_string(), json!(start_date));
query_params.insert("toPoolUser".to_string(), json!(to_pool_user));
query_params.insert("hashRate".to_string(), json!(hash_rate));
if let Some(rw) = recv_window {
query_params.insert("recvWindow".to_string(), json!(rw));
}
send_request::<models::HashrateResaleRequestResponse>(
&self.configuration,
"/sapi/v1/mining/hash-transfer/config",
reqwest::Method::POST,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
true,
)
.await
}
async fn mining_account_earning(
&self,
params: MiningAccountEarningParams,
) -> anyhow::Result<RestApiResponse<models::MiningAccountEarningResponse>> {
let MiningAccountEarningParams {
algo,
start_date,
end_date,
page_index,
page_size,
recv_window,
} = params;
let mut query_params = BTreeMap::new();
let body_params = BTreeMap::new();
query_params.insert("algo".to_string(), json!(algo));
if let Some(rw) = start_date {
query_params.insert("startDate".to_string(), json!(rw));
}
if let Some(rw) = end_date {
query_params.insert("endDate".to_string(), json!(rw));
}
if let Some(rw) = page_index {
query_params.insert("pageIndex".to_string(), json!(rw));
}
if let Some(rw) = page_size {
query_params.insert("pageSize".to_string(), json!(rw));
}
if let Some(rw) = recv_window {
query_params.insert("recvWindow".to_string(), json!(rw));
}
send_request::<models::MiningAccountEarningResponse>(
&self.configuration,
"/sapi/v1/mining/payment/uid",
reqwest::Method::GET,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
true,
)
.await
}
async fn request_for_detail_miner_list(
&self,
params: RequestForDetailMinerListParams,
) -> anyhow::Result<RestApiResponse<models::RequestForDetailMinerListResponse>> {
let RequestForDetailMinerListParams {
algo,
user_name,
worker_name,
recv_window,
} = params;
let mut query_params = BTreeMap::new();
let body_params = BTreeMap::new();
query_params.insert("algo".to_string(), json!(algo));
query_params.insert("userName".to_string(), json!(user_name));
query_params.insert("workerName".to_string(), json!(worker_name));
if let Some(rw) = recv_window {
query_params.insert("recvWindow".to_string(), json!(rw));
}
send_request::<models::RequestForDetailMinerListResponse>(
&self.configuration,
"/sapi/v1/mining/worker/detail",
reqwest::Method::GET,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
true,
)
.await
}
async fn request_for_miner_list(
&self,
params: RequestForMinerListParams,
) -> anyhow::Result<RestApiResponse<models::RequestForMinerListResponse>> {
let RequestForMinerListParams {
algo,
user_name,
page_index,
sort,
sort_column,
worker_status,
recv_window,
} = params;
let mut query_params = BTreeMap::new();
let body_params = BTreeMap::new();
query_params.insert("algo".to_string(), json!(algo));
query_params.insert("userName".to_string(), json!(user_name));
if let Some(rw) = page_index {
query_params.insert("pageIndex".to_string(), json!(rw));
}
if let Some(rw) = sort {
query_params.insert("sort".to_string(), json!(rw));
}
if let Some(rw) = sort_column {
query_params.insert("sortColumn".to_string(), json!(rw));
}
if let Some(rw) = worker_status {
query_params.insert("workerStatus".to_string(), json!(rw));
}
if let Some(rw) = recv_window {
query_params.insert("recvWindow".to_string(), json!(rw));
}
send_request::<models::RequestForMinerListResponse>(
&self.configuration,
"/sapi/v1/mining/worker/list",
reqwest::Method::GET,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
true,
)
.await
}
async fn statistic_list(
&self,
params: StatisticListParams,
) -> anyhow::Result<RestApiResponse<models::StatisticListResponse>> {
let StatisticListParams {
algo,
user_name,
recv_window,
} = params;
let mut query_params = BTreeMap::new();
let body_params = BTreeMap::new();
query_params.insert("algo".to_string(), json!(algo));
query_params.insert("userName".to_string(), json!(user_name));
if let Some(rw) = recv_window {
query_params.insert("recvWindow".to_string(), json!(rw));
}
send_request::<models::StatisticListResponse>(
&self.configuration,
"/sapi/v1/mining/statistics/user/status",
reqwest::Method::GET,
query_params,
body_params,
if HAS_TIME_UNIT {
self.configuration.time_unit
} else {
None
},
true,
)
.await
}
}
#[cfg(all(test, feature = "mining"))]
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 MockApiClient {
force_error: bool,
}
#[async_trait]
impl Api for MockApiClient {
async fn account_list(
&self,
_params: AccountListParams,
) -> anyhow::Result<RestApiResponse<models::AccountListResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"type":"H_hashrate","userName":"test","list":[{"time":1585267200000,"hashrate":"0.00000000","reject":"0.00000000"}]}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::AccountListResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::AccountListResponse");
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 acquiring_algorithm(
&self,
) -> anyhow::Result<RestApiResponse<models::AcquiringAlgorithmResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"algoName":"SHA256-BTC","algoId":1,"poolIndex":100,"unit":"h/s"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::AcquiringAlgorithmResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::AcquiringAlgorithmResponse");
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 acquiring_coinname(
&self,
) -> anyhow::Result<RestApiResponse<models::AcquiringCoinnameResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"coinName":"BTC","coinId":1,"poolIndex":0,"algoId":1,"algoName":"SHA256-BTC"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::AcquiringCoinnameResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::AcquiringCoinnameResponse");
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 cancel_hashrate_resale_configuration(
&self,
_params: CancelHashrateResaleConfigurationParams,
) -> anyhow::Result<RestApiResponse<models::CancelHashrateResaleConfigurationResponse>>
{
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":true}"#)
.unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::CancelHashrateResaleConfigurationResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::CancelHashrateResaleConfigurationResponse");
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 earnings_list(
&self,
_params: EarningsListParams,
) -> anyhow::Result<RestApiResponse<models::EarningsListResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"accountProfits":[{"time":1586188800000,"type":31,"hashTransfer":200000000000,"transferAmount":0.02180958,"dayHashRate":129129903378244,"profitAmount":8.6083060304,"coinName":"BTC","status":2}],"totalNum":3,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::EarningsListResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::EarningsListResponse");
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 extra_bonus_list(
&self,
_params: ExtraBonusListParams,
) -> anyhow::Result<RestApiResponse<models::ExtraBonusListResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"otherProfits":[{"time":1607443200000,"coinName":"BTC","type":4,"profitAmount":0.0011859,"status":2}],"totalNum":3,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::ExtraBonusListResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::ExtraBonusListResponse");
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 hashrate_resale_detail(
&self,
_params: HashrateResaleDetailParams,
) -> anyhow::Result<RestApiResponse<models::HashrateResaleDetailResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"profitTransferDetails":[{"poolUsername":"test4001","toPoolUsername":"pop","algoName":"sha256","hashRate":200000000000,"day":20201213,"amount":0.2256872,"coinName":"BTC"}],"totalNum":8,"pageSize":200}}"#).unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::HashrateResaleDetailResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::HashrateResaleDetailResponse");
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 hashrate_resale_list(
&self,
_params: HashrateResaleListParams,
) -> anyhow::Result<RestApiResponse<models::HashrateResaleListResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"configDetails":[{"configId":168,"poolUsername":"123","toPoolUsername":"user1","algoName":"Ethash","hashRate":5000000,"startDay":20201210,"endDay":20210405,"status":1,"type":0}],"totalNum":21,"pageSize":200}}"#).unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::HashrateResaleListResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::HashrateResaleListResponse");
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 hashrate_resale_request(
&self,
_params: HashrateResaleRequestParams,
) -> anyhow::Result<RestApiResponse<models::HashrateResaleRequestResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":171}"#)
.unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::HashrateResaleRequestResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::HashrateResaleRequestResponse");
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 mining_account_earning(
&self,
_params: MiningAccountEarningParams,
) -> anyhow::Result<RestApiResponse<models::MiningAccountEarningResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"accountProfits":[{"time":1607443200000,"coinName":"BTC","type":2,"puid":59985472,"subName":"vdvaghani","amount":0.09186957}],"totalNum":3,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::MiningAccountEarningResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::MiningAccountEarningResponse");
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 request_for_detail_miner_list(
&self,
_params: RequestForDetailMinerListParams,
) -> anyhow::Result<RestApiResponse<models::RequestForDetailMinerListResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"workerName":"bhdc1.16A10404B","type":"H_hashrate","hashrateDatas":[{"time":1587902400000,"hashrate":"0","reject":0}]}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::RequestForDetailMinerListResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::RequestForDetailMinerListResponse");
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 request_for_miner_list(
&self,
_params: RequestForMinerListParams,
) -> anyhow::Result<RestApiResponse<models::RequestForMinerListResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"workerDatas":[{"workerId":"1420554439452400131","workerName":"2X73","status":3,"hashRate":0,"dayHashRate":1.269778129801366E13,"rejectRate":0,"lastShareTime":1587712919000}],"totalNum":18530,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::RequestForMinerListResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::RequestForMinerListResponse");
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 statistic_list(
&self,
_params: StatisticListParams,
) -> anyhow::Result<RestApiResponse<models::StatisticListResponse>> {
if self.force_error {
return Err(ConnectorError::ConnectorClientError {
msg: "ResponseError".to_string(),
code: None,
}
.into());
}
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"fifteenMinHashRate":"457835490067496409.00000000","dayHashRate":"214289268068874127.65000000","validNum":0,"invalidNum":17562,"profitToday":{"BTC":"0.00314332","BSV":"56.17055953","BCH":"106.61586001"},"profitYesterday":{"BTC":"0.00314332","BSV":"56.17055953","BCH":"106.61586001"},"userName":"test","unit":"h/s","algo":"sha256"}}"#).unwrap_or_else(|_| serde_json::json!({}));
let dummy_response: models::StatisticListResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::StatisticListResponse");
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 account_list_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = AccountListParams::builder("sha256".to_string(),"test".to_string(),).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"type":"H_hashrate","userName":"test","list":[{"time":1585267200000,"hashrate":"0.00000000","reject":"0.00000000"}]}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::AccountListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AccountListResponse");
let resp = client.account_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 account_list_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = AccountListParams::builder("sha256".to_string(),"test".to_string(),).recv_window(5000).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"type":"H_hashrate","userName":"test","list":[{"time":1585267200000,"hashrate":"0.00000000","reject":"0.00000000"}]}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::AccountListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AccountListResponse");
let resp = client.account_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 account_list_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
let params = AccountListParams::builder("sha256".to_string(), "test".to_string())
.build()
.unwrap();
match client.account_list(params).await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn acquiring_algorithm_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"algoName":"SHA256-BTC","algoId":1,"poolIndex":100,"unit":"h/s"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::AcquiringAlgorithmResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AcquiringAlgorithmResponse");
let resp = client.acquiring_algorithm().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 acquiring_algorithm_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"algoName":"SHA256-BTC","algoId":1,"poolIndex":100,"unit":"h/s"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::AcquiringAlgorithmResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AcquiringAlgorithmResponse");
let resp = client.acquiring_algorithm().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 acquiring_algorithm_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
match client.acquiring_algorithm().await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn acquiring_coinname_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"coinName":"BTC","coinId":1,"poolIndex":0,"algoId":1,"algoName":"SHA256-BTC"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::AcquiringCoinnameResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AcquiringCoinnameResponse");
let resp = client.acquiring_coinname().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 acquiring_coinname_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"coinName":"BTC","coinId":1,"poolIndex":0,"algoId":1,"algoName":"SHA256-BTC"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::AcquiringCoinnameResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AcquiringCoinnameResponse");
let resp = client.acquiring_coinname().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 acquiring_coinname_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
match client.acquiring_coinname().await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn cancel_hashrate_resale_configuration_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = CancelHashrateResaleConfigurationParams::builder(168, "test".to_string())
.build()
.unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":true}"#)
.unwrap_or_else(|_| serde_json::json!({}));
let expected_response: models::CancelHashrateResaleConfigurationResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::CancelHashrateResaleConfigurationResponse");
let resp = client
.cancel_hashrate_resale_configuration(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 cancel_hashrate_resale_configuration_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = CancelHashrateResaleConfigurationParams::builder(168, "test".to_string())
.recv_window(5000)
.build()
.unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":true}"#)
.unwrap_or_else(|_| serde_json::json!({}));
let expected_response: models::CancelHashrateResaleConfigurationResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::CancelHashrateResaleConfigurationResponse");
let resp = client
.cancel_hashrate_resale_configuration(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 cancel_hashrate_resale_configuration_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
let params = CancelHashrateResaleConfigurationParams::builder(168, "test".to_string())
.build()
.unwrap();
match client.cancel_hashrate_resale_configuration(params).await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn earnings_list_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = EarningsListParams::builder("sha256".to_string(),"test".to_string(),).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"accountProfits":[{"time":1586188800000,"type":31,"hashTransfer":200000000000,"transferAmount":0.02180958,"dayHashRate":129129903378244,"profitAmount":8.6083060304,"coinName":"BTC","status":2}],"totalNum":3,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::EarningsListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::EarningsListResponse");
let resp = client.earnings_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 earnings_list_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = EarningsListParams::builder("sha256".to_string(),"test".to_string(),).coin("BTC".to_string()).start_date(1770736694138).end_date(1770736694138).page_index(1).page_size(10).recv_window(5000).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"accountProfits":[{"time":1586188800000,"type":31,"hashTransfer":200000000000,"transferAmount":0.02180958,"dayHashRate":129129903378244,"profitAmount":8.6083060304,"coinName":"BTC","status":2}],"totalNum":3,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::EarningsListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::EarningsListResponse");
let resp = client.earnings_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 earnings_list_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
let params = EarningsListParams::builder("sha256".to_string(), "test".to_string())
.build()
.unwrap();
match client.earnings_list(params).await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn extra_bonus_list_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = ExtraBonusListParams::builder("sha256".to_string(),"test".to_string(),).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"otherProfits":[{"time":1607443200000,"coinName":"BTC","type":4,"profitAmount":0.0011859,"status":2}],"totalNum":3,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::ExtraBonusListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::ExtraBonusListResponse");
let resp = client.extra_bonus_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 extra_bonus_list_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = ExtraBonusListParams::builder("sha256".to_string(),"test".to_string(),).coin("BTC".to_string()).start_date(1770736694138).end_date(1770736694138).page_index(1).page_size(10).recv_window(5000).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"otherProfits":[{"time":1607443200000,"coinName":"BTC","type":4,"profitAmount":0.0011859,"status":2}],"totalNum":3,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::ExtraBonusListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::ExtraBonusListResponse");
let resp = client.extra_bonus_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 extra_bonus_list_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
let params = ExtraBonusListParams::builder("sha256".to_string(), "test".to_string())
.build()
.unwrap();
match client.extra_bonus_list(params).await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn hashrate_resale_detail_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = HashrateResaleDetailParams::builder(168,).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"profitTransferDetails":[{"poolUsername":"test4001","toPoolUsername":"pop","algoName":"sha256","hashRate":200000000000,"day":20201213,"amount":0.2256872,"coinName":"BTC"}],"totalNum":8,"pageSize":200}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::HashrateResaleDetailResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::HashrateResaleDetailResponse");
let resp = client.hashrate_resale_detail(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 hashrate_resale_detail_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = HashrateResaleDetailParams::builder(168,).page_index(1).page_size(10).recv_window(5000).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"profitTransferDetails":[{"poolUsername":"test4001","toPoolUsername":"pop","algoName":"sha256","hashRate":200000000000,"day":20201213,"amount":0.2256872,"coinName":"BTC"}],"totalNum":8,"pageSize":200}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::HashrateResaleDetailResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::HashrateResaleDetailResponse");
let resp = client.hashrate_resale_detail(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 hashrate_resale_detail_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
let params = HashrateResaleDetailParams::builder(168).build().unwrap();
match client.hashrate_resale_detail(params).await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn hashrate_resale_list_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = HashrateResaleListParams::builder().build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"configDetails":[{"configId":168,"poolUsername":"123","toPoolUsername":"user1","algoName":"Ethash","hashRate":5000000,"startDay":20201210,"endDay":20210405,"status":1,"type":0}],"totalNum":21,"pageSize":200}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::HashrateResaleListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::HashrateResaleListResponse");
let resp = client.hashrate_resale_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 hashrate_resale_list_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = HashrateResaleListParams::builder().page_index(1).page_size(10).recv_window(5000).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"configDetails":[{"configId":168,"poolUsername":"123","toPoolUsername":"user1","algoName":"Ethash","hashRate":5000000,"startDay":20201210,"endDay":20210405,"status":1,"type":0}],"totalNum":21,"pageSize":200}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::HashrateResaleListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::HashrateResaleListResponse");
let resp = client.hashrate_resale_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 hashrate_resale_list_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
let params = HashrateResaleListParams::builder().build().unwrap();
match client.hashrate_resale_list(params).await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn hashrate_resale_request_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = HashrateResaleRequestParams::builder(
"test".to_string(),
"sha256".to_string(),
1770736694138,
1770736694138,
"S19pro".to_string(),
100000000,
)
.build()
.unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":171}"#)
.unwrap_or_else(|_| serde_json::json!({}));
let expected_response: models::HashrateResaleRequestResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::HashrateResaleRequestResponse");
let resp = client
.hashrate_resale_request(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 hashrate_resale_request_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = HashrateResaleRequestParams::builder(
"test".to_string(),
"sha256".to_string(),
1770736694138,
1770736694138,
"S19pro".to_string(),
100000000,
)
.recv_window(5000)
.build()
.unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":171}"#)
.unwrap_or_else(|_| serde_json::json!({}));
let expected_response: models::HashrateResaleRequestResponse =
serde_json::from_value(resp_json.clone())
.expect("should parse into models::HashrateResaleRequestResponse");
let resp = client
.hashrate_resale_request(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 hashrate_resale_request_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
let params = HashrateResaleRequestParams::builder(
"test".to_string(),
"sha256".to_string(),
1770736694138,
1770736694138,
"S19pro".to_string(),
100000000,
)
.build()
.unwrap();
match client.hashrate_resale_request(params).await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn mining_account_earning_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = MiningAccountEarningParams::builder("sha256".to_string(),).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"accountProfits":[{"time":1607443200000,"coinName":"BTC","type":2,"puid":59985472,"subName":"vdvaghani","amount":0.09186957}],"totalNum":3,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::MiningAccountEarningResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::MiningAccountEarningResponse");
let resp = client.mining_account_earning(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 mining_account_earning_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = MiningAccountEarningParams::builder("sha256".to_string(),).start_date(1770736694138).end_date(1770736694138).page_index(1).page_size(10).recv_window(5000).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"accountProfits":[{"time":1607443200000,"coinName":"BTC","type":2,"puid":59985472,"subName":"vdvaghani","amount":0.09186957}],"totalNum":3,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::MiningAccountEarningResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::MiningAccountEarningResponse");
let resp = client.mining_account_earning(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 mining_account_earning_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
let params = MiningAccountEarningParams::builder("sha256".to_string())
.build()
.unwrap();
match client.mining_account_earning(params).await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn request_for_detail_miner_list_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = RequestForDetailMinerListParams::builder("sha256".to_string(),"test".to_string(),"bhdc1.16A10404B".to_string(),).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"workerName":"bhdc1.16A10404B","type":"H_hashrate","hashrateDatas":[{"time":1587902400000,"hashrate":"0","reject":0}]}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::RequestForDetailMinerListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RequestForDetailMinerListResponse");
let resp = client.request_for_detail_miner_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 request_for_detail_miner_list_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = RequestForDetailMinerListParams::builder("sha256".to_string(),"test".to_string(),"bhdc1.16A10404B".to_string(),).recv_window(5000).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"workerName":"bhdc1.16A10404B","type":"H_hashrate","hashrateDatas":[{"time":1587902400000,"hashrate":"0","reject":0}]}]}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::RequestForDetailMinerListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RequestForDetailMinerListResponse");
let resp = client.request_for_detail_miner_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 request_for_detail_miner_list_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
let params = RequestForDetailMinerListParams::builder(
"sha256".to_string(),
"test".to_string(),
"bhdc1.16A10404B".to_string(),
)
.build()
.unwrap();
match client.request_for_detail_miner_list(params).await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn request_for_miner_list_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = RequestForMinerListParams::builder("sha256".to_string(),"test".to_string(),).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"workerDatas":[{"workerId":"1420554439452400131","workerName":"2X73","status":3,"hashRate":0,"dayHashRate":1.269778129801366E13,"rejectRate":0,"lastShareTime":1587712919000}],"totalNum":18530,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::RequestForMinerListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RequestForMinerListResponse");
let resp = client.request_for_miner_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 request_for_miner_list_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = RequestForMinerListParams::builder("sha256".to_string(),"test".to_string(),).page_index(1).sort(0).sort_column(1).worker_status(0).recv_window(5000).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"workerDatas":[{"workerId":"1420554439452400131","workerName":"2X73","status":3,"hashRate":0,"dayHashRate":1.269778129801366E13,"rejectRate":0,"lastShareTime":1587712919000}],"totalNum":18530,"pageSize":20}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::RequestForMinerListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RequestForMinerListResponse");
let resp = client.request_for_miner_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 request_for_miner_list_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
let params =
RequestForMinerListParams::builder("sha256".to_string(), "test".to_string())
.build()
.unwrap();
match client.request_for_miner_list(params).await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
#[test]
fn statistic_list_required_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = StatisticListParams::builder("sha256".to_string(),"test".to_string(),).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"fifteenMinHashRate":"457835490067496409.00000000","dayHashRate":"214289268068874127.65000000","validNum":0,"invalidNum":17562,"profitToday":{"BTC":"0.00314332","BSV":"56.17055953","BCH":"106.61586001"},"profitYesterday":{"BTC":"0.00314332","BSV":"56.17055953","BCH":"106.61586001"},"userName":"test","unit":"h/s","algo":"sha256"}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::StatisticListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::StatisticListResponse");
let resp = client.statistic_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 statistic_list_optional_params_success() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: false };
let params = StatisticListParams::builder("sha256".to_string(),"test".to_string(),).recv_window(5000).build().unwrap();
let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"fifteenMinHashRate":"457835490067496409.00000000","dayHashRate":"214289268068874127.65000000","validNum":0,"invalidNum":17562,"profitToday":{"BTC":"0.00314332","BSV":"56.17055953","BCH":"106.61586001"},"profitYesterday":{"BTC":"0.00314332","BSV":"56.17055953","BCH":"106.61586001"},"userName":"test","unit":"h/s","algo":"sha256"}}"#).unwrap_or_else(|_| serde_json::json!({}));
let expected_response : models::StatisticListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::StatisticListResponse");
let resp = client.statistic_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 statistic_list_response_error() {
TOKIO_SHARED_RT.block_on(async {
let client = MockApiClient { force_error: true };
let params = StatisticListParams::builder("sha256".to_string(), "test".to_string())
.build()
.unwrap();
match client.statistic_list(params).await {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.to_string(), "Connector client error: ResponseError");
}
}
});
}
}