Skip to main content

binance_sdk/spot/rest_api/apis/
market_api.rs

1/*
2 * Spot REST API
3 *
4 * Access market data, manage accounts, and trade on Binance Spot.
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::spot::rest_api::models;
29
30const HAS_TIME_UNIT: bool = true;
31
32#[async_trait]
33pub trait MarketApi: Send + Sync {
34    async fn agg_trades(
35        &self,
36        params: AggTradesParams,
37    ) -> anyhow::Result<RestApiResponse<Vec<models::AggTradesResponseInner>>>;
38    async fn avg_price(
39        &self,
40        params: AvgPriceParams,
41    ) -> anyhow::Result<RestApiResponse<models::AvgPriceResponse>>;
42    async fn depth(
43        &self,
44        params: DepthParams,
45    ) -> anyhow::Result<RestApiResponse<models::DepthResponse>>;
46    async fn get_trades(
47        &self,
48        params: GetTradesParams,
49    ) -> anyhow::Result<RestApiResponse<Vec<models::GetTradesResponseInner>>>;
50    async fn historical_block_trades(
51        &self,
52        params: HistoricalBlockTradesParams,
53    ) -> anyhow::Result<RestApiResponse<Vec<models::HistoricalBlockTradesResponseInner>>>;
54    async fn historical_trades(
55        &self,
56        params: HistoricalTradesParams,
57    ) -> anyhow::Result<RestApiResponse<Vec<models::GetTradesResponseInner>>>;
58    async fn klines(
59        &self,
60        params: KlinesParams,
61    ) -> anyhow::Result<RestApiResponse<Vec<Vec<models::KlinesItemInner>>>>;
62    async fn reference_price(
63        &self,
64        params: ReferencePriceParams,
65    ) -> anyhow::Result<RestApiResponse<models::ReferencePriceResponse>>;
66    async fn reference_price_calculation(
67        &self,
68        params: ReferencePriceCalculationParams,
69    ) -> anyhow::Result<RestApiResponse<models::ReferencePriceCalculationResponse>>;
70    async fn ticker(
71        &self,
72        params: TickerParams,
73    ) -> anyhow::Result<RestApiResponse<models::TickerResponse>>;
74    async fn ticker24hr(
75        &self,
76        params: Ticker24hrParams,
77    ) -> anyhow::Result<RestApiResponse<models::Ticker24hrResponse>>;
78    async fn ticker_book_ticker(
79        &self,
80        params: TickerBookTickerParams,
81    ) -> anyhow::Result<RestApiResponse<models::TickerBookTickerResponse>>;
82    async fn ticker_price(
83        &self,
84        params: TickerPriceParams,
85    ) -> anyhow::Result<RestApiResponse<models::TickerPriceResponse>>;
86    async fn ticker_trading_day(
87        &self,
88        params: TickerTradingDayParams,
89    ) -> anyhow::Result<RestApiResponse<models::TickerTradingDayResponse>>;
90    async fn ui_klines(
91        &self,
92        params: UiKlinesParams,
93    ) -> anyhow::Result<RestApiResponse<Vec<Vec<models::KlinesItemInner>>>>;
94}
95
96#[derive(Debug, Clone)]
97pub struct MarketApiClient {
98    configuration: ConfigurationRestApi,
99}
100
101impl MarketApiClient {
102    pub fn new(configuration: ConfigurationRestApi) -> Self {
103        Self { configuration }
104    }
105}
106
107#[allow(non_camel_case_types)]
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub enum DepthSymbolStatusEnum {
110    #[serde(rename = "TRADING")]
111    Trading,
112    #[serde(rename = "HALT")]
113    Halt,
114    #[serde(rename = "BREAK")]
115    Break,
116}
117
118impl DepthSymbolStatusEnum {
119    #[must_use]
120    pub fn as_str(&self) -> &'static str {
121        match self {
122            Self::Trading => "TRADING",
123            Self::Halt => "HALT",
124            Self::Break => "BREAK",
125        }
126    }
127}
128
129impl std::str::FromStr for DepthSymbolStatusEnum {
130    type Err = Box<dyn std::error::Error + Send + Sync>;
131
132    fn from_str(s: &str) -> Result<Self, Self::Err> {
133        match s {
134            "TRADING" => Ok(Self::Trading),
135            "HALT" => Ok(Self::Halt),
136            "BREAK" => Ok(Self::Break),
137            other => Err(format!("invalid DepthSymbolStatusEnum: {}", other).into()),
138        }
139    }
140}
141
142#[allow(non_camel_case_types)]
143#[derive(Debug, Clone, Serialize, Deserialize)]
144pub enum KlinesIntervalEnum {
145    #[serde(rename = "1s")]
146    Interval1s,
147    #[serde(rename = "1m")]
148    Interval1m,
149    #[serde(rename = "3m")]
150    Interval3m,
151    #[serde(rename = "5m")]
152    Interval5m,
153    #[serde(rename = "15m")]
154    Interval15m,
155    #[serde(rename = "30m")]
156    Interval30m,
157    #[serde(rename = "1h")]
158    Interval1h,
159    #[serde(rename = "2h")]
160    Interval2h,
161    #[serde(rename = "4h")]
162    Interval4h,
163    #[serde(rename = "6h")]
164    Interval6h,
165    #[serde(rename = "8h")]
166    Interval8h,
167    #[serde(rename = "12h")]
168    Interval12h,
169    #[serde(rename = "1d")]
170    Interval1d,
171    #[serde(rename = "3d")]
172    Interval3d,
173    #[serde(rename = "1w")]
174    Interval1w,
175    #[serde(rename = "1M")]
176    Interval1M,
177}
178
179impl KlinesIntervalEnum {
180    #[must_use]
181    pub fn as_str(&self) -> &'static str {
182        match self {
183            Self::Interval1s => "1s",
184            Self::Interval1m => "1m",
185            Self::Interval3m => "3m",
186            Self::Interval5m => "5m",
187            Self::Interval15m => "15m",
188            Self::Interval30m => "30m",
189            Self::Interval1h => "1h",
190            Self::Interval2h => "2h",
191            Self::Interval4h => "4h",
192            Self::Interval6h => "6h",
193            Self::Interval8h => "8h",
194            Self::Interval12h => "12h",
195            Self::Interval1d => "1d",
196            Self::Interval3d => "3d",
197            Self::Interval1w => "1w",
198            Self::Interval1M => "1M",
199        }
200    }
201}
202
203impl std::str::FromStr for KlinesIntervalEnum {
204    type Err = Box<dyn std::error::Error + Send + Sync>;
205
206    fn from_str(s: &str) -> Result<Self, Self::Err> {
207        match s {
208            "1s" => Ok(Self::Interval1s),
209            "1m" => Ok(Self::Interval1m),
210            "3m" => Ok(Self::Interval3m),
211            "5m" => Ok(Self::Interval5m),
212            "15m" => Ok(Self::Interval15m),
213            "30m" => Ok(Self::Interval30m),
214            "1h" => Ok(Self::Interval1h),
215            "2h" => Ok(Self::Interval2h),
216            "4h" => Ok(Self::Interval4h),
217            "6h" => Ok(Self::Interval6h),
218            "8h" => Ok(Self::Interval8h),
219            "12h" => Ok(Self::Interval12h),
220            "1d" => Ok(Self::Interval1d),
221            "3d" => Ok(Self::Interval3d),
222            "1w" => Ok(Self::Interval1w),
223            "1M" => Ok(Self::Interval1M),
224            other => Err(format!("invalid KlinesIntervalEnum: {}", other).into()),
225        }
226    }
227}
228
229#[allow(non_camel_case_types)]
230#[derive(Debug, Clone, Serialize, Deserialize)]
231pub enum ReferencePriceCalculationSymbolStatusEnum {
232    #[serde(rename = "TRADING")]
233    Trading,
234    #[serde(rename = "HALT")]
235    Halt,
236    #[serde(rename = "BREAK")]
237    Break,
238}
239
240impl ReferencePriceCalculationSymbolStatusEnum {
241    #[must_use]
242    pub fn as_str(&self) -> &'static str {
243        match self {
244            Self::Trading => "TRADING",
245            Self::Halt => "HALT",
246            Self::Break => "BREAK",
247        }
248    }
249}
250
251impl std::str::FromStr for ReferencePriceCalculationSymbolStatusEnum {
252    type Err = Box<dyn std::error::Error + Send + Sync>;
253
254    fn from_str(s: &str) -> Result<Self, Self::Err> {
255        match s {
256            "TRADING" => Ok(Self::Trading),
257            "HALT" => Ok(Self::Halt),
258            "BREAK" => Ok(Self::Break),
259            other => Err(format!(
260                "invalid ReferencePriceCalculationSymbolStatusEnum: {}",
261                other
262            )
263            .into()),
264        }
265    }
266}
267
268#[allow(non_camel_case_types)]
269#[derive(Debug, Clone, Serialize, Deserialize)]
270pub enum TickerWindowSizeEnum {
271    #[serde(rename = "1m")]
272    WindowSize1m,
273    #[serde(rename = "2m")]
274    WindowSize2m,
275    #[serde(rename = "3m")]
276    WindowSize3m,
277    #[serde(rename = "4m")]
278    WindowSize4m,
279    #[serde(rename = "5m")]
280    WindowSize5m,
281    #[serde(rename = "6m")]
282    WindowSize6m,
283    #[serde(rename = "7m")]
284    WindowSize7m,
285    #[serde(rename = "8m")]
286    WindowSize8m,
287    #[serde(rename = "9m")]
288    WindowSize9m,
289    #[serde(rename = "10m")]
290    WindowSize10m,
291    #[serde(rename = "11m")]
292    WindowSize11m,
293    #[serde(rename = "12m")]
294    WindowSize12m,
295    #[serde(rename = "13m")]
296    WindowSize13m,
297    #[serde(rename = "14m")]
298    WindowSize14m,
299    #[serde(rename = "15m")]
300    WindowSize15m,
301    #[serde(rename = "16m")]
302    WindowSize16m,
303    #[serde(rename = "17m")]
304    WindowSize17m,
305    #[serde(rename = "18m")]
306    WindowSize18m,
307    #[serde(rename = "19m")]
308    WindowSize19m,
309    #[serde(rename = "20m")]
310    WindowSize20m,
311    #[serde(rename = "21m")]
312    WindowSize21m,
313    #[serde(rename = "22m")]
314    WindowSize22m,
315    #[serde(rename = "23m")]
316    WindowSize23m,
317    #[serde(rename = "24m")]
318    WindowSize24m,
319    #[serde(rename = "25m")]
320    WindowSize25m,
321    #[serde(rename = "26m")]
322    WindowSize26m,
323    #[serde(rename = "27m")]
324    WindowSize27m,
325    #[serde(rename = "28m")]
326    WindowSize28m,
327    #[serde(rename = "29m")]
328    WindowSize29m,
329    #[serde(rename = "30m")]
330    WindowSize30m,
331    #[serde(rename = "31m")]
332    WindowSize31m,
333    #[serde(rename = "32m")]
334    WindowSize32m,
335    #[serde(rename = "33m")]
336    WindowSize33m,
337    #[serde(rename = "34m")]
338    WindowSize34m,
339    #[serde(rename = "35m")]
340    WindowSize35m,
341    #[serde(rename = "36m")]
342    WindowSize36m,
343    #[serde(rename = "37m")]
344    WindowSize37m,
345    #[serde(rename = "38m")]
346    WindowSize38m,
347    #[serde(rename = "39m")]
348    WindowSize39m,
349    #[serde(rename = "40m")]
350    WindowSize40m,
351    #[serde(rename = "41m")]
352    WindowSize41m,
353    #[serde(rename = "42m")]
354    WindowSize42m,
355    #[serde(rename = "43m")]
356    WindowSize43m,
357    #[serde(rename = "44m")]
358    WindowSize44m,
359    #[serde(rename = "45m")]
360    WindowSize45m,
361    #[serde(rename = "46m")]
362    WindowSize46m,
363    #[serde(rename = "47m")]
364    WindowSize47m,
365    #[serde(rename = "48m")]
366    WindowSize48m,
367    #[serde(rename = "49m")]
368    WindowSize49m,
369    #[serde(rename = "50m")]
370    WindowSize50m,
371    #[serde(rename = "51m")]
372    WindowSize51m,
373    #[serde(rename = "52m")]
374    WindowSize52m,
375    #[serde(rename = "53m")]
376    WindowSize53m,
377    #[serde(rename = "54m")]
378    WindowSize54m,
379    #[serde(rename = "55m")]
380    WindowSize55m,
381    #[serde(rename = "56m")]
382    WindowSize56m,
383    #[serde(rename = "57m")]
384    WindowSize57m,
385    #[serde(rename = "58m")]
386    WindowSize58m,
387    #[serde(rename = "59m")]
388    WindowSize59m,
389    #[serde(rename = "1h")]
390    WindowSize1h,
391    #[serde(rename = "2h")]
392    WindowSize2h,
393    #[serde(rename = "3h")]
394    WindowSize3h,
395    #[serde(rename = "4h")]
396    WindowSize4h,
397    #[serde(rename = "5h")]
398    WindowSize5h,
399    #[serde(rename = "6h")]
400    WindowSize6h,
401    #[serde(rename = "7h")]
402    WindowSize7h,
403    #[serde(rename = "8h")]
404    WindowSize8h,
405    #[serde(rename = "9h")]
406    WindowSize9h,
407    #[serde(rename = "10h")]
408    WindowSize10h,
409    #[serde(rename = "11h")]
410    WindowSize11h,
411    #[serde(rename = "12h")]
412    WindowSize12h,
413    #[serde(rename = "13h")]
414    WindowSize13h,
415    #[serde(rename = "14h")]
416    WindowSize14h,
417    #[serde(rename = "15h")]
418    WindowSize15h,
419    #[serde(rename = "16h")]
420    WindowSize16h,
421    #[serde(rename = "17h")]
422    WindowSize17h,
423    #[serde(rename = "18h")]
424    WindowSize18h,
425    #[serde(rename = "19h")]
426    WindowSize19h,
427    #[serde(rename = "20h")]
428    WindowSize20h,
429    #[serde(rename = "21h")]
430    WindowSize21h,
431    #[serde(rename = "22h")]
432    WindowSize22h,
433    #[serde(rename = "23h")]
434    WindowSize23h,
435    #[serde(rename = "1d")]
436    WindowSize1d,
437    #[serde(rename = "2d")]
438    WindowSize2d,
439    #[serde(rename = "3d")]
440    WindowSize3d,
441    #[serde(rename = "4d")]
442    WindowSize4d,
443    #[serde(rename = "5d")]
444    WindowSize5d,
445    #[serde(rename = "6d")]
446    WindowSize6d,
447    #[serde(rename = "7d")]
448    WindowSize7d,
449}
450
451impl TickerWindowSizeEnum {
452    #[must_use]
453    pub fn as_str(&self) -> &'static str {
454        match self {
455            Self::WindowSize1m => "1m",
456            Self::WindowSize2m => "2m",
457            Self::WindowSize3m => "3m",
458            Self::WindowSize4m => "4m",
459            Self::WindowSize5m => "5m",
460            Self::WindowSize6m => "6m",
461            Self::WindowSize7m => "7m",
462            Self::WindowSize8m => "8m",
463            Self::WindowSize9m => "9m",
464            Self::WindowSize10m => "10m",
465            Self::WindowSize11m => "11m",
466            Self::WindowSize12m => "12m",
467            Self::WindowSize13m => "13m",
468            Self::WindowSize14m => "14m",
469            Self::WindowSize15m => "15m",
470            Self::WindowSize16m => "16m",
471            Self::WindowSize17m => "17m",
472            Self::WindowSize18m => "18m",
473            Self::WindowSize19m => "19m",
474            Self::WindowSize20m => "20m",
475            Self::WindowSize21m => "21m",
476            Self::WindowSize22m => "22m",
477            Self::WindowSize23m => "23m",
478            Self::WindowSize24m => "24m",
479            Self::WindowSize25m => "25m",
480            Self::WindowSize26m => "26m",
481            Self::WindowSize27m => "27m",
482            Self::WindowSize28m => "28m",
483            Self::WindowSize29m => "29m",
484            Self::WindowSize30m => "30m",
485            Self::WindowSize31m => "31m",
486            Self::WindowSize32m => "32m",
487            Self::WindowSize33m => "33m",
488            Self::WindowSize34m => "34m",
489            Self::WindowSize35m => "35m",
490            Self::WindowSize36m => "36m",
491            Self::WindowSize37m => "37m",
492            Self::WindowSize38m => "38m",
493            Self::WindowSize39m => "39m",
494            Self::WindowSize40m => "40m",
495            Self::WindowSize41m => "41m",
496            Self::WindowSize42m => "42m",
497            Self::WindowSize43m => "43m",
498            Self::WindowSize44m => "44m",
499            Self::WindowSize45m => "45m",
500            Self::WindowSize46m => "46m",
501            Self::WindowSize47m => "47m",
502            Self::WindowSize48m => "48m",
503            Self::WindowSize49m => "49m",
504            Self::WindowSize50m => "50m",
505            Self::WindowSize51m => "51m",
506            Self::WindowSize52m => "52m",
507            Self::WindowSize53m => "53m",
508            Self::WindowSize54m => "54m",
509            Self::WindowSize55m => "55m",
510            Self::WindowSize56m => "56m",
511            Self::WindowSize57m => "57m",
512            Self::WindowSize58m => "58m",
513            Self::WindowSize59m => "59m",
514            Self::WindowSize1h => "1h",
515            Self::WindowSize2h => "2h",
516            Self::WindowSize3h => "3h",
517            Self::WindowSize4h => "4h",
518            Self::WindowSize5h => "5h",
519            Self::WindowSize6h => "6h",
520            Self::WindowSize7h => "7h",
521            Self::WindowSize8h => "8h",
522            Self::WindowSize9h => "9h",
523            Self::WindowSize10h => "10h",
524            Self::WindowSize11h => "11h",
525            Self::WindowSize12h => "12h",
526            Self::WindowSize13h => "13h",
527            Self::WindowSize14h => "14h",
528            Self::WindowSize15h => "15h",
529            Self::WindowSize16h => "16h",
530            Self::WindowSize17h => "17h",
531            Self::WindowSize18h => "18h",
532            Self::WindowSize19h => "19h",
533            Self::WindowSize20h => "20h",
534            Self::WindowSize21h => "21h",
535            Self::WindowSize22h => "22h",
536            Self::WindowSize23h => "23h",
537            Self::WindowSize1d => "1d",
538            Self::WindowSize2d => "2d",
539            Self::WindowSize3d => "3d",
540            Self::WindowSize4d => "4d",
541            Self::WindowSize5d => "5d",
542            Self::WindowSize6d => "6d",
543            Self::WindowSize7d => "7d",
544        }
545    }
546}
547
548impl std::str::FromStr for TickerWindowSizeEnum {
549    type Err = Box<dyn std::error::Error + Send + Sync>;
550
551    fn from_str(s: &str) -> Result<Self, Self::Err> {
552        match s {
553            "1m" => Ok(Self::WindowSize1m),
554            "2m" => Ok(Self::WindowSize2m),
555            "3m" => Ok(Self::WindowSize3m),
556            "4m" => Ok(Self::WindowSize4m),
557            "5m" => Ok(Self::WindowSize5m),
558            "6m" => Ok(Self::WindowSize6m),
559            "7m" => Ok(Self::WindowSize7m),
560            "8m" => Ok(Self::WindowSize8m),
561            "9m" => Ok(Self::WindowSize9m),
562            "10m" => Ok(Self::WindowSize10m),
563            "11m" => Ok(Self::WindowSize11m),
564            "12m" => Ok(Self::WindowSize12m),
565            "13m" => Ok(Self::WindowSize13m),
566            "14m" => Ok(Self::WindowSize14m),
567            "15m" => Ok(Self::WindowSize15m),
568            "16m" => Ok(Self::WindowSize16m),
569            "17m" => Ok(Self::WindowSize17m),
570            "18m" => Ok(Self::WindowSize18m),
571            "19m" => Ok(Self::WindowSize19m),
572            "20m" => Ok(Self::WindowSize20m),
573            "21m" => Ok(Self::WindowSize21m),
574            "22m" => Ok(Self::WindowSize22m),
575            "23m" => Ok(Self::WindowSize23m),
576            "24m" => Ok(Self::WindowSize24m),
577            "25m" => Ok(Self::WindowSize25m),
578            "26m" => Ok(Self::WindowSize26m),
579            "27m" => Ok(Self::WindowSize27m),
580            "28m" => Ok(Self::WindowSize28m),
581            "29m" => Ok(Self::WindowSize29m),
582            "30m" => Ok(Self::WindowSize30m),
583            "31m" => Ok(Self::WindowSize31m),
584            "32m" => Ok(Self::WindowSize32m),
585            "33m" => Ok(Self::WindowSize33m),
586            "34m" => Ok(Self::WindowSize34m),
587            "35m" => Ok(Self::WindowSize35m),
588            "36m" => Ok(Self::WindowSize36m),
589            "37m" => Ok(Self::WindowSize37m),
590            "38m" => Ok(Self::WindowSize38m),
591            "39m" => Ok(Self::WindowSize39m),
592            "40m" => Ok(Self::WindowSize40m),
593            "41m" => Ok(Self::WindowSize41m),
594            "42m" => Ok(Self::WindowSize42m),
595            "43m" => Ok(Self::WindowSize43m),
596            "44m" => Ok(Self::WindowSize44m),
597            "45m" => Ok(Self::WindowSize45m),
598            "46m" => Ok(Self::WindowSize46m),
599            "47m" => Ok(Self::WindowSize47m),
600            "48m" => Ok(Self::WindowSize48m),
601            "49m" => Ok(Self::WindowSize49m),
602            "50m" => Ok(Self::WindowSize50m),
603            "51m" => Ok(Self::WindowSize51m),
604            "52m" => Ok(Self::WindowSize52m),
605            "53m" => Ok(Self::WindowSize53m),
606            "54m" => Ok(Self::WindowSize54m),
607            "55m" => Ok(Self::WindowSize55m),
608            "56m" => Ok(Self::WindowSize56m),
609            "57m" => Ok(Self::WindowSize57m),
610            "58m" => Ok(Self::WindowSize58m),
611            "59m" => Ok(Self::WindowSize59m),
612            "1h" => Ok(Self::WindowSize1h),
613            "2h" => Ok(Self::WindowSize2h),
614            "3h" => Ok(Self::WindowSize3h),
615            "4h" => Ok(Self::WindowSize4h),
616            "5h" => Ok(Self::WindowSize5h),
617            "6h" => Ok(Self::WindowSize6h),
618            "7h" => Ok(Self::WindowSize7h),
619            "8h" => Ok(Self::WindowSize8h),
620            "9h" => Ok(Self::WindowSize9h),
621            "10h" => Ok(Self::WindowSize10h),
622            "11h" => Ok(Self::WindowSize11h),
623            "12h" => Ok(Self::WindowSize12h),
624            "13h" => Ok(Self::WindowSize13h),
625            "14h" => Ok(Self::WindowSize14h),
626            "15h" => Ok(Self::WindowSize15h),
627            "16h" => Ok(Self::WindowSize16h),
628            "17h" => Ok(Self::WindowSize17h),
629            "18h" => Ok(Self::WindowSize18h),
630            "19h" => Ok(Self::WindowSize19h),
631            "20h" => Ok(Self::WindowSize20h),
632            "21h" => Ok(Self::WindowSize21h),
633            "22h" => Ok(Self::WindowSize22h),
634            "23h" => Ok(Self::WindowSize23h),
635            "1d" => Ok(Self::WindowSize1d),
636            "2d" => Ok(Self::WindowSize2d),
637            "3d" => Ok(Self::WindowSize3d),
638            "4d" => Ok(Self::WindowSize4d),
639            "5d" => Ok(Self::WindowSize5d),
640            "6d" => Ok(Self::WindowSize6d),
641            "7d" => Ok(Self::WindowSize7d),
642            other => Err(format!("invalid TickerWindowSizeEnum: {}", other).into()),
643        }
644    }
645}
646
647#[allow(non_camel_case_types)]
648#[derive(Debug, Clone, Serialize, Deserialize)]
649pub enum TickerTypeEnum {
650    #[serde(rename = "FULL")]
651    Full,
652    #[serde(rename = "MINI")]
653    Mini,
654}
655
656impl TickerTypeEnum {
657    #[must_use]
658    pub fn as_str(&self) -> &'static str {
659        match self {
660            Self::Full => "FULL",
661            Self::Mini => "MINI",
662        }
663    }
664}
665
666impl std::str::FromStr for TickerTypeEnum {
667    type Err = Box<dyn std::error::Error + Send + Sync>;
668
669    fn from_str(s: &str) -> Result<Self, Self::Err> {
670        match s {
671            "FULL" => Ok(Self::Full),
672            "MINI" => Ok(Self::Mini),
673            other => Err(format!("invalid TickerTypeEnum: {}", other).into()),
674        }
675    }
676}
677
678#[allow(non_camel_case_types)]
679#[derive(Debug, Clone, Serialize, Deserialize)]
680pub enum TickerSymbolStatusEnum {
681    #[serde(rename = "TRADING")]
682    Trading,
683    #[serde(rename = "HALT")]
684    Halt,
685    #[serde(rename = "BREAK")]
686    Break,
687}
688
689impl TickerSymbolStatusEnum {
690    #[must_use]
691    pub fn as_str(&self) -> &'static str {
692        match self {
693            Self::Trading => "TRADING",
694            Self::Halt => "HALT",
695            Self::Break => "BREAK",
696        }
697    }
698}
699
700impl std::str::FromStr for TickerSymbolStatusEnum {
701    type Err = Box<dyn std::error::Error + Send + Sync>;
702
703    fn from_str(s: &str) -> Result<Self, Self::Err> {
704        match s {
705            "TRADING" => Ok(Self::Trading),
706            "HALT" => Ok(Self::Halt),
707            "BREAK" => Ok(Self::Break),
708            other => Err(format!("invalid TickerSymbolStatusEnum: {}", other).into()),
709        }
710    }
711}
712
713#[allow(non_camel_case_types)]
714#[derive(Debug, Clone, Serialize, Deserialize)]
715pub enum Ticker24hrTypeEnum {
716    #[serde(rename = "FULL")]
717    Full,
718    #[serde(rename = "MINI")]
719    Mini,
720}
721
722impl Ticker24hrTypeEnum {
723    #[must_use]
724    pub fn as_str(&self) -> &'static str {
725        match self {
726            Self::Full => "FULL",
727            Self::Mini => "MINI",
728        }
729    }
730}
731
732impl std::str::FromStr for Ticker24hrTypeEnum {
733    type Err = Box<dyn std::error::Error + Send + Sync>;
734
735    fn from_str(s: &str) -> Result<Self, Self::Err> {
736        match s {
737            "FULL" => Ok(Self::Full),
738            "MINI" => Ok(Self::Mini),
739            other => Err(format!("invalid Ticker24hrTypeEnum: {}", other).into()),
740        }
741    }
742}
743
744#[allow(non_camel_case_types)]
745#[derive(Debug, Clone, Serialize, Deserialize)]
746pub enum Ticker24hrSymbolStatusEnum {
747    #[serde(rename = "TRADING")]
748    Trading,
749    #[serde(rename = "HALT")]
750    Halt,
751    #[serde(rename = "BREAK")]
752    Break,
753}
754
755impl Ticker24hrSymbolStatusEnum {
756    #[must_use]
757    pub fn as_str(&self) -> &'static str {
758        match self {
759            Self::Trading => "TRADING",
760            Self::Halt => "HALT",
761            Self::Break => "BREAK",
762        }
763    }
764}
765
766impl std::str::FromStr for Ticker24hrSymbolStatusEnum {
767    type Err = Box<dyn std::error::Error + Send + Sync>;
768
769    fn from_str(s: &str) -> Result<Self, Self::Err> {
770        match s {
771            "TRADING" => Ok(Self::Trading),
772            "HALT" => Ok(Self::Halt),
773            "BREAK" => Ok(Self::Break),
774            other => Err(format!("invalid Ticker24hrSymbolStatusEnum: {}", other).into()),
775        }
776    }
777}
778
779#[allow(non_camel_case_types)]
780#[derive(Debug, Clone, Serialize, Deserialize)]
781pub enum TickerBookTickerSymbolStatusEnum {
782    #[serde(rename = "TRADING")]
783    Trading,
784    #[serde(rename = "HALT")]
785    Halt,
786    #[serde(rename = "BREAK")]
787    Break,
788}
789
790impl TickerBookTickerSymbolStatusEnum {
791    #[must_use]
792    pub fn as_str(&self) -> &'static str {
793        match self {
794            Self::Trading => "TRADING",
795            Self::Halt => "HALT",
796            Self::Break => "BREAK",
797        }
798    }
799}
800
801impl std::str::FromStr for TickerBookTickerSymbolStatusEnum {
802    type Err = Box<dyn std::error::Error + Send + Sync>;
803
804    fn from_str(s: &str) -> Result<Self, Self::Err> {
805        match s {
806            "TRADING" => Ok(Self::Trading),
807            "HALT" => Ok(Self::Halt),
808            "BREAK" => Ok(Self::Break),
809            other => Err(format!("invalid TickerBookTickerSymbolStatusEnum: {}", other).into()),
810        }
811    }
812}
813
814#[allow(non_camel_case_types)]
815#[derive(Debug, Clone, Serialize, Deserialize)]
816pub enum TickerPriceSymbolStatusEnum {
817    #[serde(rename = "TRADING")]
818    Trading,
819    #[serde(rename = "HALT")]
820    Halt,
821    #[serde(rename = "BREAK")]
822    Break,
823}
824
825impl TickerPriceSymbolStatusEnum {
826    #[must_use]
827    pub fn as_str(&self) -> &'static str {
828        match self {
829            Self::Trading => "TRADING",
830            Self::Halt => "HALT",
831            Self::Break => "BREAK",
832        }
833    }
834}
835
836impl std::str::FromStr for TickerPriceSymbolStatusEnum {
837    type Err = Box<dyn std::error::Error + Send + Sync>;
838
839    fn from_str(s: &str) -> Result<Self, Self::Err> {
840        match s {
841            "TRADING" => Ok(Self::Trading),
842            "HALT" => Ok(Self::Halt),
843            "BREAK" => Ok(Self::Break),
844            other => Err(format!("invalid TickerPriceSymbolStatusEnum: {}", other).into()),
845        }
846    }
847}
848
849#[allow(non_camel_case_types)]
850#[derive(Debug, Clone, Serialize, Deserialize)]
851pub enum TickerTradingDayTypeEnum {
852    #[serde(rename = "FULL")]
853    Full,
854    #[serde(rename = "MINI")]
855    Mini,
856}
857
858impl TickerTradingDayTypeEnum {
859    #[must_use]
860    pub fn as_str(&self) -> &'static str {
861        match self {
862            Self::Full => "FULL",
863            Self::Mini => "MINI",
864        }
865    }
866}
867
868impl std::str::FromStr for TickerTradingDayTypeEnum {
869    type Err = Box<dyn std::error::Error + Send + Sync>;
870
871    fn from_str(s: &str) -> Result<Self, Self::Err> {
872        match s {
873            "FULL" => Ok(Self::Full),
874            "MINI" => Ok(Self::Mini),
875            other => Err(format!("invalid TickerTradingDayTypeEnum: {}", other).into()),
876        }
877    }
878}
879
880#[allow(non_camel_case_types)]
881#[derive(Debug, Clone, Serialize, Deserialize)]
882pub enum TickerTradingDaySymbolStatusEnum {
883    #[serde(rename = "TRADING")]
884    Trading,
885    #[serde(rename = "HALT")]
886    Halt,
887    #[serde(rename = "BREAK")]
888    Break,
889}
890
891impl TickerTradingDaySymbolStatusEnum {
892    #[must_use]
893    pub fn as_str(&self) -> &'static str {
894        match self {
895            Self::Trading => "TRADING",
896            Self::Halt => "HALT",
897            Self::Break => "BREAK",
898        }
899    }
900}
901
902impl std::str::FromStr for TickerTradingDaySymbolStatusEnum {
903    type Err = Box<dyn std::error::Error + Send + Sync>;
904
905    fn from_str(s: &str) -> Result<Self, Self::Err> {
906        match s {
907            "TRADING" => Ok(Self::Trading),
908            "HALT" => Ok(Self::Halt),
909            "BREAK" => Ok(Self::Break),
910            other => Err(format!("invalid TickerTradingDaySymbolStatusEnum: {}", other).into()),
911        }
912    }
913}
914
915#[allow(non_camel_case_types)]
916#[derive(Debug, Clone, Serialize, Deserialize)]
917pub enum UiKlinesIntervalEnum {
918    #[serde(rename = "1s")]
919    Interval1s,
920    #[serde(rename = "1m")]
921    Interval1m,
922    #[serde(rename = "3m")]
923    Interval3m,
924    #[serde(rename = "5m")]
925    Interval5m,
926    #[serde(rename = "15m")]
927    Interval15m,
928    #[serde(rename = "30m")]
929    Interval30m,
930    #[serde(rename = "1h")]
931    Interval1h,
932    #[serde(rename = "2h")]
933    Interval2h,
934    #[serde(rename = "4h")]
935    Interval4h,
936    #[serde(rename = "6h")]
937    Interval6h,
938    #[serde(rename = "8h")]
939    Interval8h,
940    #[serde(rename = "12h")]
941    Interval12h,
942    #[serde(rename = "1d")]
943    Interval1d,
944    #[serde(rename = "3d")]
945    Interval3d,
946    #[serde(rename = "1w")]
947    Interval1w,
948    #[serde(rename = "1M")]
949    Interval1M,
950}
951
952impl UiKlinesIntervalEnum {
953    #[must_use]
954    pub fn as_str(&self) -> &'static str {
955        match self {
956            Self::Interval1s => "1s",
957            Self::Interval1m => "1m",
958            Self::Interval3m => "3m",
959            Self::Interval5m => "5m",
960            Self::Interval15m => "15m",
961            Self::Interval30m => "30m",
962            Self::Interval1h => "1h",
963            Self::Interval2h => "2h",
964            Self::Interval4h => "4h",
965            Self::Interval6h => "6h",
966            Self::Interval8h => "8h",
967            Self::Interval12h => "12h",
968            Self::Interval1d => "1d",
969            Self::Interval3d => "3d",
970            Self::Interval1w => "1w",
971            Self::Interval1M => "1M",
972        }
973    }
974}
975
976impl std::str::FromStr for UiKlinesIntervalEnum {
977    type Err = Box<dyn std::error::Error + Send + Sync>;
978
979    fn from_str(s: &str) -> Result<Self, Self::Err> {
980        match s {
981            "1s" => Ok(Self::Interval1s),
982            "1m" => Ok(Self::Interval1m),
983            "3m" => Ok(Self::Interval3m),
984            "5m" => Ok(Self::Interval5m),
985            "15m" => Ok(Self::Interval15m),
986            "30m" => Ok(Self::Interval30m),
987            "1h" => Ok(Self::Interval1h),
988            "2h" => Ok(Self::Interval2h),
989            "4h" => Ok(Self::Interval4h),
990            "6h" => Ok(Self::Interval6h),
991            "8h" => Ok(Self::Interval8h),
992            "12h" => Ok(Self::Interval12h),
993            "1d" => Ok(Self::Interval1d),
994            "3d" => Ok(Self::Interval3d),
995            "1w" => Ok(Self::Interval1w),
996            "1M" => Ok(Self::Interval1M),
997            other => Err(format!("invalid UiKlinesIntervalEnum: {}", other).into()),
998        }
999    }
1000}
1001
1002/// Request parameters for the [`agg_trades`] operation.
1003///
1004/// This struct holds all of the inputs you can pass when calling
1005/// [`agg_trades`](#method.agg_trades).
1006#[derive(Clone, Debug, Builder, Deserialize)]
1007#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1008pub struct AggTradesParams {
1009    ///
1010    /// The `symbol` parameter.
1011    ///
1012    /// This field is **required.
1013    #[builder(setter(into))]
1014    #[serde(rename = "symbol")]
1015    pub symbol: String,
1016    /// ID to get aggregate trades from INCLUSIVE.
1017    ///
1018    /// This field is **optional.
1019    #[builder(setter(into), default)]
1020    #[serde(rename = "fromId", default)]
1021    pub from_id: Option<i64>,
1022    /// Timestamp in ms to get aggregate trades from INCLUSIVE.
1023    ///
1024    /// This field is **optional.
1025    #[builder(setter(into), default)]
1026    #[serde(rename = "startTime", default)]
1027    pub start_time: Option<i64>,
1028    /// Timestamp in ms to get aggregate trades until INCLUSIVE.
1029    ///
1030    /// This field is **optional.
1031    #[builder(setter(into), default)]
1032    #[serde(rename = "endTime", default)]
1033    pub end_time: Option<i64>,
1034    ///
1035    /// The `limit` parameter.
1036    ///
1037    /// This field is **optional.
1038    #[builder(setter(into), default)]
1039    #[serde(rename = "limit", default)]
1040    pub limit: Option<i32>,
1041}
1042
1043impl AggTradesParams {
1044    /// Create a builder for [`agg_trades`].
1045    ///
1046    /// Required parameters:
1047    ///
1048    /// * `symbol` — String
1049    ///
1050    #[must_use]
1051    pub fn builder(symbol: String) -> AggTradesParamsBuilder {
1052        AggTradesParamsBuilder::default().symbol(symbol)
1053    }
1054}
1055/// Request parameters for the [`avg_price`] operation.
1056///
1057/// This struct holds all of the inputs you can pass when calling
1058/// [`avg_price`](#method.avg_price).
1059#[derive(Clone, Debug, Builder, Deserialize)]
1060#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1061pub struct AvgPriceParams {
1062    ///
1063    /// The `symbol` parameter.
1064    ///
1065    /// This field is **required.
1066    #[builder(setter(into))]
1067    #[serde(rename = "symbol")]
1068    pub symbol: String,
1069}
1070
1071impl AvgPriceParams {
1072    /// Create a builder for [`avg_price`].
1073    ///
1074    /// Required parameters:
1075    ///
1076    /// * `symbol` — String
1077    ///
1078    #[must_use]
1079    pub fn builder(symbol: String) -> AvgPriceParamsBuilder {
1080        AvgPriceParamsBuilder::default().symbol(symbol)
1081    }
1082}
1083/// Request parameters for the [`depth`] operation.
1084///
1085/// This struct holds all of the inputs you can pass when calling
1086/// [`depth`](#method.depth).
1087#[derive(Clone, Debug, Builder, Deserialize)]
1088#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1089pub struct DepthParams {
1090    ///
1091    /// The `symbol` parameter.
1092    ///
1093    /// This field is **required.
1094    #[builder(setter(into))]
1095    #[serde(rename = "symbol")]
1096    pub symbol: String,
1097    /// If limit > 5000, only 5000 entries will be returned.
1098    ///
1099    /// This field is **optional.
1100    #[builder(setter(into), default)]
1101    #[serde(rename = "limit", default)]
1102    pub limit: Option<i32>,
1103    /// Filters for symbols that have this `tradingStatus`.
1104    /// A status mismatch returns error `-1220 SYMBOL_DOES_NOT_MATCH_STATUS`.
1105    ///
1106    /// This field is **optional.
1107    #[builder(setter(into), default)]
1108    #[serde(rename = "symbolStatus", default)]
1109    pub symbol_status: Option<DepthSymbolStatusEnum>,
1110}
1111
1112impl DepthParams {
1113    /// Create a builder for [`depth`].
1114    ///
1115    /// Required parameters:
1116    ///
1117    /// * `symbol` — String
1118    ///
1119    #[must_use]
1120    pub fn builder(symbol: String) -> DepthParamsBuilder {
1121        DepthParamsBuilder::default().symbol(symbol)
1122    }
1123}
1124/// Request parameters for the [`get_trades`] operation.
1125///
1126/// This struct holds all of the inputs you can pass when calling
1127/// [`get_trades`](#method.get_trades).
1128#[derive(Clone, Debug, Builder, Deserialize)]
1129#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1130pub struct GetTradesParams {
1131    ///
1132    /// The `symbol` parameter.
1133    ///
1134    /// This field is **required.
1135    #[builder(setter(into))]
1136    #[serde(rename = "symbol")]
1137    pub symbol: String,
1138    ///
1139    /// The `limit` parameter.
1140    ///
1141    /// This field is **optional.
1142    #[builder(setter(into), default)]
1143    #[serde(rename = "limit", default)]
1144    pub limit: Option<i32>,
1145}
1146
1147impl GetTradesParams {
1148    /// Create a builder for [`get_trades`].
1149    ///
1150    /// Required parameters:
1151    ///
1152    /// * `symbol` — String
1153    ///
1154    #[must_use]
1155    pub fn builder(symbol: String) -> GetTradesParamsBuilder {
1156        GetTradesParamsBuilder::default().symbol(symbol)
1157    }
1158}
1159/// Request parameters for the [`historical_block_trades`] operation.
1160///
1161/// This struct holds all of the inputs you can pass when calling
1162/// [`historical_block_trades`](#method.historical_block_trades).
1163#[derive(Clone, Debug, Builder, Deserialize)]
1164#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1165pub struct HistoricalBlockTradesParams {
1166    ///
1167    /// The `symbol` parameter.
1168    ///
1169    /// This field is **required.
1170    #[builder(setter(into))]
1171    #[serde(rename = "symbol")]
1172    pub symbol: String,
1173    /// Block trade ID to fetch from
1174    ///
1175    /// This field is **required.
1176    #[builder(setter(into))]
1177    #[serde(rename = "fromId")]
1178    pub from_id: i64,
1179    /// Default: 500; Maximum: 1000
1180    ///
1181    /// This field is **optional.
1182    #[builder(setter(into), default)]
1183    #[serde(rename = "limit", default)]
1184    pub limit: Option<i64>,
1185}
1186
1187impl HistoricalBlockTradesParams {
1188    /// Create a builder for [`historical_block_trades`].
1189    ///
1190    /// Required parameters:
1191    ///
1192    /// * `symbol` — String
1193    /// * `from_id` — Block trade ID to fetch from
1194    ///
1195    #[must_use]
1196    pub fn builder(symbol: String, from_id: i64) -> HistoricalBlockTradesParamsBuilder {
1197        HistoricalBlockTradesParamsBuilder::default()
1198            .symbol(symbol)
1199            .from_id(from_id)
1200    }
1201}
1202/// Request parameters for the [`historical_trades`] operation.
1203///
1204/// This struct holds all of the inputs you can pass when calling
1205/// [`historical_trades`](#method.historical_trades).
1206#[derive(Clone, Debug, Builder, Deserialize)]
1207#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1208pub struct HistoricalTradesParams {
1209    ///
1210    /// The `symbol` parameter.
1211    ///
1212    /// This field is **required.
1213    #[builder(setter(into))]
1214    #[serde(rename = "symbol")]
1215    pub symbol: String,
1216    ///
1217    /// The `limit` parameter.
1218    ///
1219    /// This field is **optional.
1220    #[builder(setter(into), default)]
1221    #[serde(rename = "limit", default)]
1222    pub limit: Option<i32>,
1223    /// `TradeId` to fetch from. Default gets most recent trades.
1224    ///
1225    /// This field is **optional.
1226    #[builder(setter(into), default)]
1227    #[serde(rename = "fromId", default)]
1228    pub from_id: Option<i64>,
1229}
1230
1231impl HistoricalTradesParams {
1232    /// Create a builder for [`historical_trades`].
1233    ///
1234    /// Required parameters:
1235    ///
1236    /// * `symbol` — String
1237    ///
1238    #[must_use]
1239    pub fn builder(symbol: String) -> HistoricalTradesParamsBuilder {
1240        HistoricalTradesParamsBuilder::default().symbol(symbol)
1241    }
1242}
1243/// Request parameters for the [`klines`] operation.
1244///
1245/// This struct holds all of the inputs you can pass when calling
1246/// [`klines`](#method.klines).
1247#[derive(Clone, Debug, Builder, Deserialize)]
1248#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1249pub struct KlinesParams {
1250    ///
1251    /// The `symbol` parameter.
1252    ///
1253    /// This field is **required.
1254    #[builder(setter(into))]
1255    #[serde(rename = "symbol")]
1256    pub symbol: String,
1257    ///
1258    /// The `interval` parameter.
1259    ///
1260    /// This field is **required.
1261    #[builder(setter(into))]
1262    #[serde(rename = "interval")]
1263    pub interval: KlinesIntervalEnum,
1264    ///
1265    /// The `start_time` parameter.
1266    ///
1267    /// This field is **optional.
1268    #[builder(setter(into), default)]
1269    #[serde(rename = "startTime", default)]
1270    pub start_time: Option<i64>,
1271    ///
1272    /// The `end_time` parameter.
1273    ///
1274    /// This field is **optional.
1275    #[builder(setter(into), default)]
1276    #[serde(rename = "endTime", default)]
1277    pub end_time: Option<i64>,
1278    /// Default: 0 (UTC)
1279    ///
1280    /// This field is **optional.
1281    #[builder(setter(into), default)]
1282    #[serde(rename = "timeZone", default)]
1283    pub time_zone: Option<String>,
1284    ///
1285    /// The `limit` parameter.
1286    ///
1287    /// This field is **optional.
1288    #[builder(setter(into), default)]
1289    #[serde(rename = "limit", default)]
1290    pub limit: Option<i32>,
1291}
1292
1293impl KlinesParams {
1294    /// Create a builder for [`klines`].
1295    ///
1296    /// Required parameters:
1297    ///
1298    /// * `symbol` — String
1299    /// * `interval` — String
1300    ///
1301    #[must_use]
1302    pub fn builder(symbol: String, interval: KlinesIntervalEnum) -> KlinesParamsBuilder {
1303        KlinesParamsBuilder::default()
1304            .symbol(symbol)
1305            .interval(interval)
1306    }
1307}
1308/// Request parameters for the [`reference_price`] operation.
1309///
1310/// This struct holds all of the inputs you can pass when calling
1311/// [`reference_price`](#method.reference_price).
1312#[derive(Clone, Debug, Builder, Deserialize)]
1313#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1314pub struct ReferencePriceParams {
1315    ///
1316    /// The `symbol` parameter.
1317    ///
1318    /// This field is **required.
1319    #[builder(setter(into))]
1320    #[serde(rename = "symbol")]
1321    pub symbol: String,
1322}
1323
1324impl ReferencePriceParams {
1325    /// Create a builder for [`reference_price`].
1326    ///
1327    /// Required parameters:
1328    ///
1329    /// * `symbol` — String
1330    ///
1331    #[must_use]
1332    pub fn builder(symbol: String) -> ReferencePriceParamsBuilder {
1333        ReferencePriceParamsBuilder::default().symbol(symbol)
1334    }
1335}
1336/// Request parameters for the [`reference_price_calculation`] operation.
1337///
1338/// This struct holds all of the inputs you can pass when calling
1339/// [`reference_price_calculation`](#method.reference_price_calculation).
1340#[derive(Clone, Debug, Builder, Deserialize)]
1341#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1342pub struct ReferencePriceCalculationParams {
1343    ///
1344    /// The `symbol` parameter.
1345    ///
1346    /// This field is **required.
1347    #[builder(setter(into))]
1348    #[serde(rename = "symbol")]
1349    pub symbol: String,
1350    /// Supported values: `TRADING`, `HALT`, `BREAK`
1351    ///
1352    /// This field is **optional.
1353    #[builder(setter(into), default)]
1354    #[serde(rename = "symbolStatus", default)]
1355    pub symbol_status: Option<ReferencePriceCalculationSymbolStatusEnum>,
1356}
1357
1358impl ReferencePriceCalculationParams {
1359    /// Create a builder for [`reference_price_calculation`].
1360    ///
1361    /// Required parameters:
1362    ///
1363    /// * `symbol` — String
1364    ///
1365    #[must_use]
1366    pub fn builder(symbol: String) -> ReferencePriceCalculationParamsBuilder {
1367        ReferencePriceCalculationParamsBuilder::default().symbol(symbol)
1368    }
1369}
1370/// Request parameters for the [`ticker`] operation.
1371///
1372/// This struct holds all of the inputs you can pass when calling
1373/// [`ticker`](#method.ticker).
1374#[derive(Clone, Debug, Builder, Deserialize, Default)]
1375#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1376pub struct TickerParams {
1377    /// Either `symbol` or `symbols` must be provided
1378    ///
1379    /// This field is **optional.
1380    #[builder(setter(into), default)]
1381    #[serde(rename = "symbol", default)]
1382    pub symbol: Option<String>,
1383    /// Either `symbol` or `symbols` must be provided
1384    ///
1385    /// Examples of accepted format for the `symbols` parameter: ["BTCUSDT","BNBUSDT"] or %5B%22BTCUSDT%22,%22BNBUSDT%22%5D
1386    ///
1387    /// The maximum number of symbols allowed in a request is 100.
1388    ///
1389    /// This field is **optional.
1390    #[builder(setter(into), default)]
1391    #[serde(rename = "symbols", default)]
1392    pub symbols: Option<Vec<String>>,
1393    /// Units cannot be combined (e.g. `1d2h` is not allowed).
1394    ///
1395    /// This field is **optional.
1396    #[builder(setter(into), default)]
1397    #[serde(rename = "windowSize", default)]
1398    pub window_size: Option<TickerWindowSizeEnum>,
1399    ///
1400    /// The `r#type` parameter.
1401    ///
1402    /// This field is **optional.
1403    #[builder(setter(into), default)]
1404    #[serde(rename = "type", default)]
1405    pub r#type: Option<TickerTypeEnum>,
1406    ///
1407    /// The `symbol_status` parameter.
1408    ///
1409    /// This field is **optional.
1410    #[builder(setter(into), default)]
1411    #[serde(rename = "symbolStatus", default)]
1412    pub symbol_status: Option<TickerSymbolStatusEnum>,
1413}
1414
1415impl TickerParams {
1416    /// Create a builder for [`ticker`].
1417    ///
1418    #[must_use]
1419    pub fn builder() -> TickerParamsBuilder {
1420        TickerParamsBuilder::default()
1421    }
1422}
1423/// Request parameters for the [`ticker24hr`] operation.
1424///
1425/// This struct holds all of the inputs you can pass when calling
1426/// [`ticker24hr`](#method.ticker24hr).
1427#[derive(Clone, Debug, Builder, Deserialize, Default)]
1428#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1429pub struct Ticker24hrParams {
1430    /// Either `symbol` or `symbols` must be provided
1431    ///
1432    /// This field is **optional.
1433    #[builder(setter(into), default)]
1434    #[serde(rename = "symbol", default)]
1435    pub symbol: Option<String>,
1436    /// Either `symbol` or `symbols` must be provided
1437    ///
1438    /// Examples of accepted format for the `symbols` parameter: ["BTCUSDT","BNBUSDT"] or %5B%22BTCUSDT%22,%22BNBUSDT%22%5D
1439    ///
1440    /// The maximum number of symbols allowed in a request is 100.
1441    ///
1442    /// This field is **optional.
1443    #[builder(setter(into), default)]
1444    #[serde(rename = "symbols", default)]
1445    pub symbols: Option<Vec<String>>,
1446    ///
1447    /// The `r#type` parameter.
1448    ///
1449    /// This field is **optional.
1450    #[builder(setter(into), default)]
1451    #[serde(rename = "type", default)]
1452    pub r#type: Option<Ticker24hrTypeEnum>,
1453    ///
1454    /// The `symbol_status` parameter.
1455    ///
1456    /// This field is **optional.
1457    #[builder(setter(into), default)]
1458    #[serde(rename = "symbolStatus", default)]
1459    pub symbol_status: Option<Ticker24hrSymbolStatusEnum>,
1460}
1461
1462impl Ticker24hrParams {
1463    /// Create a builder for [`ticker24hr`].
1464    ///
1465    #[must_use]
1466    pub fn builder() -> Ticker24hrParamsBuilder {
1467        Ticker24hrParamsBuilder::default()
1468    }
1469}
1470/// Request parameters for the [`ticker_book_ticker`] operation.
1471///
1472/// This struct holds all of the inputs you can pass when calling
1473/// [`ticker_book_ticker`](#method.ticker_book_ticker).
1474#[derive(Clone, Debug, Builder, Deserialize, Default)]
1475#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1476pub struct TickerBookTickerParams {
1477    /// Parameter symbol and symbols cannot be used in combination.
1478    /// If neither parameter is sent, `bookTickers` for all symbols will be returned in an array.
1479    ///
1480    /// This field is **optional.
1481    #[builder(setter(into), default)]
1482    #[serde(rename = "symbol", default)]
1483    pub symbol: Option<String>,
1484    /// Parameter symbol and symbols cannot be used in combination.
1485    /// If neither parameter is sent, `bookTickers` for all symbols will be returned in an array.
1486    /// Examples of accepted format for the symbols parameter: ["BTCUSDT","BNBUSDT"] or %5B%22BTCUSDT%22,%22BNBUSDT%22%5D
1487    ///
1488    /// This field is **optional.
1489    #[builder(setter(into), default)]
1490    #[serde(rename = "symbols", default)]
1491    pub symbols: Option<Vec<String>>,
1492    /// Filters for symbols that have this `tradingStatus`.
1493    /// For a single symbol, a status mismatch returns error `-1220 SYMBOL_DOES_NOT_MATCH_STATUS`.
1494    /// For multiple or all symbols, non-matching ones are simply excluded from the response.
1495    ///
1496    /// This field is **optional.
1497    #[builder(setter(into), default)]
1498    #[serde(rename = "symbolStatus", default)]
1499    pub symbol_status: Option<TickerBookTickerSymbolStatusEnum>,
1500}
1501
1502impl TickerBookTickerParams {
1503    /// Create a builder for [`ticker_book_ticker`].
1504    ///
1505    #[must_use]
1506    pub fn builder() -> TickerBookTickerParamsBuilder {
1507        TickerBookTickerParamsBuilder::default()
1508    }
1509}
1510/// Request parameters for the [`ticker_price`] operation.
1511///
1512/// This struct holds all of the inputs you can pass when calling
1513/// [`ticker_price`](#method.ticker_price).
1514#[derive(Clone, Debug, Builder, Deserialize, Default)]
1515#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1516pub struct TickerPriceParams {
1517    /// Parameter symbol and symbols cannot be used in combination.
1518    /// If neither parameter is sent, prices for all symbols will be returned in an array.
1519    ///
1520    /// This field is **optional.
1521    #[builder(setter(into), default)]
1522    #[serde(rename = "symbol", default)]
1523    pub symbol: Option<String>,
1524    /// Parameter symbol and symbols cannot be used in combination.
1525    /// If neither parameter is sent, prices for all symbols will be returned in an array.
1526    /// Examples of accepted format for the symbols parameter: ["BTCUSDT","BNBUSDT"] or %5B%22BTCUSDT%22,%22BNBUSDT%22%5D
1527    ///
1528    /// This field is **optional.
1529    #[builder(setter(into), default)]
1530    #[serde(rename = "symbols", default)]
1531    pub symbols: Option<Vec<String>>,
1532    /// Filters for symbols that have this `tradingStatus`.
1533    /// For a single symbol, a status mismatch returns error `-1220 SYMBOL_DOES_NOT_MATCH_STATUS`.
1534    /// For multiple or all symbols, non-matching ones are simply excluded from the response.
1535    ///
1536    /// This field is **optional.
1537    #[builder(setter(into), default)]
1538    #[serde(rename = "symbolStatus", default)]
1539    pub symbol_status: Option<TickerPriceSymbolStatusEnum>,
1540}
1541
1542impl TickerPriceParams {
1543    /// Create a builder for [`ticker_price`].
1544    ///
1545    #[must_use]
1546    pub fn builder() -> TickerPriceParamsBuilder {
1547        TickerPriceParamsBuilder::default()
1548    }
1549}
1550/// Request parameters for the [`ticker_trading_day`] operation.
1551///
1552/// This struct holds all of the inputs you can pass when calling
1553/// [`ticker_trading_day`](#method.ticker_trading_day).
1554#[derive(Clone, Debug, Builder, Deserialize, Default)]
1555#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1556pub struct TickerTradingDayParams {
1557    /// Either `symbol` or `symbols` must be provided.
1558    ///
1559    /// This field is **optional.
1560    #[builder(setter(into), default)]
1561    #[serde(rename = "symbol", default)]
1562    pub symbol: Option<String>,
1563    /// Either `symbol` or `symbols` must be provided.
1564    /// Examples of accepted format for the `symbols` parameter: ["BTCUSDT","BNBUSDT"] or %5B%22BTCUSDT%22,%22BNBUSDT%22%5D.
1565    /// The maximum number of `symbols` allowed in a request is 100.
1566    ///
1567    /// This field is **optional.
1568    #[builder(setter(into), default)]
1569    #[serde(rename = "symbols", default)]
1570    pub symbols: Option<Vec<String>>,
1571    /// Default: 0 (UTC)
1572    ///
1573    /// This field is **optional.
1574    #[builder(setter(into), default)]
1575    #[serde(rename = "timeZone", default)]
1576    pub time_zone: Option<String>,
1577    ///
1578    /// The `r#type` parameter.
1579    ///
1580    /// This field is **optional.
1581    #[builder(setter(into), default)]
1582    #[serde(rename = "type", default)]
1583    pub r#type: Option<TickerTradingDayTypeEnum>,
1584    /// Filters for symbols that have this `tradingStatus`.
1585    /// For a single symbol, a status mismatch returns error `-1220 SYMBOL_DOES_NOT_MATCH_STATUS`.
1586    /// For multiple symbols, non-matching ones are simply excluded from the response.
1587    ///
1588    /// This field is **optional.
1589    #[builder(setter(into), default)]
1590    #[serde(rename = "symbolStatus", default)]
1591    pub symbol_status: Option<TickerTradingDaySymbolStatusEnum>,
1592}
1593
1594impl TickerTradingDayParams {
1595    /// Create a builder for [`ticker_trading_day`].
1596    ///
1597    #[must_use]
1598    pub fn builder() -> TickerTradingDayParamsBuilder {
1599        TickerTradingDayParamsBuilder::default()
1600    }
1601}
1602/// Request parameters for the [`ui_klines`] operation.
1603///
1604/// This struct holds all of the inputs you can pass when calling
1605/// [`ui_klines`](#method.ui_klines).
1606#[derive(Clone, Debug, Builder, Deserialize)]
1607#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1608pub struct UiKlinesParams {
1609    ///
1610    /// The `symbol` parameter.
1611    ///
1612    /// This field is **required.
1613    #[builder(setter(into))]
1614    #[serde(rename = "symbol")]
1615    pub symbol: String,
1616    ///
1617    /// The `interval` parameter.
1618    ///
1619    /// This field is **required.
1620    #[builder(setter(into))]
1621    #[serde(rename = "interval")]
1622    pub interval: UiKlinesIntervalEnum,
1623    ///
1624    /// The `start_time` parameter.
1625    ///
1626    /// This field is **optional.
1627    #[builder(setter(into), default)]
1628    #[serde(rename = "startTime", default)]
1629    pub start_time: Option<i64>,
1630    ///
1631    /// The `end_time` parameter.
1632    ///
1633    /// This field is **optional.
1634    #[builder(setter(into), default)]
1635    #[serde(rename = "endTime", default)]
1636    pub end_time: Option<i64>,
1637    /// Default: 0 (UTC)
1638    ///
1639    /// This field is **optional.
1640    #[builder(setter(into), default)]
1641    #[serde(rename = "timeZone", default)]
1642    pub time_zone: Option<String>,
1643    ///
1644    /// The `limit` parameter.
1645    ///
1646    /// This field is **optional.
1647    #[builder(setter(into), default)]
1648    #[serde(rename = "limit", default)]
1649    pub limit: Option<i32>,
1650}
1651
1652impl UiKlinesParams {
1653    /// Create a builder for [`ui_klines`].
1654    ///
1655    /// Required parameters:
1656    ///
1657    /// * `symbol` — String
1658    /// * `interval` — String
1659    ///
1660    #[must_use]
1661    pub fn builder(symbol: String, interval: UiKlinesIntervalEnum) -> UiKlinesParamsBuilder {
1662        UiKlinesParamsBuilder::default()
1663            .symbol(symbol)
1664            .interval(interval)
1665    }
1666}
1667
1668#[async_trait]
1669impl MarketApi for MarketApiClient {
1670    async fn agg_trades(
1671        &self,
1672        params: AggTradesParams,
1673    ) -> anyhow::Result<RestApiResponse<Vec<models::AggTradesResponseInner>>> {
1674        let AggTradesParams {
1675            symbol,
1676            from_id,
1677            start_time,
1678            end_time,
1679            limit,
1680        } = params;
1681
1682        let mut query_params = BTreeMap::new();
1683        let body_params = BTreeMap::new();
1684
1685        query_params.insert("symbol".to_string(), json!(symbol));
1686
1687        if let Some(rw) = from_id {
1688            query_params.insert("fromId".to_string(), json!(rw));
1689        }
1690
1691        if let Some(rw) = start_time {
1692            query_params.insert("startTime".to_string(), json!(rw));
1693        }
1694
1695        if let Some(rw) = end_time {
1696            query_params.insert("endTime".to_string(), json!(rw));
1697        }
1698
1699        if let Some(rw) = limit {
1700            query_params.insert("limit".to_string(), json!(rw));
1701        }
1702
1703        send_request::<Vec<models::AggTradesResponseInner>>(
1704            &self.configuration,
1705            "/api/v3/aggTrades",
1706            reqwest::Method::GET,
1707            query_params,
1708            body_params,
1709            if HAS_TIME_UNIT {
1710                self.configuration.time_unit
1711            } else {
1712                None
1713            },
1714            false,
1715        )
1716        .await
1717    }
1718
1719    async fn avg_price(
1720        &self,
1721        params: AvgPriceParams,
1722    ) -> anyhow::Result<RestApiResponse<models::AvgPriceResponse>> {
1723        let AvgPriceParams { symbol } = params;
1724
1725        let mut query_params = BTreeMap::new();
1726        let body_params = BTreeMap::new();
1727
1728        query_params.insert("symbol".to_string(), json!(symbol));
1729
1730        send_request::<models::AvgPriceResponse>(
1731            &self.configuration,
1732            "/api/v3/avgPrice",
1733            reqwest::Method::GET,
1734            query_params,
1735            body_params,
1736            if HAS_TIME_UNIT {
1737                self.configuration.time_unit
1738            } else {
1739                None
1740            },
1741            false,
1742        )
1743        .await
1744    }
1745
1746    async fn depth(
1747        &self,
1748        params: DepthParams,
1749    ) -> anyhow::Result<RestApiResponse<models::DepthResponse>> {
1750        let DepthParams {
1751            symbol,
1752            limit,
1753            symbol_status,
1754        } = params;
1755
1756        let mut query_params = BTreeMap::new();
1757        let body_params = BTreeMap::new();
1758
1759        query_params.insert("symbol".to_string(), json!(symbol));
1760
1761        if let Some(rw) = limit {
1762            query_params.insert("limit".to_string(), json!(rw));
1763        }
1764
1765        if let Some(rw) = symbol_status {
1766            query_params.insert("symbolStatus".to_string(), json!(rw));
1767        }
1768
1769        send_request::<models::DepthResponse>(
1770            &self.configuration,
1771            "/api/v3/depth",
1772            reqwest::Method::GET,
1773            query_params,
1774            body_params,
1775            if HAS_TIME_UNIT {
1776                self.configuration.time_unit
1777            } else {
1778                None
1779            },
1780            false,
1781        )
1782        .await
1783    }
1784
1785    async fn get_trades(
1786        &self,
1787        params: GetTradesParams,
1788    ) -> anyhow::Result<RestApiResponse<Vec<models::GetTradesResponseInner>>> {
1789        let GetTradesParams { symbol, limit } = params;
1790
1791        let mut query_params = BTreeMap::new();
1792        let body_params = BTreeMap::new();
1793
1794        query_params.insert("symbol".to_string(), json!(symbol));
1795
1796        if let Some(rw) = limit {
1797            query_params.insert("limit".to_string(), json!(rw));
1798        }
1799
1800        send_request::<Vec<models::GetTradesResponseInner>>(
1801            &self.configuration,
1802            "/api/v3/trades",
1803            reqwest::Method::GET,
1804            query_params,
1805            body_params,
1806            if HAS_TIME_UNIT {
1807                self.configuration.time_unit
1808            } else {
1809                None
1810            },
1811            false,
1812        )
1813        .await
1814    }
1815
1816    async fn historical_block_trades(
1817        &self,
1818        params: HistoricalBlockTradesParams,
1819    ) -> anyhow::Result<RestApiResponse<Vec<models::HistoricalBlockTradesResponseInner>>> {
1820        let HistoricalBlockTradesParams {
1821            symbol,
1822            from_id,
1823            limit,
1824        } = params;
1825
1826        let mut query_params = BTreeMap::new();
1827        let body_params = BTreeMap::new();
1828
1829        query_params.insert("symbol".to_string(), json!(symbol));
1830
1831        query_params.insert("fromId".to_string(), json!(from_id));
1832
1833        if let Some(rw) = limit {
1834            query_params.insert("limit".to_string(), json!(rw));
1835        }
1836
1837        send_request::<Vec<models::HistoricalBlockTradesResponseInner>>(
1838            &self.configuration,
1839            "/api/v3/historicalBlockTrades",
1840            reqwest::Method::GET,
1841            query_params,
1842            body_params,
1843            if HAS_TIME_UNIT {
1844                self.configuration.time_unit
1845            } else {
1846                None
1847            },
1848            false,
1849        )
1850        .await
1851    }
1852
1853    async fn historical_trades(
1854        &self,
1855        params: HistoricalTradesParams,
1856    ) -> anyhow::Result<RestApiResponse<Vec<models::GetTradesResponseInner>>> {
1857        let HistoricalTradesParams {
1858            symbol,
1859            limit,
1860            from_id,
1861        } = params;
1862
1863        let mut query_params = BTreeMap::new();
1864        let body_params = BTreeMap::new();
1865
1866        query_params.insert("symbol".to_string(), json!(symbol));
1867
1868        if let Some(rw) = limit {
1869            query_params.insert("limit".to_string(), json!(rw));
1870        }
1871
1872        if let Some(rw) = from_id {
1873            query_params.insert("fromId".to_string(), json!(rw));
1874        }
1875
1876        send_request::<Vec<models::GetTradesResponseInner>>(
1877            &self.configuration,
1878            "/api/v3/historicalTrades",
1879            reqwest::Method::GET,
1880            query_params,
1881            body_params,
1882            if HAS_TIME_UNIT {
1883                self.configuration.time_unit
1884            } else {
1885                None
1886            },
1887            false,
1888        )
1889        .await
1890    }
1891
1892    async fn klines(
1893        &self,
1894        params: KlinesParams,
1895    ) -> anyhow::Result<RestApiResponse<Vec<Vec<models::KlinesItemInner>>>> {
1896        let KlinesParams {
1897            symbol,
1898            interval,
1899            start_time,
1900            end_time,
1901            time_zone,
1902            limit,
1903        } = params;
1904
1905        let mut query_params = BTreeMap::new();
1906        let body_params = BTreeMap::new();
1907
1908        query_params.insert("symbol".to_string(), json!(symbol));
1909
1910        query_params.insert("interval".to_string(), json!(interval));
1911
1912        if let Some(rw) = start_time {
1913            query_params.insert("startTime".to_string(), json!(rw));
1914        }
1915
1916        if let Some(rw) = end_time {
1917            query_params.insert("endTime".to_string(), json!(rw));
1918        }
1919
1920        if let Some(rw) = time_zone {
1921            query_params.insert("timeZone".to_string(), json!(rw));
1922        }
1923
1924        if let Some(rw) = limit {
1925            query_params.insert("limit".to_string(), json!(rw));
1926        }
1927
1928        send_request::<Vec<Vec<models::KlinesItemInner>>>(
1929            &self.configuration,
1930            "/api/v3/klines",
1931            reqwest::Method::GET,
1932            query_params,
1933            body_params,
1934            if HAS_TIME_UNIT {
1935                self.configuration.time_unit
1936            } else {
1937                None
1938            },
1939            false,
1940        )
1941        .await
1942    }
1943
1944    async fn reference_price(
1945        &self,
1946        params: ReferencePriceParams,
1947    ) -> anyhow::Result<RestApiResponse<models::ReferencePriceResponse>> {
1948        let ReferencePriceParams { symbol } = params;
1949
1950        let mut query_params = BTreeMap::new();
1951        let body_params = BTreeMap::new();
1952
1953        query_params.insert("symbol".to_string(), json!(symbol));
1954
1955        send_request::<models::ReferencePriceResponse>(
1956            &self.configuration,
1957            "/api/v3/referencePrice",
1958            reqwest::Method::GET,
1959            query_params,
1960            body_params,
1961            if HAS_TIME_UNIT {
1962                self.configuration.time_unit
1963            } else {
1964                None
1965            },
1966            false,
1967        )
1968        .await
1969    }
1970
1971    async fn reference_price_calculation(
1972        &self,
1973        params: ReferencePriceCalculationParams,
1974    ) -> anyhow::Result<RestApiResponse<models::ReferencePriceCalculationResponse>> {
1975        let ReferencePriceCalculationParams {
1976            symbol,
1977            symbol_status,
1978        } = params;
1979
1980        let mut query_params = BTreeMap::new();
1981        let body_params = BTreeMap::new();
1982
1983        query_params.insert("symbol".to_string(), json!(symbol));
1984
1985        if let Some(rw) = symbol_status {
1986            query_params.insert("symbolStatus".to_string(), json!(rw));
1987        }
1988
1989        send_request::<models::ReferencePriceCalculationResponse>(
1990            &self.configuration,
1991            "/api/v3/referencePrice/calculation",
1992            reqwest::Method::GET,
1993            query_params,
1994            body_params,
1995            if HAS_TIME_UNIT {
1996                self.configuration.time_unit
1997            } else {
1998                None
1999            },
2000            false,
2001        )
2002        .await
2003    }
2004
2005    async fn ticker(
2006        &self,
2007        params: TickerParams,
2008    ) -> anyhow::Result<RestApiResponse<models::TickerResponse>> {
2009        let TickerParams {
2010            symbol,
2011            symbols,
2012            window_size,
2013            r#type,
2014            symbol_status,
2015        } = params;
2016
2017        let mut query_params = BTreeMap::new();
2018        let body_params = BTreeMap::new();
2019
2020        if let Some(rw) = symbol {
2021            query_params.insert("symbol".to_string(), json!(rw));
2022        }
2023
2024        if let Some(rw) = symbols {
2025            query_params.insert("symbols".to_string(), json!(rw));
2026        }
2027
2028        if let Some(rw) = window_size {
2029            query_params.insert("windowSize".to_string(), json!(rw));
2030        }
2031
2032        if let Some(rw) = r#type {
2033            query_params.insert("type".to_string(), json!(rw));
2034        }
2035
2036        if let Some(rw) = symbol_status {
2037            query_params.insert("symbolStatus".to_string(), json!(rw));
2038        }
2039
2040        send_request::<models::TickerResponse>(
2041            &self.configuration,
2042            "/api/v3/ticker",
2043            reqwest::Method::GET,
2044            query_params,
2045            body_params,
2046            if HAS_TIME_UNIT {
2047                self.configuration.time_unit
2048            } else {
2049                None
2050            },
2051            false,
2052        )
2053        .await
2054    }
2055
2056    async fn ticker24hr(
2057        &self,
2058        params: Ticker24hrParams,
2059    ) -> anyhow::Result<RestApiResponse<models::Ticker24hrResponse>> {
2060        let Ticker24hrParams {
2061            symbol,
2062            symbols,
2063            r#type,
2064            symbol_status,
2065        } = params;
2066
2067        let mut query_params = BTreeMap::new();
2068        let body_params = BTreeMap::new();
2069
2070        if let Some(rw) = symbol {
2071            query_params.insert("symbol".to_string(), json!(rw));
2072        }
2073
2074        if let Some(rw) = symbols {
2075            query_params.insert("symbols".to_string(), json!(rw));
2076        }
2077
2078        if let Some(rw) = r#type {
2079            query_params.insert("type".to_string(), json!(rw));
2080        }
2081
2082        if let Some(rw) = symbol_status {
2083            query_params.insert("symbolStatus".to_string(), json!(rw));
2084        }
2085
2086        send_request::<models::Ticker24hrResponse>(
2087            &self.configuration,
2088            "/api/v3/ticker/24hr",
2089            reqwest::Method::GET,
2090            query_params,
2091            body_params,
2092            if HAS_TIME_UNIT {
2093                self.configuration.time_unit
2094            } else {
2095                None
2096            },
2097            false,
2098        )
2099        .await
2100    }
2101
2102    async fn ticker_book_ticker(
2103        &self,
2104        params: TickerBookTickerParams,
2105    ) -> anyhow::Result<RestApiResponse<models::TickerBookTickerResponse>> {
2106        let TickerBookTickerParams {
2107            symbol,
2108            symbols,
2109            symbol_status,
2110        } = params;
2111
2112        let mut query_params = BTreeMap::new();
2113        let body_params = BTreeMap::new();
2114
2115        if let Some(rw) = symbol {
2116            query_params.insert("symbol".to_string(), json!(rw));
2117        }
2118
2119        if let Some(rw) = symbols {
2120            query_params.insert("symbols".to_string(), json!(rw));
2121        }
2122
2123        if let Some(rw) = symbol_status {
2124            query_params.insert("symbolStatus".to_string(), json!(rw));
2125        }
2126
2127        send_request::<models::TickerBookTickerResponse>(
2128            &self.configuration,
2129            "/api/v3/ticker/bookTicker",
2130            reqwest::Method::GET,
2131            query_params,
2132            body_params,
2133            if HAS_TIME_UNIT {
2134                self.configuration.time_unit
2135            } else {
2136                None
2137            },
2138            false,
2139        )
2140        .await
2141    }
2142
2143    async fn ticker_price(
2144        &self,
2145        params: TickerPriceParams,
2146    ) -> anyhow::Result<RestApiResponse<models::TickerPriceResponse>> {
2147        let TickerPriceParams {
2148            symbol,
2149            symbols,
2150            symbol_status,
2151        } = params;
2152
2153        let mut query_params = BTreeMap::new();
2154        let body_params = BTreeMap::new();
2155
2156        if let Some(rw) = symbol {
2157            query_params.insert("symbol".to_string(), json!(rw));
2158        }
2159
2160        if let Some(rw) = symbols {
2161            query_params.insert("symbols".to_string(), json!(rw));
2162        }
2163
2164        if let Some(rw) = symbol_status {
2165            query_params.insert("symbolStatus".to_string(), json!(rw));
2166        }
2167
2168        send_request::<models::TickerPriceResponse>(
2169            &self.configuration,
2170            "/api/v3/ticker/price",
2171            reqwest::Method::GET,
2172            query_params,
2173            body_params,
2174            if HAS_TIME_UNIT {
2175                self.configuration.time_unit
2176            } else {
2177                None
2178            },
2179            false,
2180        )
2181        .await
2182    }
2183
2184    async fn ticker_trading_day(
2185        &self,
2186        params: TickerTradingDayParams,
2187    ) -> anyhow::Result<RestApiResponse<models::TickerTradingDayResponse>> {
2188        let TickerTradingDayParams {
2189            symbol,
2190            symbols,
2191            time_zone,
2192            r#type,
2193            symbol_status,
2194        } = params;
2195
2196        let mut query_params = BTreeMap::new();
2197        let body_params = BTreeMap::new();
2198
2199        if let Some(rw) = symbol {
2200            query_params.insert("symbol".to_string(), json!(rw));
2201        }
2202
2203        if let Some(rw) = symbols {
2204            query_params.insert("symbols".to_string(), json!(rw));
2205        }
2206
2207        if let Some(rw) = time_zone {
2208            query_params.insert("timeZone".to_string(), json!(rw));
2209        }
2210
2211        if let Some(rw) = r#type {
2212            query_params.insert("type".to_string(), json!(rw));
2213        }
2214
2215        if let Some(rw) = symbol_status {
2216            query_params.insert("symbolStatus".to_string(), json!(rw));
2217        }
2218
2219        send_request::<models::TickerTradingDayResponse>(
2220            &self.configuration,
2221            "/api/v3/ticker/tradingDay",
2222            reqwest::Method::GET,
2223            query_params,
2224            body_params,
2225            if HAS_TIME_UNIT {
2226                self.configuration.time_unit
2227            } else {
2228                None
2229            },
2230            false,
2231        )
2232        .await
2233    }
2234
2235    async fn ui_klines(
2236        &self,
2237        params: UiKlinesParams,
2238    ) -> anyhow::Result<RestApiResponse<Vec<Vec<models::KlinesItemInner>>>> {
2239        let UiKlinesParams {
2240            symbol,
2241            interval,
2242            start_time,
2243            end_time,
2244            time_zone,
2245            limit,
2246        } = params;
2247
2248        let mut query_params = BTreeMap::new();
2249        let body_params = BTreeMap::new();
2250
2251        query_params.insert("symbol".to_string(), json!(symbol));
2252
2253        query_params.insert("interval".to_string(), json!(interval));
2254
2255        if let Some(rw) = start_time {
2256            query_params.insert("startTime".to_string(), json!(rw));
2257        }
2258
2259        if let Some(rw) = end_time {
2260            query_params.insert("endTime".to_string(), json!(rw));
2261        }
2262
2263        if let Some(rw) = time_zone {
2264            query_params.insert("timeZone".to_string(), json!(rw));
2265        }
2266
2267        if let Some(rw) = limit {
2268            query_params.insert("limit".to_string(), json!(rw));
2269        }
2270
2271        send_request::<Vec<Vec<models::KlinesItemInner>>>(
2272            &self.configuration,
2273            "/api/v3/uiKlines",
2274            reqwest::Method::GET,
2275            query_params,
2276            body_params,
2277            if HAS_TIME_UNIT {
2278                self.configuration.time_unit
2279            } else {
2280                None
2281            },
2282            false,
2283        )
2284        .await
2285    }
2286}
2287
2288#[cfg(all(test, feature = "spot"))]
2289mod tests {
2290    use super::*;
2291    use crate::TOKIO_SHARED_RT;
2292    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
2293    use async_trait::async_trait;
2294    use std::collections::HashMap;
2295
2296    struct DummyRestApiResponse<T> {
2297        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
2298        status: u16,
2299        headers: HashMap<String, String>,
2300        rate_limits: Option<Vec<RestApiRateLimit>>,
2301    }
2302
2303    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
2304        fn from(dummy: DummyRestApiResponse<T>) -> Self {
2305            Self {
2306                data_fn: dummy.inner,
2307                status: dummy.status,
2308                headers: dummy.headers,
2309                rate_limits: dummy.rate_limits,
2310            }
2311        }
2312    }
2313
2314    struct MockMarketApiClient {
2315        force_error: bool,
2316    }
2317
2318    #[async_trait]
2319    impl MarketApi for MockMarketApiClient {
2320        async fn agg_trades(
2321            &self,
2322            _params: AggTradesParams,
2323        ) -> anyhow::Result<RestApiResponse<Vec<models::AggTradesResponseInner>>> {
2324            if self.force_error {
2325                return Err(ConnectorError::ConnectorClientError {
2326                    msg: "ResponseError".to_string(),
2327                    code: None,
2328                }
2329                .into());
2330            }
2331
2332            let resp_json: Value = serde_json::from_str(r#"[{"a":26129,"p":"0.01633102","q":"4.70443515","f":27781,"l":27781,"T":1498793709153,"m":true,"M":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2333            let dummy_response: Vec<models::AggTradesResponseInner> =
2334                serde_json::from_value(resp_json.clone())
2335                    .expect("should parse into Vec<models::AggTradesResponseInner>");
2336
2337            let dummy = DummyRestApiResponse {
2338                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2339                status: 200,
2340                headers: HashMap::new(),
2341                rate_limits: None,
2342            };
2343
2344            Ok(dummy.into())
2345        }
2346
2347        async fn avg_price(
2348            &self,
2349            _params: AvgPriceParams,
2350        ) -> anyhow::Result<RestApiResponse<models::AvgPriceResponse>> {
2351            if self.force_error {
2352                return Err(ConnectorError::ConnectorClientError {
2353                    msg: "ResponseError".to_string(),
2354                    code: None,
2355                }
2356                .into());
2357            }
2358
2359            let resp_json: Value = serde_json::from_str(
2360                r#"{"mins":5,"price":"9.35751834","closeTime":1694061154503}"#,
2361            )
2362            .unwrap_or_else(|_| serde_json::json!({}));
2363            let dummy_response: models::AvgPriceResponse =
2364                serde_json::from_value(resp_json.clone())
2365                    .expect("should parse into models::AvgPriceResponse");
2366
2367            let dummy = DummyRestApiResponse {
2368                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2369                status: 200,
2370                headers: HashMap::new(),
2371                rate_limits: None,
2372            };
2373
2374            Ok(dummy.into())
2375        }
2376
2377        async fn depth(
2378            &self,
2379            _params: DepthParams,
2380        ) -> anyhow::Result<RestApiResponse<models::DepthResponse>> {
2381            if self.force_error {
2382                return Err(ConnectorError::ConnectorClientError {
2383                    msg: "ResponseError".to_string(),
2384                    code: None,
2385                }
2386                .into());
2387            }
2388
2389            let resp_json: Value = serde_json::from_str(r#"{"lastUpdateId":1027024,"bids":[["4.00000000","431.00000000"]],"asks":[["4.00000200","12.00000000"]]}"#).unwrap_or_else(|_| serde_json::json!({}));
2390            let dummy_response: models::DepthResponse = serde_json::from_value(resp_json.clone())
2391                .expect("should parse into models::DepthResponse");
2392
2393            let dummy = DummyRestApiResponse {
2394                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2395                status: 200,
2396                headers: HashMap::new(),
2397                rate_limits: None,
2398            };
2399
2400            Ok(dummy.into())
2401        }
2402
2403        async fn get_trades(
2404            &self,
2405            _params: GetTradesParams,
2406        ) -> anyhow::Result<RestApiResponse<Vec<models::GetTradesResponseInner>>> {
2407            if self.force_error {
2408                return Err(ConnectorError::ConnectorClientError {
2409                    msg: "ResponseError".to_string(),
2410                    code: None,
2411                }
2412                .into());
2413            }
2414
2415            let resp_json: Value = serde_json::from_str(r#"[{"id":28457,"price":"4.00000100","qty":"12.00000000","quoteQty":"48.000012","time":1499865549590,"isBuyerMaker":true,"isBestMatch":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2416            let dummy_response: Vec<models::GetTradesResponseInner> =
2417                serde_json::from_value(resp_json.clone())
2418                    .expect("should parse into Vec<models::GetTradesResponseInner>");
2419
2420            let dummy = DummyRestApiResponse {
2421                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2422                status: 200,
2423                headers: HashMap::new(),
2424                rate_limits: None,
2425            };
2426
2427            Ok(dummy.into())
2428        }
2429
2430        async fn historical_block_trades(
2431            &self,
2432            _params: HistoricalBlockTradesParams,
2433        ) -> anyhow::Result<RestApiResponse<Vec<models::HistoricalBlockTradesResponseInner>>>
2434        {
2435            if self.force_error {
2436                return Err(ConnectorError::ConnectorClientError {
2437                    msg: "ResponseError".to_string(),
2438                    code: None,
2439                }
2440                .into());
2441            }
2442
2443            let resp_json: Value = serde_json::from_str(r#"[{"id":582,"price":"0.052","qty":"5838","quoteQty":"303.576","time":1772506983321,"isBuyerMaker":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2444            let dummy_response: Vec<models::HistoricalBlockTradesResponseInner> =
2445                serde_json::from_value(resp_json.clone())
2446                    .expect("should parse into Vec<models::HistoricalBlockTradesResponseInner>");
2447
2448            let dummy = DummyRestApiResponse {
2449                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2450                status: 200,
2451                headers: HashMap::new(),
2452                rate_limits: None,
2453            };
2454
2455            Ok(dummy.into())
2456        }
2457
2458        async fn historical_trades(
2459            &self,
2460            _params: HistoricalTradesParams,
2461        ) -> anyhow::Result<RestApiResponse<Vec<models::GetTradesResponseInner>>> {
2462            if self.force_error {
2463                return Err(ConnectorError::ConnectorClientError {
2464                    msg: "ResponseError".to_string(),
2465                    code: None,
2466                }
2467                .into());
2468            }
2469
2470            let resp_json: Value = serde_json::from_str(r#"[{"id":28457,"price":"4.00000100","qty":"12.00000000","quoteQty":"48.000012","time":1499865549590,"isBuyerMaker":true,"isBestMatch":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2471            let dummy_response: Vec<models::GetTradesResponseInner> =
2472                serde_json::from_value(resp_json.clone())
2473                    .expect("should parse into Vec<models::GetTradesResponseInner>");
2474
2475            let dummy = DummyRestApiResponse {
2476                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2477                status: 200,
2478                headers: HashMap::new(),
2479                rate_limits: None,
2480            };
2481
2482            Ok(dummy.into())
2483        }
2484
2485        async fn klines(
2486            &self,
2487            _params: KlinesParams,
2488        ) -> anyhow::Result<RestApiResponse<Vec<Vec<models::KlinesItemInner>>>> {
2489            if self.force_error {
2490                return Err(ConnectorError::ConnectorClientError {
2491                    msg: "ResponseError".to_string(),
2492                    code: None,
2493                }
2494                .into());
2495            }
2496
2497            let resp_json: Value = serde_json::from_str(r"[[1499040000000]]")
2498                .unwrap_or_else(|_| serde_json::json!({}));
2499            let dummy_response: Vec<Vec<models::KlinesItemInner>> =
2500                serde_json::from_value(resp_json.clone())
2501                    .expect("should parse into Vec<Vec<models::KlinesItemInner>>");
2502
2503            let dummy = DummyRestApiResponse {
2504                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2505                status: 200,
2506                headers: HashMap::new(),
2507                rate_limits: None,
2508            };
2509
2510            Ok(dummy.into())
2511        }
2512
2513        async fn reference_price(
2514            &self,
2515            _params: ReferencePriceParams,
2516        ) -> anyhow::Result<RestApiResponse<models::ReferencePriceResponse>> {
2517            if self.force_error {
2518                return Err(ConnectorError::ConnectorClientError {
2519                    msg: "ResponseError".to_string(),
2520                    code: None,
2521                }
2522                .into());
2523            }
2524
2525            let resp_json: Value = serde_json::from_str(
2526                r#"{"symbol":"BAZUSD","referencePrice":"10.00","timestamp":1770736694138}"#,
2527            )
2528            .unwrap_or_else(|_| serde_json::json!({}));
2529            let dummy_response: models::ReferencePriceResponse =
2530                serde_json::from_value(resp_json.clone())
2531                    .expect("should parse into models::ReferencePriceResponse");
2532
2533            let dummy = DummyRestApiResponse {
2534                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2535                status: 200,
2536                headers: HashMap::new(),
2537                rate_limits: None,
2538            };
2539
2540            Ok(dummy.into())
2541        }
2542
2543        async fn reference_price_calculation(
2544            &self,
2545            _params: ReferencePriceCalculationParams,
2546        ) -> anyhow::Result<RestApiResponse<models::ReferencePriceCalculationResponse>> {
2547            if self.force_error {
2548                return Err(ConnectorError::ConnectorClientError {
2549                    msg: "ResponseError".to_string(),
2550                    code: None,
2551                }
2552                .into());
2553            }
2554
2555            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BAZUSD","calculationType":"ARITHMETIC_MEAN","bucketCount":10,"bucketWidthMs":1000,"externalCalculationId":42}"#).unwrap_or_else(|_| serde_json::json!({}));
2556            let dummy_response: models::ReferencePriceCalculationResponse =
2557                serde_json::from_value(resp_json.clone())
2558                    .expect("should parse into models::ReferencePriceCalculationResponse");
2559
2560            let dummy = DummyRestApiResponse {
2561                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2562                status: 200,
2563                headers: HashMap::new(),
2564                rate_limits: None,
2565            };
2566
2567            Ok(dummy.into())
2568        }
2569
2570        async fn ticker(
2571            &self,
2572            _params: TickerParams,
2573        ) -> anyhow::Result<RestApiResponse<models::TickerResponse>> {
2574            if self.force_error {
2575                return Err(ConnectorError::ConnectorClientError {
2576                    msg: "ResponseError".to_string(),
2577                    code: None,
2578                }
2579                .into());
2580            }
2581
2582            let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC","openTime":1656986580000,"closeTime":1657001016795,"firstId":0,"lastId":34,"count":35}"#).unwrap_or_else(|_| serde_json::json!({}));
2583            let dummy_response: models::TickerResponse = serde_json::from_value(resp_json.clone())
2584                .expect("should parse into models::TickerResponse");
2585
2586            let dummy = DummyRestApiResponse {
2587                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2588                status: 200,
2589                headers: HashMap::new(),
2590                rate_limits: None,
2591            };
2592
2593            Ok(dummy.into())
2594        }
2595
2596        async fn ticker24hr(
2597            &self,
2598            _params: Ticker24hrParams,
2599        ) -> anyhow::Result<RestApiResponse<models::Ticker24hrResponse>> {
2600            if self.force_error {
2601                return Err(ConnectorError::ConnectorClientError {
2602                    msg: "ResponseError".to_string(),
2603                    code: None,
2604                }
2605                .into());
2606            }
2607
2608            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BNBBTC","openTime":1499783499040,"closeTime":1499869899040,"firstId":28385,"lastId":28460,"count":76}"#).unwrap_or_else(|_| serde_json::json!({}));
2609            let dummy_response: models::Ticker24hrResponse =
2610                serde_json::from_value(resp_json.clone())
2611                    .expect("should parse into models::Ticker24hrResponse");
2612
2613            let dummy = DummyRestApiResponse {
2614                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2615                status: 200,
2616                headers: HashMap::new(),
2617                rate_limits: None,
2618            };
2619
2620            Ok(dummy.into())
2621        }
2622
2623        async fn ticker_book_ticker(
2624            &self,
2625            _params: TickerBookTickerParams,
2626        ) -> anyhow::Result<RestApiResponse<models::TickerBookTickerResponse>> {
2627            if self.force_error {
2628                return Err(ConnectorError::ConnectorClientError {
2629                    msg: "ResponseError".to_string(),
2630                    code: None,
2631                }
2632                .into());
2633            }
2634
2635            let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC"}"#)
2636                .unwrap_or_else(|_| serde_json::json!({}));
2637            let dummy_response: models::TickerBookTickerResponse =
2638                serde_json::from_value(resp_json.clone())
2639                    .expect("should parse into models::TickerBookTickerResponse");
2640
2641            let dummy = DummyRestApiResponse {
2642                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2643                status: 200,
2644                headers: HashMap::new(),
2645                rate_limits: None,
2646            };
2647
2648            Ok(dummy.into())
2649        }
2650
2651        async fn ticker_price(
2652            &self,
2653            _params: TickerPriceParams,
2654        ) -> anyhow::Result<RestApiResponse<models::TickerPriceResponse>> {
2655            if self.force_error {
2656                return Err(ConnectorError::ConnectorClientError {
2657                    msg: "ResponseError".to_string(),
2658                    code: None,
2659                }
2660                .into());
2661            }
2662
2663            let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC"}"#)
2664                .unwrap_or_else(|_| serde_json::json!({}));
2665            let dummy_response: models::TickerPriceResponse =
2666                serde_json::from_value(resp_json.clone())
2667                    .expect("should parse into models::TickerPriceResponse");
2668
2669            let dummy = DummyRestApiResponse {
2670                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2671                status: 200,
2672                headers: HashMap::new(),
2673                rate_limits: None,
2674            };
2675
2676            Ok(dummy.into())
2677        }
2678
2679        async fn ticker_trading_day(
2680            &self,
2681            _params: TickerTradingDayParams,
2682        ) -> anyhow::Result<RestApiResponse<models::TickerTradingDayResponse>> {
2683            if self.force_error {
2684                return Err(ConnectorError::ConnectorClientError {
2685                    msg: "ResponseError".to_string(),
2686                    code: None,
2687                }
2688                .into());
2689            }
2690
2691            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSDT","openTime":1695686400000,"closeTime":1695772799999,"firstId":3220151555,"lastId":3220849281,"count":697727}"#).unwrap_or_else(|_| serde_json::json!({}));
2692            let dummy_response: models::TickerTradingDayResponse =
2693                serde_json::from_value(resp_json.clone())
2694                    .expect("should parse into models::TickerTradingDayResponse");
2695
2696            let dummy = DummyRestApiResponse {
2697                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2698                status: 200,
2699                headers: HashMap::new(),
2700                rate_limits: None,
2701            };
2702
2703            Ok(dummy.into())
2704        }
2705
2706        async fn ui_klines(
2707            &self,
2708            _params: UiKlinesParams,
2709        ) -> anyhow::Result<RestApiResponse<Vec<Vec<models::KlinesItemInner>>>> {
2710            if self.force_error {
2711                return Err(ConnectorError::ConnectorClientError {
2712                    msg: "ResponseError".to_string(),
2713                    code: None,
2714                }
2715                .into());
2716            }
2717
2718            let resp_json: Value = serde_json::from_str(r"[[1499040000000]]")
2719                .unwrap_or_else(|_| serde_json::json!({}));
2720            let dummy_response: Vec<Vec<models::KlinesItemInner>> =
2721                serde_json::from_value(resp_json.clone())
2722                    .expect("should parse into Vec<Vec<models::KlinesItemInner>>");
2723
2724            let dummy = DummyRestApiResponse {
2725                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2726                status: 200,
2727                headers: HashMap::new(),
2728                rate_limits: None,
2729            };
2730
2731            Ok(dummy.into())
2732        }
2733    }
2734
2735    #[test]
2736    fn agg_trades_required_params_success() {
2737        TOKIO_SHARED_RT.block_on(async {
2738            let client = MockMarketApiClient { force_error: false };
2739
2740            let params = AggTradesParams::builder("BNBUSDT".to_string(),).build().unwrap();
2741
2742            let resp_json: Value = serde_json::from_str(r#"[{"a":26129,"p":"0.01633102","q":"4.70443515","f":27781,"l":27781,"T":1498793709153,"m":true,"M":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2743            let expected_response : Vec<models::AggTradesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::AggTradesResponseInner>");
2744
2745            let resp = client.agg_trades(params).await.expect("Expected a response");
2746            let data_future = resp.data();
2747            let actual_response = data_future.await.unwrap();
2748            assert_eq!(actual_response, expected_response);
2749        });
2750    }
2751
2752    #[test]
2753    fn agg_trades_optional_params_success() {
2754        TOKIO_SHARED_RT.block_on(async {
2755            let client = MockMarketApiClient { force_error: false };
2756
2757            let params = AggTradesParams::builder("BNBUSDT".to_string(),).from_id(1).start_time(1735693200000).end_time(1735693200000).limit(1).build().unwrap();
2758
2759            let resp_json: Value = serde_json::from_str(r#"[{"a":26129,"p":"0.01633102","q":"4.70443515","f":27781,"l":27781,"T":1498793709153,"m":true,"M":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2760            let expected_response : Vec<models::AggTradesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::AggTradesResponseInner>");
2761
2762            let resp = client.agg_trades(params).await.expect("Expected a response");
2763            let data_future = resp.data();
2764            let actual_response = data_future.await.unwrap();
2765            assert_eq!(actual_response, expected_response);
2766        });
2767    }
2768
2769    #[test]
2770    fn agg_trades_response_error() {
2771        TOKIO_SHARED_RT.block_on(async {
2772            let client = MockMarketApiClient { force_error: true };
2773
2774            let params = AggTradesParams::builder("BNBUSDT".to_string())
2775                .build()
2776                .unwrap();
2777
2778            match client.agg_trades(params).await {
2779                Ok(_) => panic!("Expected an error"),
2780                Err(err) => {
2781                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2782                }
2783            }
2784        });
2785    }
2786
2787    #[test]
2788    fn avg_price_required_params_success() {
2789        TOKIO_SHARED_RT.block_on(async {
2790            let client = MockMarketApiClient { force_error: false };
2791
2792            let params = AvgPriceParams::builder("BNBUSDT".to_string())
2793                .build()
2794                .unwrap();
2795
2796            let resp_json: Value = serde_json::from_str(
2797                r#"{"mins":5,"price":"9.35751834","closeTime":1694061154503}"#,
2798            )
2799            .unwrap_or_else(|_| serde_json::json!({}));
2800            let expected_response: models::AvgPriceResponse =
2801                serde_json::from_value(resp_json.clone())
2802                    .expect("should parse into models::AvgPriceResponse");
2803
2804            let resp = client.avg_price(params).await.expect("Expected a response");
2805            let data_future = resp.data();
2806            let actual_response = data_future.await.unwrap();
2807            assert_eq!(actual_response, expected_response);
2808        });
2809    }
2810
2811    #[test]
2812    fn avg_price_optional_params_success() {
2813        TOKIO_SHARED_RT.block_on(async {
2814            let client = MockMarketApiClient { force_error: false };
2815
2816            let params = AvgPriceParams::builder("BNBUSDT".to_string())
2817                .build()
2818                .unwrap();
2819
2820            let resp_json: Value = serde_json::from_str(
2821                r#"{"mins":5,"price":"9.35751834","closeTime":1694061154503}"#,
2822            )
2823            .unwrap_or_else(|_| serde_json::json!({}));
2824            let expected_response: models::AvgPriceResponse =
2825                serde_json::from_value(resp_json.clone())
2826                    .expect("should parse into models::AvgPriceResponse");
2827
2828            let resp = client.avg_price(params).await.expect("Expected a response");
2829            let data_future = resp.data();
2830            let actual_response = data_future.await.unwrap();
2831            assert_eq!(actual_response, expected_response);
2832        });
2833    }
2834
2835    #[test]
2836    fn avg_price_response_error() {
2837        TOKIO_SHARED_RT.block_on(async {
2838            let client = MockMarketApiClient { force_error: true };
2839
2840            let params = AvgPriceParams::builder("BNBUSDT".to_string())
2841                .build()
2842                .unwrap();
2843
2844            match client.avg_price(params).await {
2845                Ok(_) => panic!("Expected an error"),
2846                Err(err) => {
2847                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2848                }
2849            }
2850        });
2851    }
2852
2853    #[test]
2854    fn depth_required_params_success() {
2855        TOKIO_SHARED_RT.block_on(async {
2856            let client = MockMarketApiClient { force_error: false };
2857
2858            let params = DepthParams::builder("BNBUSDT".to_string(),).build().unwrap();
2859
2860            let resp_json: Value = serde_json::from_str(r#"{"lastUpdateId":1027024,"bids":[["4.00000000","431.00000000"]],"asks":[["4.00000200","12.00000000"]]}"#).unwrap_or_else(|_| serde_json::json!({}));
2861            let expected_response : models::DepthResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DepthResponse");
2862
2863            let resp = client.depth(params).await.expect("Expected a response");
2864            let data_future = resp.data();
2865            let actual_response = data_future.await.unwrap();
2866            assert_eq!(actual_response, expected_response);
2867        });
2868    }
2869
2870    #[test]
2871    fn depth_optional_params_success() {
2872        TOKIO_SHARED_RT.block_on(async {
2873            let client = MockMarketApiClient { force_error: false };
2874
2875            let params = DepthParams::builder("BNBUSDT".to_string(),).limit(1).symbol_status(DepthSymbolStatusEnum::Trading).build().unwrap();
2876
2877            let resp_json: Value = serde_json::from_str(r#"{"lastUpdateId":1027024,"bids":[["4.00000000","431.00000000"]],"asks":[["4.00000200","12.00000000"]]}"#).unwrap_or_else(|_| serde_json::json!({}));
2878            let expected_response : models::DepthResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DepthResponse");
2879
2880            let resp = client.depth(params).await.expect("Expected a response");
2881            let data_future = resp.data();
2882            let actual_response = data_future.await.unwrap();
2883            assert_eq!(actual_response, expected_response);
2884        });
2885    }
2886
2887    #[test]
2888    fn depth_response_error() {
2889        TOKIO_SHARED_RT.block_on(async {
2890            let client = MockMarketApiClient { force_error: true };
2891
2892            let params = DepthParams::builder("BNBUSDT".to_string()).build().unwrap();
2893
2894            match client.depth(params).await {
2895                Ok(_) => panic!("Expected an error"),
2896                Err(err) => {
2897                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2898                }
2899            }
2900        });
2901    }
2902
2903    #[test]
2904    fn get_trades_required_params_success() {
2905        TOKIO_SHARED_RT.block_on(async {
2906            let client = MockMarketApiClient { force_error: false };
2907
2908            let params = GetTradesParams::builder("BNBUSDT".to_string(),).build().unwrap();
2909
2910            let resp_json: Value = serde_json::from_str(r#"[{"id":28457,"price":"4.00000100","qty":"12.00000000","quoteQty":"48.000012","time":1499865549590,"isBuyerMaker":true,"isBestMatch":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2911            let expected_response : Vec<models::GetTradesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetTradesResponseInner>");
2912
2913            let resp = client.get_trades(params).await.expect("Expected a response");
2914            let data_future = resp.data();
2915            let actual_response = data_future.await.unwrap();
2916            assert_eq!(actual_response, expected_response);
2917        });
2918    }
2919
2920    #[test]
2921    fn get_trades_optional_params_success() {
2922        TOKIO_SHARED_RT.block_on(async {
2923            let client = MockMarketApiClient { force_error: false };
2924
2925            let params = GetTradesParams::builder("BNBUSDT".to_string(),).limit(1).build().unwrap();
2926
2927            let resp_json: Value = serde_json::from_str(r#"[{"id":28457,"price":"4.00000100","qty":"12.00000000","quoteQty":"48.000012","time":1499865549590,"isBuyerMaker":true,"isBestMatch":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2928            let expected_response : Vec<models::GetTradesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetTradesResponseInner>");
2929
2930            let resp = client.get_trades(params).await.expect("Expected a response");
2931            let data_future = resp.data();
2932            let actual_response = data_future.await.unwrap();
2933            assert_eq!(actual_response, expected_response);
2934        });
2935    }
2936
2937    #[test]
2938    fn get_trades_response_error() {
2939        TOKIO_SHARED_RT.block_on(async {
2940            let client = MockMarketApiClient { force_error: true };
2941
2942            let params = GetTradesParams::builder("BNBUSDT".to_string())
2943                .build()
2944                .unwrap();
2945
2946            match client.get_trades(params).await {
2947                Ok(_) => panic!("Expected an error"),
2948                Err(err) => {
2949                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2950                }
2951            }
2952        });
2953    }
2954
2955    #[test]
2956    fn historical_block_trades_required_params_success() {
2957        TOKIO_SHARED_RT.block_on(async {
2958            let client = MockMarketApiClient { force_error: false };
2959
2960            let params = HistoricalBlockTradesParams::builder("BNBBTC".to_string(),582,).build().unwrap();
2961
2962            let resp_json: Value = serde_json::from_str(r#"[{"id":582,"price":"0.052","qty":"5838","quoteQty":"303.576","time":1772506983321,"isBuyerMaker":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2963            let expected_response : Vec<models::HistoricalBlockTradesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::HistoricalBlockTradesResponseInner>");
2964
2965            let resp = client.historical_block_trades(params).await.expect("Expected a response");
2966            let data_future = resp.data();
2967            let actual_response = data_future.await.unwrap();
2968            assert_eq!(actual_response, expected_response);
2969        });
2970    }
2971
2972    #[test]
2973    fn historical_block_trades_optional_params_success() {
2974        TOKIO_SHARED_RT.block_on(async {
2975            let client = MockMarketApiClient { force_error: false };
2976
2977            let params = HistoricalBlockTradesParams::builder("BNBBTC".to_string(),582,).limit(500).build().unwrap();
2978
2979            let resp_json: Value = serde_json::from_str(r#"[{"id":582,"price":"0.052","qty":"5838","quoteQty":"303.576","time":1772506983321,"isBuyerMaker":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
2980            let expected_response : Vec<models::HistoricalBlockTradesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::HistoricalBlockTradesResponseInner>");
2981
2982            let resp = client.historical_block_trades(params).await.expect("Expected a response");
2983            let data_future = resp.data();
2984            let actual_response = data_future.await.unwrap();
2985            assert_eq!(actual_response, expected_response);
2986        });
2987    }
2988
2989    #[test]
2990    fn historical_block_trades_response_error() {
2991        TOKIO_SHARED_RT.block_on(async {
2992            let client = MockMarketApiClient { force_error: true };
2993
2994            let params = HistoricalBlockTradesParams::builder("BNBBTC".to_string(), 582)
2995                .build()
2996                .unwrap();
2997
2998            match client.historical_block_trades(params).await {
2999                Ok(_) => panic!("Expected an error"),
3000                Err(err) => {
3001                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3002                }
3003            }
3004        });
3005    }
3006
3007    #[test]
3008    fn historical_trades_required_params_success() {
3009        TOKIO_SHARED_RT.block_on(async {
3010            let client = MockMarketApiClient { force_error: false };
3011
3012            let params = HistoricalTradesParams::builder("BNBUSDT".to_string(),).build().unwrap();
3013
3014            let resp_json: Value = serde_json::from_str(r#"[{"id":28457,"price":"4.00000100","qty":"12.00000000","quoteQty":"48.000012","time":1499865549590,"isBuyerMaker":true,"isBestMatch":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
3015            let expected_response : Vec<models::GetTradesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetTradesResponseInner>");
3016
3017            let resp = client.historical_trades(params).await.expect("Expected a response");
3018            let data_future = resp.data();
3019            let actual_response = data_future.await.unwrap();
3020            assert_eq!(actual_response, expected_response);
3021        });
3022    }
3023
3024    #[test]
3025    fn historical_trades_optional_params_success() {
3026        TOKIO_SHARED_RT.block_on(async {
3027            let client = MockMarketApiClient { force_error: false };
3028
3029            let params = HistoricalTradesParams::builder("BNBUSDT".to_string(),).limit(1).from_id(1).build().unwrap();
3030
3031            let resp_json: Value = serde_json::from_str(r#"[{"id":28457,"price":"4.00000100","qty":"12.00000000","quoteQty":"48.000012","time":1499865549590,"isBuyerMaker":true,"isBestMatch":true}]"#).unwrap_or_else(|_| serde_json::json!({}));
3032            let expected_response : Vec<models::GetTradesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetTradesResponseInner>");
3033
3034            let resp = client.historical_trades(params).await.expect("Expected a response");
3035            let data_future = resp.data();
3036            let actual_response = data_future.await.unwrap();
3037            assert_eq!(actual_response, expected_response);
3038        });
3039    }
3040
3041    #[test]
3042    fn historical_trades_response_error() {
3043        TOKIO_SHARED_RT.block_on(async {
3044            let client = MockMarketApiClient { force_error: true };
3045
3046            let params = HistoricalTradesParams::builder("BNBUSDT".to_string())
3047                .build()
3048                .unwrap();
3049
3050            match client.historical_trades(params).await {
3051                Ok(_) => panic!("Expected an error"),
3052                Err(err) => {
3053                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3054                }
3055            }
3056        });
3057    }
3058
3059    #[test]
3060    fn klines_required_params_success() {
3061        TOKIO_SHARED_RT.block_on(async {
3062            let client = MockMarketApiClient { force_error: false };
3063
3064            let params =
3065                KlinesParams::builder("BNBUSDT".to_string(), KlinesIntervalEnum::Interval1s)
3066                    .build()
3067                    .unwrap();
3068
3069            let resp_json: Value = serde_json::from_str(r"[[1499040000000]]")
3070                .unwrap_or_else(|_| serde_json::json!({}));
3071            let expected_response: Vec<Vec<models::KlinesItemInner>> =
3072                serde_json::from_value(resp_json.clone())
3073                    .expect("should parse into Vec<Vec<models::KlinesItemInner>>");
3074
3075            let resp = client.klines(params).await.expect("Expected a response");
3076            let data_future = resp.data();
3077            let actual_response = data_future.await.unwrap();
3078            assert_eq!(actual_response, expected_response);
3079        });
3080    }
3081
3082    #[test]
3083    fn klines_optional_params_success() {
3084        TOKIO_SHARED_RT.block_on(async {
3085            let client = MockMarketApiClient { force_error: false };
3086
3087            let params =
3088                KlinesParams::builder("BNBUSDT".to_string(), KlinesIntervalEnum::Interval1s)
3089                    .start_time(1735693200000)
3090                    .end_time(1735693200000)
3091                    .time_zone("0".to_string())
3092                    .limit(1)
3093                    .build()
3094                    .unwrap();
3095
3096            let resp_json: Value = serde_json::from_str(r"[[1499040000000]]")
3097                .unwrap_or_else(|_| serde_json::json!({}));
3098            let expected_response: Vec<Vec<models::KlinesItemInner>> =
3099                serde_json::from_value(resp_json.clone())
3100                    .expect("should parse into Vec<Vec<models::KlinesItemInner>>");
3101
3102            let resp = client.klines(params).await.expect("Expected a response");
3103            let data_future = resp.data();
3104            let actual_response = data_future.await.unwrap();
3105            assert_eq!(actual_response, expected_response);
3106        });
3107    }
3108
3109    #[test]
3110    fn klines_response_error() {
3111        TOKIO_SHARED_RT.block_on(async {
3112            let client = MockMarketApiClient { force_error: true };
3113
3114            let params =
3115                KlinesParams::builder("BNBUSDT".to_string(), KlinesIntervalEnum::Interval1s)
3116                    .build()
3117                    .unwrap();
3118
3119            match client.klines(params).await {
3120                Ok(_) => panic!("Expected an error"),
3121                Err(err) => {
3122                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3123                }
3124            }
3125        });
3126    }
3127
3128    #[test]
3129    fn reference_price_required_params_success() {
3130        TOKIO_SHARED_RT.block_on(async {
3131            let client = MockMarketApiClient { force_error: false };
3132
3133            let params = ReferencePriceParams::builder("BNBUSDT".to_string())
3134                .build()
3135                .unwrap();
3136
3137            let resp_json: Value = serde_json::from_str(
3138                r#"{"symbol":"BAZUSD","referencePrice":"10.00","timestamp":1770736694138}"#,
3139            )
3140            .unwrap_or_else(|_| serde_json::json!({}));
3141            let expected_response: models::ReferencePriceResponse =
3142                serde_json::from_value(resp_json.clone())
3143                    .expect("should parse into models::ReferencePriceResponse");
3144
3145            let resp = client
3146                .reference_price(params)
3147                .await
3148                .expect("Expected a response");
3149            let data_future = resp.data();
3150            let actual_response = data_future.await.unwrap();
3151            assert_eq!(actual_response, expected_response);
3152        });
3153    }
3154
3155    #[test]
3156    fn reference_price_optional_params_success() {
3157        TOKIO_SHARED_RT.block_on(async {
3158            let client = MockMarketApiClient { force_error: false };
3159
3160            let params = ReferencePriceParams::builder("BNBUSDT".to_string())
3161                .build()
3162                .unwrap();
3163
3164            let resp_json: Value = serde_json::from_str(
3165                r#"{"symbol":"BAZUSD","referencePrice":"10.00","timestamp":1770736694138}"#,
3166            )
3167            .unwrap_or_else(|_| serde_json::json!({}));
3168            let expected_response: models::ReferencePriceResponse =
3169                serde_json::from_value(resp_json.clone())
3170                    .expect("should parse into models::ReferencePriceResponse");
3171
3172            let resp = client
3173                .reference_price(params)
3174                .await
3175                .expect("Expected a response");
3176            let data_future = resp.data();
3177            let actual_response = data_future.await.unwrap();
3178            assert_eq!(actual_response, expected_response);
3179        });
3180    }
3181
3182    #[test]
3183    fn reference_price_response_error() {
3184        TOKIO_SHARED_RT.block_on(async {
3185            let client = MockMarketApiClient { force_error: true };
3186
3187            let params = ReferencePriceParams::builder("BNBUSDT".to_string())
3188                .build()
3189                .unwrap();
3190
3191            match client.reference_price(params).await {
3192                Ok(_) => panic!("Expected an error"),
3193                Err(err) => {
3194                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3195                }
3196            }
3197        });
3198    }
3199
3200    #[test]
3201    fn reference_price_calculation_required_params_success() {
3202        TOKIO_SHARED_RT.block_on(async {
3203            let client = MockMarketApiClient { force_error: false };
3204
3205            let params = ReferencePriceCalculationParams::builder("BNBUSDT".to_string(),).build().unwrap();
3206
3207            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BAZUSD","calculationType":"ARITHMETIC_MEAN","bucketCount":10,"bucketWidthMs":1000,"externalCalculationId":42}"#).unwrap_or_else(|_| serde_json::json!({}));
3208            let expected_response : models::ReferencePriceCalculationResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::ReferencePriceCalculationResponse");
3209
3210            let resp = client.reference_price_calculation(params).await.expect("Expected a response");
3211            let data_future = resp.data();
3212            let actual_response = data_future.await.unwrap();
3213            assert_eq!(actual_response, expected_response);
3214        });
3215    }
3216
3217    #[test]
3218    fn reference_price_calculation_optional_params_success() {
3219        TOKIO_SHARED_RT.block_on(async {
3220            let client = MockMarketApiClient { force_error: false };
3221
3222            let params = ReferencePriceCalculationParams::builder("BNBUSDT".to_string(),).symbol_status(ReferencePriceCalculationSymbolStatusEnum::Trading).build().unwrap();
3223
3224            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BAZUSD","calculationType":"ARITHMETIC_MEAN","bucketCount":10,"bucketWidthMs":1000,"externalCalculationId":42}"#).unwrap_or_else(|_| serde_json::json!({}));
3225            let expected_response : models::ReferencePriceCalculationResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::ReferencePriceCalculationResponse");
3226
3227            let resp = client.reference_price_calculation(params).await.expect("Expected a response");
3228            let data_future = resp.data();
3229            let actual_response = data_future.await.unwrap();
3230            assert_eq!(actual_response, expected_response);
3231        });
3232    }
3233
3234    #[test]
3235    fn reference_price_calculation_response_error() {
3236        TOKIO_SHARED_RT.block_on(async {
3237            let client = MockMarketApiClient { force_error: true };
3238
3239            let params = ReferencePriceCalculationParams::builder("BNBUSDT".to_string())
3240                .build()
3241                .unwrap();
3242
3243            match client.reference_price_calculation(params).await {
3244                Ok(_) => panic!("Expected an error"),
3245                Err(err) => {
3246                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3247                }
3248            }
3249        });
3250    }
3251
3252    #[test]
3253    fn ticker_required_params_success() {
3254        TOKIO_SHARED_RT.block_on(async {
3255            let client = MockMarketApiClient { force_error: false };
3256
3257            let params = TickerParams::builder().build().unwrap();
3258
3259            let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC","openTime":1656986580000,"closeTime":1657001016795,"firstId":0,"lastId":34,"count":35}"#).unwrap_or_else(|_| serde_json::json!({}));
3260            let expected_response : models::TickerResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::TickerResponse");
3261
3262            let resp = client.ticker(params).await.expect("Expected a response");
3263            let data_future = resp.data();
3264            let actual_response = data_future.await.unwrap();
3265            assert_eq!(actual_response, expected_response);
3266        });
3267    }
3268
3269    #[test]
3270    fn ticker_optional_params_success() {
3271        TOKIO_SHARED_RT.block_on(async {
3272            let client = MockMarketApiClient { force_error: false };
3273
3274            let params = TickerParams::builder().symbol("BNBUSDT".to_string()).symbols(["BTCUSDT".to_string(),].to_vec()).window_size(TickerWindowSizeEnum::WindowSize1m).r#type(TickerTypeEnum::Full).symbol_status(TickerSymbolStatusEnum::Trading).build().unwrap();
3275
3276            let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC","openTime":1656986580000,"closeTime":1657001016795,"firstId":0,"lastId":34,"count":35}"#).unwrap_or_else(|_| serde_json::json!({}));
3277            let expected_response : models::TickerResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::TickerResponse");
3278
3279            let resp = client.ticker(params).await.expect("Expected a response");
3280            let data_future = resp.data();
3281            let actual_response = data_future.await.unwrap();
3282            assert_eq!(actual_response, expected_response);
3283        });
3284    }
3285
3286    #[test]
3287    fn ticker_response_error() {
3288        TOKIO_SHARED_RT.block_on(async {
3289            let client = MockMarketApiClient { force_error: true };
3290
3291            let params = TickerParams::builder().build().unwrap();
3292
3293            match client.ticker(params).await {
3294                Ok(_) => panic!("Expected an error"),
3295                Err(err) => {
3296                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3297                }
3298            }
3299        });
3300    }
3301
3302    #[test]
3303    fn ticker24hr_required_params_success() {
3304        TOKIO_SHARED_RT.block_on(async {
3305            let client = MockMarketApiClient { force_error: false };
3306
3307            let params = Ticker24hrParams::builder().build().unwrap();
3308
3309            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BNBBTC","openTime":1499783499040,"closeTime":1499869899040,"firstId":28385,"lastId":28460,"count":76}"#).unwrap_or_else(|_| serde_json::json!({}));
3310            let expected_response : models::Ticker24hrResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::Ticker24hrResponse");
3311
3312            let resp = client.ticker24hr(params).await.expect("Expected a response");
3313            let data_future = resp.data();
3314            let actual_response = data_future.await.unwrap();
3315            assert_eq!(actual_response, expected_response);
3316        });
3317    }
3318
3319    #[test]
3320    fn ticker24hr_optional_params_success() {
3321        TOKIO_SHARED_RT.block_on(async {
3322            let client = MockMarketApiClient { force_error: false };
3323
3324            let params = Ticker24hrParams::builder().symbol("BNBUSDT".to_string()).symbols(["BTCUSDT".to_string(),].to_vec()).r#type(Ticker24hrTypeEnum::Full).symbol_status(Ticker24hrSymbolStatusEnum::Trading).build().unwrap();
3325
3326            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BNBBTC","openTime":1499783499040,"closeTime":1499869899040,"firstId":28385,"lastId":28460,"count":76}"#).unwrap_or_else(|_| serde_json::json!({}));
3327            let expected_response : models::Ticker24hrResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::Ticker24hrResponse");
3328
3329            let resp = client.ticker24hr(params).await.expect("Expected a response");
3330            let data_future = resp.data();
3331            let actual_response = data_future.await.unwrap();
3332            assert_eq!(actual_response, expected_response);
3333        });
3334    }
3335
3336    #[test]
3337    fn ticker24hr_response_error() {
3338        TOKIO_SHARED_RT.block_on(async {
3339            let client = MockMarketApiClient { force_error: true };
3340
3341            let params = Ticker24hrParams::builder().build().unwrap();
3342
3343            match client.ticker24hr(params).await {
3344                Ok(_) => panic!("Expected an error"),
3345                Err(err) => {
3346                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3347                }
3348            }
3349        });
3350    }
3351
3352    #[test]
3353    fn ticker_book_ticker_required_params_success() {
3354        TOKIO_SHARED_RT.block_on(async {
3355            let client = MockMarketApiClient { force_error: false };
3356
3357            let params = TickerBookTickerParams::builder().build().unwrap();
3358
3359            let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC"}"#)
3360                .unwrap_or_else(|_| serde_json::json!({}));
3361            let expected_response: models::TickerBookTickerResponse =
3362                serde_json::from_value(resp_json.clone())
3363                    .expect("should parse into models::TickerBookTickerResponse");
3364
3365            let resp = client
3366                .ticker_book_ticker(params)
3367                .await
3368                .expect("Expected a response");
3369            let data_future = resp.data();
3370            let actual_response = data_future.await.unwrap();
3371            assert_eq!(actual_response, expected_response);
3372        });
3373    }
3374
3375    #[test]
3376    fn ticker_book_ticker_optional_params_success() {
3377        TOKIO_SHARED_RT.block_on(async {
3378            let client = MockMarketApiClient { force_error: false };
3379
3380            let params = TickerBookTickerParams::builder()
3381                .symbol("BNBUSDT".to_string())
3382                .symbols(["BTCUSDT".to_string()].to_vec())
3383                .symbol_status(TickerBookTickerSymbolStatusEnum::Trading)
3384                .build()
3385                .unwrap();
3386
3387            let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC"}"#)
3388                .unwrap_or_else(|_| serde_json::json!({}));
3389            let expected_response: models::TickerBookTickerResponse =
3390                serde_json::from_value(resp_json.clone())
3391                    .expect("should parse into models::TickerBookTickerResponse");
3392
3393            let resp = client
3394                .ticker_book_ticker(params)
3395                .await
3396                .expect("Expected a response");
3397            let data_future = resp.data();
3398            let actual_response = data_future.await.unwrap();
3399            assert_eq!(actual_response, expected_response);
3400        });
3401    }
3402
3403    #[test]
3404    fn ticker_book_ticker_response_error() {
3405        TOKIO_SHARED_RT.block_on(async {
3406            let client = MockMarketApiClient { force_error: true };
3407
3408            let params = TickerBookTickerParams::builder().build().unwrap();
3409
3410            match client.ticker_book_ticker(params).await {
3411                Ok(_) => panic!("Expected an error"),
3412                Err(err) => {
3413                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3414                }
3415            }
3416        });
3417    }
3418
3419    #[test]
3420    fn ticker_price_required_params_success() {
3421        TOKIO_SHARED_RT.block_on(async {
3422            let client = MockMarketApiClient { force_error: false };
3423
3424            let params = TickerPriceParams::builder().build().unwrap();
3425
3426            let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC"}"#)
3427                .unwrap_or_else(|_| serde_json::json!({}));
3428            let expected_response: models::TickerPriceResponse =
3429                serde_json::from_value(resp_json.clone())
3430                    .expect("should parse into models::TickerPriceResponse");
3431
3432            let resp = client
3433                .ticker_price(params)
3434                .await
3435                .expect("Expected a response");
3436            let data_future = resp.data();
3437            let actual_response = data_future.await.unwrap();
3438            assert_eq!(actual_response, expected_response);
3439        });
3440    }
3441
3442    #[test]
3443    fn ticker_price_optional_params_success() {
3444        TOKIO_SHARED_RT.block_on(async {
3445            let client = MockMarketApiClient { force_error: false };
3446
3447            let params = TickerPriceParams::builder()
3448                .symbol("BNBUSDT".to_string())
3449                .symbols(["BTCUSDT".to_string()].to_vec())
3450                .symbol_status(TickerPriceSymbolStatusEnum::Trading)
3451                .build()
3452                .unwrap();
3453
3454            let resp_json: Value = serde_json::from_str(r#"{"symbol":"LTCBTC"}"#)
3455                .unwrap_or_else(|_| serde_json::json!({}));
3456            let expected_response: models::TickerPriceResponse =
3457                serde_json::from_value(resp_json.clone())
3458                    .expect("should parse into models::TickerPriceResponse");
3459
3460            let resp = client
3461                .ticker_price(params)
3462                .await
3463                .expect("Expected a response");
3464            let data_future = resp.data();
3465            let actual_response = data_future.await.unwrap();
3466            assert_eq!(actual_response, expected_response);
3467        });
3468    }
3469
3470    #[test]
3471    fn ticker_price_response_error() {
3472        TOKIO_SHARED_RT.block_on(async {
3473            let client = MockMarketApiClient { force_error: true };
3474
3475            let params = TickerPriceParams::builder().build().unwrap();
3476
3477            match client.ticker_price(params).await {
3478                Ok(_) => panic!("Expected an error"),
3479                Err(err) => {
3480                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3481                }
3482            }
3483        });
3484    }
3485
3486    #[test]
3487    fn ticker_trading_day_required_params_success() {
3488        TOKIO_SHARED_RT.block_on(async {
3489            let client = MockMarketApiClient { force_error: false };
3490
3491            let params = TickerTradingDayParams::builder().build().unwrap();
3492
3493            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSDT","openTime":1695686400000,"closeTime":1695772799999,"firstId":3220151555,"lastId":3220849281,"count":697727}"#).unwrap_or_else(|_| serde_json::json!({}));
3494            let expected_response : models::TickerTradingDayResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::TickerTradingDayResponse");
3495
3496            let resp = client.ticker_trading_day(params).await.expect("Expected a response");
3497            let data_future = resp.data();
3498            let actual_response = data_future.await.unwrap();
3499            assert_eq!(actual_response, expected_response);
3500        });
3501    }
3502
3503    #[test]
3504    fn ticker_trading_day_optional_params_success() {
3505        TOKIO_SHARED_RT.block_on(async {
3506            let client = MockMarketApiClient { force_error: false };
3507
3508            let params = TickerTradingDayParams::builder().symbol("BNBUSDT".to_string()).symbols(["BTCUSDT".to_string(),].to_vec()).time_zone("0".to_string()).r#type(TickerTradingDayTypeEnum::Full).symbol_status(TickerTradingDaySymbolStatusEnum::Trading).build().unwrap();
3509
3510            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSDT","openTime":1695686400000,"closeTime":1695772799999,"firstId":3220151555,"lastId":3220849281,"count":697727}"#).unwrap_or_else(|_| serde_json::json!({}));
3511            let expected_response : models::TickerTradingDayResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::TickerTradingDayResponse");
3512
3513            let resp = client.ticker_trading_day(params).await.expect("Expected a response");
3514            let data_future = resp.data();
3515            let actual_response = data_future.await.unwrap();
3516            assert_eq!(actual_response, expected_response);
3517        });
3518    }
3519
3520    #[test]
3521    fn ticker_trading_day_response_error() {
3522        TOKIO_SHARED_RT.block_on(async {
3523            let client = MockMarketApiClient { force_error: true };
3524
3525            let params = TickerTradingDayParams::builder().build().unwrap();
3526
3527            match client.ticker_trading_day(params).await {
3528                Ok(_) => panic!("Expected an error"),
3529                Err(err) => {
3530                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3531                }
3532            }
3533        });
3534    }
3535
3536    #[test]
3537    fn ui_klines_required_params_success() {
3538        TOKIO_SHARED_RT.block_on(async {
3539            let client = MockMarketApiClient { force_error: false };
3540
3541            let params =
3542                UiKlinesParams::builder("BNBUSDT".to_string(), UiKlinesIntervalEnum::Interval1s)
3543                    .build()
3544                    .unwrap();
3545
3546            let resp_json: Value = serde_json::from_str(r"[[1499040000000]]")
3547                .unwrap_or_else(|_| serde_json::json!({}));
3548            let expected_response: Vec<Vec<models::KlinesItemInner>> =
3549                serde_json::from_value(resp_json.clone())
3550                    .expect("should parse into Vec<Vec<models::KlinesItemInner>>");
3551
3552            let resp = client.ui_klines(params).await.expect("Expected a response");
3553            let data_future = resp.data();
3554            let actual_response = data_future.await.unwrap();
3555            assert_eq!(actual_response, expected_response);
3556        });
3557    }
3558
3559    #[test]
3560    fn ui_klines_optional_params_success() {
3561        TOKIO_SHARED_RT.block_on(async {
3562            let client = MockMarketApiClient { force_error: false };
3563
3564            let params =
3565                UiKlinesParams::builder("BNBUSDT".to_string(), UiKlinesIntervalEnum::Interval1s)
3566                    .start_time(1735693200000)
3567                    .end_time(1735693200000)
3568                    .time_zone("0".to_string())
3569                    .limit(1)
3570                    .build()
3571                    .unwrap();
3572
3573            let resp_json: Value = serde_json::from_str(r"[[1499040000000]]")
3574                .unwrap_or_else(|_| serde_json::json!({}));
3575            let expected_response: Vec<Vec<models::KlinesItemInner>> =
3576                serde_json::from_value(resp_json.clone())
3577                    .expect("should parse into Vec<Vec<models::KlinesItemInner>>");
3578
3579            let resp = client.ui_klines(params).await.expect("Expected a response");
3580            let data_future = resp.data();
3581            let actual_response = data_future.await.unwrap();
3582            assert_eq!(actual_response, expected_response);
3583        });
3584    }
3585
3586    #[test]
3587    fn ui_klines_response_error() {
3588        TOKIO_SHARED_RT.block_on(async {
3589            let client = MockMarketApiClient { force_error: true };
3590
3591            let params =
3592                UiKlinesParams::builder("BNBUSDT".to_string(), UiKlinesIntervalEnum::Interval1s)
3593                    .build()
3594                    .unwrap();
3595
3596            match client.ui_klines(params).await {
3597                Ok(_) => panic!("Expected an error"),
3598                Err(err) => {
3599                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3600                }
3601            }
3602        });
3603    }
3604}