Skip to main content

binance_sdk/mining/rest_api/apis/
mining_api.rs

1/*
2 * Binance Mining REST API
3 *
4 * OpenAPI Specification for the Binance Mining REST API
5 *
6 * The version of the OpenAPI document: 1.0.0
7 *
8 *
9 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
10 * https://openapi-generator.tech
11 * Do not edit the class manually.
12 */
13
14#![allow(unused_imports)]
15use async_trait::async_trait;
16use derive_builder::Builder;
17use reqwest;
18use rust_decimal::prelude::*;
19use serde::{Deserialize, Serialize};
20use serde_json::{Value, json};
21use std::collections::BTreeMap;
22
23use crate::common::{
24    config::ConfigurationRestApi,
25    models::{ParamBuildError, RestApiResponse},
26    utils::send_request,
27};
28use crate::mining::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait MiningApi: Send + Sync {
34    async fn account_list(
35        &self,
36        params: AccountListParams,
37    ) -> anyhow::Result<RestApiResponse<models::AccountListResponse>>;
38    async fn acquiring_algorithm(
39        &self,
40    ) -> anyhow::Result<RestApiResponse<models::AcquiringAlgorithmResponse>>;
41    async fn acquiring_coinname(
42        &self,
43    ) -> anyhow::Result<RestApiResponse<models::AcquiringCoinnameResponse>>;
44    async fn cancel_hashrate_resale_configuration(
45        &self,
46        params: CancelHashrateResaleConfigurationParams,
47    ) -> anyhow::Result<RestApiResponse<models::CancelHashrateResaleConfigurationResponse>>;
48    async fn earnings_list(
49        &self,
50        params: EarningsListParams,
51    ) -> anyhow::Result<RestApiResponse<models::EarningsListResponse>>;
52    async fn extra_bonus_list(
53        &self,
54        params: ExtraBonusListParams,
55    ) -> anyhow::Result<RestApiResponse<models::ExtraBonusListResponse>>;
56    async fn hashrate_resale_detail(
57        &self,
58        params: HashrateResaleDetailParams,
59    ) -> anyhow::Result<RestApiResponse<models::HashrateResaleDetailResponse>>;
60    async fn hashrate_resale_list(
61        &self,
62        params: HashrateResaleListParams,
63    ) -> anyhow::Result<RestApiResponse<models::HashrateResaleListResponse>>;
64    async fn hashrate_resale_request(
65        &self,
66        params: HashrateResaleRequestParams,
67    ) -> anyhow::Result<RestApiResponse<models::HashrateResaleRequestResponse>>;
68    async fn mining_account_earning(
69        &self,
70        params: MiningAccountEarningParams,
71    ) -> anyhow::Result<RestApiResponse<models::MiningAccountEarningResponse>>;
72    async fn request_for_detail_miner_list(
73        &self,
74        params: RequestForDetailMinerListParams,
75    ) -> anyhow::Result<RestApiResponse<models::RequestForDetailMinerListResponse>>;
76    async fn request_for_miner_list(
77        &self,
78        params: RequestForMinerListParams,
79    ) -> anyhow::Result<RestApiResponse<models::RequestForMinerListResponse>>;
80    async fn statistic_list(
81        &self,
82        params: StatisticListParams,
83    ) -> anyhow::Result<RestApiResponse<models::StatisticListResponse>>;
84}
85
86#[derive(Debug, Clone)]
87pub struct MiningApiClient {
88    configuration: ConfigurationRestApi,
89}
90
91impl MiningApiClient {
92    pub fn new(configuration: ConfigurationRestApi) -> Self {
93        Self { configuration }
94    }
95}
96
97/// Request parameters for the [`account_list`] operation.
98///
99/// This struct holds all of the inputs you can pass when calling
100/// [`account_list`](#method.account_list).
101#[derive(Clone, Debug, Builder)]
102#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
103pub struct AccountListParams {
104    /// Algorithm(sha256) sha256
105    ///
106    /// This field is **required.
107    #[builder(setter(into))]
108    pub algo: String,
109    /// Mining account test
110    ///
111    /// This field is **required.
112    #[builder(setter(into))]
113    pub user_name: String,
114    ///
115    /// The `recv_window` parameter.
116    ///
117    /// This field is **optional.
118    #[builder(setter(into), default)]
119    pub recv_window: Option<i64>,
120}
121
122impl AccountListParams {
123    /// Create a builder for [`account_list`].
124    ///
125    /// Required parameters:
126    ///
127    /// * `algo` — Algorithm(sha256) sha256
128    /// * `user_name` — Mining account test
129    ///
130    #[must_use]
131    pub fn builder(algo: String, user_name: String) -> AccountListParamsBuilder {
132        AccountListParamsBuilder::default()
133            .algo(algo)
134            .user_name(user_name)
135    }
136}
137/// Request parameters for the [`cancel_hashrate_resale_configuration`] operation.
138///
139/// This struct holds all of the inputs you can pass when calling
140/// [`cancel_hashrate_resale_configuration`](#method.cancel_hashrate_resale_configuration).
141#[derive(Clone, Debug, Builder)]
142#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
143pub struct CancelHashrateResaleConfigurationParams {
144    /// Mining ID 168
145    ///
146    /// This field is **required.
147    #[builder(setter(into))]
148    pub config_id: i64,
149    /// Mining account test
150    ///
151    /// This field is **required.
152    #[builder(setter(into))]
153    pub user_name: String,
154    ///
155    /// The `recv_window` parameter.
156    ///
157    /// This field is **optional.
158    #[builder(setter(into), default)]
159    pub recv_window: Option<i64>,
160}
161
162impl CancelHashrateResaleConfigurationParams {
163    /// Create a builder for [`cancel_hashrate_resale_configuration`].
164    ///
165    /// Required parameters:
166    ///
167    /// * `config_id` — Mining ID 168
168    /// * `user_name` — Mining account test
169    ///
170    #[must_use]
171    pub fn builder(
172        config_id: i64,
173        user_name: String,
174    ) -> CancelHashrateResaleConfigurationParamsBuilder {
175        CancelHashrateResaleConfigurationParamsBuilder::default()
176            .config_id(config_id)
177            .user_name(user_name)
178    }
179}
180/// Request parameters for the [`earnings_list`] operation.
181///
182/// This struct holds all of the inputs you can pass when calling
183/// [`earnings_list`](#method.earnings_list).
184#[derive(Clone, Debug, Builder)]
185#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
186pub struct EarningsListParams {
187    /// Algorithm(sha256) sha256
188    ///
189    /// This field is **required.
190    #[builder(setter(into))]
191    pub algo: String,
192    /// Mining account test
193    ///
194    /// This field is **required.
195    #[builder(setter(into))]
196    pub user_name: String,
197    /// Coin Name
198    ///
199    /// This field is **optional.
200    #[builder(setter(into), default)]
201    pub coin: Option<String>,
202    /// Millisecond timestamp
203    ///
204    /// This field is **optional.
205    #[builder(setter(into), default)]
206    pub start_date: Option<i64>,
207    /// Millisecond timestamp
208    ///
209    /// This field is **optional.
210    #[builder(setter(into), default)]
211    pub end_date: Option<i64>,
212    /// Page number, empty default first page, starting from 1
213    ///
214    /// This field is **optional.
215    #[builder(setter(into), default)]
216    pub page_index: Option<i64>,
217    /// Min 10,Max 200
218    ///
219    /// This field is **optional.
220    #[builder(setter(into), default)]
221    pub page_size: Option<i64>,
222    ///
223    /// The `recv_window` parameter.
224    ///
225    /// This field is **optional.
226    #[builder(setter(into), default)]
227    pub recv_window: Option<i64>,
228}
229
230impl EarningsListParams {
231    /// Create a builder for [`earnings_list`].
232    ///
233    /// Required parameters:
234    ///
235    /// * `algo` — Algorithm(sha256) sha256
236    /// * `user_name` — Mining account test
237    ///
238    #[must_use]
239    pub fn builder(algo: String, user_name: String) -> EarningsListParamsBuilder {
240        EarningsListParamsBuilder::default()
241            .algo(algo)
242            .user_name(user_name)
243    }
244}
245/// Request parameters for the [`extra_bonus_list`] operation.
246///
247/// This struct holds all of the inputs you can pass when calling
248/// [`extra_bonus_list`](#method.extra_bonus_list).
249#[derive(Clone, Debug, Builder)]
250#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
251pub struct ExtraBonusListParams {
252    /// Algorithm(sha256) sha256
253    ///
254    /// This field is **required.
255    #[builder(setter(into))]
256    pub algo: String,
257    /// Mining account test
258    ///
259    /// This field is **required.
260    #[builder(setter(into))]
261    pub user_name: String,
262    /// Coin Name
263    ///
264    /// This field is **optional.
265    #[builder(setter(into), default)]
266    pub coin: Option<String>,
267    /// Millisecond timestamp
268    ///
269    /// This field is **optional.
270    #[builder(setter(into), default)]
271    pub start_date: Option<i64>,
272    /// Millisecond timestamp
273    ///
274    /// This field is **optional.
275    #[builder(setter(into), default)]
276    pub end_date: Option<i64>,
277    /// Page number, empty default first page, starting from 1
278    ///
279    /// This field is **optional.
280    #[builder(setter(into), default)]
281    pub page_index: Option<i64>,
282    /// Min 10,Max 200
283    ///
284    /// This field is **optional.
285    #[builder(setter(into), default)]
286    pub page_size: Option<i64>,
287    ///
288    /// The `recv_window` parameter.
289    ///
290    /// This field is **optional.
291    #[builder(setter(into), default)]
292    pub recv_window: Option<i64>,
293}
294
295impl ExtraBonusListParams {
296    /// Create a builder for [`extra_bonus_list`].
297    ///
298    /// Required parameters:
299    ///
300    /// * `algo` — Algorithm(sha256) sha256
301    /// * `user_name` — Mining account test
302    ///
303    #[must_use]
304    pub fn builder(algo: String, user_name: String) -> ExtraBonusListParamsBuilder {
305        ExtraBonusListParamsBuilder::default()
306            .algo(algo)
307            .user_name(user_name)
308    }
309}
310/// Request parameters for the [`hashrate_resale_detail`] operation.
311///
312/// This struct holds all of the inputs you can pass when calling
313/// [`hashrate_resale_detail`](#method.hashrate_resale_detail).
314#[derive(Clone, Debug, Builder)]
315#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
316pub struct HashrateResaleDetailParams {
317    /// Mining ID 168
318    ///
319    /// This field is **required.
320    #[builder(setter(into))]
321    pub config_id: i64,
322    /// Page number, empty default first page, starting from 1
323    ///
324    /// This field is **optional.
325    #[builder(setter(into), default)]
326    pub page_index: Option<i64>,
327    /// Min 10,Max 200
328    ///
329    /// This field is **optional.
330    #[builder(setter(into), default)]
331    pub page_size: Option<i64>,
332    ///
333    /// The `recv_window` parameter.
334    ///
335    /// This field is **optional.
336    #[builder(setter(into), default)]
337    pub recv_window: Option<i64>,
338}
339
340impl HashrateResaleDetailParams {
341    /// Create a builder for [`hashrate_resale_detail`].
342    ///
343    /// Required parameters:
344    ///
345    /// * `config_id` — Mining ID 168
346    ///
347    #[must_use]
348    pub fn builder(config_id: i64) -> HashrateResaleDetailParamsBuilder {
349        HashrateResaleDetailParamsBuilder::default().config_id(config_id)
350    }
351}
352/// Request parameters for the [`hashrate_resale_list`] operation.
353///
354/// This struct holds all of the inputs you can pass when calling
355/// [`hashrate_resale_list`](#method.hashrate_resale_list).
356#[derive(Clone, Debug, Builder, Default)]
357#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
358pub struct HashrateResaleListParams {
359    /// Page number, empty default first page, starting from 1
360    ///
361    /// This field is **optional.
362    #[builder(setter(into), default)]
363    pub page_index: Option<i64>,
364    /// Min 10,Max 200
365    ///
366    /// This field is **optional.
367    #[builder(setter(into), default)]
368    pub page_size: Option<i64>,
369    ///
370    /// The `recv_window` parameter.
371    ///
372    /// This field is **optional.
373    #[builder(setter(into), default)]
374    pub recv_window: Option<i64>,
375}
376
377impl HashrateResaleListParams {
378    /// Create a builder for [`hashrate_resale_list`].
379    ///
380    #[must_use]
381    pub fn builder() -> HashrateResaleListParamsBuilder {
382        HashrateResaleListParamsBuilder::default()
383    }
384}
385/// Request parameters for the [`hashrate_resale_request`] operation.
386///
387/// This struct holds all of the inputs you can pass when calling
388/// [`hashrate_resale_request`](#method.hashrate_resale_request).
389#[derive(Clone, Debug, Builder)]
390#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
391pub struct HashrateResaleRequestParams {
392    /// Mining account test
393    ///
394    /// This field is **required.
395    #[builder(setter(into))]
396    pub user_name: String,
397    /// Algorithm(sha256) sha256
398    ///
399    /// This field is **required.
400    #[builder(setter(into))]
401    pub algo: String,
402    /// Resale End Time (Millisecond timestamp) 1617659086000
403    ///
404    /// This field is **required.
405    #[builder(setter(into))]
406    pub end_date: i64,
407    /// Resale Start Time(Millisecond timestamp) 1607659086000
408    ///
409    /// This field is **required.
410    #[builder(setter(into))]
411    pub start_date: i64,
412    /// Mining Account S19pro
413    ///
414    /// This field is **required.
415    #[builder(setter(into))]
416    pub to_pool_user: String,
417    /// Resale hashrate h/s must be transferred (BTC is greater than 500000000000 ETH is greater than 500000) 100000000
418    ///
419    /// This field is **required.
420    #[builder(setter(into))]
421    pub hash_rate: i64,
422    ///
423    /// The `recv_window` parameter.
424    ///
425    /// This field is **optional.
426    #[builder(setter(into), default)]
427    pub recv_window: Option<i64>,
428}
429
430impl HashrateResaleRequestParams {
431    /// Create a builder for [`hashrate_resale_request`].
432    ///
433    /// Required parameters:
434    ///
435    /// * `user_name` — Mining account test
436    /// * `algo` — Algorithm(sha256) sha256
437    /// * `end_date` — Resale End Time (Millisecond timestamp) 1617659086000
438    /// * `start_date` — Resale Start Time(Millisecond timestamp) 1607659086000
439    /// * `to_pool_user` — Mining Account S19pro
440    /// * `hash_rate` — Resale hashrate h/s must be transferred (BTC is greater than 500000000000 ETH is greater than 500000) 100000000
441    ///
442    #[must_use]
443    pub fn builder(
444        user_name: String,
445        algo: String,
446        end_date: i64,
447        start_date: i64,
448        to_pool_user: String,
449        hash_rate: i64,
450    ) -> HashrateResaleRequestParamsBuilder {
451        HashrateResaleRequestParamsBuilder::default()
452            .user_name(user_name)
453            .algo(algo)
454            .end_date(end_date)
455            .start_date(start_date)
456            .to_pool_user(to_pool_user)
457            .hash_rate(hash_rate)
458    }
459}
460/// Request parameters for the [`mining_account_earning`] operation.
461///
462/// This struct holds all of the inputs you can pass when calling
463/// [`mining_account_earning`](#method.mining_account_earning).
464#[derive(Clone, Debug, Builder)]
465#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
466pub struct MiningAccountEarningParams {
467    /// Algorithm(sha256) sha256
468    ///
469    /// This field is **required.
470    #[builder(setter(into))]
471    pub algo: String,
472    /// Millisecond timestamp
473    ///
474    /// This field is **optional.
475    #[builder(setter(into), default)]
476    pub start_date: Option<i64>,
477    /// Millisecond timestamp
478    ///
479    /// This field is **optional.
480    #[builder(setter(into), default)]
481    pub end_date: Option<i64>,
482    /// Page number, empty default first page, starting from 1
483    ///
484    /// This field is **optional.
485    #[builder(setter(into), default)]
486    pub page_index: Option<i64>,
487    /// Min 10,Max 200
488    ///
489    /// This field is **optional.
490    #[builder(setter(into), default)]
491    pub page_size: Option<i64>,
492    ///
493    /// The `recv_window` parameter.
494    ///
495    /// This field is **optional.
496    #[builder(setter(into), default)]
497    pub recv_window: Option<i64>,
498}
499
500impl MiningAccountEarningParams {
501    /// Create a builder for [`mining_account_earning`].
502    ///
503    /// Required parameters:
504    ///
505    /// * `algo` — Algorithm(sha256) sha256
506    ///
507    #[must_use]
508    pub fn builder(algo: String) -> MiningAccountEarningParamsBuilder {
509        MiningAccountEarningParamsBuilder::default().algo(algo)
510    }
511}
512/// Request parameters for the [`request_for_detail_miner_list`] operation.
513///
514/// This struct holds all of the inputs you can pass when calling
515/// [`request_for_detail_miner_list`](#method.request_for_detail_miner_list).
516#[derive(Clone, Debug, Builder)]
517#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
518pub struct RequestForDetailMinerListParams {
519    /// Algorithm(sha256) sha256
520    ///
521    /// This field is **required.
522    #[builder(setter(into))]
523    pub algo: String,
524    /// Mining account test
525    ///
526    /// This field is **required.
527    #[builder(setter(into))]
528    pub user_name: String,
529    /// Miner’s name(required) bhdc1.16A10404B
530    ///
531    /// This field is **required.
532    #[builder(setter(into))]
533    pub worker_name: String,
534    ///
535    /// The `recv_window` parameter.
536    ///
537    /// This field is **optional.
538    #[builder(setter(into), default)]
539    pub recv_window: Option<i64>,
540}
541
542impl RequestForDetailMinerListParams {
543    /// Create a builder for [`request_for_detail_miner_list`].
544    ///
545    /// Required parameters:
546    ///
547    /// * `algo` — Algorithm(sha256) sha256
548    /// * `user_name` — Mining account test
549    /// * `worker_name` — Miner’s name(required) bhdc1.16A10404B
550    ///
551    #[must_use]
552    pub fn builder(
553        algo: String,
554        user_name: String,
555        worker_name: String,
556    ) -> RequestForDetailMinerListParamsBuilder {
557        RequestForDetailMinerListParamsBuilder::default()
558            .algo(algo)
559            .user_name(user_name)
560            .worker_name(worker_name)
561    }
562}
563/// Request parameters for the [`request_for_miner_list`] operation.
564///
565/// This struct holds all of the inputs you can pass when calling
566/// [`request_for_miner_list`](#method.request_for_miner_list).
567#[derive(Clone, Debug, Builder)]
568#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
569pub struct RequestForMinerListParams {
570    /// Algorithm(sha256) sha256
571    ///
572    /// This field is **required.
573    #[builder(setter(into))]
574    pub algo: String,
575    /// Mining account test
576    ///
577    /// This field is **required.
578    #[builder(setter(into))]
579    pub user_name: String,
580    /// Page number, empty default first page, starting from 1
581    ///
582    /// This field is **optional.
583    #[builder(setter(into), default)]
584    pub page_index: Option<i64>,
585    /// sort sequence(default=0)0 positive sequence,1 negative sequence
586    ///
587    /// This field is **optional.
588    #[builder(setter(into), default)]
589    pub sort: Option<i64>,
590    /// Sort by( default 1): <br></br>1: miner name, <br></br>2: real-time computing power, <br></br>3: daily average computing power, <br></br>4: real-time rejection rate, <br></br>5: last submission time
591    ///
592    /// This field is **optional.
593    #[builder(setter(into), default)]
594    pub sort_column: Option<i64>,
595    /// miners status(default=0),0 all,1 valid,2 invalid,3 failure
596    ///
597    /// This field is **optional.
598    #[builder(setter(into), default)]
599    pub worker_status: Option<i64>,
600    ///
601    /// The `recv_window` parameter.
602    ///
603    /// This field is **optional.
604    #[builder(setter(into), default)]
605    pub recv_window: Option<i64>,
606}
607
608impl RequestForMinerListParams {
609    /// Create a builder for [`request_for_miner_list`].
610    ///
611    /// Required parameters:
612    ///
613    /// * `algo` — Algorithm(sha256) sha256
614    /// * `user_name` — Mining account test
615    ///
616    #[must_use]
617    pub fn builder(algo: String, user_name: String) -> RequestForMinerListParamsBuilder {
618        RequestForMinerListParamsBuilder::default()
619            .algo(algo)
620            .user_name(user_name)
621    }
622}
623/// Request parameters for the [`statistic_list`] operation.
624///
625/// This struct holds all of the inputs you can pass when calling
626/// [`statistic_list`](#method.statistic_list).
627#[derive(Clone, Debug, Builder)]
628#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
629pub struct StatisticListParams {
630    /// Algorithm(sha256) sha256
631    ///
632    /// This field is **required.
633    #[builder(setter(into))]
634    pub algo: String,
635    /// Mining account test
636    ///
637    /// This field is **required.
638    #[builder(setter(into))]
639    pub user_name: String,
640    ///
641    /// The `recv_window` parameter.
642    ///
643    /// This field is **optional.
644    #[builder(setter(into), default)]
645    pub recv_window: Option<i64>,
646}
647
648impl StatisticListParams {
649    /// Create a builder for [`statistic_list`].
650    ///
651    /// Required parameters:
652    ///
653    /// * `algo` — Algorithm(sha256) sha256
654    /// * `user_name` — Mining account test
655    ///
656    #[must_use]
657    pub fn builder(algo: String, user_name: String) -> StatisticListParamsBuilder {
658        StatisticListParamsBuilder::default()
659            .algo(algo)
660            .user_name(user_name)
661    }
662}
663
664#[async_trait]
665impl MiningApi for MiningApiClient {
666    async fn account_list(
667        &self,
668        params: AccountListParams,
669    ) -> anyhow::Result<RestApiResponse<models::AccountListResponse>> {
670        let AccountListParams {
671            algo,
672            user_name,
673            recv_window,
674        } = params;
675
676        let mut query_params = BTreeMap::new();
677        let body_params = BTreeMap::new();
678
679        query_params.insert("algo".to_string(), json!(algo));
680
681        query_params.insert("userName".to_string(), json!(user_name));
682
683        if let Some(rw) = recv_window {
684            query_params.insert("recvWindow".to_string(), json!(rw));
685        }
686
687        send_request::<models::AccountListResponse>(
688            &self.configuration,
689            "/sapi/v1/mining/statistics/user/list",
690            reqwest::Method::GET,
691            query_params,
692            body_params,
693            if HAS_TIME_UNIT {
694                self.configuration.time_unit
695            } else {
696                None
697            },
698            true,
699        )
700        .await
701    }
702
703    async fn acquiring_algorithm(
704        &self,
705    ) -> anyhow::Result<RestApiResponse<models::AcquiringAlgorithmResponse>> {
706        let query_params = BTreeMap::new();
707        let body_params = BTreeMap::new();
708
709        send_request::<models::AcquiringAlgorithmResponse>(
710            &self.configuration,
711            "/sapi/v1/mining/pub/algoList",
712            reqwest::Method::GET,
713            query_params,
714            body_params,
715            if HAS_TIME_UNIT {
716                self.configuration.time_unit
717            } else {
718                None
719            },
720            false,
721        )
722        .await
723    }
724
725    async fn acquiring_coinname(
726        &self,
727    ) -> anyhow::Result<RestApiResponse<models::AcquiringCoinnameResponse>> {
728        let query_params = BTreeMap::new();
729        let body_params = BTreeMap::new();
730
731        send_request::<models::AcquiringCoinnameResponse>(
732            &self.configuration,
733            "/sapi/v1/mining/pub/coinList",
734            reqwest::Method::GET,
735            query_params,
736            body_params,
737            if HAS_TIME_UNIT {
738                self.configuration.time_unit
739            } else {
740                None
741            },
742            false,
743        )
744        .await
745    }
746
747    async fn cancel_hashrate_resale_configuration(
748        &self,
749        params: CancelHashrateResaleConfigurationParams,
750    ) -> anyhow::Result<RestApiResponse<models::CancelHashrateResaleConfigurationResponse>> {
751        let CancelHashrateResaleConfigurationParams {
752            config_id,
753            user_name,
754            recv_window,
755        } = params;
756
757        let mut query_params = BTreeMap::new();
758        let body_params = BTreeMap::new();
759
760        query_params.insert("configId".to_string(), json!(config_id));
761
762        query_params.insert("userName".to_string(), json!(user_name));
763
764        if let Some(rw) = recv_window {
765            query_params.insert("recvWindow".to_string(), json!(rw));
766        }
767
768        send_request::<models::CancelHashrateResaleConfigurationResponse>(
769            &self.configuration,
770            "/sapi/v1/mining/hash-transfer/config/cancel",
771            reqwest::Method::POST,
772            query_params,
773            body_params,
774            if HAS_TIME_UNIT {
775                self.configuration.time_unit
776            } else {
777                None
778            },
779            true,
780        )
781        .await
782    }
783
784    async fn earnings_list(
785        &self,
786        params: EarningsListParams,
787    ) -> anyhow::Result<RestApiResponse<models::EarningsListResponse>> {
788        let EarningsListParams {
789            algo,
790            user_name,
791            coin,
792            start_date,
793            end_date,
794            page_index,
795            page_size,
796            recv_window,
797        } = params;
798
799        let mut query_params = BTreeMap::new();
800        let body_params = BTreeMap::new();
801
802        query_params.insert("algo".to_string(), json!(algo));
803
804        query_params.insert("userName".to_string(), json!(user_name));
805
806        if let Some(rw) = coin {
807            query_params.insert("coin".to_string(), json!(rw));
808        }
809
810        if let Some(rw) = start_date {
811            query_params.insert("startDate".to_string(), json!(rw));
812        }
813
814        if let Some(rw) = end_date {
815            query_params.insert("endDate".to_string(), json!(rw));
816        }
817
818        if let Some(rw) = page_index {
819            query_params.insert("pageIndex".to_string(), json!(rw));
820        }
821
822        if let Some(rw) = page_size {
823            query_params.insert("pageSize".to_string(), json!(rw));
824        }
825
826        if let Some(rw) = recv_window {
827            query_params.insert("recvWindow".to_string(), json!(rw));
828        }
829
830        send_request::<models::EarningsListResponse>(
831            &self.configuration,
832            "/sapi/v1/mining/payment/list",
833            reqwest::Method::GET,
834            query_params,
835            body_params,
836            if HAS_TIME_UNIT {
837                self.configuration.time_unit
838            } else {
839                None
840            },
841            true,
842        )
843        .await
844    }
845
846    async fn extra_bonus_list(
847        &self,
848        params: ExtraBonusListParams,
849    ) -> anyhow::Result<RestApiResponse<models::ExtraBonusListResponse>> {
850        let ExtraBonusListParams {
851            algo,
852            user_name,
853            coin,
854            start_date,
855            end_date,
856            page_index,
857            page_size,
858            recv_window,
859        } = params;
860
861        let mut query_params = BTreeMap::new();
862        let body_params = BTreeMap::new();
863
864        query_params.insert("algo".to_string(), json!(algo));
865
866        query_params.insert("userName".to_string(), json!(user_name));
867
868        if let Some(rw) = coin {
869            query_params.insert("coin".to_string(), json!(rw));
870        }
871
872        if let Some(rw) = start_date {
873            query_params.insert("startDate".to_string(), json!(rw));
874        }
875
876        if let Some(rw) = end_date {
877            query_params.insert("endDate".to_string(), json!(rw));
878        }
879
880        if let Some(rw) = page_index {
881            query_params.insert("pageIndex".to_string(), json!(rw));
882        }
883
884        if let Some(rw) = page_size {
885            query_params.insert("pageSize".to_string(), json!(rw));
886        }
887
888        if let Some(rw) = recv_window {
889            query_params.insert("recvWindow".to_string(), json!(rw));
890        }
891
892        send_request::<models::ExtraBonusListResponse>(
893            &self.configuration,
894            "/sapi/v1/mining/payment/other",
895            reqwest::Method::GET,
896            query_params,
897            body_params,
898            if HAS_TIME_UNIT {
899                self.configuration.time_unit
900            } else {
901                None
902            },
903            true,
904        )
905        .await
906    }
907
908    async fn hashrate_resale_detail(
909        &self,
910        params: HashrateResaleDetailParams,
911    ) -> anyhow::Result<RestApiResponse<models::HashrateResaleDetailResponse>> {
912        let HashrateResaleDetailParams {
913            config_id,
914            page_index,
915            page_size,
916            recv_window,
917        } = params;
918
919        let mut query_params = BTreeMap::new();
920        let body_params = BTreeMap::new();
921
922        query_params.insert("configId".to_string(), json!(config_id));
923
924        if let Some(rw) = page_index {
925            query_params.insert("pageIndex".to_string(), json!(rw));
926        }
927
928        if let Some(rw) = page_size {
929            query_params.insert("pageSize".to_string(), json!(rw));
930        }
931
932        if let Some(rw) = recv_window {
933            query_params.insert("recvWindow".to_string(), json!(rw));
934        }
935
936        send_request::<models::HashrateResaleDetailResponse>(
937            &self.configuration,
938            "/sapi/v1/mining/hash-transfer/profit/details",
939            reqwest::Method::GET,
940            query_params,
941            body_params,
942            if HAS_TIME_UNIT {
943                self.configuration.time_unit
944            } else {
945                None
946            },
947            true,
948        )
949        .await
950    }
951
952    async fn hashrate_resale_list(
953        &self,
954        params: HashrateResaleListParams,
955    ) -> anyhow::Result<RestApiResponse<models::HashrateResaleListResponse>> {
956        let HashrateResaleListParams {
957            page_index,
958            page_size,
959            recv_window,
960        } = params;
961
962        let mut query_params = BTreeMap::new();
963        let body_params = BTreeMap::new();
964
965        if let Some(rw) = page_index {
966            query_params.insert("pageIndex".to_string(), json!(rw));
967        }
968
969        if let Some(rw) = page_size {
970            query_params.insert("pageSize".to_string(), json!(rw));
971        }
972
973        if let Some(rw) = recv_window {
974            query_params.insert("recvWindow".to_string(), json!(rw));
975        }
976
977        send_request::<models::HashrateResaleListResponse>(
978            &self.configuration,
979            "/sapi/v1/mining/hash-transfer/config/details/list",
980            reqwest::Method::GET,
981            query_params,
982            body_params,
983            if HAS_TIME_UNIT {
984                self.configuration.time_unit
985            } else {
986                None
987            },
988            true,
989        )
990        .await
991    }
992
993    async fn hashrate_resale_request(
994        &self,
995        params: HashrateResaleRequestParams,
996    ) -> anyhow::Result<RestApiResponse<models::HashrateResaleRequestResponse>> {
997        let HashrateResaleRequestParams {
998            user_name,
999            algo,
1000            end_date,
1001            start_date,
1002            to_pool_user,
1003            hash_rate,
1004            recv_window,
1005        } = params;
1006
1007        let mut query_params = BTreeMap::new();
1008        let body_params = BTreeMap::new();
1009
1010        query_params.insert("userName".to_string(), json!(user_name));
1011
1012        query_params.insert("algo".to_string(), json!(algo));
1013
1014        query_params.insert("endDate".to_string(), json!(end_date));
1015
1016        query_params.insert("startDate".to_string(), json!(start_date));
1017
1018        query_params.insert("toPoolUser".to_string(), json!(to_pool_user));
1019
1020        query_params.insert("hashRate".to_string(), json!(hash_rate));
1021
1022        if let Some(rw) = recv_window {
1023            query_params.insert("recvWindow".to_string(), json!(rw));
1024        }
1025
1026        send_request::<models::HashrateResaleRequestResponse>(
1027            &self.configuration,
1028            "/sapi/v1/mining/hash-transfer/config",
1029            reqwest::Method::POST,
1030            query_params,
1031            body_params,
1032            if HAS_TIME_UNIT {
1033                self.configuration.time_unit
1034            } else {
1035                None
1036            },
1037            true,
1038        )
1039        .await
1040    }
1041
1042    async fn mining_account_earning(
1043        &self,
1044        params: MiningAccountEarningParams,
1045    ) -> anyhow::Result<RestApiResponse<models::MiningAccountEarningResponse>> {
1046        let MiningAccountEarningParams {
1047            algo,
1048            start_date,
1049            end_date,
1050            page_index,
1051            page_size,
1052            recv_window,
1053        } = params;
1054
1055        let mut query_params = BTreeMap::new();
1056        let body_params = BTreeMap::new();
1057
1058        query_params.insert("algo".to_string(), json!(algo));
1059
1060        if let Some(rw) = start_date {
1061            query_params.insert("startDate".to_string(), json!(rw));
1062        }
1063
1064        if let Some(rw) = end_date {
1065            query_params.insert("endDate".to_string(), json!(rw));
1066        }
1067
1068        if let Some(rw) = page_index {
1069            query_params.insert("pageIndex".to_string(), json!(rw));
1070        }
1071
1072        if let Some(rw) = page_size {
1073            query_params.insert("pageSize".to_string(), json!(rw));
1074        }
1075
1076        if let Some(rw) = recv_window {
1077            query_params.insert("recvWindow".to_string(), json!(rw));
1078        }
1079
1080        send_request::<models::MiningAccountEarningResponse>(
1081            &self.configuration,
1082            "/sapi/v1/mining/payment/uid",
1083            reqwest::Method::GET,
1084            query_params,
1085            body_params,
1086            if HAS_TIME_UNIT {
1087                self.configuration.time_unit
1088            } else {
1089                None
1090            },
1091            true,
1092        )
1093        .await
1094    }
1095
1096    async fn request_for_detail_miner_list(
1097        &self,
1098        params: RequestForDetailMinerListParams,
1099    ) -> anyhow::Result<RestApiResponse<models::RequestForDetailMinerListResponse>> {
1100        let RequestForDetailMinerListParams {
1101            algo,
1102            user_name,
1103            worker_name,
1104            recv_window,
1105        } = params;
1106
1107        let mut query_params = BTreeMap::new();
1108        let body_params = BTreeMap::new();
1109
1110        query_params.insert("algo".to_string(), json!(algo));
1111
1112        query_params.insert("userName".to_string(), json!(user_name));
1113
1114        query_params.insert("workerName".to_string(), json!(worker_name));
1115
1116        if let Some(rw) = recv_window {
1117            query_params.insert("recvWindow".to_string(), json!(rw));
1118        }
1119
1120        send_request::<models::RequestForDetailMinerListResponse>(
1121            &self.configuration,
1122            "/sapi/v1/mining/worker/detail",
1123            reqwest::Method::GET,
1124            query_params,
1125            body_params,
1126            if HAS_TIME_UNIT {
1127                self.configuration.time_unit
1128            } else {
1129                None
1130            },
1131            true,
1132        )
1133        .await
1134    }
1135
1136    async fn request_for_miner_list(
1137        &self,
1138        params: RequestForMinerListParams,
1139    ) -> anyhow::Result<RestApiResponse<models::RequestForMinerListResponse>> {
1140        let RequestForMinerListParams {
1141            algo,
1142            user_name,
1143            page_index,
1144            sort,
1145            sort_column,
1146            worker_status,
1147            recv_window,
1148        } = params;
1149
1150        let mut query_params = BTreeMap::new();
1151        let body_params = BTreeMap::new();
1152
1153        query_params.insert("algo".to_string(), json!(algo));
1154
1155        query_params.insert("userName".to_string(), json!(user_name));
1156
1157        if let Some(rw) = page_index {
1158            query_params.insert("pageIndex".to_string(), json!(rw));
1159        }
1160
1161        if let Some(rw) = sort {
1162            query_params.insert("sort".to_string(), json!(rw));
1163        }
1164
1165        if let Some(rw) = sort_column {
1166            query_params.insert("sortColumn".to_string(), json!(rw));
1167        }
1168
1169        if let Some(rw) = worker_status {
1170            query_params.insert("workerStatus".to_string(), json!(rw));
1171        }
1172
1173        if let Some(rw) = recv_window {
1174            query_params.insert("recvWindow".to_string(), json!(rw));
1175        }
1176
1177        send_request::<models::RequestForMinerListResponse>(
1178            &self.configuration,
1179            "/sapi/v1/mining/worker/list",
1180            reqwest::Method::GET,
1181            query_params,
1182            body_params,
1183            if HAS_TIME_UNIT {
1184                self.configuration.time_unit
1185            } else {
1186                None
1187            },
1188            true,
1189        )
1190        .await
1191    }
1192
1193    async fn statistic_list(
1194        &self,
1195        params: StatisticListParams,
1196    ) -> anyhow::Result<RestApiResponse<models::StatisticListResponse>> {
1197        let StatisticListParams {
1198            algo,
1199            user_name,
1200            recv_window,
1201        } = params;
1202
1203        let mut query_params = BTreeMap::new();
1204        let body_params = BTreeMap::new();
1205
1206        query_params.insert("algo".to_string(), json!(algo));
1207
1208        query_params.insert("userName".to_string(), json!(user_name));
1209
1210        if let Some(rw) = recv_window {
1211            query_params.insert("recvWindow".to_string(), json!(rw));
1212        }
1213
1214        send_request::<models::StatisticListResponse>(
1215            &self.configuration,
1216            "/sapi/v1/mining/statistics/user/status",
1217            reqwest::Method::GET,
1218            query_params,
1219            body_params,
1220            if HAS_TIME_UNIT {
1221                self.configuration.time_unit
1222            } else {
1223                None
1224            },
1225            true,
1226        )
1227        .await
1228    }
1229}
1230
1231#[cfg(all(test, feature = "mining"))]
1232mod tests {
1233    use super::*;
1234    use crate::TOKIO_SHARED_RT;
1235    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
1236    use async_trait::async_trait;
1237    use std::collections::HashMap;
1238
1239    struct DummyRestApiResponse<T> {
1240        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
1241        status: u16,
1242        headers: HashMap<String, String>,
1243        rate_limits: Option<Vec<RestApiRateLimit>>,
1244    }
1245
1246    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
1247        fn from(dummy: DummyRestApiResponse<T>) -> Self {
1248            Self {
1249                data_fn: dummy.inner,
1250                status: dummy.status,
1251                headers: dummy.headers,
1252                rate_limits: dummy.rate_limits,
1253            }
1254        }
1255    }
1256
1257    struct MockMiningApiClient {
1258        force_error: bool,
1259    }
1260
1261    #[async_trait]
1262    impl MiningApi for MockMiningApiClient {
1263        async fn account_list(
1264            &self,
1265            _params: AccountListParams,
1266        ) -> anyhow::Result<RestApiResponse<models::AccountListResponse>> {
1267            if self.force_error {
1268                return Err(ConnectorError::ConnectorClientError {
1269                    msg: "ResponseError".to_string(),
1270                    code: None,
1271                }
1272                .into());
1273            }
1274
1275            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"type":"H_hashrate","userName":"test","list":[{"time":1585267200000,"hashrate":"0.00000000","reject":"0.00000000"},{"time":1585353600000,"hashrate":"0.00000000","reject":"0.00000000"}]},{"type":"D_hashrate","userName":"test","list":[{"time":1587906000000,"hashrate":"0.00000000","reject":"0.00000000"},{"time":1587909600000,"hashrate":"0.00000000","reject":"0.00000000"}]}]}"#).unwrap();
1276            let dummy_response: models::AccountListResponse =
1277                serde_json::from_value(resp_json.clone())
1278                    .expect("should parse into models::AccountListResponse");
1279
1280            let dummy = DummyRestApiResponse {
1281                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1282                status: 200,
1283                headers: HashMap::new(),
1284                rate_limits: None,
1285            };
1286
1287            Ok(dummy.into())
1288        }
1289
1290        async fn acquiring_algorithm(
1291            &self,
1292        ) -> anyhow::Result<RestApiResponse<models::AcquiringAlgorithmResponse>> {
1293            if self.force_error {
1294                return Err(ConnectorError::ConnectorClientError {
1295                    msg: "ResponseError".to_string(),
1296                    code: None,
1297                }
1298                .into());
1299            }
1300
1301            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"algoName":"sha256","algoId":1,"poolIndex":0,"unit":"h/s"}]}"#).unwrap();
1302            let dummy_response: models::AcquiringAlgorithmResponse =
1303                serde_json::from_value(resp_json.clone())
1304                    .expect("should parse into models::AcquiringAlgorithmResponse");
1305
1306            let dummy = DummyRestApiResponse {
1307                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1308                status: 200,
1309                headers: HashMap::new(),
1310                rate_limits: None,
1311            };
1312
1313            Ok(dummy.into())
1314        }
1315
1316        async fn acquiring_coinname(
1317            &self,
1318        ) -> anyhow::Result<RestApiResponse<models::AcquiringCoinnameResponse>> {
1319            if self.force_error {
1320                return Err(ConnectorError::ConnectorClientError {
1321                    msg: "ResponseError".to_string(),
1322                    code: None,
1323                }
1324                .into());
1325            }
1326
1327            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"coinName":"BTC","coinId":1,"poolIndex":0,"algoId":1,"algoName":"sha256"}]}"#).unwrap();
1328            let dummy_response: models::AcquiringCoinnameResponse =
1329                serde_json::from_value(resp_json.clone())
1330                    .expect("should parse into models::AcquiringCoinnameResponse");
1331
1332            let dummy = DummyRestApiResponse {
1333                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1334                status: 200,
1335                headers: HashMap::new(),
1336                rate_limits: None,
1337            };
1338
1339            Ok(dummy.into())
1340        }
1341
1342        async fn cancel_hashrate_resale_configuration(
1343            &self,
1344            _params: CancelHashrateResaleConfigurationParams,
1345        ) -> anyhow::Result<RestApiResponse<models::CancelHashrateResaleConfigurationResponse>>
1346        {
1347            if self.force_error {
1348                return Err(ConnectorError::ConnectorClientError {
1349                    msg: "ResponseError".to_string(),
1350                    code: None,
1351                }
1352                .into());
1353            }
1354
1355            let resp_json: Value =
1356                serde_json::from_str(r#"{"code":0,"msg":"","data":true}"#).unwrap();
1357            let dummy_response: models::CancelHashrateResaleConfigurationResponse =
1358                serde_json::from_value(resp_json.clone())
1359                    .expect("should parse into models::CancelHashrateResaleConfigurationResponse");
1360
1361            let dummy = DummyRestApiResponse {
1362                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1363                status: 200,
1364                headers: HashMap::new(),
1365                rate_limits: None,
1366            };
1367
1368            Ok(dummy.into())
1369        }
1370
1371        async fn earnings_list(
1372            &self,
1373            _params: EarningsListParams,
1374        ) -> anyhow::Result<RestApiResponse<models::EarningsListResponse>> {
1375            if self.force_error {
1376                return Err(ConnectorError::ConnectorClientError {
1377                    msg: "ResponseError".to_string(),
1378                    code: None,
1379                }
1380                .into());
1381            }
1382
1383            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"accountProfits":[{"time":1586188800000,"type":31,"hashTransfer":null,"transferAmount":null,"dayHashRate":129129903378244,"profitAmount":8.6083060304,"coinName":"BTC","status":2},{"time":1607529600000,"coinName":"BTC","type":0,"dayHashRate":9942053925926,"profitAmount":0.85426469,"hashTransfer":200000000000,"transferAmount":0.02180958,"status":2},{"time":1607443200000,"coinName":"BTC","type":31,"dayHashRate":200000000000,"profitAmount":0.02905916,"hashTransfer":null,"transferAmount":null,"status":2}],"totalNum":3,"pageSize":20}}"#).unwrap();
1384            let dummy_response: models::EarningsListResponse =
1385                serde_json::from_value(resp_json.clone())
1386                    .expect("should parse into models::EarningsListResponse");
1387
1388            let dummy = DummyRestApiResponse {
1389                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1390                status: 200,
1391                headers: HashMap::new(),
1392                rate_limits: None,
1393            };
1394
1395            Ok(dummy.into())
1396        }
1397
1398        async fn extra_bonus_list(
1399            &self,
1400            _params: ExtraBonusListParams,
1401        ) -> anyhow::Result<RestApiResponse<models::ExtraBonusListResponse>> {
1402            if self.force_error {
1403                return Err(ConnectorError::ConnectorClientError {
1404                    msg: "ResponseError".to_string(),
1405                    code: None,
1406                }
1407                .into());
1408            }
1409
1410            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();
1411            let dummy_response: models::ExtraBonusListResponse =
1412                serde_json::from_value(resp_json.clone())
1413                    .expect("should parse into models::ExtraBonusListResponse");
1414
1415            let dummy = DummyRestApiResponse {
1416                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1417                status: 200,
1418                headers: HashMap::new(),
1419                rate_limits: None,
1420            };
1421
1422            Ok(dummy.into())
1423        }
1424
1425        async fn hashrate_resale_detail(
1426            &self,
1427            _params: HashrateResaleDetailParams,
1428        ) -> anyhow::Result<RestApiResponse<models::HashrateResaleDetailResponse>> {
1429            if self.force_error {
1430                return Err(ConnectorError::ConnectorClientError {
1431                    msg: "ResponseError".to_string(),
1432                    code: None,
1433                }
1434                .into());
1435            }
1436
1437            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"},{"poolUsername":"test4001","toPoolUsername":"pop","algoName":"sha256","hashRate":200000000000,"day":20201213,"amount":0.2256872,"coinName":"BTC"}],"totalNum":8,"pageSize":200}}"#).unwrap();
1438            let dummy_response: models::HashrateResaleDetailResponse =
1439                serde_json::from_value(resp_json.clone())
1440                    .expect("should parse into models::HashrateResaleDetailResponse");
1441
1442            let dummy = DummyRestApiResponse {
1443                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1444                status: 200,
1445                headers: HashMap::new(),
1446                rate_limits: None,
1447            };
1448
1449            Ok(dummy.into())
1450        }
1451
1452        async fn hashrate_resale_list(
1453            &self,
1454            _params: HashrateResaleListParams,
1455        ) -> anyhow::Result<RestApiResponse<models::HashrateResaleListResponse>> {
1456            if self.force_error {
1457                return Err(ConnectorError::ConnectorClientError {
1458                    msg: "ResponseError".to_string(),
1459                    code: None,
1460                }
1461                .into());
1462            }
1463
1464            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},{"configId":166,"poolUsername":"pop","toPoolUsername":"111111","algoName":"Ethash","hashRate":3320000,"startDay":20201226,"endDay":20201227,"status":0,"type":0}],"totalNum":21,"pageSize":200}}"#).unwrap();
1465            let dummy_response: models::HashrateResaleListResponse =
1466                serde_json::from_value(resp_json.clone())
1467                    .expect("should parse into models::HashrateResaleListResponse");
1468
1469            let dummy = DummyRestApiResponse {
1470                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1471                status: 200,
1472                headers: HashMap::new(),
1473                rate_limits: None,
1474            };
1475
1476            Ok(dummy.into())
1477        }
1478
1479        async fn hashrate_resale_request(
1480            &self,
1481            _params: HashrateResaleRequestParams,
1482        ) -> anyhow::Result<RestApiResponse<models::HashrateResaleRequestResponse>> {
1483            if self.force_error {
1484                return Err(ConnectorError::ConnectorClientError {
1485                    msg: "ResponseError".to_string(),
1486                    code: None,
1487                }
1488                .into());
1489            }
1490
1491            let resp_json: Value =
1492                serde_json::from_str(r#"{"code":0,"msg":"","data":171}"#).unwrap();
1493            let dummy_response: models::HashrateResaleRequestResponse =
1494                serde_json::from_value(resp_json.clone())
1495                    .expect("should parse into models::HashrateResaleRequestResponse");
1496
1497            let dummy = DummyRestApiResponse {
1498                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1499                status: 200,
1500                headers: HashMap::new(),
1501                rate_limits: None,
1502            };
1503
1504            Ok(dummy.into())
1505        }
1506
1507        async fn mining_account_earning(
1508            &self,
1509            _params: MiningAccountEarningParams,
1510        ) -> anyhow::Result<RestApiResponse<models::MiningAccountEarningResponse>> {
1511            if self.force_error {
1512                return Err(ConnectorError::ConnectorClientError {
1513                    msg: "ResponseError".to_string(),
1514                    code: None,
1515                }
1516                .into());
1517            }
1518
1519            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();
1520            let dummy_response: models::MiningAccountEarningResponse =
1521                serde_json::from_value(resp_json.clone())
1522                    .expect("should parse into models::MiningAccountEarningResponse");
1523
1524            let dummy = DummyRestApiResponse {
1525                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1526                status: 200,
1527                headers: HashMap::new(),
1528                rate_limits: None,
1529            };
1530
1531            Ok(dummy.into())
1532        }
1533
1534        async fn request_for_detail_miner_list(
1535            &self,
1536            _params: RequestForDetailMinerListParams,
1537        ) -> anyhow::Result<RestApiResponse<models::RequestForDetailMinerListResponse>> {
1538            if self.force_error {
1539                return Err(ConnectorError::ConnectorClientError {
1540                    msg: "ResponseError".to_string(),
1541                    code: None,
1542                }
1543                .into());
1544            }
1545
1546            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},{"time":1587906000000,"hashrate":"0","reject":0}]},{"workerName":"bhdc1.16A10404B","type":"D_hashrate","hashrateDatas":[{"time":1587902400000,"hashrate":"0","reject":0},{"time":1587906000000,"hashrate":"0","reject":0}]}]}"#).unwrap();
1547            let dummy_response: models::RequestForDetailMinerListResponse =
1548                serde_json::from_value(resp_json.clone())
1549                    .expect("should parse into models::RequestForDetailMinerListResponse");
1550
1551            let dummy = DummyRestApiResponse {
1552                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1553                status: 200,
1554                headers: HashMap::new(),
1555                rate_limits: None,
1556            };
1557
1558            Ok(dummy.into())
1559        }
1560
1561        async fn request_for_miner_list(
1562            &self,
1563            _params: RequestForMinerListParams,
1564        ) -> anyhow::Result<RestApiResponse<models::RequestForMinerListResponse>> {
1565            if self.force_error {
1566                return Err(ConnectorError::ConnectorClientError {
1567                    msg: "ResponseError".to_string(),
1568                    code: None,
1569                }
1570                .into());
1571            }
1572
1573            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"workerDatas":[{"workerId":"1420554439452400131","workerName":"2X73","status":3,"hashRate":0,"dayHashRate":0,"rejectRate":0,"lastShareTime":1587712919000},{"workerId":"7893926126382807951","workerName":"AZDC1.1A10101","status":2,"hashRate":29711247541680,"dayHashRate":1.269778129801366E13,"rejectRate":0,"lastShareTime":1587969727000}],"totalNum":18530,"pageSize":20}}"#).unwrap();
1574            let dummy_response: models::RequestForMinerListResponse =
1575                serde_json::from_value(resp_json.clone())
1576                    .expect("should parse into models::RequestForMinerListResponse");
1577
1578            let dummy = DummyRestApiResponse {
1579                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1580                status: 200,
1581                headers: HashMap::new(),
1582                rate_limits: None,
1583            };
1584
1585            Ok(dummy.into())
1586        }
1587
1588        async fn statistic_list(
1589            &self,
1590            _params: StatisticListParams,
1591        ) -> anyhow::Result<RestApiResponse<models::StatisticListResponse>> {
1592            if self.force_error {
1593                return Err(ConnectorError::ConnectorClientError {
1594                    msg: "ResponseError".to_string(),
1595                    code: None,
1596                }
1597                .into());
1598            }
1599
1600            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();
1601            let dummy_response: models::StatisticListResponse =
1602                serde_json::from_value(resp_json.clone())
1603                    .expect("should parse into models::StatisticListResponse");
1604
1605            let dummy = DummyRestApiResponse {
1606                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1607                status: 200,
1608                headers: HashMap::new(),
1609                rate_limits: None,
1610            };
1611
1612            Ok(dummy.into())
1613        }
1614    }
1615
1616    #[test]
1617    fn account_list_required_params_success() {
1618        TOKIO_SHARED_RT.block_on(async {
1619            let client = MockMiningApiClient { force_error: false };
1620
1621            let params = AccountListParams::builder("algo_example".to_string(),"user_name_example".to_string(),).build().unwrap();
1622
1623            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"},{"time":1585353600000,"hashrate":"0.00000000","reject":"0.00000000"}]},{"type":"D_hashrate","userName":"test","list":[{"time":1587906000000,"hashrate":"0.00000000","reject":"0.00000000"},{"time":1587909600000,"hashrate":"0.00000000","reject":"0.00000000"}]}]}"#).unwrap();
1624            let expected_response : models::AccountListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AccountListResponse");
1625
1626            let resp = client.account_list(params).await.expect("Expected a response");
1627            let data_future = resp.data();
1628            let actual_response = data_future.await.unwrap();
1629            assert_eq!(actual_response, expected_response);
1630        });
1631    }
1632
1633    #[test]
1634    fn account_list_optional_params_success() {
1635        TOKIO_SHARED_RT.block_on(async {
1636            let client = MockMiningApiClient { force_error: false };
1637
1638            let params = AccountListParams::builder("algo_example".to_string(),"user_name_example".to_string(),).recv_window(5000).build().unwrap();
1639
1640            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"},{"time":1585353600000,"hashrate":"0.00000000","reject":"0.00000000"}]},{"type":"D_hashrate","userName":"test","list":[{"time":1587906000000,"hashrate":"0.00000000","reject":"0.00000000"},{"time":1587909600000,"hashrate":"0.00000000","reject":"0.00000000"}]}]}"#).unwrap();
1641            let expected_response : models::AccountListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AccountListResponse");
1642
1643            let resp = client.account_list(params).await.expect("Expected a response");
1644            let data_future = resp.data();
1645            let actual_response = data_future.await.unwrap();
1646            assert_eq!(actual_response, expected_response);
1647        });
1648    }
1649
1650    #[test]
1651    fn account_list_response_error() {
1652        TOKIO_SHARED_RT.block_on(async {
1653            let client = MockMiningApiClient { force_error: true };
1654
1655            let params = AccountListParams::builder(
1656                "algo_example".to_string(),
1657                "user_name_example".to_string(),
1658            )
1659            .build()
1660            .unwrap();
1661
1662            match client.account_list(params).await {
1663                Ok(_) => panic!("Expected an error"),
1664                Err(err) => {
1665                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1666                }
1667            }
1668        });
1669    }
1670
1671    #[test]
1672    fn acquiring_algorithm_required_params_success() {
1673        TOKIO_SHARED_RT.block_on(async {
1674            let client = MockMiningApiClient { force_error: false };
1675
1676
1677            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"algoName":"sha256","algoId":1,"poolIndex":0,"unit":"h/s"}]}"#).unwrap();
1678            let expected_response : models::AcquiringAlgorithmResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AcquiringAlgorithmResponse");
1679
1680            let resp = client.acquiring_algorithm().await.expect("Expected a response");
1681            let data_future = resp.data();
1682            let actual_response = data_future.await.unwrap();
1683            assert_eq!(actual_response, expected_response);
1684        });
1685    }
1686
1687    #[test]
1688    fn acquiring_algorithm_optional_params_success() {
1689        TOKIO_SHARED_RT.block_on(async {
1690            let client = MockMiningApiClient { force_error: false };
1691
1692
1693            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"algoName":"sha256","algoId":1,"poolIndex":0,"unit":"h/s"}]}"#).unwrap();
1694            let expected_response : models::AcquiringAlgorithmResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AcquiringAlgorithmResponse");
1695
1696            let resp = client.acquiring_algorithm().await.expect("Expected a response");
1697            let data_future = resp.data();
1698            let actual_response = data_future.await.unwrap();
1699            assert_eq!(actual_response, expected_response);
1700        });
1701    }
1702
1703    #[test]
1704    fn acquiring_algorithm_response_error() {
1705        TOKIO_SHARED_RT.block_on(async {
1706            let client = MockMiningApiClient { force_error: true };
1707
1708            match client.acquiring_algorithm().await {
1709                Ok(_) => panic!("Expected an error"),
1710                Err(err) => {
1711                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1712                }
1713            }
1714        });
1715    }
1716
1717    #[test]
1718    fn acquiring_coinname_required_params_success() {
1719        TOKIO_SHARED_RT.block_on(async {
1720            let client = MockMiningApiClient { force_error: false };
1721
1722
1723            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"coinName":"BTC","coinId":1,"poolIndex":0,"algoId":1,"algoName":"sha256"}]}"#).unwrap();
1724            let expected_response : models::AcquiringCoinnameResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AcquiringCoinnameResponse");
1725
1726            let resp = client.acquiring_coinname().await.expect("Expected a response");
1727            let data_future = resp.data();
1728            let actual_response = data_future.await.unwrap();
1729            assert_eq!(actual_response, expected_response);
1730        });
1731    }
1732
1733    #[test]
1734    fn acquiring_coinname_optional_params_success() {
1735        TOKIO_SHARED_RT.block_on(async {
1736            let client = MockMiningApiClient { force_error: false };
1737
1738
1739            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":[{"coinName":"BTC","coinId":1,"poolIndex":0,"algoId":1,"algoName":"sha256"}]}"#).unwrap();
1740            let expected_response : models::AcquiringCoinnameResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AcquiringCoinnameResponse");
1741
1742            let resp = client.acquiring_coinname().await.expect("Expected a response");
1743            let data_future = resp.data();
1744            let actual_response = data_future.await.unwrap();
1745            assert_eq!(actual_response, expected_response);
1746        });
1747    }
1748
1749    #[test]
1750    fn acquiring_coinname_response_error() {
1751        TOKIO_SHARED_RT.block_on(async {
1752            let client = MockMiningApiClient { force_error: true };
1753
1754            match client.acquiring_coinname().await {
1755                Ok(_) => panic!("Expected an error"),
1756                Err(err) => {
1757                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1758                }
1759            }
1760        });
1761    }
1762
1763    #[test]
1764    fn cancel_hashrate_resale_configuration_required_params_success() {
1765        TOKIO_SHARED_RT.block_on(async {
1766            let client = MockMiningApiClient { force_error: false };
1767
1768            let params = CancelHashrateResaleConfigurationParams::builder(
1769                1,
1770                "user_name_example".to_string(),
1771            )
1772            .build()
1773            .unwrap();
1774
1775            let resp_json: Value =
1776                serde_json::from_str(r#"{"code":0,"msg":"","data":true}"#).unwrap();
1777            let expected_response: models::CancelHashrateResaleConfigurationResponse =
1778                serde_json::from_value(resp_json.clone())
1779                    .expect("should parse into models::CancelHashrateResaleConfigurationResponse");
1780
1781            let resp = client
1782                .cancel_hashrate_resale_configuration(params)
1783                .await
1784                .expect("Expected a response");
1785            let data_future = resp.data();
1786            let actual_response = data_future.await.unwrap();
1787            assert_eq!(actual_response, expected_response);
1788        });
1789    }
1790
1791    #[test]
1792    fn cancel_hashrate_resale_configuration_optional_params_success() {
1793        TOKIO_SHARED_RT.block_on(async {
1794            let client = MockMiningApiClient { force_error: false };
1795
1796            let params = CancelHashrateResaleConfigurationParams::builder(
1797                1,
1798                "user_name_example".to_string(),
1799            )
1800            .recv_window(5000)
1801            .build()
1802            .unwrap();
1803
1804            let resp_json: Value =
1805                serde_json::from_str(r#"{"code":0,"msg":"","data":true}"#).unwrap();
1806            let expected_response: models::CancelHashrateResaleConfigurationResponse =
1807                serde_json::from_value(resp_json.clone())
1808                    .expect("should parse into models::CancelHashrateResaleConfigurationResponse");
1809
1810            let resp = client
1811                .cancel_hashrate_resale_configuration(params)
1812                .await
1813                .expect("Expected a response");
1814            let data_future = resp.data();
1815            let actual_response = data_future.await.unwrap();
1816            assert_eq!(actual_response, expected_response);
1817        });
1818    }
1819
1820    #[test]
1821    fn cancel_hashrate_resale_configuration_response_error() {
1822        TOKIO_SHARED_RT.block_on(async {
1823            let client = MockMiningApiClient { force_error: true };
1824
1825            let params = CancelHashrateResaleConfigurationParams::builder(
1826                1,
1827                "user_name_example".to_string(),
1828            )
1829            .build()
1830            .unwrap();
1831
1832            match client.cancel_hashrate_resale_configuration(params).await {
1833                Ok(_) => panic!("Expected an error"),
1834                Err(err) => {
1835                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1836                }
1837            }
1838        });
1839    }
1840
1841    #[test]
1842    fn earnings_list_required_params_success() {
1843        TOKIO_SHARED_RT.block_on(async {
1844            let client = MockMiningApiClient { force_error: false };
1845
1846            let params = EarningsListParams::builder("algo_example".to_string(),"user_name_example".to_string(),).build().unwrap();
1847
1848            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"accountProfits":[{"time":1586188800000,"type":31,"hashTransfer":null,"transferAmount":null,"dayHashRate":129129903378244,"profitAmount":8.6083060304,"coinName":"BTC","status":2},{"time":1607529600000,"coinName":"BTC","type":0,"dayHashRate":9942053925926,"profitAmount":0.85426469,"hashTransfer":200000000000,"transferAmount":0.02180958,"status":2},{"time":1607443200000,"coinName":"BTC","type":31,"dayHashRate":200000000000,"profitAmount":0.02905916,"hashTransfer":null,"transferAmount":null,"status":2}],"totalNum":3,"pageSize":20}}"#).unwrap();
1849            let expected_response : models::EarningsListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::EarningsListResponse");
1850
1851            let resp = client.earnings_list(params).await.expect("Expected a response");
1852            let data_future = resp.data();
1853            let actual_response = data_future.await.unwrap();
1854            assert_eq!(actual_response, expected_response);
1855        });
1856    }
1857
1858    #[test]
1859    fn earnings_list_optional_params_success() {
1860        TOKIO_SHARED_RT.block_on(async {
1861            let client = MockMiningApiClient { force_error: false };
1862
1863            let params = EarningsListParams::builder("algo_example".to_string(),"user_name_example".to_string(),).coin("coin_example".to_string()).start_date(789).end_date(789).page_index(1).page_size(789).recv_window(5000).build().unwrap();
1864
1865            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"accountProfits":[{"time":1586188800000,"type":31,"hashTransfer":null,"transferAmount":null,"dayHashRate":129129903378244,"profitAmount":8.6083060304,"coinName":"BTC","status":2},{"time":1607529600000,"coinName":"BTC","type":0,"dayHashRate":9942053925926,"profitAmount":0.85426469,"hashTransfer":200000000000,"transferAmount":0.02180958,"status":2},{"time":1607443200000,"coinName":"BTC","type":31,"dayHashRate":200000000000,"profitAmount":0.02905916,"hashTransfer":null,"transferAmount":null,"status":2}],"totalNum":3,"pageSize":20}}"#).unwrap();
1866            let expected_response : models::EarningsListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::EarningsListResponse");
1867
1868            let resp = client.earnings_list(params).await.expect("Expected a response");
1869            let data_future = resp.data();
1870            let actual_response = data_future.await.unwrap();
1871            assert_eq!(actual_response, expected_response);
1872        });
1873    }
1874
1875    #[test]
1876    fn earnings_list_response_error() {
1877        TOKIO_SHARED_RT.block_on(async {
1878            let client = MockMiningApiClient { force_error: true };
1879
1880            let params = EarningsListParams::builder(
1881                "algo_example".to_string(),
1882                "user_name_example".to_string(),
1883            )
1884            .build()
1885            .unwrap();
1886
1887            match client.earnings_list(params).await {
1888                Ok(_) => panic!("Expected an error"),
1889                Err(err) => {
1890                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1891                }
1892            }
1893        });
1894    }
1895
1896    #[test]
1897    fn extra_bonus_list_required_params_success() {
1898        TOKIO_SHARED_RT.block_on(async {
1899            let client = MockMiningApiClient { force_error: false };
1900
1901            let params = ExtraBonusListParams::builder("algo_example".to_string(),"user_name_example".to_string(),).build().unwrap();
1902
1903            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();
1904            let expected_response : models::ExtraBonusListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::ExtraBonusListResponse");
1905
1906            let resp = client.extra_bonus_list(params).await.expect("Expected a response");
1907            let data_future = resp.data();
1908            let actual_response = data_future.await.unwrap();
1909            assert_eq!(actual_response, expected_response);
1910        });
1911    }
1912
1913    #[test]
1914    fn extra_bonus_list_optional_params_success() {
1915        TOKIO_SHARED_RT.block_on(async {
1916            let client = MockMiningApiClient { force_error: false };
1917
1918            let params = ExtraBonusListParams::builder("algo_example".to_string(),"user_name_example".to_string(),).coin("coin_example".to_string()).start_date(789).end_date(789).page_index(1).page_size(789).recv_window(5000).build().unwrap();
1919
1920            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();
1921            let expected_response : models::ExtraBonusListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::ExtraBonusListResponse");
1922
1923            let resp = client.extra_bonus_list(params).await.expect("Expected a response");
1924            let data_future = resp.data();
1925            let actual_response = data_future.await.unwrap();
1926            assert_eq!(actual_response, expected_response);
1927        });
1928    }
1929
1930    #[test]
1931    fn extra_bonus_list_response_error() {
1932        TOKIO_SHARED_RT.block_on(async {
1933            let client = MockMiningApiClient { force_error: true };
1934
1935            let params = ExtraBonusListParams::builder(
1936                "algo_example".to_string(),
1937                "user_name_example".to_string(),
1938            )
1939            .build()
1940            .unwrap();
1941
1942            match client.extra_bonus_list(params).await {
1943                Ok(_) => panic!("Expected an error"),
1944                Err(err) => {
1945                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1946                }
1947            }
1948        });
1949    }
1950
1951    #[test]
1952    fn hashrate_resale_detail_required_params_success() {
1953        TOKIO_SHARED_RT.block_on(async {
1954            let client = MockMiningApiClient { force_error: false };
1955
1956            let params = HashrateResaleDetailParams::builder(1,).build().unwrap();
1957
1958            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"},{"poolUsername":"test4001","toPoolUsername":"pop","algoName":"sha256","hashRate":200000000000,"day":20201213,"amount":0.2256872,"coinName":"BTC"}],"totalNum":8,"pageSize":200}}"#).unwrap();
1959            let expected_response : models::HashrateResaleDetailResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::HashrateResaleDetailResponse");
1960
1961            let resp = client.hashrate_resale_detail(params).await.expect("Expected a response");
1962            let data_future = resp.data();
1963            let actual_response = data_future.await.unwrap();
1964            assert_eq!(actual_response, expected_response);
1965        });
1966    }
1967
1968    #[test]
1969    fn hashrate_resale_detail_optional_params_success() {
1970        TOKIO_SHARED_RT.block_on(async {
1971            let client = MockMiningApiClient { force_error: false };
1972
1973            let params = HashrateResaleDetailParams::builder(1,).page_index(1).page_size(789).recv_window(5000).build().unwrap();
1974
1975            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"},{"poolUsername":"test4001","toPoolUsername":"pop","algoName":"sha256","hashRate":200000000000,"day":20201213,"amount":0.2256872,"coinName":"BTC"}],"totalNum":8,"pageSize":200}}"#).unwrap();
1976            let expected_response : models::HashrateResaleDetailResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::HashrateResaleDetailResponse");
1977
1978            let resp = client.hashrate_resale_detail(params).await.expect("Expected a response");
1979            let data_future = resp.data();
1980            let actual_response = data_future.await.unwrap();
1981            assert_eq!(actual_response, expected_response);
1982        });
1983    }
1984
1985    #[test]
1986    fn hashrate_resale_detail_response_error() {
1987        TOKIO_SHARED_RT.block_on(async {
1988            let client = MockMiningApiClient { force_error: true };
1989
1990            let params = HashrateResaleDetailParams::builder(1).build().unwrap();
1991
1992            match client.hashrate_resale_detail(params).await {
1993                Ok(_) => panic!("Expected an error"),
1994                Err(err) => {
1995                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1996                }
1997            }
1998        });
1999    }
2000
2001    #[test]
2002    fn hashrate_resale_list_required_params_success() {
2003        TOKIO_SHARED_RT.block_on(async {
2004            let client = MockMiningApiClient { force_error: false };
2005
2006            let params = HashrateResaleListParams::builder().build().unwrap();
2007
2008            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},{"configId":166,"poolUsername":"pop","toPoolUsername":"111111","algoName":"Ethash","hashRate":3320000,"startDay":20201226,"endDay":20201227,"status":0,"type":0}],"totalNum":21,"pageSize":200}}"#).unwrap();
2009            let expected_response : models::HashrateResaleListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::HashrateResaleListResponse");
2010
2011            let resp = client.hashrate_resale_list(params).await.expect("Expected a response");
2012            let data_future = resp.data();
2013            let actual_response = data_future.await.unwrap();
2014            assert_eq!(actual_response, expected_response);
2015        });
2016    }
2017
2018    #[test]
2019    fn hashrate_resale_list_optional_params_success() {
2020        TOKIO_SHARED_RT.block_on(async {
2021            let client = MockMiningApiClient { force_error: false };
2022
2023            let params = HashrateResaleListParams::builder().page_index(1).page_size(789).recv_window(5000).build().unwrap();
2024
2025            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},{"configId":166,"poolUsername":"pop","toPoolUsername":"111111","algoName":"Ethash","hashRate":3320000,"startDay":20201226,"endDay":20201227,"status":0,"type":0}],"totalNum":21,"pageSize":200}}"#).unwrap();
2026            let expected_response : models::HashrateResaleListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::HashrateResaleListResponse");
2027
2028            let resp = client.hashrate_resale_list(params).await.expect("Expected a response");
2029            let data_future = resp.data();
2030            let actual_response = data_future.await.unwrap();
2031            assert_eq!(actual_response, expected_response);
2032        });
2033    }
2034
2035    #[test]
2036    fn hashrate_resale_list_response_error() {
2037        TOKIO_SHARED_RT.block_on(async {
2038            let client = MockMiningApiClient { force_error: true };
2039
2040            let params = HashrateResaleListParams::builder().build().unwrap();
2041
2042            match client.hashrate_resale_list(params).await {
2043                Ok(_) => panic!("Expected an error"),
2044                Err(err) => {
2045                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2046                }
2047            }
2048        });
2049    }
2050
2051    #[test]
2052    fn hashrate_resale_request_required_params_success() {
2053        TOKIO_SHARED_RT.block_on(async {
2054            let client = MockMiningApiClient { force_error: false };
2055
2056            let params = HashrateResaleRequestParams::builder(
2057                "user_name_example".to_string(),
2058                "algo_example".to_string(),
2059                789,
2060                789,
2061                "to_pool_user_example".to_string(),
2062                789,
2063            )
2064            .build()
2065            .unwrap();
2066
2067            let resp_json: Value =
2068                serde_json::from_str(r#"{"code":0,"msg":"","data":171}"#).unwrap();
2069            let expected_response: models::HashrateResaleRequestResponse =
2070                serde_json::from_value(resp_json.clone())
2071                    .expect("should parse into models::HashrateResaleRequestResponse");
2072
2073            let resp = client
2074                .hashrate_resale_request(params)
2075                .await
2076                .expect("Expected a response");
2077            let data_future = resp.data();
2078            let actual_response = data_future.await.unwrap();
2079            assert_eq!(actual_response, expected_response);
2080        });
2081    }
2082
2083    #[test]
2084    fn hashrate_resale_request_optional_params_success() {
2085        TOKIO_SHARED_RT.block_on(async {
2086            let client = MockMiningApiClient { force_error: false };
2087
2088            let params = HashrateResaleRequestParams::builder(
2089                "user_name_example".to_string(),
2090                "algo_example".to_string(),
2091                789,
2092                789,
2093                "to_pool_user_example".to_string(),
2094                789,
2095            )
2096            .recv_window(5000)
2097            .build()
2098            .unwrap();
2099
2100            let resp_json: Value =
2101                serde_json::from_str(r#"{"code":0,"msg":"","data":171}"#).unwrap();
2102            let expected_response: models::HashrateResaleRequestResponse =
2103                serde_json::from_value(resp_json.clone())
2104                    .expect("should parse into models::HashrateResaleRequestResponse");
2105
2106            let resp = client
2107                .hashrate_resale_request(params)
2108                .await
2109                .expect("Expected a response");
2110            let data_future = resp.data();
2111            let actual_response = data_future.await.unwrap();
2112            assert_eq!(actual_response, expected_response);
2113        });
2114    }
2115
2116    #[test]
2117    fn hashrate_resale_request_response_error() {
2118        TOKIO_SHARED_RT.block_on(async {
2119            let client = MockMiningApiClient { force_error: true };
2120
2121            let params = HashrateResaleRequestParams::builder(
2122                "user_name_example".to_string(),
2123                "algo_example".to_string(),
2124                789,
2125                789,
2126                "to_pool_user_example".to_string(),
2127                789,
2128            )
2129            .build()
2130            .unwrap();
2131
2132            match client.hashrate_resale_request(params).await {
2133                Ok(_) => panic!("Expected an error"),
2134                Err(err) => {
2135                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2136                }
2137            }
2138        });
2139    }
2140
2141    #[test]
2142    fn mining_account_earning_required_params_success() {
2143        TOKIO_SHARED_RT.block_on(async {
2144            let client = MockMiningApiClient { force_error: false };
2145
2146            let params = MiningAccountEarningParams::builder("algo_example".to_string(),).build().unwrap();
2147
2148            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();
2149            let expected_response : models::MiningAccountEarningResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::MiningAccountEarningResponse");
2150
2151            let resp = client.mining_account_earning(params).await.expect("Expected a response");
2152            let data_future = resp.data();
2153            let actual_response = data_future.await.unwrap();
2154            assert_eq!(actual_response, expected_response);
2155        });
2156    }
2157
2158    #[test]
2159    fn mining_account_earning_optional_params_success() {
2160        TOKIO_SHARED_RT.block_on(async {
2161            let client = MockMiningApiClient { force_error: false };
2162
2163            let params = MiningAccountEarningParams::builder("algo_example".to_string(),).start_date(789).end_date(789).page_index(1).page_size(789).recv_window(5000).build().unwrap();
2164
2165            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();
2166            let expected_response : models::MiningAccountEarningResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::MiningAccountEarningResponse");
2167
2168            let resp = client.mining_account_earning(params).await.expect("Expected a response");
2169            let data_future = resp.data();
2170            let actual_response = data_future.await.unwrap();
2171            assert_eq!(actual_response, expected_response);
2172        });
2173    }
2174
2175    #[test]
2176    fn mining_account_earning_response_error() {
2177        TOKIO_SHARED_RT.block_on(async {
2178            let client = MockMiningApiClient { force_error: true };
2179
2180            let params = MiningAccountEarningParams::builder("algo_example".to_string())
2181                .build()
2182                .unwrap();
2183
2184            match client.mining_account_earning(params).await {
2185                Ok(_) => panic!("Expected an error"),
2186                Err(err) => {
2187                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2188                }
2189            }
2190        });
2191    }
2192
2193    #[test]
2194    fn request_for_detail_miner_list_required_params_success() {
2195        TOKIO_SHARED_RT.block_on(async {
2196            let client = MockMiningApiClient { force_error: false };
2197
2198            let params = RequestForDetailMinerListParams::builder("algo_example".to_string(),"user_name_example".to_string(),"worker_name_example".to_string(),).build().unwrap();
2199
2200            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},{"time":1587906000000,"hashrate":"0","reject":0}]},{"workerName":"bhdc1.16A10404B","type":"D_hashrate","hashrateDatas":[{"time":1587902400000,"hashrate":"0","reject":0},{"time":1587906000000,"hashrate":"0","reject":0}]}]}"#).unwrap();
2201            let expected_response : models::RequestForDetailMinerListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RequestForDetailMinerListResponse");
2202
2203            let resp = client.request_for_detail_miner_list(params).await.expect("Expected a response");
2204            let data_future = resp.data();
2205            let actual_response = data_future.await.unwrap();
2206            assert_eq!(actual_response, expected_response);
2207        });
2208    }
2209
2210    #[test]
2211    fn request_for_detail_miner_list_optional_params_success() {
2212        TOKIO_SHARED_RT.block_on(async {
2213            let client = MockMiningApiClient { force_error: false };
2214
2215            let params = RequestForDetailMinerListParams::builder("algo_example".to_string(),"user_name_example".to_string(),"worker_name_example".to_string(),).recv_window(5000).build().unwrap();
2216
2217            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},{"time":1587906000000,"hashrate":"0","reject":0}]},{"workerName":"bhdc1.16A10404B","type":"D_hashrate","hashrateDatas":[{"time":1587902400000,"hashrate":"0","reject":0},{"time":1587906000000,"hashrate":"0","reject":0}]}]}"#).unwrap();
2218            let expected_response : models::RequestForDetailMinerListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RequestForDetailMinerListResponse");
2219
2220            let resp = client.request_for_detail_miner_list(params).await.expect("Expected a response");
2221            let data_future = resp.data();
2222            let actual_response = data_future.await.unwrap();
2223            assert_eq!(actual_response, expected_response);
2224        });
2225    }
2226
2227    #[test]
2228    fn request_for_detail_miner_list_response_error() {
2229        TOKIO_SHARED_RT.block_on(async {
2230            let client = MockMiningApiClient { force_error: true };
2231
2232            let params = RequestForDetailMinerListParams::builder(
2233                "algo_example".to_string(),
2234                "user_name_example".to_string(),
2235                "worker_name_example".to_string(),
2236            )
2237            .build()
2238            .unwrap();
2239
2240            match client.request_for_detail_miner_list(params).await {
2241                Ok(_) => panic!("Expected an error"),
2242                Err(err) => {
2243                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2244                }
2245            }
2246        });
2247    }
2248
2249    #[test]
2250    fn request_for_miner_list_required_params_success() {
2251        TOKIO_SHARED_RT.block_on(async {
2252            let client = MockMiningApiClient { force_error: false };
2253
2254            let params = RequestForMinerListParams::builder("algo_example".to_string(),"user_name_example".to_string(),).build().unwrap();
2255
2256            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"workerDatas":[{"workerId":"1420554439452400131","workerName":"2X73","status":3,"hashRate":0,"dayHashRate":0,"rejectRate":0,"lastShareTime":1587712919000},{"workerId":"7893926126382807951","workerName":"AZDC1.1A10101","status":2,"hashRate":29711247541680,"dayHashRate":1.269778129801366E13,"rejectRate":0,"lastShareTime":1587969727000}],"totalNum":18530,"pageSize":20}}"#).unwrap();
2257            let expected_response : models::RequestForMinerListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RequestForMinerListResponse");
2258
2259            let resp = client.request_for_miner_list(params).await.expect("Expected a response");
2260            let data_future = resp.data();
2261            let actual_response = data_future.await.unwrap();
2262            assert_eq!(actual_response, expected_response);
2263        });
2264    }
2265
2266    #[test]
2267    fn request_for_miner_list_optional_params_success() {
2268        TOKIO_SHARED_RT.block_on(async {
2269            let client = MockMiningApiClient { force_error: false };
2270
2271            let params = RequestForMinerListParams::builder("algo_example".to_string(),"user_name_example".to_string(),).page_index(1).sort(0).sort_column(1).worker_status(0).recv_window(5000).build().unwrap();
2272
2273            let resp_json: Value = serde_json::from_str(r#"{"code":0,"msg":"","data":{"workerDatas":[{"workerId":"1420554439452400131","workerName":"2X73","status":3,"hashRate":0,"dayHashRate":0,"rejectRate":0,"lastShareTime":1587712919000},{"workerId":"7893926126382807951","workerName":"AZDC1.1A10101","status":2,"hashRate":29711247541680,"dayHashRate":1.269778129801366E13,"rejectRate":0,"lastShareTime":1587969727000}],"totalNum":18530,"pageSize":20}}"#).unwrap();
2274            let expected_response : models::RequestForMinerListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::RequestForMinerListResponse");
2275
2276            let resp = client.request_for_miner_list(params).await.expect("Expected a response");
2277            let data_future = resp.data();
2278            let actual_response = data_future.await.unwrap();
2279            assert_eq!(actual_response, expected_response);
2280        });
2281    }
2282
2283    #[test]
2284    fn request_for_miner_list_response_error() {
2285        TOKIO_SHARED_RT.block_on(async {
2286            let client = MockMiningApiClient { force_error: true };
2287
2288            let params = RequestForMinerListParams::builder(
2289                "algo_example".to_string(),
2290                "user_name_example".to_string(),
2291            )
2292            .build()
2293            .unwrap();
2294
2295            match client.request_for_miner_list(params).await {
2296                Ok(_) => panic!("Expected an error"),
2297                Err(err) => {
2298                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2299                }
2300            }
2301        });
2302    }
2303
2304    #[test]
2305    fn statistic_list_required_params_success() {
2306        TOKIO_SHARED_RT.block_on(async {
2307            let client = MockMiningApiClient { force_error: false };
2308
2309            let params = StatisticListParams::builder("algo_example".to_string(),"user_name_example".to_string(),).build().unwrap();
2310
2311            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();
2312            let expected_response : models::StatisticListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::StatisticListResponse");
2313
2314            let resp = client.statistic_list(params).await.expect("Expected a response");
2315            let data_future = resp.data();
2316            let actual_response = data_future.await.unwrap();
2317            assert_eq!(actual_response, expected_response);
2318        });
2319    }
2320
2321    #[test]
2322    fn statistic_list_optional_params_success() {
2323        TOKIO_SHARED_RT.block_on(async {
2324            let client = MockMiningApiClient { force_error: false };
2325
2326            let params = StatisticListParams::builder("algo_example".to_string(),"user_name_example".to_string(),).recv_window(5000).build().unwrap();
2327
2328            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();
2329            let expected_response : models::StatisticListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::StatisticListResponse");
2330
2331            let resp = client.statistic_list(params).await.expect("Expected a response");
2332            let data_future = resp.data();
2333            let actual_response = data_future.await.unwrap();
2334            assert_eq!(actual_response, expected_response);
2335        });
2336    }
2337
2338    #[test]
2339    fn statistic_list_response_error() {
2340        TOKIO_SHARED_RT.block_on(async {
2341            let client = MockMiningApiClient { force_error: true };
2342
2343            let params = StatisticListParams::builder(
2344                "algo_example".to_string(),
2345                "user_name_example".to_string(),
2346            )
2347            .build()
2348            .unwrap();
2349
2350            match client.statistic_list(params).await {
2351                Ok(_) => panic!("Expected an error"),
2352                Err(err) => {
2353                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2354                }
2355            }
2356        });
2357    }
2358}