Skip to main content

datamaxi/
generated.rs

1// Code generated by datamaxi-codegen. DO NOT EDIT.
2
3use self::async_internal::*;
4use crate::api::Client;
5use serde::{Deserialize, Serialize};
6
7// --- Response models ---
8
9#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10pub struct CexAnnouncementsResponse {
11    /// specifies the exchanges of the announcements
12    #[serde(default)]
13    pub category: Vec<String>,
14    /// `Data` specifies an array of the announcements
15    pub data: Vec<CexAnnouncementsView>,
16    /// specifies the categories of the announcements
17    #[serde(default)]
18    pub exchange: Vec<String>,
19    #[serde(default)]
20    pub key: Option<String>,
21    pub limit: i64,
22    pub page: i64,
23    pub sort: String,
24    pub total: i64,
25}
26
27#[derive(Debug, Clone, Default, Serialize, Deserialize)]
28pub struct CexAnnouncementsView {
29    /// specifies the category of the announcement
30    #[serde(rename = "c")]
31    pub category: String,
32    /// specifies the date of the announcement
33    #[serde(rename = "d")]
34    pub timestamp: i64,
35    /// specifies the exchange of the announcement
36    #[serde(rename = "e")]
37    pub exchange: String,
38    /// specifies the summary of the announcement
39    #[serde(rename = "s")]
40    pub summary: String,
41    /// specifies the title of the announcement
42    #[serde(rename = "t")]
43    pub title: String,
44    /// specifies the URL of the announcement
45    #[serde(rename = "u")]
46    pub url: String,
47}
48
49#[derive(Debug, Clone, Default, Serialize, Deserialize)]
50pub struct CexCandleResponse {
51    pub currency: String,
52    pub data: Vec<CexCandleView>,
53    pub exchange: String,
54    pub interval: String,
55    pub market: String,
56    pub symbol: String,
57}
58
59#[derive(Debug, Clone, Default, Serialize, Deserialize)]
60pub struct CexCandleSymbolsView {
61    /// specifies the base symbol
62    #[serde(rename = "b")]
63    pub base: String,
64    /// specifies the exchange
65    #[serde(rename = "e")]
66    pub exchange: String,
67    /// specifies the unique id
68    pub id: String,
69    /// specifies the market
70    #[serde(rename = "m")]
71    pub market: String,
72    /// specifies the quote symbol
73    #[serde(rename = "q")]
74    pub quote: String,
75    /// specifies the api symbol
76    #[serde(rename = "s")]
77    pub symbol: String,
78}
79
80#[derive(Debug, Clone, Default, Serialize, Deserialize)]
81pub struct CexCandleView {
82    /// specifies close price of the candle
83    #[serde(rename = "c")]
84    pub close: f64,
85    /// specifies the opening date and time of candle
86    #[serde(rename = "d")]
87    pub timestamp: i64,
88    /// specifies high price of the candle
89    #[serde(rename = "h")]
90    pub high: f64,
91    /// specifies low price of the candle
92    #[serde(rename = "l")]
93    pub low: f64,
94    /// specifies open price of the candle
95    #[serde(rename = "o")]
96    pub open: f64,
97    /// specifies trading volume (base token) of the candle
98    #[serde(rename = "v")]
99    pub volume: f64,
100}
101
102#[derive(Debug, Clone, Default, Serialize, Deserialize)]
103pub struct CexFeesView {
104    /// specifies base symbol
105    pub base: String,
106    /// specifies exchange
107    pub exchange: String,
108    /// specifies maker fee percentage for futures market
109    #[serde(default)]
110    pub futures_maker_fee: Option<f64>,
111    /// specifies taker fee percentage for futures market
112    #[serde(default)]
113    pub futures_taker_fee: Option<f64>,
114    /// specifies quote symbol
115    pub quote: String,
116    /// specifies maker fee percentage for spot market (e.g. 0.001 = 0.1%)
117    #[serde(default)]
118    pub spot_maker_fee: Option<f64>,
119    /// specifies taker fee percentage for spot market
120    #[serde(default)]
121    pub spot_take_fee: Option<f64>,
122    /// specifies symbol
123    pub symbol: String,
124}
125
126#[derive(Debug, Clone, Default, Serialize, Deserialize)]
127pub struct CexSymbolCautionsView {
128    #[serde(rename = "b")]
129    pub base: String,
130    /// caution | warning | danger
131    pub caution_level: String,
132    #[serde(rename = "e")]
133    pub exchange: String,
134    /// ms, 0 = indefinite
135    #[serde(default)]
136    pub end_at: Option<i64>,
137    #[serde(rename = "m")]
138    pub market: String,
139    #[serde(rename = "q")]
140    pub quote: String,
141    #[serde(default)]
142    pub reasons: Vec<String>,
143}
144
145#[derive(Debug, Clone, Default, Serialize, Deserialize)]
146pub struct CexSymbolDelistingsView {
147    #[serde(rename = "b")]
148    pub base: String,
149    /// ms (scheduled or past)
150    pub delisting_at: i64,
151    #[serde(rename = "e")]
152    pub exchange: String,
153    /// ms
154    #[serde(default)]
155    pub listed_at: Option<i64>,
156    #[serde(rename = "m")]
157    pub market: String,
158    #[serde(rename = "q")]
159    pub quote: String,
160    /// delisting | delisted
161    pub status: String,
162}
163
164#[derive(Debug, Clone, Default, Serialize, Deserialize)]
165pub struct CexSymbolLiquidationView {
166    #[serde(rename = "b")]
167    pub base: String,
168    #[serde(rename = "e")]
169    pub exchange: String,
170    pub event_count: i64,
171    pub long_volume: f64,
172    #[serde(default)]
173    pub long_volume_usd: Option<f64>,
174    /// always "futures"
175    #[serde(rename = "m")]
176    pub market: String,
177    #[serde(rename = "q")]
178    pub quote: String,
179    pub short_volume: f64,
180    #[serde(default)]
181    pub short_volume_usd: Option<f64>,
182    pub total_volume: f64,
183    #[serde(default)]
184    pub total_volume_usd: Option<f64>,
185}
186
187#[derive(Debug, Clone, Default, Serialize, Deserialize)]
188pub struct CexSymbolMetadataView {
189    #[serde(rename = "b")]
190    pub base: String,
191    /// ms
192    #[serde(default)]
193    pub caution_end_at: Option<i64>,
194    /// "", caution, warning, danger
195    #[serde(default)]
196    pub caution_level: Option<String>,
197    #[serde(default)]
198    pub caution_reasons: Vec<String>,
199    #[serde(default)]
200    pub delisting_at: Option<i64>,
201    #[serde(rename = "e")]
202    pub exchange: String,
203    #[serde(default)]
204    pub listed_at: Option<i64>,
205    /// "spot" | "futures"
206    #[serde(rename = "m")]
207    pub market: String,
208    #[serde(rename = "q")]
209    pub quote: String,
210    /// trading|pre_listing|halt|close_only|delisting|delisted
211    pub status: String,
212    #[serde(default)]
213    pub tags: Vec<String>,
214}
215
216#[derive(Debug, Clone, Default, Serialize, Deserialize)]
217pub struct CexSymbolOiStatsView {
218    #[serde(rename = "b")]
219    pub base: String,
220    /// %
221    #[serde(default)]
222    pub change_1h: Option<f64>,
223    /// %
224    #[serde(default)]
225    pub change_24h: Option<f64>,
226    /// %
227    #[serde(default)]
228    pub change_4h: Option<f64>,
229    #[serde(rename = "e")]
230    pub exchange: String,
231    /// always "futures"
232    #[serde(rename = "m")]
233    pub market: String,
234    #[serde(default)]
235    pub oi_to_vol_ratio: Option<f64>,
236    pub open_interest: f64,
237    #[serde(default)]
238    pub open_interest_usd: Option<f64>,
239    #[serde(rename = "q")]
240    pub quote: String,
241    #[serde(default)]
242    pub token_id: Option<String>,
243    pub ts: i64,
244    #[serde(default)]
245    pub volume_24h_usd: Option<f64>,
246}
247
248#[derive(Debug, Clone, Default, Serialize, Deserialize)]
249pub struct CexSymbolOiView {
250    #[serde(rename = "b")]
251    pub base: String,
252    #[serde(rename = "e")]
253    pub exchange: String,
254    /// always "futures" for OI
255    #[serde(rename = "m")]
256    pub market: String,
257    pub open_interest: f64,
258    #[serde(default)]
259    pub open_interest_usd: Option<f64>,
260    #[serde(rename = "q")]
261    pub quote: String,
262    pub ts: i64,
263}
264
265#[derive(Debug, Clone, Default, Serialize, Deserialize)]
266pub struct CexSymbolTagsView {
267    #[serde(rename = "b")]
268    pub base: String,
269    pub confidence: i64,
270    #[serde(rename = "e")]
271    pub exchange: String,
272    #[serde(rename = "m")]
273    pub market: String,
274    #[serde(rename = "q")]
275    pub quote: String,
276    pub source: String,
277    pub tag: String,
278}
279
280#[derive(Debug, Clone, Default, Serialize, Deserialize)]
281pub struct CexSymbolVolumeView {
282    #[serde(rename = "b")]
283    pub base: String,
284    #[serde(rename = "e")]
285    pub exchange: String,
286    /// spot | futures
287    #[serde(rename = "m")]
288    pub market: String,
289    #[serde(rename = "q")]
290    pub quote: String,
291    /// USD-ish, dashboard-friendly
292    pub quote_volume: f64,
293    /// ms, collector wall-time
294    pub ts: i64,
295    /// base-denominated (raw)
296    pub volume: f64,
297}
298
299#[derive(Debug, Clone, Default, Serialize, Deserialize)]
300pub struct CexTokenUpdatesResponse {
301    /// `data` specifies an array of the token updates
302    pub data: Vec<CexTokenUpdatesView>,
303    #[serde(default)]
304    pub key: Option<String>,
305    pub limit: i64,
306    pub page: i64,
307    pub sort: String,
308    pub total: i64,
309}
310
311#[derive(Debug, Clone, Default, Serialize, Deserialize)]
312pub struct CexTokenUpdatesView {
313    /// Specifies the base token
314    #[serde(rename = "b")]
315    pub base: String,
316    /// Specifies the timestamp
317    #[serde(rename = "d")]
318    pub timestamp: i64,
319    /// Specifies the exchange
320    #[serde(rename = "e")]
321    pub exchange: String,
322    /// Specifies the market
323    #[serde(rename = "m")]
324    pub market: String,
325    /// Specifies the quote token
326    #[serde(rename = "q")]
327    pub quote: String,
328    /// Specifies the type of the token update (listed or delisted)
329    #[serde(rename = "t")]
330    pub update_type: String,
331}
332
333#[derive(Debug, Clone, Default, Serialize, Deserialize)]
334pub struct ForexResponse {
335    /// specifies the unix timestamp of the forex rate
336    #[serde(rename = "d")]
337    pub timestamp: i64,
338    /// specifies the forex rate
339    #[serde(rename = "r")]
340    pub rate: f64,
341    /// specifies the name of the forex symbol
342    #[serde(rename = "s")]
343    pub symbol: String,
344}
345
346#[derive(Debug, Clone, Default, Serialize, Deserialize)]
347pub struct FundingRateHistoryResponse {
348    pub data: Vec<FundingRateHistoryView>,
349    pub exchange: String,
350    pub limit: i64,
351    pub page: i64,
352    pub sort: String,
353    pub symbol: String,
354}
355
356#[derive(Debug, Clone, Default, Serialize, Deserialize)]
357pub struct FundingRateHistoryView {
358    /// specifies the date and time in UNIX timestamp format
359    #[serde(rename = "d")]
360    pub timestamp: i64,
361    /// specifies the funding rate
362    #[serde(rename = "f", default)]
363    pub funding_rate: Option<f64>,
364}
365
366#[derive(Debug, Clone, Default, Serialize, Deserialize)]
367pub struct FundingRateLatestResponse {
368    /// Specifies the base
369    #[serde(rename = "b")]
370    pub base: String,
371    /// Specifies the timestamp
372    #[serde(rename = "d")]
373    pub timestamp: i64,
374    /// Specifies the exchange
375    #[serde(rename = "e")]
376    pub exchange: String,
377    /// Specifies the funding rate
378    #[serde(rename = "f", default)]
379    pub funding_rate: Option<f64>,
380    /// Specifies the interval hours
381    #[serde(rename = "i", default)]
382    pub interval_hours: Option<i64>,
383    /// Specifies the token id
384    #[serde(rename = "id")]
385    pub token_id: String,
386    /// Specifies the quote
387    #[serde(rename = "q")]
388    pub quote: String,
389    /// Specifies the symbol
390    #[serde(rename = "s")]
391    pub symbol: String,
392}
393
394#[derive(Debug, Clone, Default, Serialize, Deserialize)]
395pub struct FundingRateSymbolsView {
396    /// specifies the base symbol
397    #[serde(rename = "b")]
398    pub base: String,
399    /// specifies the exchange
400    #[serde(rename = "e")]
401    pub exchange: String,
402    /// specifies the unique id
403    pub id: String,
404    /// specifies the market
405    #[serde(rename = "m")]
406    pub market: String,
407    /// specifies the quote symbol
408    #[serde(rename = "q")]
409    pub quote: String,
410    /// specifies the api symbol
411    #[serde(rename = "s")]
412    pub symbol: String,
413}
414
415#[derive(Debug, Clone, Default, Serialize, Deserialize)]
416pub struct IndexPriceResponse {
417    pub data: Vec<IndexPriceView>,
418}
419
420#[derive(Debug, Clone, Default, Serialize, Deserialize)]
421pub struct IndexPriceView {
422    pub price: f64,
423    pub timestamp: i64,
424    pub volume: f64,
425}
426
427#[derive(Debug, Clone, Default, Serialize, Deserialize)]
428pub struct LiquidationEntry {
429    pub base: String,
430    pub exchange: String,
431    pub price: f64,
432    #[serde(rename = "priceUsd", default)]
433    pub price_usd: Option<f64>,
434    pub quote: String,
435    pub side: String,
436    pub symbol: String,
437    pub timestamp: i64,
438    #[serde(rename = "tokenId")]
439    pub token_id: String,
440    pub volume: f64,
441    #[serde(rename = "volumeUsd", default)]
442    pub volume_usd: Option<f64>,
443}
444
445#[derive(Debug, Clone, Default, Serialize, Deserialize)]
446pub struct LiquidationFeedEntry {
447    pub base: String,
448    pub exchange: String,
449    pub price: f64,
450    #[serde(rename = "priceUsd", default)]
451    pub price_usd: Option<f64>,
452    pub quote: String,
453    pub side: String,
454    pub symbol: String,
455    pub timestamp: i64,
456    #[serde(rename = "tokenId")]
457    pub token_id: String,
458    pub volume: f64,
459    #[serde(rename = "volumeUsd", default)]
460    pub volume_usd: Option<f64>,
461}
462
463#[derive(Debug, Clone, Default, Serialize, Deserialize)]
464pub struct LiquidationFeedResponse {
465    pub data: Vec<LiquidationFeedEntry>,
466}
467
468#[derive(Debug, Clone, Default, Serialize, Deserialize)]
469pub struct LiquidationHeatmapCell {
470    pub base: String,
471    pub exchange: String,
472    #[serde(rename = "longUsd")]
473    pub long_usd: f64,
474    #[serde(rename = "shortUsd")]
475    pub short_usd: f64,
476    #[serde(rename = "tokenId")]
477    pub token_id: String,
478    #[serde(rename = "totalUsd")]
479    pub total_usd: f64,
480}
481
482#[derive(Debug, Clone, Default, Serialize, Deserialize)]
483pub struct LiquidationHeatmapExchangesummary {
484    pub exchange: String,
485    #[serde(rename = "longUsd")]
486    pub long_usd: f64,
487    #[serde(rename = "shortUsd")]
488    pub short_usd: f64,
489    #[serde(rename = "totalUsd")]
490    pub total_usd: f64,
491}
492
493#[derive(Debug, Clone, Default, Serialize, Deserialize)]
494pub struct LiquidationHeatmapResponse {
495    /// (top tokens) × (all exchanges with data)
496    pub cells: Vec<LiquidationHeatmapCell>,
497    /// sorted desc, includes only venues with data
498    pub exchanges: Vec<LiquidationHeatmapExchangesummary>,
499    /// ms
500    #[serde(rename = "generatedAt")]
501    pub generated_at: i64,
502    #[serde(rename = "grandTotal")]
503    pub grand_total: f64,
504    /// top N by TotalUsd desc
505    pub tokens: Vec<LiquidationHeatmapTokensummary>,
506    /// "1h" | "4h" | "24h"
507    pub window: String,
508}
509
510#[derive(Debug, Clone, Default, Serialize, Deserialize)]
511pub struct LiquidationHeatmapTokensummary {
512    pub base: String,
513    #[serde(rename = "longUsd")]
514    pub long_usd: f64,
515    pub name: String,
516    #[serde(rename = "shortUsd")]
517    pub short_usd: f64,
518    pub symbol: String,
519    #[serde(rename = "tokenId")]
520    pub token_id: String,
521    #[serde(rename = "totalUsd")]
522    pub total_usd: f64,
523}
524
525#[derive(Debug, Clone, Default, Serialize, Deserialize)]
526pub struct LiquidationMapAssumptions {
527    #[serde(rename = "entrySamples")]
528    pub entry_samples: i64,
529    #[serde(rename = "entryWindow")]
530    pub entry_window: String,
531    #[serde(rename = "longShareOfOi")]
532    pub long_share_of_oi: f64,
533    pub mmr: f64,
534    pub tiers: Vec<LiquidationMapTierassumption>,
535}
536
537#[derive(Debug, Clone, Default, Serialize, Deserialize)]
538pub struct LiquidationMapBucket {
539    #[serde(rename = "l100xUsd")]
540    pub l100x_usd: f64,
541    #[serde(rename = "l10xUsd")]
542    pub l10x_usd: f64,
543    #[serde(rename = "l25xUsd")]
544    pub l25x_usd: f64,
545    #[serde(rename = "l50xUsd")]
546    pub l50x_usd: f64,
547    pub price: f64,
548    pub side: String,
549    #[serde(rename = "totalUsd")]
550    pub total_usd: f64,
551}
552
553#[derive(Debug, Clone, Default, Serialize, Deserialize)]
554pub struct LiquidationMapResponse {
555    pub assumptions: LiquidationMapAssumptions,
556    pub base: String,
557    pub buckets: Vec<LiquidationMapBucket>,
558    #[serde(rename = "cumulativeLongUsd")]
559    pub cumulative_long_usd: f64,
560    #[serde(rename = "cumulativeShortUsd")]
561    pub cumulative_short_usd: f64,
562    #[serde(rename = "currentPrice")]
563    pub current_price: f64,
564    pub exchange: String,
565    #[serde(rename = "generatedAt")]
566    pub generated_at: i64,
567    pub quote: String,
568    pub symbol: String,
569    #[serde(rename = "totalOiUsd")]
570    pub total_oi_usd: f64,
571}
572
573#[derive(Debug, Clone, Default, Serialize, Deserialize)]
574pub struct LiquidationMapTierassumption {
575    pub leverage: i64,
576    pub share: f64,
577}
578
579#[derive(Debug, Clone, Default, Serialize, Deserialize)]
580pub struct LiquidationResponse {
581    pub data: Vec<LiquidationEntry>,
582}
583
584#[derive(Debug, Clone, Default, Serialize, Deserialize)]
585pub struct LiquidationStatsBiggest {
586    pub base: String,
587    pub exchange: String,
588    pub quote: String,
589    #[serde(rename = "volumeUsd")]
590    pub volume_usd: f64,
591}
592
593#[derive(Debug, Clone, Default, Serialize, Deserialize)]
594pub struct LiquidationStatsResponse {
595    #[serde(default)]
596    pub biggest: Option<LiquidationStatsBiggest>,
597    /// number of events
598    pub count: i64,
599    /// ms
600    #[serde(rename = "generatedAt")]
601    pub generated_at: i64,
602    /// round(long/total*100), 0 when empty
603    #[serde(rename = "longRatio")]
604    pub long_ratio: i64,
605    /// sell-side
606    #[serde(rename = "longUsd")]
607    pub long_usd: f64,
608    /// buy-side
609    #[serde(rename = "shortUsd")]
610    pub short_usd: f64,
611    /// long + short
612    pub total: f64,
613    /// distinct exchanges
614    pub venues: i64,
615    /// "1h" | "4h" | "24h"
616    pub window: String,
617}
618
619#[derive(Debug, Clone, Default, Serialize, Deserialize)]
620pub struct LiquidationSymbolHistoryBucket {
621    #[serde(rename = "longUsd")]
622    pub long_usd: f64,
623    #[serde(default)]
624    pub price: Option<f64>,
625    #[serde(rename = "shortUsd")]
626    pub short_usd: f64,
627    #[serde(rename = "totalUsd")]
628    pub total_usd: f64,
629    pub ts: i64,
630}
631
632#[derive(Debug, Clone, Default, Serialize, Deserialize)]
633pub struct LiquidationSymbolHistoryResponse {
634    pub buckets: Vec<LiquidationSymbolHistoryBucket>,
635    pub exchange: String,
636    #[serde(rename = "generatedAt")]
637    pub generated_at: i64,
638    pub interval: String,
639    pub quote: String,
640    pub symbol: String,
641    #[serde(rename = "totalLongUsd")]
642    pub total_long_usd: f64,
643    #[serde(rename = "totalShortUsd")]
644    pub total_short_usd: f64,
645    pub window: String,
646}
647
648#[derive(Debug, Clone, Default, Serialize, Deserialize)]
649pub struct ListingsHistoricalResponse {
650    pub data: Vec<ListingsHistoricalView>,
651}
652
653#[derive(Debug, Clone, Default, Serialize, Deserialize)]
654pub struct ListingsHistoricalView {
655    pub announced_at: i64,
656    pub base: String,
657    #[serde(default)]
658    pub deposit_at: Option<i64>,
659    pub exchange: String,
660    #[serde(default)]
661    pub network: Option<String>,
662    #[serde(default)]
663    pub trade_at: Option<i64>,
664    pub url: String,
665}
666
667#[derive(Debug, Clone, Default, Serialize, Deserialize)]
668pub struct MarginBorrowResponse {
669    pub cross: serde_json::Value,
670    pub isolated: serde_json::Value,
671}
672
673#[derive(Debug, Clone, Default, Serialize, Deserialize)]
674pub struct NaverTrendView {
675    #[serde(rename = "d")]
676    pub timestamp: i64,
677    #[serde(rename = "v")]
678    pub value: f64,
679}
680
681#[derive(Debug, Clone, Default, Serialize, Deserialize)]
682pub struct OpenInterestHistoryAggregatedResponse {
683    /// Data is keyed by exchange id → time-series points ordered by t asc.
684    pub data: serde_json::Value,
685    pub exchange_url: serde_json::Value,
686    pub token: TokenDetail,
687}
688
689#[derive(Debug, Clone, Default, Serialize, Deserialize)]
690pub struct OpenInterestListEntry {
691    pub base: String,
692    pub exchange: String,
693    #[serde(rename = "openInterest")]
694    pub open_interest: f64,
695    #[serde(rename = "openInterestUsd", default)]
696    pub open_interest_usd: Option<f64>,
697    pub quote: String,
698    pub symbol: String,
699    pub timestamp: i64,
700    #[serde(rename = "tokenId")]
701    pub token_id: String,
702}
703
704#[derive(Debug, Clone, Default, Serialize, Deserialize)]
705pub struct OpenInterestListResponse {
706    pub data: Vec<OpenInterestListEntry>,
707}
708
709#[derive(Debug, Clone, Default, Serialize, Deserialize)]
710pub struct OpenInterestOverviewResponse {
711    pub data: Vec<OpenInterestOverviewView>,
712    #[serde(default)]
713    pub key: Option<String>,
714    pub limit: i64,
715    pub page: i64,
716    pub sort: String,
717    pub total: i64,
718}
719
720#[derive(Debug, Clone, Default, Serialize, Deserialize)]
721pub struct OpenInterestOverviewView {
722    pub exchanges: serde_json::Value,
723    pub id: String,
724    pub token: TokenDetail,
725}
726
727#[derive(Debug, Clone, Default, Serialize, Deserialize)]
728pub struct OpenInterestResponse {
729    pub base: String,
730    pub exchange: String,
731    #[serde(rename = "openInterest")]
732    pub open_interest: f64,
733    #[serde(rename = "openInterestUsd", default)]
734    pub open_interest_usd: Option<f64>,
735    pub quote: String,
736    pub symbol: String,
737    pub timestamp: i64,
738    #[serde(rename = "tokenId")]
739    pub token_id: String,
740}
741
742#[derive(Debug, Clone, Default, Serialize, Deserialize)]
743pub struct OpenInterestSummaryExchangesummary {
744    pub exchange: String,
745    #[serde(rename = "openInterestUsd")]
746    pub open_interest_usd: f64,
747    pub tokens: i64,
748}
749
750#[derive(Debug, Clone, Default, Serialize, Deserialize)]
751pub struct OpenInterestSummaryResponse {
752    pub exchanges: Vec<OpenInterestSummaryExchangesummary>,
753    #[serde(rename = "generatedAt")]
754    pub generated_at: i64,
755    #[serde(rename = "grandTotal")]
756    pub grand_total: f64,
757    pub tokens: Vec<OpenInterestSummaryTokensummary>,
758    #[serde(rename = "totalTokens")]
759    pub total_tokens: i64,
760}
761
762#[derive(Debug, Clone, Default, Serialize, Deserialize)]
763pub struct OpenInterestSummaryTokensummary {
764    pub base: String,
765    pub icon: String,
766    pub name: String,
767    #[serde(rename = "openInterestUsd")]
768    pub open_interest_usd: f64,
769    pub symbol: String,
770    #[serde(rename = "tokenId")]
771    pub token_id: String,
772    pub venues: i64,
773}
774
775#[derive(Debug, Clone, Default, Serialize, Deserialize)]
776pub struct PremiumDetail {
777    pub bid: String,
778    /// specifies the date and the time in UTC milliseconds
779    pub d: i64,
780    /// funding gap which is difference between source and target fundingrate without funding interval consideration
781    #[serde(default)]
782    pub fg: Option<f64>,
783    /// net fundingrate which takes funding interval into account
784    #[serde(default)]
785    pub nfr: Option<f64>,
786    /// specifies the price difference percentage between the source and target exchanges
787    #[serde(default)]
788    pub pdp: Option<f64>,
789    /// specifies the price difference percentage between the source and target exchanges 15m ago
790    #[serde(default)]
791    pub pdp15m: Option<f64>,
792    /// specifies the price difference percentage between the source and target exchanges 1h ago
793    #[serde(default)]
794    pub pdp1h: Option<f64>,
795    /// specifies the price difference percentage between the source and target exchanges 24h ago
796    #[serde(default)]
797    pub pdp24h: Option<f64>,
798    /// specifies the price difference percentage between the source and target exchanges 30m ago
799    #[serde(default)]
800    pub pdp30m: Option<f64>,
801    /// specifies the price difference percentage between the source and target exchanges 4h ago
802    #[serde(default)]
803    pub pdp4h: Option<f64>,
804    /// specifies the price difference percentage between the source and target exchanges 5m ago
805    #[serde(default)]
806    pub pdp5m: Option<f64>,
807    /// sepcifies premium duration
808    #[serde(default)]
809    pub pmd: Option<i64>,
810    /// source ask depth within +2% base
811    #[serde(default)]
812    pub sad: Option<f64>,
813    /// specifies -2% volume depth from source exchange
814    #[serde(default)]
815    pub sad2p: Option<f64>,
816    /// source ask depth within +2% quote
817    #[serde(default)]
818    pub sadf: Option<f64>,
819    /// specifies the base token of the source exchange
820    pub sb: String,
821    /// specifies +2% volume depth from source exchange
822    #[serde(default)]
823    pub sbd2p: Option<f64>,
824    /// for amm source ticker, amm source chain
825    #[serde(default)]
826    pub sc: Option<String>,
827    /// specifies the source exchange name
828    pub se: String,
829    /// source funding rate
830    #[serde(default)]
831    pub sfr: Option<f64>,
832    /// source funding rate interval, 1 stands for 1 hour
833    #[serde(default)]
834    pub sfri: Option<i64>,
835    /// source fundingrate info timestamp in UTC millisecond
836    #[serde(default)]
837    pub sfrt: Option<i64>,
838    /// specifies highest bid from source exchange
839    #[serde(default)]
840    pub shb: Option<f64>,
841    /// specifies lowest bid from source exchange
842    #[serde(default)]
843    pub sla: Option<f64>,
844    /// specifies the source market type
845    pub sm: String,
846    /// boolean if source exchange margin is supported, returned only for spot market
847    #[serde(default)]
848    pub sms: Option<bool>,
849    /// source next distribution time in UTC milliseconds
850    #[serde(default)]
851    pub snd: Option<i64>,
852    /// Open Interest snapshot — USD-denominated. Source and target sides.
853    #[serde(default)]
854    pub soi: Option<f64>,
855    /// OI % change over rolling 1h / 4h / 24h windows.
856    #[serde(default)]
857    pub soich1h: Option<f64>,
858    #[serde(default)]
859    pub soich24h: Option<f64>,
860    #[serde(default)]
861    pub soich4h: Option<f64>,
862    /// OI / 24h USD quote volume. Crude "leverage per turnover" metric.
863    #[serde(default)]
864    pub soivr: Option<f64>,
865    /// specifies the latest price of the source exchange in requested currency
866    #[serde(default)]
867    pub sp: Option<f64>,
868    /// for amm source ticker, amm pool address
869    #[serde(default)]
870    pub spa: Option<String>,
871    /// specifies the price difference percentage of the source exchange in the last 15m
872    #[serde(default)]
873    pub spdp15m: Option<f64>,
874    /// specifies the price difference percentage of the source exchange in the last 1h
875    #[serde(default)]
876    pub spdp1h: Option<f64>,
877    /// specifies the price difference percentage of the source exchange in the last 24h
878    #[serde(default)]
879    pub spdp24h: Option<f64>,
880    /// specifies the price difference percentage of the source exchange in the last 30m
881    #[serde(default)]
882    pub spdp30m: Option<f64>,
883    /// specifies the price difference percentage of the source exchange in the last 4h
884    #[serde(default)]
885    pub spdp4h: Option<f64>,
886    /// specifies the price difference percentage of the source exchange in the last 5m
887    #[serde(default)]
888    pub spdp5m: Option<f64>,
889    /// specifies the quote token of the source exchange
890    pub sq: String,
891    /// specifies the date and the time of source ticker in UTC milliseconds
892    pub st: i64,
893    /// specifies the trading volume of the source exchange in the last 24 hours in requested currency
894    #[serde(default)]
895    pub sv: Option<f64>,
896    /// transferable, null if unknown
897    #[serde(default)]
898    pub t: Option<bool>,
899    /// specifies -2% volume depth from target exchange
900    #[serde(default)]
901    pub tad2p: Option<f64>,
902    /// specifies the base token of the target exchange
903    pub tb: String,
904    /// target bid depth within -2% base
905    #[serde(default)]
906    pub tbd: Option<f64>,
907    /// specifies +2% volume depth from target exchange
908    #[serde(default)]
909    pub tbd2p: Option<f64>,
910    /// target bid depth within -2% quote
911    #[serde(default)]
912    pub tbdf: Option<f64>,
913    /// for amm target ticker, amm target chain
914    #[serde(default)]
915    pub tc: Option<String>,
916    /// specifies the target exchange name
917    pub te: String,
918    /// target funding rate
919    #[serde(default)]
920    pub tfr: Option<f64>,
921    /// target funding rate interval, 1 stands for 1 hour
922    #[serde(default)]
923    pub tfri: Option<i64>,
924    /// target fundingrate info timestamp in UTC millisecond
925    #[serde(default)]
926    pub tfrt: Option<i64>,
927    /// specifies highest bid from target exchange
928    #[serde(default)]
929    pub thb: Option<f64>,
930    /// specifies lowest bid from target exchange
931    #[serde(default)]
932    pub tla: Option<f64>,
933    /// specifies the target market type
934    pub tm: String,
935    /// boolean if target exchange margin is supported, returned only for spot market
936    #[serde(default)]
937    pub tms: Option<bool>,
938    /// target next distribution time in UTC millisconds
939    #[serde(default)]
940    pub tnd: Option<i64>,
941    #[serde(default)]
942    pub toi: Option<f64>,
943    #[serde(default)]
944    pub toich1h: Option<f64>,
945    #[serde(default)]
946    pub toich24h: Option<f64>,
947    #[serde(default)]
948    pub toich4h: Option<f64>,
949    #[serde(default)]
950    pub toivr: Option<f64>,
951    /// specifies the latest price of the target exchange
952    #[serde(default)]
953    pub tp: Option<f64>,
954    /// for amm target ticker, amm pool address
955    #[serde(default)]
956    pub tpa: Option<String>,
957    /// specifies the price difference percentage of the target exchange in the last 15m
958    #[serde(default)]
959    pub tpdp15m: Option<f64>,
960    /// specifies the price difference percentage of the target exchange in the last 1h
961    #[serde(default)]
962    pub tpdp1h: Option<f64>,
963    /// specifies the price difference percentage of the target exchange in the last 24h
964    #[serde(default)]
965    pub tpdp24h: Option<f64>,
966    /// specifies the price difference percentage of the target exchange in the last 30m
967    #[serde(default)]
968    pub tpdp30m: Option<f64>,
969    /// specifies the price difference percentage of the target exchange in the last 4h
970    #[serde(default)]
971    pub tpdp4h: Option<f64>,
972    /// specifies the price difference percentage of the target exchange in the last 5m
973    #[serde(default)]
974    pub tpdp5m: Option<f64>,
975    /// specifies the quote token of the target exchange
976    pub tq: String,
977    /// specifies the date and the time of target ticker in UTC milliseconds
978    pub tt: i64,
979    /// specifies the trading volume of the target exchange in the last 24 hours in requested currency
980    #[serde(default)]
981    pub tv: Option<f64>,
982}
983
984#[derive(Debug, Clone, Default, Serialize, Deserialize)]
985pub struct PremiumResponse {
986    #[serde(default)]
987    pub conversion_base: Option<String>,
988    #[serde(default)]
989    pub currency: Option<String>,
990    pub data: Vec<PremiumView>,
991    #[serde(default)]
992    pub key: Option<String>,
993    pub limit: i64,
994    pub page: i64,
995    pub sort: String,
996    pub total: i64,
997}
998
999#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1000pub struct PremiumView {
1001    pub detail: PremiumDetail,
1002    #[serde(default)]
1003    pub source_annualized_funding_rate: Option<f64>,
1004    #[serde(default)]
1005    pub target_annualized_funding_rate: Option<f64>,
1006}
1007
1008#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1009pub struct TelegramChannelsResponse {
1010    #[serde(default)]
1011    pub category: Option<String>,
1012    pub data: Vec<TelegramChannelsView>,
1013    #[serde(default)]
1014    pub key: Option<String>,
1015    pub limit: i64,
1016    pub page: i64,
1017    pub sort: String,
1018    pub total: i64,
1019}
1020
1021#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1022pub struct TelegramChannelsView {
1023    /// specifies the channel category
1024    pub category: String,
1025    /// specifies the channel name
1026    #[serde(rename = "channelName")]
1027    pub channel_name: String,
1028    /// specifies the channel title
1029    #[serde(rename = "channelTitle")]
1030    pub channel_title: String,
1031    /// specifies the creation time of the channel
1032    #[serde(rename = "createdAt", default)]
1033    pub created_at: Option<i64>,
1034    /// specifies the channel description
1035    pub description: String,
1036    /// specifies the channel link
1037    pub link: String,
1038    /// specifies the number of subscribers
1039    pub subscribers: i64,
1040}
1041
1042#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1043pub struct TelegramMessagesResponse {
1044    #[serde(default)]
1045    pub category: Option<String>,
1046    /// specifies an array of the Telegram messages
1047    pub data: Vec<TelegramMessagesView>,
1048    #[serde(default)]
1049    pub key: Option<String>,
1050    pub limit: i64,
1051    pub page: i64,
1052    pub sort: String,
1053    pub total: i64,
1054}
1055
1056#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1057pub struct TelegramMessagesView {
1058    /// specifies the channel handle
1059    #[serde(rename = "channelHandle")]
1060    pub channel_handle: String,
1061    /// specifies the channel id
1062    #[serde(rename = "channelId")]
1063    pub channel_id: String,
1064    /// specifies the channel name
1065    #[serde(rename = "channelName")]
1066    pub channel_name: String,
1067    /// specifies the number of forwards
1068    pub forwards: i64,
1069    /// specifies the message text
1070    pub message: String,
1071    /// specifies the message id
1072    #[serde(rename = "messageId")]
1073    pub message_id: String,
1074    /// specifies the link to Telegram message
1075    #[serde(rename = "messageLink")]
1076    pub message_link: String,
1077    /// specifies the published date
1078    #[serde(rename = "publishedAt")]
1079    pub published_at: i64,
1080    /// specifies the number of reactions
1081    pub reactions: i64,
1082    /// specifies the number of views
1083    pub views: i64,
1084}
1085
1086#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1087pub struct TickerResponse {
1088    pub currency: String,
1089    pub data: TickerView,
1090    pub market: String,
1091}
1092
1093#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1094pub struct TickerView {
1095    /// specifies the base token
1096    #[serde(rename = "b")]
1097    pub base: String,
1098    /// specifies the date and the time in UTC milliseconds
1099    #[serde(rename = "d")]
1100    pub timestamp: i64,
1101    /// specifies the exchange name
1102    #[serde(rename = "e")]
1103    pub exchange: String,
1104    /// highest bid from orderbook
1105    #[serde(rename = "hb", default)]
1106    pub highest_bid: Option<f64>,
1107    /// lowest ask from orderbook
1108    #[serde(rename = "la", default)]
1109    pub lowest_ask: Option<f64>,
1110    /// lower depth(2%)
1111    #[serde(rename = "ld", default)]
1112    pub lower_depth: Option<f64>,
1113    /// specifies the market type
1114    #[serde(rename = "m")]
1115    pub market: String,
1116    /// specifies the latest price
1117    #[serde(rename = "p", default)]
1118    pub price: Option<f64>,
1119    /// specifies the price 24 hours ago
1120    #[serde(rename = "p24h", default)]
1121    pub price_24h: Option<f64>,
1122    /// specified price change between the latest price and the price 24 hours ago
1123    #[serde(rename = "pc", default)]
1124    pub price_change: Option<f64>,
1125    /// specifies the quote token
1126    #[serde(rename = "q")]
1127    pub quote: String,
1128    /// specifies the symbol (base-quote)
1129    #[serde(rename = "s")]
1130    pub symbol: String,
1131    /// upper depth(2%)
1132    #[serde(rename = "ud", default)]
1133    pub upper_depth: Option<f64>,
1134    /// specifies the trading volume in the last 24 hours
1135    #[serde(rename = "v", default)]
1136    pub volume: Option<f64>,
1137}
1138
1139#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1140pub struct TokenDetail {
1141    /// specifies cmc id of the token
1142    #[serde(default)]
1143    pub cmc_id: Option<String>,
1144    /// specifies the token icon url path
1145    pub icon: String,
1146    /// specifies the unique id
1147    pub id: String,
1148    /// specifies the name of token
1149    pub name: String,
1150    /// specifies the token symbol
1151    pub symbol: String,
1152}
1153
1154#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1155pub struct WalletStatusView {
1156    pub currency: String,
1157    pub deposit_message: String,
1158    pub deposit_state: String,
1159    pub exchange: String,
1160    pub network: String,
1161    pub updated_at: i64,
1162    pub withdraw_message: String,
1163    pub withdraw_state: String,
1164}
1165
1166// --- Announcements ---
1167
1168/// Specifies sort
1169#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1170#[allow(non_camel_case_types)]
1171#[non_exhaustive]
1172pub enum CexAnnouncementsSort {
1173    Asc,
1174    Desc,
1175}
1176
1177impl CexAnnouncementsSort {
1178    /// The exact wire value this variant serializes to.
1179    pub fn as_str(&self) -> &'static str {
1180        match self {
1181            CexAnnouncementsSort::Asc => "asc",
1182            CexAnnouncementsSort::Desc => "desc",
1183        }
1184    }
1185}
1186
1187impl std::fmt::Display for CexAnnouncementsSort {
1188    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1189        f.write_str(self.as_str())
1190    }
1191}
1192
1193/// Specifies key to sort by
1194#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1195#[allow(non_camel_case_types)]
1196#[non_exhaustive]
1197pub enum CexAnnouncementsKey {
1198    Exchange,
1199    Category,
1200    Title,
1201    Timestamp,
1202}
1203
1204impl CexAnnouncementsKey {
1205    /// The exact wire value this variant serializes to.
1206    pub fn as_str(&self) -> &'static str {
1207        match self {
1208            CexAnnouncementsKey::Exchange => "exchange",
1209            CexAnnouncementsKey::Category => "category",
1210            CexAnnouncementsKey::Title => "title",
1211            CexAnnouncementsKey::Timestamp => "timestamp",
1212        }
1213    }
1214}
1215
1216impl std::fmt::Display for CexAnnouncementsKey {
1217    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1218        f.write_str(self.as_str())
1219    }
1220}
1221
1222/// Specifies category(s), separated by ,
1223#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1224#[allow(non_camel_case_types)]
1225#[non_exhaustive]
1226pub enum CexAnnouncementsCategory {
1227    Notice,
1228    Listing,
1229    Delisting,
1230    UserEvents,
1231}
1232
1233impl CexAnnouncementsCategory {
1234    /// The exact wire value this variant serializes to.
1235    pub fn as_str(&self) -> &'static str {
1236        match self {
1237            CexAnnouncementsCategory::Notice => "notice",
1238            CexAnnouncementsCategory::Listing => "listing",
1239            CexAnnouncementsCategory::Delisting => "delisting",
1240            CexAnnouncementsCategory::UserEvents => "user_events",
1241        }
1242    }
1243}
1244
1245impl std::fmt::Display for CexAnnouncementsCategory {
1246    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1247        f.write_str(self.as_str())
1248    }
1249}
1250
1251#[derive(Default, Clone)]
1252pub struct CexAnnouncementsOptions {
1253    /// Page number (e.g. `1`)
1254    pub page: Option<i64>,
1255    /// Page size (e.g. `100`)
1256    pub limit: Option<i64>,
1257    /// Specifies sort (e.g. `asc`)
1258    pub sort: Option<CexAnnouncementsSort>,
1259    /// Specifies key to sort by (e.g. `title`)
1260    pub key: Option<CexAnnouncementsKey>,
1261    /// Specifies exchange(s), separated by , (e.g. `binance`)
1262    pub exchange: Option<String>,
1263    /// Specifies category(s), separated by , (e.g. `listing`)
1264    pub category: Option<CexAnnouncementsCategory>,
1265}
1266
1267impl CexAnnouncementsOptions {
1268    pub fn new() -> Self {
1269        CexAnnouncementsOptions {
1270            page: None,
1271            limit: None,
1272            sort: None,
1273            key: None,
1274            exchange: None,
1275            category: None,
1276        }
1277    }
1278
1279    /// Page number (e.g. `1`)
1280    pub fn page(mut self, page: i64) -> Self {
1281        self.page = Some(page);
1282        self
1283    }
1284
1285    /// Page size (e.g. `100`)
1286    pub fn limit(mut self, limit: i64) -> Self {
1287        self.limit = Some(limit);
1288        self
1289    }
1290
1291    /// Specifies sort (e.g. `asc`)
1292    pub fn sort(mut self, sort: CexAnnouncementsSort) -> Self {
1293        self.sort = Some(sort);
1294        self
1295    }
1296
1297    /// Specifies key to sort by (e.g. `title`)
1298    pub fn key(mut self, key: CexAnnouncementsKey) -> Self {
1299        self.key = Some(key);
1300        self
1301    }
1302
1303    /// Specifies exchange(s), separated by , (e.g. `binance`)
1304    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
1305        self.exchange = Some(exchange.into());
1306        self
1307    }
1308
1309    /// Specifies category(s), separated by , (e.g. `listing`)
1310    pub fn category(mut self, category: CexAnnouncementsCategory) -> Self {
1311        self.category = Some(category);
1312        self
1313    }
1314}
1315
1316// --- CexCandle ---
1317
1318/// Specifies market
1319#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1320#[allow(non_camel_case_types)]
1321#[non_exhaustive]
1322pub enum CexCandleMarket {
1323    Spot,
1324    Futures,
1325}
1326
1327impl CexCandleMarket {
1328    /// The exact wire value this variant serializes to.
1329    pub fn as_str(&self) -> &'static str {
1330        match self {
1331            CexCandleMarket::Spot => "spot",
1332            CexCandleMarket::Futures => "futures",
1333        }
1334    }
1335}
1336
1337impl std::fmt::Display for CexCandleMarket {
1338    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1339        f.write_str(self.as_str())
1340    }
1341}
1342
1343/// Specifies currency
1344#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1345#[allow(non_camel_case_types)]
1346#[non_exhaustive]
1347pub enum CexCandleCurrency {
1348    USD,
1349    KRW,
1350}
1351
1352impl CexCandleCurrency {
1353    /// The exact wire value this variant serializes to.
1354    pub fn as_str(&self) -> &'static str {
1355        match self {
1356            CexCandleCurrency::USD => "USD",
1357            CexCandleCurrency::KRW => "KRW",
1358        }
1359    }
1360}
1361
1362impl std::fmt::Display for CexCandleCurrency {
1363    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1364        f.write_str(self.as_str())
1365    }
1366}
1367
1368/// Specifies interval
1369#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1370#[allow(non_camel_case_types)]
1371#[non_exhaustive]
1372pub enum CexCandleInterval {
1373    _1m,
1374    _5m,
1375    _15m,
1376    _1h,
1377    _4h,
1378    _12h,
1379    _1d,
1380}
1381
1382impl CexCandleInterval {
1383    /// The exact wire value this variant serializes to.
1384    pub fn as_str(&self) -> &'static str {
1385        match self {
1386            CexCandleInterval::_1m => "1m",
1387            CexCandleInterval::_5m => "5m",
1388            CexCandleInterval::_15m => "15m",
1389            CexCandleInterval::_1h => "1h",
1390            CexCandleInterval::_4h => "4h",
1391            CexCandleInterval::_12h => "12h",
1392            CexCandleInterval::_1d => "1d",
1393        }
1394    }
1395}
1396
1397impl std::fmt::Display for CexCandleInterval {
1398    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1399        f.write_str(self.as_str())
1400    }
1401}
1402
1403/// Specifies market type
1404#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1405#[allow(non_camel_case_types)]
1406#[non_exhaustive]
1407pub enum CexCandleExchangesMarket {
1408    Spot,
1409    Futures,
1410}
1411
1412impl CexCandleExchangesMarket {
1413    /// The exact wire value this variant serializes to.
1414    pub fn as_str(&self) -> &'static str {
1415        match self {
1416            CexCandleExchangesMarket::Spot => "spot",
1417            CexCandleExchangesMarket::Futures => "futures",
1418        }
1419    }
1420}
1421
1422impl std::fmt::Display for CexCandleExchangesMarket {
1423    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1424        f.write_str(self.as_str())
1425    }
1426}
1427
1428/// Specifies market type
1429#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1430#[allow(non_camel_case_types)]
1431#[non_exhaustive]
1432pub enum CexCandleSymbolsMarket {
1433    Spot,
1434    Futures,
1435}
1436
1437impl CexCandleSymbolsMarket {
1438    /// The exact wire value this variant serializes to.
1439    pub fn as_str(&self) -> &'static str {
1440        match self {
1441            CexCandleSymbolsMarket::Spot => "spot",
1442            CexCandleSymbolsMarket::Futures => "futures",
1443        }
1444    }
1445}
1446
1447impl std::fmt::Display for CexCandleSymbolsMarket {
1448    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1449        f.write_str(self.as_str())
1450    }
1451}
1452
1453#[derive(Default, Clone)]
1454pub struct CexCandleOptions {
1455    /// Specifies market (e.g. `spot`)
1456    pub market: Option<CexCandleMarket>,
1457    /// Specifies currency (e.g. `USD`)
1458    pub currency: Option<CexCandleCurrency>,
1459    /// Specifies interval (e.g. `1d`)
1460    pub interval: Option<CexCandleInterval>,
1461    /// Specifies from (unix seconds) (e.g. `1735657200`)
1462    pub from: Option<i64>,
1463    /// Specifies to (unix seconds) (e.g. `1735693200`)
1464    pub to: Option<i64>,
1465}
1466
1467impl CexCandleOptions {
1468    pub fn new() -> Self {
1469        CexCandleOptions {
1470            market: None,
1471            currency: None,
1472            interval: None,
1473            from: None,
1474            to: None,
1475        }
1476    }
1477
1478    /// Specifies market (e.g. `spot`)
1479    pub fn market(mut self, market: CexCandleMarket) -> Self {
1480        self.market = Some(market);
1481        self
1482    }
1483
1484    /// Specifies currency (e.g. `USD`)
1485    pub fn currency(mut self, currency: CexCandleCurrency) -> Self {
1486        self.currency = Some(currency);
1487        self
1488    }
1489
1490    /// Specifies interval (e.g. `1d`)
1491    pub fn interval(mut self, interval: CexCandleInterval) -> Self {
1492        self.interval = Some(interval);
1493        self
1494    }
1495
1496    /// Specifies from (unix seconds) (e.g. `1735657200`)
1497    pub fn from(mut self, from: i64) -> Self {
1498        self.from = Some(from);
1499        self
1500    }
1501
1502    /// Specifies to (unix seconds) (e.g. `1735693200`)
1503    pub fn to(mut self, to: i64) -> Self {
1504        self.to = Some(to);
1505        self
1506    }
1507}
1508
1509#[derive(Default, Clone)]
1510pub struct CexCandleSymbolsOptions {
1511    /// Specifies market type (e.g. `spot`)
1512    pub market: Option<CexCandleSymbolsMarket>,
1513}
1514
1515impl CexCandleSymbolsOptions {
1516    pub fn new() -> Self {
1517        CexCandleSymbolsOptions { market: None }
1518    }
1519
1520    /// Specifies market type (e.g. `spot`)
1521    pub fn market(mut self, market: CexCandleSymbolsMarket) -> Self {
1522        self.market = Some(market);
1523        self
1524    }
1525}
1526
1527// --- CexSymbol ---
1528
1529/// spot or futures
1530#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1531#[allow(non_camel_case_types)]
1532#[non_exhaustive]
1533pub enum CexSymbolCautionsMarket {
1534    Spot,
1535    Futures,
1536}
1537
1538impl CexSymbolCautionsMarket {
1539    /// The exact wire value this variant serializes to.
1540    pub fn as_str(&self) -> &'static str {
1541        match self {
1542            CexSymbolCautionsMarket::Spot => "spot",
1543            CexSymbolCautionsMarket::Futures => "futures",
1544        }
1545    }
1546}
1547
1548impl std::fmt::Display for CexSymbolCautionsMarket {
1549    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1550        f.write_str(self.as_str())
1551    }
1552}
1553
1554/// Minimum severity
1555#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1556#[allow(non_camel_case_types)]
1557#[non_exhaustive]
1558pub enum CexSymbolCautionsMinLevel {
1559    Caution,
1560    Warning,
1561    Danger,
1562}
1563
1564impl CexSymbolCautionsMinLevel {
1565    /// The exact wire value this variant serializes to.
1566    pub fn as_str(&self) -> &'static str {
1567        match self {
1568            CexSymbolCautionsMinLevel::Caution => "caution",
1569            CexSymbolCautionsMinLevel::Warning => "warning",
1570            CexSymbolCautionsMinLevel::Danger => "danger",
1571        }
1572    }
1573}
1574
1575impl std::fmt::Display for CexSymbolCautionsMinLevel {
1576    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1577        f.write_str(self.as_str())
1578    }
1579}
1580
1581/// spot or futures
1582#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1583#[allow(non_camel_case_types)]
1584#[non_exhaustive]
1585pub enum CexSymbolDelistingsMarket {
1586    Spot,
1587    Futures,
1588}
1589
1590impl CexSymbolDelistingsMarket {
1591    /// The exact wire value this variant serializes to.
1592    pub fn as_str(&self) -> &'static str {
1593        match self {
1594            CexSymbolDelistingsMarket::Spot => "spot",
1595            CexSymbolDelistingsMarket::Futures => "futures",
1596        }
1597    }
1598}
1599
1600impl std::fmt::Display for CexSymbolDelistingsMarket {
1601    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1602        f.write_str(self.as_str())
1603    }
1604}
1605
1606/// spot or futures (empty = both)
1607#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1608#[allow(non_camel_case_types)]
1609#[non_exhaustive]
1610pub enum CexSymbolMetadataMarket {
1611    Spot,
1612    Futures,
1613}
1614
1615impl CexSymbolMetadataMarket {
1616    /// The exact wire value this variant serializes to.
1617    pub fn as_str(&self) -> &'static str {
1618        match self {
1619            CexSymbolMetadataMarket::Spot => "spot",
1620            CexSymbolMetadataMarket::Futures => "futures",
1621        }
1622    }
1623}
1624
1625impl std::fmt::Display for CexSymbolMetadataMarket {
1626    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1627        f.write_str(self.as_str())
1628    }
1629}
1630
1631/// Convert *_usd fields to target currency (USD or KRW)
1632#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1633#[allow(non_camel_case_types)]
1634#[non_exhaustive]
1635pub enum CexSymbolOiStatsCurrency {
1636    USD,
1637    KRW,
1638}
1639
1640impl CexSymbolOiStatsCurrency {
1641    /// The exact wire value this variant serializes to.
1642    pub fn as_str(&self) -> &'static str {
1643        match self {
1644            CexSymbolOiStatsCurrency::USD => "USD",
1645            CexSymbolOiStatsCurrency::KRW => "KRW",
1646        }
1647    }
1648}
1649
1650impl std::fmt::Display for CexSymbolOiStatsCurrency {
1651    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1652        f.write_str(self.as_str())
1653    }
1654}
1655
1656/// spot or futures
1657#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1658#[allow(non_camel_case_types)]
1659#[non_exhaustive]
1660pub enum CexSymbolTagsMarket {
1661    Spot,
1662    Futures,
1663}
1664
1665impl CexSymbolTagsMarket {
1666    /// The exact wire value this variant serializes to.
1667    pub fn as_str(&self) -> &'static str {
1668        match self {
1669            CexSymbolTagsMarket::Spot => "spot",
1670            CexSymbolTagsMarket::Futures => "futures",
1671        }
1672    }
1673}
1674
1675impl std::fmt::Display for CexSymbolTagsMarket {
1676    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1677        f.write_str(self.as_str())
1678    }
1679}
1680
1681/// Tag source filter
1682#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1683#[allow(non_camel_case_types)]
1684#[non_exhaustive]
1685pub enum CexSymbolTagsSource {
1686    RestNative,
1687    Announcement,
1688    Cmc,
1689    Manual,
1690}
1691
1692impl CexSymbolTagsSource {
1693    /// The exact wire value this variant serializes to.
1694    pub fn as_str(&self) -> &'static str {
1695        match self {
1696            CexSymbolTagsSource::RestNative => "rest_native",
1697            CexSymbolTagsSource::Announcement => "announcement",
1698            CexSymbolTagsSource::Cmc => "cmc",
1699            CexSymbolTagsSource::Manual => "manual",
1700        }
1701    }
1702}
1703
1704impl std::fmt::Display for CexSymbolTagsSource {
1705    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1706        f.write_str(self.as_str())
1707    }
1708}
1709
1710/// Filter to spot or futures
1711#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1712#[allow(non_camel_case_types)]
1713#[non_exhaustive]
1714pub enum CexSymbolVolumeMarket {
1715    Spot,
1716    Futures,
1717}
1718
1719impl CexSymbolVolumeMarket {
1720    /// The exact wire value this variant serializes to.
1721    pub fn as_str(&self) -> &'static str {
1722        match self {
1723            CexSymbolVolumeMarket::Spot => "spot",
1724            CexSymbolVolumeMarket::Futures => "futures",
1725        }
1726    }
1727}
1728
1729impl std::fmt::Display for CexSymbolVolumeMarket {
1730    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1731        f.write_str(self.as_str())
1732    }
1733}
1734
1735#[derive(Default, Clone)]
1736pub struct CexSymbolCautionsOptions {
1737    /// Exchange filter (comma-separated, empty = all)
1738    pub exchange: Option<String>,
1739    /// spot or futures
1740    pub market: Option<CexSymbolCautionsMarket>,
1741    /// Minimum severity
1742    pub min_level: Option<CexSymbolCautionsMinLevel>,
1743    /// Exclude rows whose end_at is in the past (default true)
1744    pub active_only: Option<bool>,
1745    /// Page size (default 500, max 5000)
1746    pub limit: Option<i64>,
1747    /// Page number (1-based)
1748    pub page: Option<i64>,
1749}
1750
1751impl CexSymbolCautionsOptions {
1752    pub fn new() -> Self {
1753        CexSymbolCautionsOptions {
1754            exchange: None,
1755            market: None,
1756            min_level: None,
1757            active_only: None,
1758            limit: None,
1759            page: None,
1760        }
1761    }
1762
1763    /// Exchange filter (comma-separated, empty = all)
1764    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
1765        self.exchange = Some(exchange.into());
1766        self
1767    }
1768
1769    /// spot or futures
1770    pub fn market(mut self, market: CexSymbolCautionsMarket) -> Self {
1771        self.market = Some(market);
1772        self
1773    }
1774
1775    /// Minimum severity
1776    pub fn min_level(mut self, min_level: CexSymbolCautionsMinLevel) -> Self {
1777        self.min_level = Some(min_level);
1778        self
1779    }
1780
1781    /// Exclude rows whose end_at is in the past (default true)
1782    pub fn active_only(mut self, active_only: bool) -> Self {
1783        self.active_only = Some(active_only);
1784        self
1785    }
1786
1787    /// Page size (default 500, max 5000)
1788    pub fn limit(mut self, limit: i64) -> Self {
1789        self.limit = Some(limit);
1790        self
1791    }
1792
1793    /// Page number (1-based)
1794    pub fn page(mut self, page: i64) -> Self {
1795        self.page = Some(page);
1796        self
1797    }
1798}
1799
1800#[derive(Default, Clone)]
1801pub struct CexSymbolDelistingsOptions {
1802    /// Exchange filter (comma-separated)
1803    pub exchange: Option<String>,
1804    /// spot or futures
1805    pub market: Option<CexSymbolDelistingsMarket>,
1806    /// Lower bound for delisting_at (ms epoch, default = now)
1807    pub from_ms: Option<i64>,
1808    /// Upper bound for delisting_at (ms epoch, default = now+30 days)
1809    pub to_ms: Option<i64>,
1810    /// Include already-delisted rows (default false)
1811    pub include_past: Option<bool>,
1812    /// Page size (default 200, max 2000)
1813    pub limit: Option<i64>,
1814    /// Page number (1-based)
1815    pub page: Option<i64>,
1816}
1817
1818impl CexSymbolDelistingsOptions {
1819    pub fn new() -> Self {
1820        CexSymbolDelistingsOptions {
1821            exchange: None,
1822            market: None,
1823            from_ms: None,
1824            to_ms: None,
1825            include_past: None,
1826            limit: None,
1827            page: None,
1828        }
1829    }
1830
1831    /// Exchange filter (comma-separated)
1832    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
1833        self.exchange = Some(exchange.into());
1834        self
1835    }
1836
1837    /// spot or futures
1838    pub fn market(mut self, market: CexSymbolDelistingsMarket) -> Self {
1839        self.market = Some(market);
1840        self
1841    }
1842
1843    /// Lower bound for delisting_at (ms epoch, default = now)
1844    pub fn from_ms(mut self, from_ms: i64) -> Self {
1845        self.from_ms = Some(from_ms);
1846        self
1847    }
1848
1849    /// Upper bound for delisting_at (ms epoch, default = now+30 days)
1850    pub fn to_ms(mut self, to_ms: i64) -> Self {
1851        self.to_ms = Some(to_ms);
1852        self
1853    }
1854
1855    /// Include already-delisted rows (default false)
1856    pub fn include_past(mut self, include_past: bool) -> Self {
1857        self.include_past = Some(include_past);
1858        self
1859    }
1860
1861    /// Page size (default 200, max 2000)
1862    pub fn limit(mut self, limit: i64) -> Self {
1863        self.limit = Some(limit);
1864        self
1865    }
1866
1867    /// Page number (1-based)
1868    pub fn page(mut self, page: i64) -> Self {
1869        self.page = Some(page);
1870        self
1871    }
1872}
1873
1874#[derive(Default, Clone)]
1875pub struct CexSymbolLiquidationOptions {
1876    /// Time window: 1h / 24h / 7d (default 24h, max 30d)
1877    pub window: Option<String>,
1878}
1879
1880impl CexSymbolLiquidationOptions {
1881    pub fn new() -> Self {
1882        CexSymbolLiquidationOptions { window: None }
1883    }
1884
1885    /// Time window: 1h / 24h / 7d (default 24h, max 30d)
1886    pub fn window(mut self, window: impl Into<String>) -> Self {
1887        self.window = Some(window.into());
1888        self
1889    }
1890}
1891
1892#[derive(Default, Clone)]
1893pub struct CexSymbolMetadataOptions {
1894    /// Comma-separated exchange names (empty = all) (e.g. `upbit,bithumb`)
1895    pub exchange: Option<String>,
1896    /// spot or futures (empty = both)
1897    pub market: Option<CexSymbolMetadataMarket>,
1898    /// Base asset filter (e.g. `BTC`)
1899    pub base: Option<String>,
1900    /// Quote asset filter (e.g. `USDT`)
1901    pub quote: Option<String>,
1902    /// trading_status filter (repeatable, comma-separated) (e.g. `trading,delisting`)
1903    pub status: Option<String>,
1904    /// Page size (default 200, max 2000)
1905    pub limit: Option<i64>,
1906    /// Page number (1-based)
1907    pub page: Option<i64>,
1908}
1909
1910impl CexSymbolMetadataOptions {
1911    pub fn new() -> Self {
1912        CexSymbolMetadataOptions {
1913            exchange: None,
1914            market: None,
1915            base: None,
1916            quote: None,
1917            status: None,
1918            limit: None,
1919            page: None,
1920        }
1921    }
1922
1923    /// Comma-separated exchange names (empty = all) (e.g. `upbit,bithumb`)
1924    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
1925        self.exchange = Some(exchange.into());
1926        self
1927    }
1928
1929    /// spot or futures (empty = both)
1930    pub fn market(mut self, market: CexSymbolMetadataMarket) -> Self {
1931        self.market = Some(market);
1932        self
1933    }
1934
1935    /// Base asset filter (e.g. `BTC`)
1936    pub fn base(mut self, base: impl Into<String>) -> Self {
1937        self.base = Some(base.into());
1938        self
1939    }
1940
1941    /// Quote asset filter (e.g. `USDT`)
1942    pub fn quote(mut self, quote: impl Into<String>) -> Self {
1943        self.quote = Some(quote.into());
1944        self
1945    }
1946
1947    /// trading_status filter (repeatable, comma-separated) (e.g. `trading,delisting`)
1948    pub fn status(mut self, status: impl Into<String>) -> Self {
1949        self.status = Some(status.into());
1950        self
1951    }
1952
1953    /// Page size (default 200, max 2000)
1954    pub fn limit(mut self, limit: i64) -> Self {
1955        self.limit = Some(limit);
1956        self
1957    }
1958
1959    /// Page number (1-based)
1960    pub fn page(mut self, page: i64) -> Self {
1961        self.page = Some(page);
1962        self
1963    }
1964}
1965
1966#[derive(Default, Clone)]
1967pub struct CexSymbolOiOptions {
1968    /// Exchange filter (narrows to a single venue)
1969    pub exchange: Option<String>,
1970}
1971
1972impl CexSymbolOiOptions {
1973    pub fn new() -> Self {
1974        CexSymbolOiOptions { exchange: None }
1975    }
1976
1977    /// Exchange filter (narrows to a single venue)
1978    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
1979        self.exchange = Some(exchange.into());
1980        self
1981    }
1982}
1983
1984#[derive(Default, Clone)]
1985pub struct CexSymbolOiStatsOptions {
1986    /// Exchange filter — when omitted, returns every venue carrying the base
1987    pub exchange: Option<String>,
1988    /// Convert *_usd fields to target currency (USD or KRW)
1989    pub currency: Option<CexSymbolOiStatsCurrency>,
1990}
1991
1992impl CexSymbolOiStatsOptions {
1993    pub fn new() -> Self {
1994        CexSymbolOiStatsOptions {
1995            exchange: None,
1996            currency: None,
1997        }
1998    }
1999
2000    /// Exchange filter — when omitted, returns every venue carrying the base
2001    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
2002        self.exchange = Some(exchange.into());
2003        self
2004    }
2005
2006    /// Convert *_usd fields to target currency (USD or KRW)
2007    pub fn currency(mut self, currency: CexSymbolOiStatsCurrency) -> Self {
2008        self.currency = Some(currency);
2009        self
2010    }
2011}
2012
2013#[derive(Default, Clone)]
2014pub struct CexSymbolTagsOptions {
2015    /// Tag filter (repeatable, comma-separated) (e.g. `meme,ai`)
2016    pub tag: Option<String>,
2017    /// Exchange filter (repeatable, comma-separated) (e.g. `binance`)
2018    pub exchange: Option<String>,
2019    /// spot or futures
2020    pub market: Option<CexSymbolTagsMarket>,
2021    /// Base asset filter (e.g. `BTC`)
2022    pub base: Option<String>,
2023    /// Tag source filter
2024    pub source: Option<CexSymbolTagsSource>,
2025    /// Minimum confidence (0-100, default 80)
2026    pub min_confidence: Option<i64>,
2027    /// Page size (default 500, max 5000)
2028    pub limit: Option<i64>,
2029    /// Page number (1-based)
2030    pub page: Option<i64>,
2031}
2032
2033impl CexSymbolTagsOptions {
2034    pub fn new() -> Self {
2035        CexSymbolTagsOptions {
2036            tag: None,
2037            exchange: None,
2038            market: None,
2039            base: None,
2040            source: None,
2041            min_confidence: None,
2042            limit: None,
2043            page: None,
2044        }
2045    }
2046
2047    /// Tag filter (repeatable, comma-separated) (e.g. `meme,ai`)
2048    pub fn tag(mut self, tag: impl Into<String>) -> Self {
2049        self.tag = Some(tag.into());
2050        self
2051    }
2052
2053    /// Exchange filter (repeatable, comma-separated) (e.g. `binance`)
2054    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
2055        self.exchange = Some(exchange.into());
2056        self
2057    }
2058
2059    /// spot or futures
2060    pub fn market(mut self, market: CexSymbolTagsMarket) -> Self {
2061        self.market = Some(market);
2062        self
2063    }
2064
2065    /// Base asset filter (e.g. `BTC`)
2066    pub fn base(mut self, base: impl Into<String>) -> Self {
2067        self.base = Some(base.into());
2068        self
2069    }
2070
2071    /// Tag source filter
2072    pub fn source(mut self, source: CexSymbolTagsSource) -> Self {
2073        self.source = Some(source);
2074        self
2075    }
2076
2077    /// Minimum confidence (0-100, default 80)
2078    pub fn min_confidence(mut self, min_confidence: i64) -> Self {
2079        self.min_confidence = Some(min_confidence);
2080        self
2081    }
2082
2083    /// Page size (default 500, max 5000)
2084    pub fn limit(mut self, limit: i64) -> Self {
2085        self.limit = Some(limit);
2086        self
2087    }
2088
2089    /// Page number (1-based)
2090    pub fn page(mut self, page: i64) -> Self {
2091        self.page = Some(page);
2092        self
2093    }
2094}
2095
2096#[derive(Default, Clone)]
2097pub struct CexSymbolVolumeOptions {
2098    /// Filter to spot or futures
2099    pub market: Option<CexSymbolVolumeMarket>,
2100}
2101
2102impl CexSymbolVolumeOptions {
2103    pub fn new() -> Self {
2104        CexSymbolVolumeOptions { market: None }
2105    }
2106
2107    /// Filter to spot or futures
2108    pub fn market(mut self, market: CexSymbolVolumeMarket) -> Self {
2109        self.market = Some(market);
2110        self
2111    }
2112}
2113
2114// --- FundingRate ---
2115
2116/// Specifies sort
2117#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2118#[allow(non_camel_case_types)]
2119#[non_exhaustive]
2120pub enum FundingRateHistorySort {
2121    Asc,
2122    Desc,
2123}
2124
2125impl FundingRateHistorySort {
2126    /// The exact wire value this variant serializes to.
2127    pub fn as_str(&self) -> &'static str {
2128        match self {
2129            FundingRateHistorySort::Asc => "asc",
2130            FundingRateHistorySort::Desc => "desc",
2131        }
2132    }
2133}
2134
2135impl std::fmt::Display for FundingRateHistorySort {
2136    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2137        f.write_str(self.as_str())
2138    }
2139}
2140
2141#[derive(Default, Clone)]
2142pub struct FundingRateHistoryOptions {
2143    /// Specifies page (e.g. `1`)
2144    pub page: Option<i64>,
2145    /// Specifies limit (e.g. `1000`)
2146    pub limit: Option<i64>,
2147    /// Specifies from (unix seconds) (e.g. `1735657200`)
2148    pub from: Option<i64>,
2149    /// Specifies to (unix seconds) (e.g. `1735693200`)
2150    pub to: Option<i64>,
2151    /// Specifies sort (e.g. `asc`)
2152    pub sort: Option<FundingRateHistorySort>,
2153}
2154
2155impl FundingRateHistoryOptions {
2156    pub fn new() -> Self {
2157        FundingRateHistoryOptions {
2158            page: None,
2159            limit: None,
2160            from: None,
2161            to: None,
2162            sort: None,
2163        }
2164    }
2165
2166    /// Specifies page (e.g. `1`)
2167    pub fn page(mut self, page: i64) -> Self {
2168        self.page = Some(page);
2169        self
2170    }
2171
2172    /// Specifies limit (e.g. `1000`)
2173    pub fn limit(mut self, limit: i64) -> Self {
2174        self.limit = Some(limit);
2175        self
2176    }
2177
2178    /// Specifies from (unix seconds) (e.g. `1735657200`)
2179    pub fn from(mut self, from: i64) -> Self {
2180        self.from = Some(from);
2181        self
2182    }
2183
2184    /// Specifies to (unix seconds) (e.g. `1735693200`)
2185    pub fn to(mut self, to: i64) -> Self {
2186        self.to = Some(to);
2187        self
2188    }
2189
2190    /// Specifies sort (e.g. `asc`)
2191    pub fn sort(mut self, sort: FundingRateHistorySort) -> Self {
2192        self.sort = Some(sort);
2193        self
2194    }
2195}
2196
2197#[derive(Default, Clone)]
2198pub struct FundingRateSymbolsOptions {
2199    /// Specifies exchange name. Omit to receive symbols for all exchanges; constrain to a single exchange when filtering. (e.g. `binance`)
2200    pub exchange: Option<String>,
2201}
2202
2203impl FundingRateSymbolsOptions {
2204    pub fn new() -> Self {
2205        FundingRateSymbolsOptions { exchange: None }
2206    }
2207
2208    /// Specifies exchange name. Omit to receive symbols for all exchanges; constrain to a single exchange when filtering. (e.g. `binance`)
2209    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
2210        self.exchange = Some(exchange.into());
2211        self
2212    }
2213}
2214
2215// --- IndexPrice ---
2216
2217/// interval
2218#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2219#[allow(non_camel_case_types)]
2220#[non_exhaustive]
2221pub enum IndexPriceInterval {
2222    _5m,
2223    _15m,
2224    _1h,
2225    _4h,
2226    _12h,
2227    _1d,
2228}
2229
2230impl IndexPriceInterval {
2231    /// The exact wire value this variant serializes to.
2232    pub fn as_str(&self) -> &'static str {
2233        match self {
2234            IndexPriceInterval::_5m => "5m",
2235            IndexPriceInterval::_15m => "15m",
2236            IndexPriceInterval::_1h => "1h",
2237            IndexPriceInterval::_4h => "4h",
2238            IndexPriceInterval::_12h => "12h",
2239            IndexPriceInterval::_1d => "1d",
2240        }
2241    }
2242}
2243
2244impl std::fmt::Display for IndexPriceInterval {
2245    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2246        f.write_str(self.as_str())
2247    }
2248}
2249
2250#[derive(Default, Clone)]
2251pub struct IndexPriceOptions {
2252    /// Specifies from (unix seconds) (e.g. `1735657200`)
2253    pub from: Option<i64>,
2254    /// Specifies to (unix seconds) (e.g. `1735693200`)
2255    pub to: Option<i64>,
2256    /// interval (e.g. `5m`)
2257    pub interval: Option<IndexPriceInterval>,
2258}
2259
2260impl IndexPriceOptions {
2261    pub fn new() -> Self {
2262        IndexPriceOptions {
2263            from: None,
2264            to: None,
2265            interval: None,
2266        }
2267    }
2268
2269    /// Specifies from (unix seconds) (e.g. `1735657200`)
2270    pub fn from(mut self, from: i64) -> Self {
2271        self.from = Some(from);
2272        self
2273    }
2274
2275    /// Specifies to (unix seconds) (e.g. `1735693200`)
2276    pub fn to(mut self, to: i64) -> Self {
2277        self.to = Some(to);
2278        self
2279    }
2280
2281    /// interval (e.g. `5m`)
2282    pub fn interval(mut self, interval: IndexPriceInterval) -> Self {
2283        self.interval = Some(interval);
2284        self
2285    }
2286}
2287
2288// --- Liquidation ---
2289
2290/// Rolling window
2291#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2292#[allow(non_camel_case_types)]
2293#[non_exhaustive]
2294pub enum LiquidationHeatmapWindow {
2295    _1h,
2296    _4h,
2297    _24h,
2298}
2299
2300impl LiquidationHeatmapWindow {
2301    /// The exact wire value this variant serializes to.
2302    pub fn as_str(&self) -> &'static str {
2303        match self {
2304            LiquidationHeatmapWindow::_1h => "1h",
2305            LiquidationHeatmapWindow::_4h => "4h",
2306            LiquidationHeatmapWindow::_24h => "24h",
2307        }
2308    }
2309}
2310
2311impl std::fmt::Display for LiquidationHeatmapWindow {
2312    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2313        f.write_str(self.as_str())
2314    }
2315}
2316
2317/// Rolling window
2318#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2319#[allow(non_camel_case_types)]
2320#[non_exhaustive]
2321pub enum LiquidationStatsWindow {
2322    _1h,
2323    _4h,
2324    _24h,
2325}
2326
2327impl LiquidationStatsWindow {
2328    /// The exact wire value this variant serializes to.
2329    pub fn as_str(&self) -> &'static str {
2330        match self {
2331            LiquidationStatsWindow::_1h => "1h",
2332            LiquidationStatsWindow::_4h => "4h",
2333            LiquidationStatsWindow::_24h => "24h",
2334        }
2335    }
2336}
2337
2338impl std::fmt::Display for LiquidationStatsWindow {
2339    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2340        f.write_str(self.as_str())
2341    }
2342}
2343
2344/// Bucket interval
2345#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2346#[allow(non_camel_case_types)]
2347#[non_exhaustive]
2348pub enum LiquidationSymbolHistoryInterval {
2349    _5m,
2350    _15m,
2351    _1h,
2352}
2353
2354impl LiquidationSymbolHistoryInterval {
2355    /// The exact wire value this variant serializes to.
2356    pub fn as_str(&self) -> &'static str {
2357        match self {
2358            LiquidationSymbolHistoryInterval::_5m => "5m",
2359            LiquidationSymbolHistoryInterval::_15m => "15m",
2360            LiquidationSymbolHistoryInterval::_1h => "1h",
2361        }
2362    }
2363}
2364
2365impl std::fmt::Display for LiquidationSymbolHistoryInterval {
2366    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2367        f.write_str(self.as_str())
2368    }
2369}
2370
2371/// Lookback window
2372#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2373#[allow(non_camel_case_types)]
2374#[non_exhaustive]
2375pub enum LiquidationSymbolHistoryWindow {
2376    _24h,
2377    _72h,
2378    _7d,
2379}
2380
2381impl LiquidationSymbolHistoryWindow {
2382    /// The exact wire value this variant serializes to.
2383    pub fn as_str(&self) -> &'static str {
2384        match self {
2385            LiquidationSymbolHistoryWindow::_24h => "24h",
2386            LiquidationSymbolHistoryWindow::_72h => "72h",
2387            LiquidationSymbolHistoryWindow::_7d => "7d",
2388        }
2389    }
2390}
2391
2392impl std::fmt::Display for LiquidationSymbolHistoryWindow {
2393    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2394        f.write_str(self.as_str())
2395    }
2396}
2397
2398#[derive(Default, Clone)]
2399pub struct LiquidationOptions {
2400    /// Number of events to return (1-1000) (e.g. `100`)
2401    pub limit: Option<i64>,
2402}
2403
2404impl LiquidationOptions {
2405    pub fn new() -> Self {
2406        LiquidationOptions { limit: None }
2407    }
2408
2409    /// Number of events to return (1-1000) (e.g. `100`)
2410    pub fn limit(mut self, limit: i64) -> Self {
2411        self.limit = Some(limit);
2412        self
2413    }
2414}
2415
2416#[derive(Default, Clone)]
2417pub struct LiquidationFeedOptions {
2418    /// Exchange filter (e.g. `bybit`)
2419    pub exchange: Option<String>,
2420    /// Base asset filter (case-insensitive) (e.g. `BTC`)
2421    pub base: Option<String>,
2422    /// Minimum VolumeUsd filter (e.g. `10000`)
2423    pub min_volume_usd: Option<f64>,
2424    /// Number of events (1-1000) (e.g. `100`)
2425    pub limit: Option<i64>,
2426}
2427
2428impl LiquidationFeedOptions {
2429    pub fn new() -> Self {
2430        LiquidationFeedOptions {
2431            exchange: None,
2432            base: None,
2433            min_volume_usd: None,
2434            limit: None,
2435        }
2436    }
2437
2438    /// Exchange filter (e.g. `bybit`)
2439    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
2440        self.exchange = Some(exchange.into());
2441        self
2442    }
2443
2444    /// Base asset filter (case-insensitive) (e.g. `BTC`)
2445    pub fn base(mut self, base: impl Into<String>) -> Self {
2446        self.base = Some(base.into());
2447        self
2448    }
2449
2450    /// Minimum VolumeUsd filter (e.g. `10000`)
2451    pub fn min_volume_usd(mut self, min_volume_usd: f64) -> Self {
2452        self.min_volume_usd = Some(min_volume_usd);
2453        self
2454    }
2455
2456    /// Number of events (1-1000) (e.g. `100`)
2457    pub fn limit(mut self, limit: i64) -> Self {
2458        self.limit = Some(limit);
2459        self
2460    }
2461}
2462
2463#[derive(Default, Clone)]
2464pub struct LiquidationHeatmapOptions {
2465    /// Rolling window
2466    pub window: Option<LiquidationHeatmapWindow>,
2467    /// Top N tokens by total
2468    pub top_n: Option<i64>,
2469}
2470
2471impl LiquidationHeatmapOptions {
2472    pub fn new() -> Self {
2473        LiquidationHeatmapOptions {
2474            window: None,
2475            top_n: None,
2476        }
2477    }
2478
2479    /// Rolling window
2480    pub fn window(mut self, window: LiquidationHeatmapWindow) -> Self {
2481        self.window = Some(window);
2482        self
2483    }
2484
2485    /// Top N tokens by total
2486    pub fn top_n(mut self, top_n: i64) -> Self {
2487        self.top_n = Some(top_n);
2488        self
2489    }
2490}
2491
2492#[derive(Default, Clone)]
2493pub struct LiquidationMapOptions {
2494    /// Exchange
2495    pub exchange: Option<String>,
2496    /// Base asset (e.g. `BTC`)
2497    pub base: Option<String>,
2498    /// Quote asset
2499    pub quote: Option<String>,
2500}
2501
2502impl LiquidationMapOptions {
2503    pub fn new() -> Self {
2504        LiquidationMapOptions {
2505            exchange: None,
2506            base: None,
2507            quote: None,
2508        }
2509    }
2510
2511    /// Exchange
2512    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
2513        self.exchange = Some(exchange.into());
2514        self
2515    }
2516
2517    /// Base asset (e.g. `BTC`)
2518    pub fn base(mut self, base: impl Into<String>) -> Self {
2519        self.base = Some(base.into());
2520        self
2521    }
2522
2523    /// Quote asset
2524    pub fn quote(mut self, quote: impl Into<String>) -> Self {
2525        self.quote = Some(quote.into());
2526        self
2527    }
2528}
2529
2530#[derive(Default, Clone)]
2531pub struct LiquidationStatsOptions {
2532    /// Rolling window
2533    pub window: Option<LiquidationStatsWindow>,
2534    /// Exchange filter (e.g. `bybit`)
2535    pub exchange: Option<String>,
2536    /// Minimum VolumeUsd filter (e.g. `10000`)
2537    pub min_volume_usd: Option<f64>,
2538}
2539
2540impl LiquidationStatsOptions {
2541    pub fn new() -> Self {
2542        LiquidationStatsOptions {
2543            window: None,
2544            exchange: None,
2545            min_volume_usd: None,
2546        }
2547    }
2548
2549    /// Rolling window
2550    pub fn window(mut self, window: LiquidationStatsWindow) -> Self {
2551        self.window = Some(window);
2552        self
2553    }
2554
2555    /// Exchange filter (e.g. `bybit`)
2556    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
2557        self.exchange = Some(exchange.into());
2558        self
2559    }
2560
2561    /// Minimum VolumeUsd filter (e.g. `10000`)
2562    pub fn min_volume_usd(mut self, min_volume_usd: f64) -> Self {
2563        self.min_volume_usd = Some(min_volume_usd);
2564        self
2565    }
2566}
2567
2568#[derive(Default, Clone)]
2569pub struct LiquidationSymbolHistoryOptions {
2570    /// Quote asset
2571    pub quote: Option<String>,
2572    /// Optional exchange filter for the liquidation aggregation. The price line stays on Binance unless this is set.
2573    pub exchange: Option<String>,
2574    /// Bucket interval
2575    pub interval: Option<LiquidationSymbolHistoryInterval>,
2576    /// Lookback window
2577    pub window: Option<LiquidationSymbolHistoryWindow>,
2578}
2579
2580impl LiquidationSymbolHistoryOptions {
2581    pub fn new() -> Self {
2582        LiquidationSymbolHistoryOptions {
2583            quote: None,
2584            exchange: None,
2585            interval: None,
2586            window: None,
2587        }
2588    }
2589
2590    /// Quote asset
2591    pub fn quote(mut self, quote: impl Into<String>) -> Self {
2592        self.quote = Some(quote.into());
2593        self
2594    }
2595
2596    /// Optional exchange filter for the liquidation aggregation. The price line stays on Binance unless this is set.
2597    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
2598        self.exchange = Some(exchange.into());
2599        self
2600    }
2601
2602    /// Bucket interval
2603    pub fn interval(mut self, interval: LiquidationSymbolHistoryInterval) -> Self {
2604        self.interval = Some(interval);
2605        self
2606    }
2607
2608    /// Lookback window
2609    pub fn window(mut self, window: LiquidationSymbolHistoryWindow) -> Self {
2610        self.window = Some(window);
2611        self
2612    }
2613}
2614
2615// --- Listing ---
2616
2617#[derive(Default, Clone)]
2618pub struct ListingsHistoricalOptions {
2619    /// Refresh cache (e.g. `true`)
2620    pub refresh: Option<bool>,
2621}
2622
2623impl ListingsHistoricalOptions {
2624    pub fn new() -> Self {
2625        ListingsHistoricalOptions { refresh: None }
2626    }
2627
2628    /// Refresh cache (e.g. `true`)
2629    pub fn refresh(mut self, refresh: bool) -> Self {
2630        self.refresh = Some(refresh);
2631        self
2632    }
2633}
2634
2635// --- OpenInterest ---
2636
2637/// Aggregation interval
2638#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2639#[allow(non_camel_case_types)]
2640#[non_exhaustive]
2641pub enum OpenInterestHistoryAggregatedInterval {
2642    _5m,
2643    _15m,
2644    _1h,
2645    _4h,
2646    _1d,
2647}
2648
2649impl OpenInterestHistoryAggregatedInterval {
2650    /// The exact wire value this variant serializes to.
2651    pub fn as_str(&self) -> &'static str {
2652        match self {
2653            OpenInterestHistoryAggregatedInterval::_5m => "5m",
2654            OpenInterestHistoryAggregatedInterval::_15m => "15m",
2655            OpenInterestHistoryAggregatedInterval::_1h => "1h",
2656            OpenInterestHistoryAggregatedInterval::_4h => "4h",
2657            OpenInterestHistoryAggregatedInterval::_1d => "1d",
2658        }
2659    }
2660}
2661
2662impl std::fmt::Display for OpenInterestHistoryAggregatedInterval {
2663    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2664        f.write_str(self.as_str())
2665    }
2666}
2667
2668/// Sort direction
2669#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2670#[allow(non_camel_case_types)]
2671#[non_exhaustive]
2672pub enum OpenInterestOverviewSort {
2673    Asc,
2674    Desc,
2675}
2676
2677impl OpenInterestOverviewSort {
2678    /// The exact wire value this variant serializes to.
2679    pub fn as_str(&self) -> &'static str {
2680        match self {
2681            OpenInterestOverviewSort::Asc => "asc",
2682            OpenInterestOverviewSort::Desc => "desc",
2683        }
2684    }
2685}
2686
2687impl std::fmt::Display for OpenInterestOverviewSort {
2688    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2689        f.write_str(self.as_str())
2690    }
2691}
2692
2693#[derive(Default, Clone)]
2694pub struct OpenInterestHistoryAggregatedOptions {
2695    /// Aggregation interval (e.g. `1h`)
2696    pub interval: Option<OpenInterestHistoryAggregatedInterval>,
2697    /// Start unix-ms (default: depends on interval — 7d for 1h, 30d for 4h, 1y for 1d) (e.g. `1776000000000`)
2698    pub from: Option<i64>,
2699    /// End unix-ms (default: now) (e.g. `1776900000000`)
2700    pub to: Option<i64>,
2701}
2702
2703impl OpenInterestHistoryAggregatedOptions {
2704    pub fn new() -> Self {
2705        OpenInterestHistoryAggregatedOptions {
2706            interval: None,
2707            from: None,
2708            to: None,
2709        }
2710    }
2711
2712    /// Aggregation interval (e.g. `1h`)
2713    pub fn interval(mut self, interval: OpenInterestHistoryAggregatedInterval) -> Self {
2714        self.interval = Some(interval);
2715        self
2716    }
2717
2718    /// Start unix-ms (default: depends on interval — 7d for 1h, 30d for 4h, 1y for 1d) (e.g. `1776000000000`)
2719    pub fn from(mut self, from: i64) -> Self {
2720        self.from = Some(from);
2721        self
2722    }
2723
2724    /// End unix-ms (default: now) (e.g. `1776900000000`)
2725    pub fn to(mut self, to: i64) -> Self {
2726        self.to = Some(to);
2727        self
2728    }
2729}
2730
2731#[derive(Default, Clone)]
2732pub struct OpenInterestListOptions {
2733    /// Exchange filter (e.g. `bybit`)
2734    pub exchange: Option<String>,
2735}
2736
2737impl OpenInterestListOptions {
2738    pub fn new() -> Self {
2739        OpenInterestListOptions { exchange: None }
2740    }
2741
2742    /// Exchange filter (e.g. `bybit`)
2743    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
2744        self.exchange = Some(exchange.into());
2745        self
2746    }
2747}
2748
2749#[derive(Default, Clone)]
2750pub struct OpenInterestOverviewOptions {
2751    /// Page (e.g. `1`)
2752    pub page: Option<i64>,
2753    /// Page size (e.g. `20`)
2754    pub limit: Option<i64>,
2755    /// Sort-by exchange (e.g. `binance`)
2756    pub key: Option<String>,
2757    /// Sort direction (e.g. `desc`)
2758    pub sort: Option<OpenInterestOverviewSort>,
2759    /// Base symbol search (e.g. `BTC`)
2760    pub query: Option<String>,
2761}
2762
2763impl OpenInterestOverviewOptions {
2764    pub fn new() -> Self {
2765        OpenInterestOverviewOptions {
2766            page: None,
2767            limit: None,
2768            key: None,
2769            sort: None,
2770            query: None,
2771        }
2772    }
2773
2774    /// Page (e.g. `1`)
2775    pub fn page(mut self, page: i64) -> Self {
2776        self.page = Some(page);
2777        self
2778    }
2779
2780    /// Page size (e.g. `20`)
2781    pub fn limit(mut self, limit: i64) -> Self {
2782        self.limit = Some(limit);
2783        self
2784    }
2785
2786    /// Sort-by exchange (e.g. `binance`)
2787    pub fn key(mut self, key: impl Into<String>) -> Self {
2788        self.key = Some(key.into());
2789        self
2790    }
2791
2792    /// Sort direction (e.g. `desc`)
2793    pub fn sort(mut self, sort: OpenInterestOverviewSort) -> Self {
2794        self.sort = Some(sort);
2795        self
2796    }
2797
2798    /// Base symbol search (e.g. `BTC`)
2799    pub fn query(mut self, query: impl Into<String>) -> Self {
2800        self.query = Some(query.into());
2801        self
2802    }
2803}
2804
2805#[derive(Default, Clone)]
2806pub struct OpenInterestSummaryOptions {
2807    /// Top N tokens to return
2808    pub top_n: Option<i64>,
2809}
2810
2811impl OpenInterestSummaryOptions {
2812    pub fn new() -> Self {
2813        OpenInterestSummaryOptions { top_n: None }
2814    }
2815
2816    /// Top N tokens to return
2817    pub fn top_n(mut self, top_n: i64) -> Self {
2818        self.top_n = Some(top_n);
2819        self
2820    }
2821}
2822
2823// --- Premium ---
2824
2825/// Specifies source market
2826#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2827#[allow(non_camel_case_types)]
2828#[non_exhaustive]
2829pub enum PremiumSourceMarket {
2830    Spot,
2831    Futures,
2832}
2833
2834impl PremiumSourceMarket {
2835    /// The exact wire value this variant serializes to.
2836    pub fn as_str(&self) -> &'static str {
2837        match self {
2838            PremiumSourceMarket::Spot => "spot",
2839            PremiumSourceMarket::Futures => "futures",
2840        }
2841    }
2842}
2843
2844impl std::fmt::Display for PremiumSourceMarket {
2845    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2846        f.write_str(self.as_str())
2847    }
2848}
2849
2850/// Specifies target market
2851#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2852#[allow(non_camel_case_types)]
2853#[non_exhaustive]
2854pub enum PremiumTargetMarket {
2855    Spot,
2856    Futures,
2857}
2858
2859impl PremiumTargetMarket {
2860    /// The exact wire value this variant serializes to.
2861    pub fn as_str(&self) -> &'static str {
2862        match self {
2863            PremiumTargetMarket::Spot => "spot",
2864            PremiumTargetMarket::Futures => "futures",
2865        }
2866    }
2867}
2868
2869impl std::fmt::Display for PremiumTargetMarket {
2870    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2871        f.write_str(self.as_str())
2872    }
2873}
2874
2875/// Specifies premium type(s), separated by ,
2876#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2877#[allow(non_camel_case_types)]
2878#[non_exhaustive]
2879pub enum PremiumPremiumType {
2880    SpotSpot,
2881    FuturesFutures,
2882    SpotFutures,
2883}
2884
2885impl PremiumPremiumType {
2886    /// The exact wire value this variant serializes to.
2887    pub fn as_str(&self) -> &'static str {
2888        match self {
2889            PremiumPremiumType::SpotSpot => "spot-spot",
2890            PremiumPremiumType::FuturesFutures => "futures-futures",
2891            PremiumPremiumType::SpotFutures => "spot-futures",
2892        }
2893    }
2894}
2895
2896impl std::fmt::Display for PremiumPremiumType {
2897    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2898        f.write_str(self.as_str())
2899    }
2900}
2901
2902/// Specifies sort order
2903#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2904#[allow(non_camel_case_types)]
2905#[non_exhaustive]
2906pub enum PremiumSort {
2907    Asc,
2908    Desc,
2909}
2910
2911impl PremiumSort {
2912    /// The exact wire value this variant serializes to.
2913    pub fn as_str(&self) -> &'static str {
2914        match self {
2915            PremiumSort::Asc => "asc",
2916            PremiumSort::Desc => "desc",
2917        }
2918    }
2919}
2920
2921impl std::fmt::Display for PremiumSort {
2922    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2923        f.write_str(self.as_str())
2924    }
2925}
2926
2927#[derive(Default, Clone)]
2928pub struct PremiumOptions {
2929    /// Specifies source exchange(s), separated by , (e.g. `binance`)
2930    pub source_exchange: Option<String>,
2931    /// Specifies target exchange(s), separated by , (e.g. `upbit`)
2932    pub target_exchange: Option<String>,
2933    /// Specifies asset(s), separated by , (e.g. `BTC`)
2934    pub asset: Option<String>,
2935    /// Specifies source quote(s), separated by , (e.g. `USDT`)
2936    pub source_quote: Option<String>,
2937    /// Specifies target quote(s), separated by , (e.g. `KRW`)
2938    pub target_quote: Option<String>,
2939    /// Specifies source market (e.g. `spot`)
2940    pub source_market: Option<PremiumSourceMarket>,
2941    /// Specifies target market (e.g. `spot`)
2942    pub target_market: Option<PremiumTargetMarket>,
2943    /// Specifies premium type(s), separated by , (e.g. `spot-spot`)
2944    pub premium_type: Option<PremiumPremiumType>,
2945    /// Specifies currency applied to price values (e.g. `KRW`)
2946    pub currency: Option<String>,
2947    /// Specifies conversion base (e.g. `USDT`)
2948    pub conversion_base: Option<String>,
2949    /// Page number (e.g. `1`)
2950    pub page: Option<i64>,
2951    /// Page size (e.g. `10`)
2952    pub limit: Option<i64>,
2953    /// Specifies sort order (e.g. `desc`)
2954    pub sort: Option<PremiumSort>,
2955    /// Specifies key to sort by (e.g. `pdp`)
2956    pub key: Option<String>,
2957    /// Search query for filtering assets (e.g. `BTC`)
2958    pub query: Option<String>,
2959    /// Filter only transferable assets (e.g. `false`)
2960    pub only_transferable: Option<bool>,
2961    /// Specifies network(s), separated by , (e.g. `ethereum`)
2962    pub network: Option<String>,
2963    /// Minimum source volume (e.g. `10000`)
2964    pub min_sv: Option<f64>,
2965    /// Minimum target volume (e.g. `10000`)
2966    pub min_tv: Option<f64>,
2967    /// Specifies token id(s) to include, separated by , (e.g. `bitcoin`)
2968    pub token_include: Option<String>,
2969    /// Specifies token id(s) to exclude, separated by , (e.g. `bitcoin`)
2970    pub token_exclude: Option<String>,
2971}
2972
2973impl PremiumOptions {
2974    pub fn new() -> Self {
2975        PremiumOptions {
2976            source_exchange: None,
2977            target_exchange: None,
2978            asset: None,
2979            source_quote: None,
2980            target_quote: None,
2981            source_market: None,
2982            target_market: None,
2983            premium_type: None,
2984            currency: None,
2985            conversion_base: None,
2986            page: None,
2987            limit: None,
2988            sort: None,
2989            key: None,
2990            query: None,
2991            only_transferable: None,
2992            network: None,
2993            min_sv: None,
2994            min_tv: None,
2995            token_include: None,
2996            token_exclude: None,
2997        }
2998    }
2999
3000    /// Specifies source exchange(s), separated by , (e.g. `binance`)
3001    pub fn source_exchange(mut self, source_exchange: impl Into<String>) -> Self {
3002        self.source_exchange = Some(source_exchange.into());
3003        self
3004    }
3005
3006    /// Specifies target exchange(s), separated by , (e.g. `upbit`)
3007    pub fn target_exchange(mut self, target_exchange: impl Into<String>) -> Self {
3008        self.target_exchange = Some(target_exchange.into());
3009        self
3010    }
3011
3012    /// Specifies asset(s), separated by , (e.g. `BTC`)
3013    pub fn asset(mut self, asset: impl Into<String>) -> Self {
3014        self.asset = Some(asset.into());
3015        self
3016    }
3017
3018    /// Specifies source quote(s), separated by , (e.g. `USDT`)
3019    pub fn source_quote(mut self, source_quote: impl Into<String>) -> Self {
3020        self.source_quote = Some(source_quote.into());
3021        self
3022    }
3023
3024    /// Specifies target quote(s), separated by , (e.g. `KRW`)
3025    pub fn target_quote(mut self, target_quote: impl Into<String>) -> Self {
3026        self.target_quote = Some(target_quote.into());
3027        self
3028    }
3029
3030    /// Specifies source market (e.g. `spot`)
3031    pub fn source_market(mut self, source_market: PremiumSourceMarket) -> Self {
3032        self.source_market = Some(source_market);
3033        self
3034    }
3035
3036    /// Specifies target market (e.g. `spot`)
3037    pub fn target_market(mut self, target_market: PremiumTargetMarket) -> Self {
3038        self.target_market = Some(target_market);
3039        self
3040    }
3041
3042    /// Specifies premium type(s), separated by , (e.g. `spot-spot`)
3043    pub fn premium_type(mut self, premium_type: PremiumPremiumType) -> Self {
3044        self.premium_type = Some(premium_type);
3045        self
3046    }
3047
3048    /// Specifies currency applied to price values (e.g. `KRW`)
3049    pub fn currency(mut self, currency: impl Into<String>) -> Self {
3050        self.currency = Some(currency.into());
3051        self
3052    }
3053
3054    /// Specifies conversion base (e.g. `USDT`)
3055    pub fn conversion_base(mut self, conversion_base: impl Into<String>) -> Self {
3056        self.conversion_base = Some(conversion_base.into());
3057        self
3058    }
3059
3060    /// Page number (e.g. `1`)
3061    pub fn page(mut self, page: i64) -> Self {
3062        self.page = Some(page);
3063        self
3064    }
3065
3066    /// Page size (e.g. `10`)
3067    pub fn limit(mut self, limit: i64) -> Self {
3068        self.limit = Some(limit);
3069        self
3070    }
3071
3072    /// Specifies sort order (e.g. `desc`)
3073    pub fn sort(mut self, sort: PremiumSort) -> Self {
3074        self.sort = Some(sort);
3075        self
3076    }
3077
3078    /// Specifies key to sort by (e.g. `pdp`)
3079    pub fn key(mut self, key: impl Into<String>) -> Self {
3080        self.key = Some(key.into());
3081        self
3082    }
3083
3084    /// Search query for filtering assets (e.g. `BTC`)
3085    pub fn query(mut self, query: impl Into<String>) -> Self {
3086        self.query = Some(query.into());
3087        self
3088    }
3089
3090    /// Filter only transferable assets (e.g. `false`)
3091    pub fn only_transferable(mut self, only_transferable: bool) -> Self {
3092        self.only_transferable = Some(only_transferable);
3093        self
3094    }
3095
3096    /// Specifies network(s), separated by , (e.g. `ethereum`)
3097    pub fn network(mut self, network: impl Into<String>) -> Self {
3098        self.network = Some(network.into());
3099        self
3100    }
3101
3102    /// Minimum source volume (e.g. `10000`)
3103    pub fn min_sv(mut self, min_sv: f64) -> Self {
3104        self.min_sv = Some(min_sv);
3105        self
3106    }
3107
3108    /// Minimum target volume (e.g. `10000`)
3109    pub fn min_tv(mut self, min_tv: f64) -> Self {
3110        self.min_tv = Some(min_tv);
3111        self
3112    }
3113
3114    /// Specifies token id(s) to include, separated by , (e.g. `bitcoin`)
3115    pub fn token_include(mut self, token_include: impl Into<String>) -> Self {
3116        self.token_include = Some(token_include.into());
3117        self
3118    }
3119
3120    /// Specifies token id(s) to exclude, separated by , (e.g. `bitcoin`)
3121    pub fn token_exclude(mut self, token_exclude: impl Into<String>) -> Self {
3122        self.token_exclude = Some(token_exclude.into());
3123        self
3124    }
3125}
3126
3127// --- Telegram ---
3128
3129/// Specifies key to sort by
3130#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3131#[allow(non_camel_case_types)]
3132#[non_exhaustive]
3133pub enum TelegramChannelsKey {
3134    ChannelName,
3135    Handle,
3136    Subscribers,
3137    CreatedAt,
3138}
3139
3140impl TelegramChannelsKey {
3141    /// The exact wire value this variant serializes to.
3142    pub fn as_str(&self) -> &'static str {
3143        match self {
3144            TelegramChannelsKey::ChannelName => "channelName",
3145            TelegramChannelsKey::Handle => "handle",
3146            TelegramChannelsKey::Subscribers => "subscribers",
3147            TelegramChannelsKey::CreatedAt => "createdAt",
3148        }
3149    }
3150}
3151
3152impl std::fmt::Display for TelegramChannelsKey {
3153    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3154        f.write_str(self.as_str())
3155    }
3156}
3157
3158/// Specifies sort
3159#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3160#[allow(non_camel_case_types)]
3161#[non_exhaustive]
3162pub enum TelegramChannelsSort {
3163    Asc,
3164    Desc,
3165}
3166
3167impl TelegramChannelsSort {
3168    /// The exact wire value this variant serializes to.
3169    pub fn as_str(&self) -> &'static str {
3170        match self {
3171            TelegramChannelsSort::Asc => "asc",
3172            TelegramChannelsSort::Desc => "desc",
3173        }
3174    }
3175}
3176
3177impl std::fmt::Display for TelegramChannelsSort {
3178    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3179        f.write_str(self.as_str())
3180    }
3181}
3182
3183/// Specifies key to sort by
3184#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3185#[allow(non_camel_case_types)]
3186#[non_exhaustive]
3187pub enum TelegramMessagesKey {
3188    ChannelName,
3189    Views,
3190    Reactions,
3191    Forwards,
3192    PublishedAt,
3193}
3194
3195impl TelegramMessagesKey {
3196    /// The exact wire value this variant serializes to.
3197    pub fn as_str(&self) -> &'static str {
3198        match self {
3199            TelegramMessagesKey::ChannelName => "channelName",
3200            TelegramMessagesKey::Views => "views",
3201            TelegramMessagesKey::Reactions => "reactions",
3202            TelegramMessagesKey::Forwards => "forwards",
3203            TelegramMessagesKey::PublishedAt => "publishedAt",
3204        }
3205    }
3206}
3207
3208impl std::fmt::Display for TelegramMessagesKey {
3209    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3210        f.write_str(self.as_str())
3211    }
3212}
3213
3214/// Specifies sort
3215#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3216#[allow(non_camel_case_types)]
3217#[non_exhaustive]
3218pub enum TelegramMessagesSort {
3219    Asc,
3220    Desc,
3221}
3222
3223impl TelegramMessagesSort {
3224    /// The exact wire value this variant serializes to.
3225    pub fn as_str(&self) -> &'static str {
3226        match self {
3227            TelegramMessagesSort::Asc => "asc",
3228            TelegramMessagesSort::Desc => "desc",
3229        }
3230    }
3231}
3232
3233impl std::fmt::Display for TelegramMessagesSort {
3234    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3235        f.write_str(self.as_str())
3236    }
3237}
3238
3239/// Specifies category
3240#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3241#[allow(non_camel_case_types)]
3242#[non_exhaustive]
3243pub enum TelegramMessagesCategory {
3244    English,
3245    Korean,
3246}
3247
3248impl TelegramMessagesCategory {
3249    /// The exact wire value this variant serializes to.
3250    pub fn as_str(&self) -> &'static str {
3251        match self {
3252            TelegramMessagesCategory::English => "english",
3253            TelegramMessagesCategory::Korean => "korean",
3254        }
3255    }
3256}
3257
3258impl std::fmt::Display for TelegramMessagesCategory {
3259    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3260        f.write_str(self.as_str())
3261    }
3262}
3263
3264#[derive(Default, Clone)]
3265pub struct TelegramChannelsOptions {
3266    /// Page number (e.g. `1`)
3267    pub page: Option<i64>,
3268    /// Page size (e.g. `100`)
3269    pub limit: Option<i64>,
3270    /// Specifies language category of telegram channel (e.g. `english`)
3271    pub category: Option<String>,
3272    /// Specifies key to sort by (e.g. `channelName`)
3273    pub key: Option<TelegramChannelsKey>,
3274    /// Specifies sort (e.g. `asc`)
3275    pub sort: Option<TelegramChannelsSort>,
3276}
3277
3278impl TelegramChannelsOptions {
3279    pub fn new() -> Self {
3280        TelegramChannelsOptions {
3281            page: None,
3282            limit: None,
3283            category: None,
3284            key: None,
3285            sort: None,
3286        }
3287    }
3288
3289    /// Page number (e.g. `1`)
3290    pub fn page(mut self, page: i64) -> Self {
3291        self.page = Some(page);
3292        self
3293    }
3294
3295    /// Page size (e.g. `100`)
3296    pub fn limit(mut self, limit: i64) -> Self {
3297        self.limit = Some(limit);
3298        self
3299    }
3300
3301    /// Specifies language category of telegram channel (e.g. `english`)
3302    pub fn category(mut self, category: impl Into<String>) -> Self {
3303        self.category = Some(category.into());
3304        self
3305    }
3306
3307    /// Specifies key to sort by (e.g. `channelName`)
3308    pub fn key(mut self, key: TelegramChannelsKey) -> Self {
3309        self.key = Some(key);
3310        self
3311    }
3312
3313    /// Specifies sort (e.g. `asc`)
3314    pub fn sort(mut self, sort: TelegramChannelsSort) -> Self {
3315        self.sort = Some(sort);
3316        self
3317    }
3318}
3319
3320#[derive(Default, Clone)]
3321pub struct TelegramMessagesOptions {
3322    /// Specifies channel username (e.g. `datamaxiplus`)
3323    pub channel: Option<String>,
3324    /// Page number (e.g. `1`)
3325    pub page: Option<i64>,
3326    /// Page size (e.g. `100`)
3327    pub limit: Option<i64>,
3328    /// Specifies key to sort by (e.g. `publishedAt`)
3329    pub key: Option<TelegramMessagesKey>,
3330    /// Specifies sort (e.g. `asc`)
3331    pub sort: Option<TelegramMessagesSort>,
3332    /// Specifies category (e.g. `english`)
3333    pub category: Option<TelegramMessagesCategory>,
3334    /// Specifies search query (e.g. `BTC`)
3335    pub search_query: Option<String>,
3336}
3337
3338impl TelegramMessagesOptions {
3339    pub fn new() -> Self {
3340        TelegramMessagesOptions {
3341            channel: None,
3342            page: None,
3343            limit: None,
3344            key: None,
3345            sort: None,
3346            category: None,
3347            search_query: None,
3348        }
3349    }
3350
3351    /// Specifies channel username (e.g. `datamaxiplus`)
3352    pub fn channel(mut self, channel: impl Into<String>) -> Self {
3353        self.channel = Some(channel.into());
3354        self
3355    }
3356
3357    /// Page number (e.g. `1`)
3358    pub fn page(mut self, page: i64) -> Self {
3359        self.page = Some(page);
3360        self
3361    }
3362
3363    /// Page size (e.g. `100`)
3364    pub fn limit(mut self, limit: i64) -> Self {
3365        self.limit = Some(limit);
3366        self
3367    }
3368
3369    /// Specifies key to sort by (e.g. `publishedAt`)
3370    pub fn key(mut self, key: TelegramMessagesKey) -> Self {
3371        self.key = Some(key);
3372        self
3373    }
3374
3375    /// Specifies sort (e.g. `asc`)
3376    pub fn sort(mut self, sort: TelegramMessagesSort) -> Self {
3377        self.sort = Some(sort);
3378        self
3379    }
3380
3381    /// Specifies category (e.g. `english`)
3382    pub fn category(mut self, category: TelegramMessagesCategory) -> Self {
3383        self.category = Some(category);
3384        self
3385    }
3386
3387    /// Specifies search query (e.g. `BTC`)
3388    pub fn search_query(mut self, search_query: impl Into<String>) -> Self {
3389        self.search_query = Some(search_query.into());
3390        self
3391    }
3392}
3393
3394// --- Ticker ---
3395
3396/// Specifies market
3397#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3398#[allow(non_camel_case_types)]
3399#[non_exhaustive]
3400pub enum TickerMarket {
3401    Spot,
3402    Futures,
3403}
3404
3405impl TickerMarket {
3406    /// The exact wire value this variant serializes to.
3407    pub fn as_str(&self) -> &'static str {
3408        match self {
3409            TickerMarket::Spot => "spot",
3410            TickerMarket::Futures => "futures",
3411        }
3412    }
3413}
3414
3415impl std::fmt::Display for TickerMarket {
3416    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3417        f.write_str(self.as_str())
3418    }
3419}
3420
3421/// Specifies currency applied to price values
3422#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3423#[allow(non_camel_case_types)]
3424#[non_exhaustive]
3425pub enum TickerCurrency {
3426    KRW,
3427    USD,
3428}
3429
3430impl TickerCurrency {
3431    /// The exact wire value this variant serializes to.
3432    pub fn as_str(&self) -> &'static str {
3433        match self {
3434            TickerCurrency::KRW => "KRW",
3435            TickerCurrency::USD => "USD",
3436        }
3437    }
3438}
3439
3440impl std::fmt::Display for TickerCurrency {
3441    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3442        f.write_str(self.as_str())
3443    }
3444}
3445
3446/// Specifies conversion base applied to price values
3447#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3448#[allow(non_camel_case_types)]
3449#[non_exhaustive]
3450pub enum TickerConversionBase {
3451    USD,
3452    USDT,
3453}
3454
3455impl TickerConversionBase {
3456    /// The exact wire value this variant serializes to.
3457    pub fn as_str(&self) -> &'static str {
3458        match self {
3459            TickerConversionBase::USD => "USD",
3460            TickerConversionBase::USDT => "USDT",
3461        }
3462    }
3463}
3464
3465impl std::fmt::Display for TickerConversionBase {
3466    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3467        f.write_str(self.as_str())
3468    }
3469}
3470
3471/// Specifies market
3472#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3473#[allow(non_camel_case_types)]
3474#[non_exhaustive]
3475pub enum TickerExchangesMarket {
3476    Spot,
3477    Futures,
3478}
3479
3480impl TickerExchangesMarket {
3481    /// The exact wire value this variant serializes to.
3482    pub fn as_str(&self) -> &'static str {
3483        match self {
3484            TickerExchangesMarket::Spot => "spot",
3485            TickerExchangesMarket::Futures => "futures",
3486        }
3487    }
3488}
3489
3490impl std::fmt::Display for TickerExchangesMarket {
3491    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3492        f.write_str(self.as_str())
3493    }
3494}
3495
3496/// Specifies market
3497#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3498#[allow(non_camel_case_types)]
3499#[non_exhaustive]
3500pub enum TickerSymbolsMarket {
3501    Spot,
3502    Futures,
3503}
3504
3505impl TickerSymbolsMarket {
3506    /// The exact wire value this variant serializes to.
3507    pub fn as_str(&self) -> &'static str {
3508        match self {
3509            TickerSymbolsMarket::Spot => "spot",
3510            TickerSymbolsMarket::Futures => "futures",
3511        }
3512    }
3513}
3514
3515impl std::fmt::Display for TickerSymbolsMarket {
3516    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3517        f.write_str(self.as_str())
3518    }
3519}
3520
3521#[derive(Default, Clone)]
3522pub struct TickerOptions {
3523    /// Specifies currency applied to price values (e.g. `KRW`)
3524    pub currency: Option<TickerCurrency>,
3525    /// Specifies conversion base applied to price values (e.g. `USDT`)
3526    pub conversion_base: Option<TickerConversionBase>,
3527}
3528
3529impl TickerOptions {
3530    pub fn new() -> Self {
3531        TickerOptions {
3532            currency: None,
3533            conversion_base: None,
3534        }
3535    }
3536
3537    /// Specifies currency applied to price values (e.g. `KRW`)
3538    pub fn currency(mut self, currency: TickerCurrency) -> Self {
3539        self.currency = Some(currency);
3540        self
3541    }
3542
3543    /// Specifies conversion base applied to price values (e.g. `USDT`)
3544    pub fn conversion_base(mut self, conversion_base: TickerConversionBase) -> Self {
3545        self.conversion_base = Some(conversion_base);
3546        self
3547    }
3548}
3549
3550// --- Token ---
3551
3552/// Specifies type of token update
3553#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3554#[allow(non_camel_case_types)]
3555#[non_exhaustive]
3556pub enum CexTokenUpdatesType {
3557    Listed,
3558    Delisted,
3559}
3560
3561impl CexTokenUpdatesType {
3562    /// The exact wire value this variant serializes to.
3563    pub fn as_str(&self) -> &'static str {
3564        match self {
3565            CexTokenUpdatesType::Listed => "listed",
3566            CexTokenUpdatesType::Delisted => "delisted",
3567        }
3568    }
3569}
3570
3571impl std::fmt::Display for CexTokenUpdatesType {
3572    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3573        f.write_str(self.as_str())
3574    }
3575}
3576
3577#[derive(Default, Clone)]
3578pub struct CexTokenUpdatesOptions {
3579    /// Specifies page (e.g. `1`)
3580    pub page: Option<String>,
3581    /// Specifies limit (e.g. `10`)
3582    pub limit: Option<String>,
3583    /// Specifies type of token update (e.g. `listed`)
3584    pub r#type: Option<CexTokenUpdatesType>,
3585}
3586
3587impl CexTokenUpdatesOptions {
3588    pub fn new() -> Self {
3589        CexTokenUpdatesOptions {
3590            page: None,
3591            limit: None,
3592            r#type: None,
3593        }
3594    }
3595
3596    /// Specifies page (e.g. `1`)
3597    pub fn page(mut self, page: impl Into<String>) -> Self {
3598        self.page = Some(page.into());
3599        self
3600    }
3601
3602    /// Specifies limit (e.g. `10`)
3603    pub fn limit(mut self, limit: impl Into<String>) -> Self {
3604        self.limit = Some(limit.into());
3605        self
3606    }
3607
3608    /// Specifies type of token update (e.g. `listed`)
3609    pub fn r#type(mut self, r#type: CexTokenUpdatesType) -> Self {
3610        self.r#type = Some(r#type);
3611        self
3612    }
3613}
3614
3615// --- TradingFees ---
3616
3617#[derive(Default, Clone)]
3618pub struct CexFeesOptions {
3619    /// Specifies exchange (e.g. `binance`)
3620    pub exchange: Option<String>,
3621    /// Specifies symbol (e.g. `BTC-USDT`)
3622    pub symbol: Option<String>,
3623}
3624
3625impl CexFeesOptions {
3626    pub fn new() -> Self {
3627        CexFeesOptions {
3628            exchange: None,
3629            symbol: None,
3630        }
3631    }
3632
3633    /// Specifies exchange (e.g. `binance`)
3634    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
3635        self.exchange = Some(exchange.into());
3636        self
3637    }
3638
3639    /// Specifies symbol (e.g. `BTC-USDT`)
3640    pub fn symbol(mut self, symbol: impl Into<String>) -> Self {
3641        self.symbol = Some(symbol.into());
3642        self
3643    }
3644}
3645
3646// --- WalletStatus ---
3647
3648#[derive(Default, Clone)]
3649pub struct WalletStatusOptions {
3650    /// Specifes exchange (e.g. `binance`)
3651    pub exchange: Option<String>,
3652}
3653
3654impl WalletStatusOptions {
3655    pub fn new() -> Self {
3656        WalletStatusOptions { exchange: None }
3657    }
3658
3659    /// Specifes exchange (e.g. `binance`)
3660    pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
3661        self.exchange = Some(exchange.into());
3662        self
3663    }
3664}
3665
3666#[doc(hidden)]
3667pub mod async_internal {
3668    //! Async endpoint-wrapper structs (crate-internal; re-exported at the
3669    //! crate root). Enums, Options, and response structs are shared with the
3670    //! sync mirror and live at the generated root, imported below.
3671    use super::*;
3672    use crate::api::{Client, Result};
3673    use std::collections::BTreeMap;
3674
3675    // --- Announcements ---
3676
3677    #[derive(Clone)]
3678    pub struct Announcements {
3679        client: Client,
3680    }
3681
3682    impl Announcements {
3683        /// Wraps an already-built client (e.g. from `ClientBuilder`).
3684        pub fn from_client(client: Client) -> Self {
3685            Self { client }
3686        }
3687
3688        /// Get latest announcements from centralized exchanges
3689        pub async fn announcements(
3690            &self,
3691            options: CexAnnouncementsOptions,
3692        ) -> Result<CexAnnouncementsResponse> {
3693            let mut parameters = BTreeMap::new();
3694            if let Some(v) = options.page {
3695                parameters.insert("page".to_string(), v.to_string());
3696            }
3697            if let Some(v) = options.limit {
3698                parameters.insert("limit".to_string(), v.to_string());
3699            }
3700            if let Some(v) = options.sort {
3701                parameters.insert("sort".to_string(), v.to_string());
3702            }
3703            if let Some(v) = options.key {
3704                parameters.insert("key".to_string(), v.to_string());
3705            }
3706            if let Some(v) = options.exchange {
3707                parameters.insert("exchange".to_string(), v.to_string());
3708            }
3709            if let Some(v) = options.category {
3710                parameters.insert("category".to_string(), v.to_string());
3711            }
3712            self.client
3713                .get("/api/v1/cex/announcements", Some(parameters))
3714                .await
3715        }
3716    }
3717
3718    // --- CexCandle ---
3719
3720    #[derive(Clone)]
3721    pub struct CexCandle {
3722        client: Client,
3723    }
3724
3725    impl CexCandle {
3726        /// Wraps an already-built client (e.g. from `ClientBuilder`).
3727        pub fn from_client(client: Client) -> Self {
3728            Self { client }
3729        }
3730
3731        /// Get historical candle data for a given `exchange`, `symbol`, `interval` and `market`.
3732        pub async fn get(
3733            &self,
3734            exchange: impl Into<String>,
3735            symbol: impl Into<String>,
3736            options: CexCandleOptions,
3737        ) -> Result<CexCandleResponse> {
3738            let mut parameters = BTreeMap::new();
3739            parameters.insert("exchange".to_string(), exchange.into());
3740            parameters.insert("symbol".to_string(), symbol.into());
3741            if let Some(v) = options.market {
3742                parameters.insert("market".to_string(), v.to_string());
3743            }
3744            if let Some(v) = options.currency {
3745                parameters.insert("currency".to_string(), v.to_string());
3746            }
3747            if let Some(v) = options.interval {
3748                parameters.insert("interval".to_string(), v.to_string());
3749            }
3750            if let Some(v) = options.from {
3751                parameters.insert("from".to_string(), v.to_string());
3752            }
3753            if let Some(v) = options.to {
3754                parameters.insert("to".to_string(), v.to_string());
3755            }
3756            self.client
3757                .get("/api/v1/cex/candle", Some(parameters))
3758                .await
3759        }
3760
3761        /// Get supported exchanges accepted by `/api/v1/cex/candle` endpoint.
3762        pub async fn exchanges(&self, market: CexCandleExchangesMarket) -> Result<Vec<String>> {
3763            let mut parameters = BTreeMap::new();
3764            parameters.insert("market".to_string(), market.to_string());
3765            self.client
3766                .get("/api/v1/cex/candle/exchanges", Some(parameters))
3767                .await
3768        }
3769
3770        /// Fetch supported intervals accepted by `/api/v1/cex/candle` endpoint.
3771        pub async fn intervals(&self) -> Result<Vec<String>> {
3772            self.client.get("/api/v1/cex/candle/intervals", None).await
3773        }
3774
3775        /// Fetch supported symbols accepted by `/api/v1/cex/candle` endpoint.
3776        pub async fn symbols(
3777            &self,
3778            exchange: impl Into<String>,
3779            options: CexCandleSymbolsOptions,
3780        ) -> Result<Vec<CexCandleSymbolsView>> {
3781            let mut parameters = BTreeMap::new();
3782            parameters.insert("exchange".to_string(), exchange.into());
3783            if let Some(v) = options.market {
3784                parameters.insert("market".to_string(), v.to_string());
3785            }
3786            self.client
3787                .get("/api/v1/cex/candle/symbols", Some(parameters))
3788                .await
3789        }
3790    }
3791
3792    // --- CexSymbol ---
3793
3794    #[derive(Clone)]
3795    pub struct CexSymbol {
3796        client: Client,
3797    }
3798
3799    impl CexSymbol {
3800        /// Wraps an already-built client (e.g. from `ClientBuilder`).
3801        pub fn from_client(client: Client) -> Self {
3802            Self { client }
3803        }
3804
3805        /// Return currently-active caution/warning/danger flagged symbols. Bithumb provides an expiry (end_at); other exchanges are open-ended until the next collector poll clears them.
3806        pub async fn cautions(
3807            &self,
3808            options: CexSymbolCautionsOptions,
3809        ) -> Result<Vec<CexSymbolCautionsView>> {
3810            let mut parameters = BTreeMap::new();
3811            if let Some(v) = options.exchange {
3812                parameters.insert("exchange".to_string(), v.to_string());
3813            }
3814            if let Some(v) = options.market {
3815                parameters.insert("market".to_string(), v.to_string());
3816            }
3817            if let Some(v) = options.min_level {
3818                parameters.insert("min_level".to_string(), v.to_string());
3819            }
3820            if let Some(v) = options.active_only {
3821                parameters.insert("active_only".to_string(), v.to_string());
3822            }
3823            if let Some(v) = options.limit {
3824                parameters.insert("limit".to_string(), v.to_string());
3825            }
3826            if let Some(v) = options.page {
3827                parameters.insert("page".to_string(), v.to_string());
3828            }
3829            self.client
3830                .get("/api/v1/cex/symbol/cautions", Some(parameters))
3831                .await
3832        }
3833
3834        /// Return symbols with a known delisting_at timestamp or trading_status in {delisting, delisted}. Filter by time window to get upcoming delistings.
3835        pub async fn delistings(
3836            &self,
3837            options: CexSymbolDelistingsOptions,
3838        ) -> Result<Vec<CexSymbolDelistingsView>> {
3839            let mut parameters = BTreeMap::new();
3840            if let Some(v) = options.exchange {
3841                parameters.insert("exchange".to_string(), v.to_string());
3842            }
3843            if let Some(v) = options.market {
3844                parameters.insert("market".to_string(), v.to_string());
3845            }
3846            if let Some(v) = options.from_ms {
3847                parameters.insert("from_ms".to_string(), v.to_string());
3848            }
3849            if let Some(v) = options.to_ms {
3850                parameters.insert("to_ms".to_string(), v.to_string());
3851            }
3852            if let Some(v) = options.include_past {
3853                parameters.insert("include_past".to_string(), v.to_string());
3854            }
3855            if let Some(v) = options.limit {
3856                parameters.insert("limit".to_string(), v.to_string());
3857            }
3858            if let Some(v) = options.page {
3859                parameters.insert("page".to_string(), v.to_string());
3860            }
3861            self.client
3862                .get("/api/v1/cex/symbol/delistings", Some(parameters))
3863                .await
3864        }
3865
3866        /// Sums long/short liquidation volume across all events in a rolling window for every exchange × quote pairing of the base asset. Window max 30d; default 24h.
3867        pub async fn liquidation(
3868            &self,
3869            base: impl Into<String>,
3870            options: CexSymbolLiquidationOptions,
3871        ) -> Result<Vec<CexSymbolLiquidationView>> {
3872            let mut parameters = BTreeMap::new();
3873            parameters.insert("base".to_string(), base.into());
3874            if let Some(v) = options.window {
3875                parameters.insert("window".to_string(), v.to_string());
3876            }
3877            self.client
3878                .get("/api/v1/cex/symbol/liquidation", Some(parameters))
3879                .await
3880        }
3881
3882        /// Fetch per-symbol trading status, caution flags, tags and timing metadata collected by tfsymbolmeta.
3883        pub async fn metadata(
3884            &self,
3885            options: CexSymbolMetadataOptions,
3886        ) -> Result<Vec<CexSymbolMetadataView>> {
3887            let mut parameters = BTreeMap::new();
3888            if let Some(v) = options.exchange {
3889                parameters.insert("exchange".to_string(), v.to_string());
3890            }
3891            if let Some(v) = options.market {
3892                parameters.insert("market".to_string(), v.to_string());
3893            }
3894            if let Some(v) = options.base {
3895                parameters.insert("base".to_string(), v.to_string());
3896            }
3897            if let Some(v) = options.quote {
3898                parameters.insert("quote".to_string(), v.to_string());
3899            }
3900            if let Some(v) = options.status {
3901                parameters.insert("status".to_string(), v.to_string());
3902            }
3903            if let Some(v) = options.limit {
3904                parameters.insert("limit".to_string(), v.to_string());
3905            }
3906            if let Some(v) = options.page {
3907                parameters.insert("page".to_string(), v.to_string());
3908            }
3909            self.client
3910                .get("/api/v1/cex/symbol/metadata", Some(parameters))
3911                .await
3912        }
3913
3914        /// Latest Open Interest snapshot across every futures venue carrying the given base. Sorted by USD value descending, NULLs last.
3915        pub async fn oi(
3916            &self,
3917            base: impl Into<String>,
3918            options: CexSymbolOiOptions,
3919        ) -> Result<Vec<CexSymbolOiView>> {
3920            let mut parameters = BTreeMap::new();
3921            parameters.insert("base".to_string(), base.into());
3922            if let Some(v) = options.exchange {
3923                parameters.insert("exchange".to_string(), v.to_string());
3924            }
3925            self.client
3926                .get("/api/v1/cex/symbol/oi", Some(parameters))
3927                .await
3928        }
3929
3930        /// Enriched snapshot combining the latest OI (USD) with 1h/4h/24h change percentages and OI/24h volume ratio. Backed by the tfopeninterest taskflow's Redis HASH.
3931        pub async fn oi_stats(
3932            &self,
3933            base: impl Into<String>,
3934            options: CexSymbolOiStatsOptions,
3935        ) -> Result<Vec<CexSymbolOiStatsView>> {
3936            let mut parameters = BTreeMap::new();
3937            parameters.insert("base".to_string(), base.into());
3938            if let Some(v) = options.exchange {
3939                parameters.insert("exchange".to_string(), v.to_string());
3940            }
3941            if let Some(v) = options.currency {
3942                parameters.insert("currency".to_string(), v.to_string());
3943            }
3944            self.client
3945                .get("/api/v1/cex/symbol/oi-stats", Some(parameters))
3946                .await
3947        }
3948
3949        /// Fetch (exchange, market, base, quote, tag) rows from cex_symbol_tag. Use to find every symbol flagged with a given tag (e.g. all meme coins across exchanges).
3950        pub async fn tags(&self, options: CexSymbolTagsOptions) -> Result<Vec<CexSymbolTagsView>> {
3951            let mut parameters = BTreeMap::new();
3952            if let Some(v) = options.tag {
3953                parameters.insert("tag".to_string(), v.to_string());
3954            }
3955            if let Some(v) = options.exchange {
3956                parameters.insert("exchange".to_string(), v.to_string());
3957            }
3958            if let Some(v) = options.market {
3959                parameters.insert("market".to_string(), v.to_string());
3960            }
3961            if let Some(v) = options.base {
3962                parameters.insert("base".to_string(), v.to_string());
3963            }
3964            if let Some(v) = options.source {
3965                parameters.insert("source".to_string(), v.to_string());
3966            }
3967            if let Some(v) = options.min_confidence {
3968                parameters.insert("min_confidence".to_string(), v.to_string());
3969            }
3970            if let Some(v) = options.limit {
3971                parameters.insert("limit".to_string(), v.to_string());
3972            }
3973            if let Some(v) = options.page {
3974                parameters.insert("page".to_string(), v.to_string());
3975            }
3976            self.client
3977                .get("/api/v1/cex/symbol/tags", Some(parameters))
3978                .await
3979        }
3980
3981        /// Latest 24h trading volume across every (exchange, market, quote) a token lists on. Backed by cache.latest_volume.
3982        pub async fn volume(
3983            &self,
3984            base: impl Into<String>,
3985            options: CexSymbolVolumeOptions,
3986        ) -> Result<Vec<CexSymbolVolumeView>> {
3987            let mut parameters = BTreeMap::new();
3988            parameters.insert("base".to_string(), base.into());
3989            if let Some(v) = options.market {
3990                parameters.insert("market".to_string(), v.to_string());
3991            }
3992            self.client
3993                .get("/api/v1/cex/symbol/volume", Some(parameters))
3994                .await
3995        }
3996    }
3997
3998    // --- Forex ---
3999
4000    #[derive(Clone)]
4001    pub struct Forex {
4002        client: Client,
4003    }
4004
4005    impl Forex {
4006        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4007        pub fn from_client(client: Client) -> Self {
4008            Self { client }
4009        }
4010
4011        /// Get the latest forex rate for given symbol.
4012        pub async fn get(&self, symbol: impl Into<String>) -> Result<ForexResponse> {
4013            let mut parameters = BTreeMap::new();
4014            parameters.insert("symbol".to_string(), symbol.into());
4015            self.client.get("/api/v1/forex", Some(parameters)).await
4016        }
4017
4018        /// Get supported forex symbols.
4019        pub async fn symbols(&self) -> Result<Vec<String>> {
4020            self.client.get("/api/v1/forex/symbols", None).await
4021        }
4022    }
4023
4024    // --- FundingRate ---
4025
4026    #[derive(Clone)]
4027    pub struct FundingRate {
4028        client: Client,
4029    }
4030
4031    impl FundingRate {
4032        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4033        pub fn from_client(client: Client) -> Self {
4034            Self { client }
4035        }
4036
4037        /// Get supported exchanges accepted by `/api/v1/funding-rate` endpoint.
4038        pub async fn exchanges(&self) -> Result<Vec<String>> {
4039            self.client
4040                .get("/api/v1/funding-rate/exchanges", None)
4041                .await
4042        }
4043
4044        /// Get historical funding rate data for a given `exchange` and `symbol`.
4045        pub async fn history(
4046            &self,
4047            exchange: impl Into<String>,
4048            symbol: impl Into<String>,
4049            options: FundingRateHistoryOptions,
4050        ) -> Result<FundingRateHistoryResponse> {
4051            let mut parameters = BTreeMap::new();
4052            parameters.insert("exchange".to_string(), exchange.into());
4053            parameters.insert("symbol".to_string(), symbol.into());
4054            if let Some(v) = options.page {
4055                parameters.insert("page".to_string(), v.to_string());
4056            }
4057            if let Some(v) = options.limit {
4058                parameters.insert("limit".to_string(), v.to_string());
4059            }
4060            if let Some(v) = options.from {
4061                parameters.insert("from".to_string(), v.to_string());
4062            }
4063            if let Some(v) = options.to {
4064                parameters.insert("to".to_string(), v.to_string());
4065            }
4066            if let Some(v) = options.sort {
4067                parameters.insert("sort".to_string(), v.to_string());
4068            }
4069            self.client
4070                .get("/api/v1/funding-rate/history", Some(parameters))
4071                .await
4072        }
4073
4074        /// Fetch the latest funding rate data for a given `exchange` and `symbol`.
4075        pub async fn latest(
4076            &self,
4077            exchange: impl Into<String>,
4078            symbol: impl Into<String>,
4079        ) -> Result<FundingRateLatestResponse> {
4080            let mut parameters = BTreeMap::new();
4081            parameters.insert("exchange".to_string(), exchange.into());
4082            parameters.insert("symbol".to_string(), symbol.into());
4083            self.client
4084                .get("/api/v1/funding-rate/latest", Some(parameters))
4085                .await
4086        }
4087
4088        /// Fetch supported symbols accepted by `/api/v1/funding-rate` endpoint.
4089        pub async fn symbols(
4090            &self,
4091            options: FundingRateSymbolsOptions,
4092        ) -> Result<Vec<FundingRateSymbolsView>> {
4093            let mut parameters = BTreeMap::new();
4094            if let Some(v) = options.exchange {
4095                parameters.insert("exchange".to_string(), v.to_string());
4096            }
4097            self.client
4098                .get("/api/v1/funding-rate/symbols", Some(parameters))
4099                .await
4100        }
4101    }
4102
4103    // --- IndexPrice ---
4104
4105    #[derive(Clone)]
4106    pub struct IndexPrice {
4107        client: Client,
4108    }
4109
4110    impl IndexPrice {
4111        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4112        pub fn from_client(client: Client) -> Self {
4113            Self { client }
4114        }
4115
4116        /// Get index price
4117        pub async fn get(
4118            &self,
4119            asset: impl Into<String>,
4120            options: IndexPriceOptions,
4121        ) -> Result<IndexPriceResponse> {
4122            let mut parameters = BTreeMap::new();
4123            parameters.insert("asset".to_string(), asset.into());
4124            if let Some(v) = options.from {
4125                parameters.insert("from".to_string(), v.to_string());
4126            }
4127            if let Some(v) = options.to {
4128                parameters.insert("to".to_string(), v.to_string());
4129            }
4130            if let Some(v) = options.interval {
4131                parameters.insert("interval".to_string(), v.to_string());
4132            }
4133            self.client
4134                .get("/api/v1/index-price", Some(parameters))
4135                .await
4136        }
4137    }
4138
4139    // --- Liquidation ---
4140
4141    #[derive(Clone)]
4142    pub struct Liquidation {
4143        client: Client,
4144    }
4145
4146    impl Liquidation {
4147        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4148        pub fn from_client(client: Client) -> Self {
4149            Self { client }
4150        }
4151
4152        /// Fetch recent liquidation events for a futures symbol on a given exchange, newest first.
4153        pub async fn get(
4154            &self,
4155            exchange: impl Into<String>,
4156            symbol: impl Into<String>,
4157            options: LiquidationOptions,
4158        ) -> Result<LiquidationResponse> {
4159            let mut parameters = BTreeMap::new();
4160            parameters.insert("exchange".to_string(), exchange.into());
4161            parameters.insert("symbol".to_string(), symbol.into());
4162            if let Some(v) = options.limit {
4163                parameters.insert("limit".to_string(), v.to_string());
4164            }
4165            self.client
4166                .get("/api/v1/liquidation", Some(parameters))
4167                .await
4168        }
4169
4170        /// Fetch most recent liquidation events across all futures symbols, newest first. Use together with the `/ws/v1/liquidation/feed` firehose for a live feed view.
4171        pub async fn feed(
4172            &self,
4173            options: LiquidationFeedOptions,
4174        ) -> Result<LiquidationFeedResponse> {
4175            let mut parameters = BTreeMap::new();
4176            if let Some(v) = options.exchange {
4177                parameters.insert("exchange".to_string(), v.to_string());
4178            }
4179            if let Some(v) = options.base {
4180                parameters.insert("base".to_string(), v.to_string());
4181            }
4182            if let Some(v) = options.min_volume_usd {
4183                parameters.insert("min_volume_usd".to_string(), v.to_string());
4184            }
4185            if let Some(v) = options.limit {
4186                parameters.insert("limit".to_string(), v.to_string());
4187            }
4188            self.client
4189                .get("/api/v1/liquidation/feed", Some(parameters))
4190                .await
4191        }
4192
4193        /// Aggregated long/short liquidation USD by (token, exchange) over a rolling window. Result is cached for ~10s. Sub-1h windows are not supported; use the WS feed for finer granularity.
4194        pub async fn heatmap(
4195            &self,
4196            options: LiquidationHeatmapOptions,
4197        ) -> Result<LiquidationHeatmapResponse> {
4198            let mut parameters = BTreeMap::new();
4199            if let Some(v) = options.window {
4200                parameters.insert("window".to_string(), v.to_string());
4201            }
4202            if let Some(v) = options.top_n {
4203                parameters.insert("top_n".to_string(), v.to_string());
4204            }
4205            self.client
4206                .get("/api/v1/liquidation/heatmap", Some(parameters))
4207                .await
4208        }
4209
4210        /// Coinglass-style liquidation map for one perpetual pair. Returns a price-grid breakdown of where leveraged positions would be liquidated, split by leverage tier (10x / 25x / 50x / 100x) and side (long below current price, short above). Built from current OI + last-24h candle entries + a fixed leverage-cohort prior. Read the `assumptions` field in the response for the modelling disclaimer. Cached server-side (~5s) so back-to-back polls are cheap.
4211        pub async fn map(&self, options: LiquidationMapOptions) -> Result<LiquidationMapResponse> {
4212            let mut parameters = BTreeMap::new();
4213            if let Some(v) = options.exchange {
4214                parameters.insert("exchange".to_string(), v.to_string());
4215            }
4216            if let Some(v) = options.base {
4217                parameters.insert("base".to_string(), v.to_string());
4218            }
4219            if let Some(v) = options.quote {
4220                parameters.insert("quote".to_string(), v.to_string());
4221            }
4222            self.client
4223                .get("/api/v1/liquidation/map", Some(parameters))
4224                .await
4225        }
4226
4227        /// Aggregate liquidation stats (total, long/short split, count, venue count, biggest single event) over a 1h/4h/24h window. Backs the liquidation page KPI strip for windows the live feed buffer can't cover.
4228        pub async fn stats(
4229            &self,
4230            options: LiquidationStatsOptions,
4231        ) -> Result<LiquidationStatsResponse> {
4232            let mut parameters = BTreeMap::new();
4233            if let Some(v) = options.window {
4234                parameters.insert("window".to_string(), v.to_string());
4235            }
4236            if let Some(v) = options.exchange {
4237                parameters.insert("exchange".to_string(), v.to_string());
4238            }
4239            if let Some(v) = options.min_volume_usd {
4240                parameters.insert("min_volume_usd".to_string(), v.to_string());
4241            }
4242            self.client
4243                .get("/api/v1/liquidation/stats", Some(parameters))
4244                .await
4245        }
4246
4247        /// Bucketed long / short liquidation USD over time for a single (base, quote) pair, joined with the futures-candle close as a reference price line. Long/short USD comes from `cex.liquidation` (Side='sell' = long position liquidated, 'buy' = short). Price comes from `candle.futures_1m` on the requested exchange — or Binance as the reference when none is specified. Cached ~30s server-side.
4248        pub async fn symbol_history(
4249            &self,
4250            symbol: impl Into<String>,
4251            options: LiquidationSymbolHistoryOptions,
4252        ) -> Result<LiquidationSymbolHistoryResponse> {
4253            let mut parameters = BTreeMap::new();
4254            parameters.insert("symbol".to_string(), symbol.into());
4255            if let Some(v) = options.quote {
4256                parameters.insert("quote".to_string(), v.to_string());
4257            }
4258            if let Some(v) = options.exchange {
4259                parameters.insert("exchange".to_string(), v.to_string());
4260            }
4261            if let Some(v) = options.interval {
4262                parameters.insert("interval".to_string(), v.to_string());
4263            }
4264            if let Some(v) = options.window {
4265                parameters.insert("window".to_string(), v.to_string());
4266            }
4267            self.client
4268                .get("/api/v1/liquidation/symbol-history", Some(parameters))
4269                .await
4270        }
4271    }
4272
4273    // --- Listing ---
4274
4275    #[derive(Clone)]
4276    pub struct Listing {
4277        client: Client,
4278    }
4279
4280    impl Listing {
4281        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4282        pub fn from_client(client: Client) -> Self {
4283            Self { client }
4284        }
4285
4286        /// Get historical token listings for Upbit and Bithumb for KRW market
4287        pub async fn historical(
4288            &self,
4289            options: ListingsHistoricalOptions,
4290        ) -> Result<ListingsHistoricalResponse> {
4291            let mut parameters = BTreeMap::new();
4292            if let Some(v) = options.refresh {
4293                parameters.insert("refresh".to_string(), v.to_string());
4294            }
4295            self.client
4296                .get("/api/v1/listings/historical", Some(parameters))
4297                .await
4298        }
4299    }
4300
4301    // --- MarginBorrow ---
4302
4303    #[derive(Clone)]
4304    pub struct MarginBorrow {
4305        client: Client,
4306    }
4307
4308    impl MarginBorrow {
4309        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4310        pub fn from_client(client: Client) -> Self {
4311            Self { client }
4312        }
4313
4314        /// Get the margin borrow data.
4315        pub async fn get(&self, asset: impl Into<String>) -> Result<MarginBorrowResponse> {
4316            let mut parameters = BTreeMap::new();
4317            parameters.insert("asset".to_string(), asset.into());
4318            self.client
4319                .get("/api/v1/margin-borrow", Some(parameters))
4320                .await
4321        }
4322    }
4323
4324    // --- NaverTrend ---
4325
4326    #[derive(Clone)]
4327    pub struct NaverTrend {
4328        client: Client,
4329    }
4330
4331    impl NaverTrend {
4332        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4333        pub fn from_client(client: Client) -> Self {
4334            Self { client }
4335        }
4336
4337        /// Get Naver trend data with a daily frequency for a project that is associated with a given [symbol](./symbols). The values in response are normalized into a range from 0 to 100, where 0 corresponds to a minimum interest, and 100 corresponds to a maximum interest of users in Naver search engine.
4338        pub async fn get(&self, symbol: impl Into<String>) -> Result<Vec<NaverTrendView>> {
4339            let mut parameters = BTreeMap::new();
4340            parameters.insert("symbol".to_string(), symbol.into());
4341            self.client
4342                .get("/api/v1/naver-trend", Some(parameters))
4343                .await
4344        }
4345
4346        /// Get crypto symbols that are accepted by [Naver trend endpoint](./trend).
4347        pub async fn symbols(&self) -> Result<Vec<String>> {
4348            self.client.get("/api/v1/naver-trend/symbols", None).await
4349        }
4350    }
4351
4352    // --- OpenInterest ---
4353
4354    #[derive(Clone)]
4355    pub struct OpenInterest {
4356        client: Client,
4357    }
4358
4359    impl OpenInterest {
4360        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4361        pub fn from_client(client: Client) -> Self {
4362            Self { client }
4363        }
4364
4365        /// Fetch the most recent Open Interest snapshot for a futures symbol on a given exchange.
4366        pub async fn get(
4367            &self,
4368            exchange: impl Into<String>,
4369            symbol: impl Into<String>,
4370        ) -> Result<OpenInterestResponse> {
4371            let mut parameters = BTreeMap::new();
4372            parameters.insert("exchange".to_string(), exchange.into());
4373            parameters.insert("symbol".to_string(), symbol.into());
4374            self.client
4375                .get("/api/v1/open-interest", Some(parameters))
4376                .await
4377        }
4378
4379        /// Historical Open Interest time series for a single token, broken down per exchange and aggregated to a fixed bucket (avg within bucket). The default lookback depends on the requested interval — 7 days for 1h, 30 days for 4h, 1 year for 1d — so callers don't have to hand-tune `from`/`to` for typical queries. The response also includes token metadata (icon, symbol, name) so a single call paints the whole header strip.
4380        pub async fn history_aggregated(
4381            &self,
4382            token_id: impl Into<String>,
4383            options: OpenInterestHistoryAggregatedOptions,
4384        ) -> Result<OpenInterestHistoryAggregatedResponse> {
4385            let mut parameters = BTreeMap::new();
4386            parameters.insert("token_id".to_string(), token_id.into());
4387            if let Some(v) = options.interval {
4388                parameters.insert("interval".to_string(), v.to_string());
4389            }
4390            if let Some(v) = options.from {
4391                parameters.insert("from".to_string(), v.to_string());
4392            }
4393            if let Some(v) = options.to {
4394                parameters.insert("to".to_string(), v.to_string());
4395            }
4396            self.client
4397                .get("/api/v1/open-interest/history-aggregated", Some(parameters))
4398                .await
4399        }
4400
4401        /// Fetch latest Open Interest snapshots across exchanges/symbols. Optionally filter by `exchange`. Results are sorted by `openInterestUsd` descending (null values last).
4402        pub async fn list(
4403            &self,
4404            options: OpenInterestListOptions,
4405        ) -> Result<OpenInterestListResponse> {
4406            let mut parameters = BTreeMap::new();
4407            if let Some(v) = options.exchange {
4408                parameters.insert("exchange".to_string(), v.to_string());
4409            }
4410            self.client
4411                .get("/api/v1/open-interest/list", Some(parameters))
4412                .await
4413        }
4414
4415        /// Paginated token × exchange Open Interest matrix. For each base asset we list the per-exchange notional OI in USD (when a venue carries the token) and `null` when it doesn't trade there. The matrix is sortable by any exchange column and searchable by base symbol — same shape the DataMaxi+ dashboard uses on `/open-interest`. Cached snapshot rebuilds every few seconds, so back-to-back requests are cheap.
4416        pub async fn overview(
4417            &self,
4418            options: OpenInterestOverviewOptions,
4419        ) -> Result<OpenInterestOverviewResponse> {
4420            let mut parameters = BTreeMap::new();
4421            if let Some(v) = options.page {
4422                parameters.insert("page".to_string(), v.to_string());
4423            }
4424            if let Some(v) = options.limit {
4425                parameters.insert("limit".to_string(), v.to_string());
4426            }
4427            if let Some(v) = options.key {
4428                parameters.insert("key".to_string(), v.to_string());
4429            }
4430            if let Some(v) = options.sort {
4431                parameters.insert("sort".to_string(), v.to_string());
4432            }
4433            if let Some(v) = options.query {
4434                parameters.insert("query".to_string(), v.to_string());
4435            }
4436            self.client
4437                .get("/api/v1/open-interest/overview", Some(parameters))
4438                .await
4439        }
4440
4441        /// Top-line aggregates over the current Open Interest snapshot — total OI USD, top tokens by OI, top exchanges by OI, and the count of venues currently reporting any base. Powers the OI page's KPI strip and breakdown card without forcing the caller to fetch the full token list.
4442        pub async fn summary(
4443            &self,
4444            options: OpenInterestSummaryOptions,
4445        ) -> Result<OpenInterestSummaryResponse> {
4446            let mut parameters = BTreeMap::new();
4447            if let Some(v) = options.top_n {
4448                parameters.insert("top_n".to_string(), v.to_string());
4449            }
4450            self.client
4451                .get("/api/v1/open-interest/summary", Some(parameters))
4452                .await
4453        }
4454    }
4455
4456    // --- Premium ---
4457
4458    #[derive(Clone)]
4459    pub struct Premium {
4460        client: Client,
4461    }
4462
4463    impl Premium {
4464        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4465        pub fn from_client(client: Client) -> Self {
4466            Self { client }
4467        }
4468
4469        /// Get real-time premium (price difference) data across exchanges.
4470        pub async fn get(&self, options: PremiumOptions) -> Result<PremiumResponse> {
4471            let mut parameters = BTreeMap::new();
4472            if let Some(v) = options.source_exchange {
4473                parameters.insert("source_exchange".to_string(), v.to_string());
4474            }
4475            if let Some(v) = options.target_exchange {
4476                parameters.insert("target_exchange".to_string(), v.to_string());
4477            }
4478            if let Some(v) = options.asset {
4479                parameters.insert("asset".to_string(), v.to_string());
4480            }
4481            if let Some(v) = options.source_quote {
4482                parameters.insert("source_quote".to_string(), v.to_string());
4483            }
4484            if let Some(v) = options.target_quote {
4485                parameters.insert("target_quote".to_string(), v.to_string());
4486            }
4487            if let Some(v) = options.source_market {
4488                parameters.insert("source_market".to_string(), v.to_string());
4489            }
4490            if let Some(v) = options.target_market {
4491                parameters.insert("target_market".to_string(), v.to_string());
4492            }
4493            if let Some(v) = options.premium_type {
4494                parameters.insert("premium_type".to_string(), v.to_string());
4495            }
4496            if let Some(v) = options.currency {
4497                parameters.insert("currency".to_string(), v.to_string());
4498            }
4499            if let Some(v) = options.conversion_base {
4500                parameters.insert("conversion_base".to_string(), v.to_string());
4501            }
4502            if let Some(v) = options.page {
4503                parameters.insert("page".to_string(), v.to_string());
4504            }
4505            if let Some(v) = options.limit {
4506                parameters.insert("limit".to_string(), v.to_string());
4507            }
4508            if let Some(v) = options.sort {
4509                parameters.insert("sort".to_string(), v.to_string());
4510            }
4511            if let Some(v) = options.key {
4512                parameters.insert("key".to_string(), v.to_string());
4513            }
4514            if let Some(v) = options.query {
4515                parameters.insert("query".to_string(), v.to_string());
4516            }
4517            if let Some(v) = options.only_transferable {
4518                parameters.insert("only_transferable".to_string(), v.to_string());
4519            }
4520            if let Some(v) = options.network {
4521                parameters.insert("network".to_string(), v.to_string());
4522            }
4523            if let Some(v) = options.min_sv {
4524                parameters.insert("min_sv".to_string(), v.to_string());
4525            }
4526            if let Some(v) = options.min_tv {
4527                parameters.insert("min_tv".to_string(), v.to_string());
4528            }
4529            if let Some(v) = options.token_include {
4530                parameters.insert("token_include".to_string(), v.to_string());
4531            }
4532            if let Some(v) = options.token_exclude {
4533                parameters.insert("token_exclude".to_string(), v.to_string());
4534            }
4535            self.client.get("/api/v1/premium", Some(parameters)).await
4536        }
4537
4538        /// Get supported source exchanges for premium data.
4539        pub async fn exchanges(&self) -> Result<Vec<String>> {
4540            self.client.get("/api/v1/premium/exchanges", None).await
4541        }
4542    }
4543
4544    // --- Telegram ---
4545
4546    #[derive(Clone)]
4547    pub struct Telegram {
4548        client: Client,
4549    }
4550
4551    impl Telegram {
4552        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4553        pub fn from_client(client: Client) -> Self {
4554            Self { client }
4555        }
4556
4557        /// Get Telegram channels
4558        pub async fn channels(
4559            &self,
4560            options: TelegramChannelsOptions,
4561        ) -> Result<TelegramChannelsResponse> {
4562            let mut parameters = BTreeMap::new();
4563            if let Some(v) = options.page {
4564                parameters.insert("page".to_string(), v.to_string());
4565            }
4566            if let Some(v) = options.limit {
4567                parameters.insert("limit".to_string(), v.to_string());
4568            }
4569            if let Some(v) = options.category {
4570                parameters.insert("category".to_string(), v.to_string());
4571            }
4572            if let Some(v) = options.key {
4573                parameters.insert("key".to_string(), v.to_string());
4574            }
4575            if let Some(v) = options.sort {
4576                parameters.insert("sort".to_string(), v.to_string());
4577            }
4578            self.client
4579                .get("/api/v1/telegram/channels", Some(parameters))
4580                .await
4581        }
4582
4583        /// Get Telegram messages.
4584        pub async fn messages(
4585            &self,
4586            options: TelegramMessagesOptions,
4587        ) -> Result<TelegramMessagesResponse> {
4588            let mut parameters = BTreeMap::new();
4589            if let Some(v) = options.channel {
4590                parameters.insert("channel".to_string(), v.to_string());
4591            }
4592            if let Some(v) = options.page {
4593                parameters.insert("page".to_string(), v.to_string());
4594            }
4595            if let Some(v) = options.limit {
4596                parameters.insert("limit".to_string(), v.to_string());
4597            }
4598            if let Some(v) = options.key {
4599                parameters.insert("key".to_string(), v.to_string());
4600            }
4601            if let Some(v) = options.sort {
4602                parameters.insert("sort".to_string(), v.to_string());
4603            }
4604            if let Some(v) = options.category {
4605                parameters.insert("category".to_string(), v.to_string());
4606            }
4607            if let Some(v) = options.search_query {
4608                parameters.insert("search_query".to_string(), v.to_string());
4609            }
4610            self.client
4611                .get("/api/v1/telegram/messages", Some(parameters))
4612                .await
4613        }
4614    }
4615
4616    // --- Ticker ---
4617
4618    #[derive(Clone)]
4619    pub struct Ticker {
4620        client: Client,
4621    }
4622
4623    impl Ticker {
4624        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4625        pub fn from_client(client: Client) -> Self {
4626            Self { client }
4627        }
4628
4629        /// Fetch the latest ticker for symbol from given exchange.
4630        pub async fn get(
4631            &self,
4632            exchange: impl Into<String>,
4633            symbol: impl Into<String>,
4634            market: TickerMarket,
4635            options: TickerOptions,
4636        ) -> Result<TickerResponse> {
4637            let mut parameters = BTreeMap::new();
4638            parameters.insert("exchange".to_string(), exchange.into());
4639            parameters.insert("symbol".to_string(), symbol.into());
4640            parameters.insert("market".to_string(), market.to_string());
4641            if let Some(v) = options.currency {
4642                parameters.insert("currency".to_string(), v.to_string());
4643            }
4644            if let Some(v) = options.conversion_base {
4645                parameters.insert("conversion_base".to_string(), v.to_string());
4646            }
4647            self.client.get("/api/v1/ticker", Some(parameters)).await
4648        }
4649
4650        /// Get supported exchanges accepted by `/api/v1/ticker` endpoint.
4651        pub async fn exchanges(&self, market: TickerExchangesMarket) -> Result<Vec<String>> {
4652            let mut parameters = BTreeMap::new();
4653            parameters.insert("market".to_string(), market.to_string());
4654            self.client
4655                .get("/api/v1/ticker/exchanges", Some(parameters))
4656                .await
4657        }
4658
4659        /// Get supported symbols accepted by `/api/v1/ticker` endpoint.
4660        pub async fn symbols(
4661            &self,
4662            exchange: impl Into<String>,
4663            market: TickerSymbolsMarket,
4664        ) -> Result<Vec<String>> {
4665            let mut parameters = BTreeMap::new();
4666            parameters.insert("exchange".to_string(), exchange.into());
4667            parameters.insert("market".to_string(), market.to_string());
4668            self.client
4669                .get("/api/v1/ticker/symbols", Some(parameters))
4670                .await
4671        }
4672    }
4673
4674    // --- Token ---
4675
4676    #[derive(Clone)]
4677    pub struct Token {
4678        client: Client,
4679    }
4680
4681    impl Token {
4682        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4683        pub fn from_client(client: Client) -> Self {
4684            Self { client }
4685        }
4686
4687        /// Fetch latest token updates
4688        pub async fn updates(
4689            &self,
4690            options: CexTokenUpdatesOptions,
4691        ) -> Result<CexTokenUpdatesResponse> {
4692            let mut parameters = BTreeMap::new();
4693            if let Some(v) = options.page {
4694                parameters.insert("page".to_string(), v.to_string());
4695            }
4696            if let Some(v) = options.limit {
4697                parameters.insert("limit".to_string(), v.to_string());
4698            }
4699            if let Some(v) = options.r#type {
4700                parameters.insert("type".to_string(), v.to_string());
4701            }
4702            self.client
4703                .get("/api/v1/cex/token/updates", Some(parameters))
4704                .await
4705        }
4706    }
4707
4708    // --- TradingFees ---
4709
4710    #[derive(Clone)]
4711    pub struct TradingFees {
4712        client: Client,
4713    }
4714
4715    impl TradingFees {
4716        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4717        pub fn from_client(client: Client) -> Self {
4718            Self { client }
4719        }
4720
4721        /// Get trading fees.
4722        pub async fn fees(&self, options: CexFeesOptions) -> Result<Vec<CexFeesView>> {
4723            let mut parameters = BTreeMap::new();
4724            if let Some(v) = options.exchange {
4725                parameters.insert("exchange".to_string(), v.to_string());
4726            }
4727            if let Some(v) = options.symbol {
4728                parameters.insert("symbol".to_string(), v.to_string());
4729            }
4730            self.client.get("/api/v1/cex/fees", Some(parameters)).await
4731        }
4732
4733        /// Get supported exchanges accepted by `/api/v1/trading-fees` endpoint.
4734        pub async fn exchanges(&self) -> Result<Vec<String>> {
4735            self.client.get("/api/v1/cex/fees/exchanges", None).await
4736        }
4737
4738        /// Get supported symbols accepted by `/api/v1/trading-fees` endpoint.
4739        pub async fn symbols(&self, exchange: impl Into<String>) -> Result<Vec<String>> {
4740            let mut parameters = BTreeMap::new();
4741            parameters.insert("exchange".to_string(), exchange.into());
4742            self.client
4743                .get("/api/v1/cex/fees/symbols", Some(parameters))
4744                .await
4745        }
4746    }
4747
4748    // --- WalletStatus ---
4749
4750    #[derive(Clone)]
4751    pub struct WalletStatus {
4752        client: Client,
4753    }
4754
4755    impl WalletStatus {
4756        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4757        pub fn from_client(client: Client) -> Self {
4758            Self { client }
4759        }
4760
4761        /// Get the latest wallet status for asset from given exchange.
4762        pub async fn get(
4763            &self,
4764            asset: impl Into<String>,
4765            options: WalletStatusOptions,
4766        ) -> Result<Vec<WalletStatusView>> {
4767            let mut parameters = BTreeMap::new();
4768            parameters.insert("asset".to_string(), asset.into());
4769            if let Some(v) = options.exchange {
4770                parameters.insert("exchange".to_string(), v.to_string());
4771            }
4772            self.client
4773                .get("/api/v1/wallet-status", Some(parameters))
4774                .await
4775        }
4776
4777        /// Get assets accepted by `/api/v1/wallet-status` endpoint.
4778        pub async fn assets(&self, exchange: impl Into<String>) -> Result<Vec<String>> {
4779            let mut parameters = BTreeMap::new();
4780            parameters.insert("exchange".to_string(), exchange.into());
4781            self.client
4782                .get("/api/v1/wallet-status/assets", Some(parameters))
4783                .await
4784        }
4785
4786        /// Get exchanges accepted by `/api/v1/wallet-status` endpoint.
4787        pub async fn exchanges(&self) -> Result<Vec<String>> {
4788            self.client
4789                .get("/api/v1/wallet-status/exchanges", None)
4790                .await
4791        }
4792    }
4793}
4794
4795// --- Root client accessors ---
4796
4797impl Client {
4798    /// Returns a handle to the `Announcements` endpoint group.
4799    pub fn announcements(&self) -> Announcements {
4800        Announcements::from_client(self.clone())
4801    }
4802
4803    /// Returns a handle to the `CexCandle` endpoint group.
4804    pub fn cex_candle(&self) -> CexCandle {
4805        CexCandle::from_client(self.clone())
4806    }
4807
4808    /// Returns a handle to the `CexSymbol` endpoint group.
4809    pub fn cex_symbol(&self) -> CexSymbol {
4810        CexSymbol::from_client(self.clone())
4811    }
4812
4813    /// Returns a handle to the `Forex` endpoint group.
4814    pub fn forex(&self) -> Forex {
4815        Forex::from_client(self.clone())
4816    }
4817
4818    /// Returns a handle to the `FundingRate` endpoint group.
4819    pub fn funding_rate(&self) -> FundingRate {
4820        FundingRate::from_client(self.clone())
4821    }
4822
4823    /// Returns a handle to the `IndexPrice` endpoint group.
4824    pub fn index_price(&self) -> IndexPrice {
4825        IndexPrice::from_client(self.clone())
4826    }
4827
4828    /// Returns a handle to the `Liquidation` endpoint group.
4829    pub fn liquidation(&self) -> Liquidation {
4830        Liquidation::from_client(self.clone())
4831    }
4832
4833    /// Returns a handle to the `Listing` endpoint group.
4834    pub fn listing(&self) -> Listing {
4835        Listing::from_client(self.clone())
4836    }
4837
4838    /// Returns a handle to the `MarginBorrow` endpoint group.
4839    pub fn margin_borrow(&self) -> MarginBorrow {
4840        MarginBorrow::from_client(self.clone())
4841    }
4842
4843    /// Returns a handle to the `NaverTrend` endpoint group.
4844    pub fn naver_trend(&self) -> NaverTrend {
4845        NaverTrend::from_client(self.clone())
4846    }
4847
4848    /// Returns a handle to the `OpenInterest` endpoint group.
4849    pub fn open_interest(&self) -> OpenInterest {
4850        OpenInterest::from_client(self.clone())
4851    }
4852
4853    /// Returns a handle to the `Premium` endpoint group.
4854    pub fn premium(&self) -> Premium {
4855        Premium::from_client(self.clone())
4856    }
4857
4858    /// Returns a handle to the `Telegram` endpoint group.
4859    pub fn telegram(&self) -> Telegram {
4860        Telegram::from_client(self.clone())
4861    }
4862
4863    /// Returns a handle to the `Ticker` endpoint group.
4864    pub fn ticker(&self) -> Ticker {
4865        Ticker::from_client(self.clone())
4866    }
4867
4868    /// Returns a handle to the `Token` endpoint group.
4869    pub fn token(&self) -> Token {
4870        Token::from_client(self.clone())
4871    }
4872
4873    /// Returns a handle to the `TradingFees` endpoint group.
4874    pub fn trading_fees(&self) -> TradingFees {
4875        TradingFees::from_client(self.clone())
4876    }
4877
4878    /// Returns a handle to the `WalletStatus` endpoint group.
4879    pub fn wallet_status(&self) -> WalletStatus {
4880        WalletStatus::from_client(self.clone())
4881    }
4882}
4883
4884#[cfg(feature = "sync")]
4885#[doc(hidden)]
4886pub mod sync_internal {
4887    //! Synchronous mirror of the endpoint wrappers (feature `sync`).
4888    //!
4889    //! Identical API to the async surface minus `async`/`.await`, backed by
4890    //! [`crate::api::sync::Client`]. Enums, Options, and response structs
4891    //! are shared with the async surface via the glob import below.
4892    use super::*;
4893    use crate::api::sync::Client;
4894    use crate::api::Result;
4895    use std::collections::BTreeMap;
4896
4897    // --- Announcements ---
4898
4899    #[derive(Clone)]
4900    pub struct Announcements {
4901        client: Client,
4902    }
4903
4904    impl Announcements {
4905        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4906        pub fn from_client(client: Client) -> Self {
4907            Self { client }
4908        }
4909
4910        /// Get latest announcements from centralized exchanges
4911        pub fn announcements(
4912            &self,
4913            options: CexAnnouncementsOptions,
4914        ) -> Result<CexAnnouncementsResponse> {
4915            let mut parameters = BTreeMap::new();
4916            if let Some(v) = options.page {
4917                parameters.insert("page".to_string(), v.to_string());
4918            }
4919            if let Some(v) = options.limit {
4920                parameters.insert("limit".to_string(), v.to_string());
4921            }
4922            if let Some(v) = options.sort {
4923                parameters.insert("sort".to_string(), v.to_string());
4924            }
4925            if let Some(v) = options.key {
4926                parameters.insert("key".to_string(), v.to_string());
4927            }
4928            if let Some(v) = options.exchange {
4929                parameters.insert("exchange".to_string(), v.to_string());
4930            }
4931            if let Some(v) = options.category {
4932                parameters.insert("category".to_string(), v.to_string());
4933            }
4934            self.client
4935                .get("/api/v1/cex/announcements", Some(parameters))
4936        }
4937    }
4938
4939    // --- CexCandle ---
4940
4941    #[derive(Clone)]
4942    pub struct CexCandle {
4943        client: Client,
4944    }
4945
4946    impl CexCandle {
4947        /// Wraps an already-built client (e.g. from `ClientBuilder`).
4948        pub fn from_client(client: Client) -> Self {
4949            Self { client }
4950        }
4951
4952        /// Get historical candle data for a given `exchange`, `symbol`, `interval` and `market`.
4953        pub fn get(
4954            &self,
4955            exchange: impl Into<String>,
4956            symbol: impl Into<String>,
4957            options: CexCandleOptions,
4958        ) -> Result<CexCandleResponse> {
4959            let mut parameters = BTreeMap::new();
4960            parameters.insert("exchange".to_string(), exchange.into());
4961            parameters.insert("symbol".to_string(), symbol.into());
4962            if let Some(v) = options.market {
4963                parameters.insert("market".to_string(), v.to_string());
4964            }
4965            if let Some(v) = options.currency {
4966                parameters.insert("currency".to_string(), v.to_string());
4967            }
4968            if let Some(v) = options.interval {
4969                parameters.insert("interval".to_string(), v.to_string());
4970            }
4971            if let Some(v) = options.from {
4972                parameters.insert("from".to_string(), v.to_string());
4973            }
4974            if let Some(v) = options.to {
4975                parameters.insert("to".to_string(), v.to_string());
4976            }
4977            self.client.get("/api/v1/cex/candle", Some(parameters))
4978        }
4979
4980        /// Get supported exchanges accepted by `/api/v1/cex/candle` endpoint.
4981        pub fn exchanges(&self, market: CexCandleExchangesMarket) -> Result<Vec<String>> {
4982            let mut parameters = BTreeMap::new();
4983            parameters.insert("market".to_string(), market.to_string());
4984            self.client
4985                .get("/api/v1/cex/candle/exchanges", Some(parameters))
4986        }
4987
4988        /// Fetch supported intervals accepted by `/api/v1/cex/candle` endpoint.
4989        pub fn intervals(&self) -> Result<Vec<String>> {
4990            self.client.get("/api/v1/cex/candle/intervals", None)
4991        }
4992
4993        /// Fetch supported symbols accepted by `/api/v1/cex/candle` endpoint.
4994        pub fn symbols(
4995            &self,
4996            exchange: impl Into<String>,
4997            options: CexCandleSymbolsOptions,
4998        ) -> Result<Vec<CexCandleSymbolsView>> {
4999            let mut parameters = BTreeMap::new();
5000            parameters.insert("exchange".to_string(), exchange.into());
5001            if let Some(v) = options.market {
5002                parameters.insert("market".to_string(), v.to_string());
5003            }
5004            self.client
5005                .get("/api/v1/cex/candle/symbols", Some(parameters))
5006        }
5007    }
5008
5009    // --- CexSymbol ---
5010
5011    #[derive(Clone)]
5012    pub struct CexSymbol {
5013        client: Client,
5014    }
5015
5016    impl CexSymbol {
5017        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5018        pub fn from_client(client: Client) -> Self {
5019            Self { client }
5020        }
5021
5022        /// Return currently-active caution/warning/danger flagged symbols. Bithumb provides an expiry (end_at); other exchanges are open-ended until the next collector poll clears them.
5023        pub fn cautions(
5024            &self,
5025            options: CexSymbolCautionsOptions,
5026        ) -> Result<Vec<CexSymbolCautionsView>> {
5027            let mut parameters = BTreeMap::new();
5028            if let Some(v) = options.exchange {
5029                parameters.insert("exchange".to_string(), v.to_string());
5030            }
5031            if let Some(v) = options.market {
5032                parameters.insert("market".to_string(), v.to_string());
5033            }
5034            if let Some(v) = options.min_level {
5035                parameters.insert("min_level".to_string(), v.to_string());
5036            }
5037            if let Some(v) = options.active_only {
5038                parameters.insert("active_only".to_string(), v.to_string());
5039            }
5040            if let Some(v) = options.limit {
5041                parameters.insert("limit".to_string(), v.to_string());
5042            }
5043            if let Some(v) = options.page {
5044                parameters.insert("page".to_string(), v.to_string());
5045            }
5046            self.client
5047                .get("/api/v1/cex/symbol/cautions", Some(parameters))
5048        }
5049
5050        /// Return symbols with a known delisting_at timestamp or trading_status in {delisting, delisted}. Filter by time window to get upcoming delistings.
5051        pub fn delistings(
5052            &self,
5053            options: CexSymbolDelistingsOptions,
5054        ) -> Result<Vec<CexSymbolDelistingsView>> {
5055            let mut parameters = BTreeMap::new();
5056            if let Some(v) = options.exchange {
5057                parameters.insert("exchange".to_string(), v.to_string());
5058            }
5059            if let Some(v) = options.market {
5060                parameters.insert("market".to_string(), v.to_string());
5061            }
5062            if let Some(v) = options.from_ms {
5063                parameters.insert("from_ms".to_string(), v.to_string());
5064            }
5065            if let Some(v) = options.to_ms {
5066                parameters.insert("to_ms".to_string(), v.to_string());
5067            }
5068            if let Some(v) = options.include_past {
5069                parameters.insert("include_past".to_string(), v.to_string());
5070            }
5071            if let Some(v) = options.limit {
5072                parameters.insert("limit".to_string(), v.to_string());
5073            }
5074            if let Some(v) = options.page {
5075                parameters.insert("page".to_string(), v.to_string());
5076            }
5077            self.client
5078                .get("/api/v1/cex/symbol/delistings", Some(parameters))
5079        }
5080
5081        /// Sums long/short liquidation volume across all events in a rolling window for every exchange × quote pairing of the base asset. Window max 30d; default 24h.
5082        pub fn liquidation(
5083            &self,
5084            base: impl Into<String>,
5085            options: CexSymbolLiquidationOptions,
5086        ) -> Result<Vec<CexSymbolLiquidationView>> {
5087            let mut parameters = BTreeMap::new();
5088            parameters.insert("base".to_string(), base.into());
5089            if let Some(v) = options.window {
5090                parameters.insert("window".to_string(), v.to_string());
5091            }
5092            self.client
5093                .get("/api/v1/cex/symbol/liquidation", Some(parameters))
5094        }
5095
5096        /// Fetch per-symbol trading status, caution flags, tags and timing metadata collected by tfsymbolmeta.
5097        pub fn metadata(
5098            &self,
5099            options: CexSymbolMetadataOptions,
5100        ) -> Result<Vec<CexSymbolMetadataView>> {
5101            let mut parameters = BTreeMap::new();
5102            if let Some(v) = options.exchange {
5103                parameters.insert("exchange".to_string(), v.to_string());
5104            }
5105            if let Some(v) = options.market {
5106                parameters.insert("market".to_string(), v.to_string());
5107            }
5108            if let Some(v) = options.base {
5109                parameters.insert("base".to_string(), v.to_string());
5110            }
5111            if let Some(v) = options.quote {
5112                parameters.insert("quote".to_string(), v.to_string());
5113            }
5114            if let Some(v) = options.status {
5115                parameters.insert("status".to_string(), v.to_string());
5116            }
5117            if let Some(v) = options.limit {
5118                parameters.insert("limit".to_string(), v.to_string());
5119            }
5120            if let Some(v) = options.page {
5121                parameters.insert("page".to_string(), v.to_string());
5122            }
5123            self.client
5124                .get("/api/v1/cex/symbol/metadata", Some(parameters))
5125        }
5126
5127        /// Latest Open Interest snapshot across every futures venue carrying the given base. Sorted by USD value descending, NULLs last.
5128        pub fn oi(
5129            &self,
5130            base: impl Into<String>,
5131            options: CexSymbolOiOptions,
5132        ) -> Result<Vec<CexSymbolOiView>> {
5133            let mut parameters = BTreeMap::new();
5134            parameters.insert("base".to_string(), base.into());
5135            if let Some(v) = options.exchange {
5136                parameters.insert("exchange".to_string(), v.to_string());
5137            }
5138            self.client.get("/api/v1/cex/symbol/oi", Some(parameters))
5139        }
5140
5141        /// Enriched snapshot combining the latest OI (USD) with 1h/4h/24h change percentages and OI/24h volume ratio. Backed by the tfopeninterest taskflow's Redis HASH.
5142        pub fn oi_stats(
5143            &self,
5144            base: impl Into<String>,
5145            options: CexSymbolOiStatsOptions,
5146        ) -> Result<Vec<CexSymbolOiStatsView>> {
5147            let mut parameters = BTreeMap::new();
5148            parameters.insert("base".to_string(), base.into());
5149            if let Some(v) = options.exchange {
5150                parameters.insert("exchange".to_string(), v.to_string());
5151            }
5152            if let Some(v) = options.currency {
5153                parameters.insert("currency".to_string(), v.to_string());
5154            }
5155            self.client
5156                .get("/api/v1/cex/symbol/oi-stats", Some(parameters))
5157        }
5158
5159        /// Fetch (exchange, market, base, quote, tag) rows from cex_symbol_tag. Use to find every symbol flagged with a given tag (e.g. all meme coins across exchanges).
5160        pub fn tags(&self, options: CexSymbolTagsOptions) -> Result<Vec<CexSymbolTagsView>> {
5161            let mut parameters = BTreeMap::new();
5162            if let Some(v) = options.tag {
5163                parameters.insert("tag".to_string(), v.to_string());
5164            }
5165            if let Some(v) = options.exchange {
5166                parameters.insert("exchange".to_string(), v.to_string());
5167            }
5168            if let Some(v) = options.market {
5169                parameters.insert("market".to_string(), v.to_string());
5170            }
5171            if let Some(v) = options.base {
5172                parameters.insert("base".to_string(), v.to_string());
5173            }
5174            if let Some(v) = options.source {
5175                parameters.insert("source".to_string(), v.to_string());
5176            }
5177            if let Some(v) = options.min_confidence {
5178                parameters.insert("min_confidence".to_string(), v.to_string());
5179            }
5180            if let Some(v) = options.limit {
5181                parameters.insert("limit".to_string(), v.to_string());
5182            }
5183            if let Some(v) = options.page {
5184                parameters.insert("page".to_string(), v.to_string());
5185            }
5186            self.client.get("/api/v1/cex/symbol/tags", Some(parameters))
5187        }
5188
5189        /// Latest 24h trading volume across every (exchange, market, quote) a token lists on. Backed by cache.latest_volume.
5190        pub fn volume(
5191            &self,
5192            base: impl Into<String>,
5193            options: CexSymbolVolumeOptions,
5194        ) -> Result<Vec<CexSymbolVolumeView>> {
5195            let mut parameters = BTreeMap::new();
5196            parameters.insert("base".to_string(), base.into());
5197            if let Some(v) = options.market {
5198                parameters.insert("market".to_string(), v.to_string());
5199            }
5200            self.client
5201                .get("/api/v1/cex/symbol/volume", Some(parameters))
5202        }
5203    }
5204
5205    // --- Forex ---
5206
5207    #[derive(Clone)]
5208    pub struct Forex {
5209        client: Client,
5210    }
5211
5212    impl Forex {
5213        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5214        pub fn from_client(client: Client) -> Self {
5215            Self { client }
5216        }
5217
5218        /// Get the latest forex rate for given symbol.
5219        pub fn get(&self, symbol: impl Into<String>) -> Result<ForexResponse> {
5220            let mut parameters = BTreeMap::new();
5221            parameters.insert("symbol".to_string(), symbol.into());
5222            self.client.get("/api/v1/forex", Some(parameters))
5223        }
5224
5225        /// Get supported forex symbols.
5226        pub fn symbols(&self) -> Result<Vec<String>> {
5227            self.client.get("/api/v1/forex/symbols", None)
5228        }
5229    }
5230
5231    // --- FundingRate ---
5232
5233    #[derive(Clone)]
5234    pub struct FundingRate {
5235        client: Client,
5236    }
5237
5238    impl FundingRate {
5239        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5240        pub fn from_client(client: Client) -> Self {
5241            Self { client }
5242        }
5243
5244        /// Get supported exchanges accepted by `/api/v1/funding-rate` endpoint.
5245        pub fn exchanges(&self) -> Result<Vec<String>> {
5246            self.client.get("/api/v1/funding-rate/exchanges", None)
5247        }
5248
5249        /// Get historical funding rate data for a given `exchange` and `symbol`.
5250        pub fn history(
5251            &self,
5252            exchange: impl Into<String>,
5253            symbol: impl Into<String>,
5254            options: FundingRateHistoryOptions,
5255        ) -> Result<FundingRateHistoryResponse> {
5256            let mut parameters = BTreeMap::new();
5257            parameters.insert("exchange".to_string(), exchange.into());
5258            parameters.insert("symbol".to_string(), symbol.into());
5259            if let Some(v) = options.page {
5260                parameters.insert("page".to_string(), v.to_string());
5261            }
5262            if let Some(v) = options.limit {
5263                parameters.insert("limit".to_string(), v.to_string());
5264            }
5265            if let Some(v) = options.from {
5266                parameters.insert("from".to_string(), v.to_string());
5267            }
5268            if let Some(v) = options.to {
5269                parameters.insert("to".to_string(), v.to_string());
5270            }
5271            if let Some(v) = options.sort {
5272                parameters.insert("sort".to_string(), v.to_string());
5273            }
5274            self.client
5275                .get("/api/v1/funding-rate/history", Some(parameters))
5276        }
5277
5278        /// Fetch the latest funding rate data for a given `exchange` and `symbol`.
5279        pub fn latest(
5280            &self,
5281            exchange: impl Into<String>,
5282            symbol: impl Into<String>,
5283        ) -> Result<FundingRateLatestResponse> {
5284            let mut parameters = BTreeMap::new();
5285            parameters.insert("exchange".to_string(), exchange.into());
5286            parameters.insert("symbol".to_string(), symbol.into());
5287            self.client
5288                .get("/api/v1/funding-rate/latest", Some(parameters))
5289        }
5290
5291        /// Fetch supported symbols accepted by `/api/v1/funding-rate` endpoint.
5292        pub fn symbols(
5293            &self,
5294            options: FundingRateSymbolsOptions,
5295        ) -> Result<Vec<FundingRateSymbolsView>> {
5296            let mut parameters = BTreeMap::new();
5297            if let Some(v) = options.exchange {
5298                parameters.insert("exchange".to_string(), v.to_string());
5299            }
5300            self.client
5301                .get("/api/v1/funding-rate/symbols", Some(parameters))
5302        }
5303    }
5304
5305    // --- IndexPrice ---
5306
5307    #[derive(Clone)]
5308    pub struct IndexPrice {
5309        client: Client,
5310    }
5311
5312    impl IndexPrice {
5313        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5314        pub fn from_client(client: Client) -> Self {
5315            Self { client }
5316        }
5317
5318        /// Get index price
5319        pub fn get(
5320            &self,
5321            asset: impl Into<String>,
5322            options: IndexPriceOptions,
5323        ) -> Result<IndexPriceResponse> {
5324            let mut parameters = BTreeMap::new();
5325            parameters.insert("asset".to_string(), asset.into());
5326            if let Some(v) = options.from {
5327                parameters.insert("from".to_string(), v.to_string());
5328            }
5329            if let Some(v) = options.to {
5330                parameters.insert("to".to_string(), v.to_string());
5331            }
5332            if let Some(v) = options.interval {
5333                parameters.insert("interval".to_string(), v.to_string());
5334            }
5335            self.client.get("/api/v1/index-price", Some(parameters))
5336        }
5337    }
5338
5339    // --- Liquidation ---
5340
5341    #[derive(Clone)]
5342    pub struct Liquidation {
5343        client: Client,
5344    }
5345
5346    impl Liquidation {
5347        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5348        pub fn from_client(client: Client) -> Self {
5349            Self { client }
5350        }
5351
5352        /// Fetch recent liquidation events for a futures symbol on a given exchange, newest first.
5353        pub fn get(
5354            &self,
5355            exchange: impl Into<String>,
5356            symbol: impl Into<String>,
5357            options: LiquidationOptions,
5358        ) -> Result<LiquidationResponse> {
5359            let mut parameters = BTreeMap::new();
5360            parameters.insert("exchange".to_string(), exchange.into());
5361            parameters.insert("symbol".to_string(), symbol.into());
5362            if let Some(v) = options.limit {
5363                parameters.insert("limit".to_string(), v.to_string());
5364            }
5365            self.client.get("/api/v1/liquidation", Some(parameters))
5366        }
5367
5368        /// Fetch most recent liquidation events across all futures symbols, newest first. Use together with the `/ws/v1/liquidation/feed` firehose for a live feed view.
5369        pub fn feed(&self, options: LiquidationFeedOptions) -> Result<LiquidationFeedResponse> {
5370            let mut parameters = BTreeMap::new();
5371            if let Some(v) = options.exchange {
5372                parameters.insert("exchange".to_string(), v.to_string());
5373            }
5374            if let Some(v) = options.base {
5375                parameters.insert("base".to_string(), v.to_string());
5376            }
5377            if let Some(v) = options.min_volume_usd {
5378                parameters.insert("min_volume_usd".to_string(), v.to_string());
5379            }
5380            if let Some(v) = options.limit {
5381                parameters.insert("limit".to_string(), v.to_string());
5382            }
5383            self.client
5384                .get("/api/v1/liquidation/feed", Some(parameters))
5385        }
5386
5387        /// Aggregated long/short liquidation USD by (token, exchange) over a rolling window. Result is cached for ~10s. Sub-1h windows are not supported; use the WS feed for finer granularity.
5388        pub fn heatmap(
5389            &self,
5390            options: LiquidationHeatmapOptions,
5391        ) -> Result<LiquidationHeatmapResponse> {
5392            let mut parameters = BTreeMap::new();
5393            if let Some(v) = options.window {
5394                parameters.insert("window".to_string(), v.to_string());
5395            }
5396            if let Some(v) = options.top_n {
5397                parameters.insert("top_n".to_string(), v.to_string());
5398            }
5399            self.client
5400                .get("/api/v1/liquidation/heatmap", Some(parameters))
5401        }
5402
5403        /// Coinglass-style liquidation map for one perpetual pair. Returns a price-grid breakdown of where leveraged positions would be liquidated, split by leverage tier (10x / 25x / 50x / 100x) and side (long below current price, short above). Built from current OI + last-24h candle entries + a fixed leverage-cohort prior. Read the `assumptions` field in the response for the modelling disclaimer. Cached server-side (~5s) so back-to-back polls are cheap.
5404        pub fn map(&self, options: LiquidationMapOptions) -> Result<LiquidationMapResponse> {
5405            let mut parameters = BTreeMap::new();
5406            if let Some(v) = options.exchange {
5407                parameters.insert("exchange".to_string(), v.to_string());
5408            }
5409            if let Some(v) = options.base {
5410                parameters.insert("base".to_string(), v.to_string());
5411            }
5412            if let Some(v) = options.quote {
5413                parameters.insert("quote".to_string(), v.to_string());
5414            }
5415            self.client.get("/api/v1/liquidation/map", Some(parameters))
5416        }
5417
5418        /// Aggregate liquidation stats (total, long/short split, count, venue count, biggest single event) over a 1h/4h/24h window. Backs the liquidation page KPI strip for windows the live feed buffer can't cover.
5419        pub fn stats(&self, options: LiquidationStatsOptions) -> Result<LiquidationStatsResponse> {
5420            let mut parameters = BTreeMap::new();
5421            if let Some(v) = options.window {
5422                parameters.insert("window".to_string(), v.to_string());
5423            }
5424            if let Some(v) = options.exchange {
5425                parameters.insert("exchange".to_string(), v.to_string());
5426            }
5427            if let Some(v) = options.min_volume_usd {
5428                parameters.insert("min_volume_usd".to_string(), v.to_string());
5429            }
5430            self.client
5431                .get("/api/v1/liquidation/stats", Some(parameters))
5432        }
5433
5434        /// Bucketed long / short liquidation USD over time for a single (base, quote) pair, joined with the futures-candle close as a reference price line. Long/short USD comes from `cex.liquidation` (Side='sell' = long position liquidated, 'buy' = short). Price comes from `candle.futures_1m` on the requested exchange — or Binance as the reference when none is specified. Cached ~30s server-side.
5435        pub fn symbol_history(
5436            &self,
5437            symbol: impl Into<String>,
5438            options: LiquidationSymbolHistoryOptions,
5439        ) -> Result<LiquidationSymbolHistoryResponse> {
5440            let mut parameters = BTreeMap::new();
5441            parameters.insert("symbol".to_string(), symbol.into());
5442            if let Some(v) = options.quote {
5443                parameters.insert("quote".to_string(), v.to_string());
5444            }
5445            if let Some(v) = options.exchange {
5446                parameters.insert("exchange".to_string(), v.to_string());
5447            }
5448            if let Some(v) = options.interval {
5449                parameters.insert("interval".to_string(), v.to_string());
5450            }
5451            if let Some(v) = options.window {
5452                parameters.insert("window".to_string(), v.to_string());
5453            }
5454            self.client
5455                .get("/api/v1/liquidation/symbol-history", Some(parameters))
5456        }
5457    }
5458
5459    // --- Listing ---
5460
5461    #[derive(Clone)]
5462    pub struct Listing {
5463        client: Client,
5464    }
5465
5466    impl Listing {
5467        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5468        pub fn from_client(client: Client) -> Self {
5469            Self { client }
5470        }
5471
5472        /// Get historical token listings for Upbit and Bithumb for KRW market
5473        pub fn historical(
5474            &self,
5475            options: ListingsHistoricalOptions,
5476        ) -> Result<ListingsHistoricalResponse> {
5477            let mut parameters = BTreeMap::new();
5478            if let Some(v) = options.refresh {
5479                parameters.insert("refresh".to_string(), v.to_string());
5480            }
5481            self.client
5482                .get("/api/v1/listings/historical", Some(parameters))
5483        }
5484    }
5485
5486    // --- MarginBorrow ---
5487
5488    #[derive(Clone)]
5489    pub struct MarginBorrow {
5490        client: Client,
5491    }
5492
5493    impl MarginBorrow {
5494        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5495        pub fn from_client(client: Client) -> Self {
5496            Self { client }
5497        }
5498
5499        /// Get the margin borrow data.
5500        pub fn get(&self, asset: impl Into<String>) -> Result<MarginBorrowResponse> {
5501            let mut parameters = BTreeMap::new();
5502            parameters.insert("asset".to_string(), asset.into());
5503            self.client.get("/api/v1/margin-borrow", Some(parameters))
5504        }
5505    }
5506
5507    // --- NaverTrend ---
5508
5509    #[derive(Clone)]
5510    pub struct NaverTrend {
5511        client: Client,
5512    }
5513
5514    impl NaverTrend {
5515        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5516        pub fn from_client(client: Client) -> Self {
5517            Self { client }
5518        }
5519
5520        /// Get Naver trend data with a daily frequency for a project that is associated with a given [symbol](./symbols). The values in response are normalized into a range from 0 to 100, where 0 corresponds to a minimum interest, and 100 corresponds to a maximum interest of users in Naver search engine.
5521        pub fn get(&self, symbol: impl Into<String>) -> Result<Vec<NaverTrendView>> {
5522            let mut parameters = BTreeMap::new();
5523            parameters.insert("symbol".to_string(), symbol.into());
5524            self.client.get("/api/v1/naver-trend", Some(parameters))
5525        }
5526
5527        /// Get crypto symbols that are accepted by [Naver trend endpoint](./trend).
5528        pub fn symbols(&self) -> Result<Vec<String>> {
5529            self.client.get("/api/v1/naver-trend/symbols", None)
5530        }
5531    }
5532
5533    // --- OpenInterest ---
5534
5535    #[derive(Clone)]
5536    pub struct OpenInterest {
5537        client: Client,
5538    }
5539
5540    impl OpenInterest {
5541        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5542        pub fn from_client(client: Client) -> Self {
5543            Self { client }
5544        }
5545
5546        /// Fetch the most recent Open Interest snapshot for a futures symbol on a given exchange.
5547        pub fn get(
5548            &self,
5549            exchange: impl Into<String>,
5550            symbol: impl Into<String>,
5551        ) -> Result<OpenInterestResponse> {
5552            let mut parameters = BTreeMap::new();
5553            parameters.insert("exchange".to_string(), exchange.into());
5554            parameters.insert("symbol".to_string(), symbol.into());
5555            self.client.get("/api/v1/open-interest", Some(parameters))
5556        }
5557
5558        /// Historical Open Interest time series for a single token, broken down per exchange and aggregated to a fixed bucket (avg within bucket). The default lookback depends on the requested interval — 7 days for 1h, 30 days for 4h, 1 year for 1d — so callers don't have to hand-tune `from`/`to` for typical queries. The response also includes token metadata (icon, symbol, name) so a single call paints the whole header strip.
5559        pub fn history_aggregated(
5560            &self,
5561            token_id: impl Into<String>,
5562            options: OpenInterestHistoryAggregatedOptions,
5563        ) -> Result<OpenInterestHistoryAggregatedResponse> {
5564            let mut parameters = BTreeMap::new();
5565            parameters.insert("token_id".to_string(), token_id.into());
5566            if let Some(v) = options.interval {
5567                parameters.insert("interval".to_string(), v.to_string());
5568            }
5569            if let Some(v) = options.from {
5570                parameters.insert("from".to_string(), v.to_string());
5571            }
5572            if let Some(v) = options.to {
5573                parameters.insert("to".to_string(), v.to_string());
5574            }
5575            self.client
5576                .get("/api/v1/open-interest/history-aggregated", Some(parameters))
5577        }
5578
5579        /// Fetch latest Open Interest snapshots across exchanges/symbols. Optionally filter by `exchange`. Results are sorted by `openInterestUsd` descending (null values last).
5580        pub fn list(&self, options: OpenInterestListOptions) -> Result<OpenInterestListResponse> {
5581            let mut parameters = BTreeMap::new();
5582            if let Some(v) = options.exchange {
5583                parameters.insert("exchange".to_string(), v.to_string());
5584            }
5585            self.client
5586                .get("/api/v1/open-interest/list", Some(parameters))
5587        }
5588
5589        /// Paginated token × exchange Open Interest matrix. For each base asset we list the per-exchange notional OI in USD (when a venue carries the token) and `null` when it doesn't trade there. The matrix is sortable by any exchange column and searchable by base symbol — same shape the DataMaxi+ dashboard uses on `/open-interest`. Cached snapshot rebuilds every few seconds, so back-to-back requests are cheap.
5590        pub fn overview(
5591            &self,
5592            options: OpenInterestOverviewOptions,
5593        ) -> Result<OpenInterestOverviewResponse> {
5594            let mut parameters = BTreeMap::new();
5595            if let Some(v) = options.page {
5596                parameters.insert("page".to_string(), v.to_string());
5597            }
5598            if let Some(v) = options.limit {
5599                parameters.insert("limit".to_string(), v.to_string());
5600            }
5601            if let Some(v) = options.key {
5602                parameters.insert("key".to_string(), v.to_string());
5603            }
5604            if let Some(v) = options.sort {
5605                parameters.insert("sort".to_string(), v.to_string());
5606            }
5607            if let Some(v) = options.query {
5608                parameters.insert("query".to_string(), v.to_string());
5609            }
5610            self.client
5611                .get("/api/v1/open-interest/overview", Some(parameters))
5612        }
5613
5614        /// Top-line aggregates over the current Open Interest snapshot — total OI USD, top tokens by OI, top exchanges by OI, and the count of venues currently reporting any base. Powers the OI page's KPI strip and breakdown card without forcing the caller to fetch the full token list.
5615        pub fn summary(
5616            &self,
5617            options: OpenInterestSummaryOptions,
5618        ) -> Result<OpenInterestSummaryResponse> {
5619            let mut parameters = BTreeMap::new();
5620            if let Some(v) = options.top_n {
5621                parameters.insert("top_n".to_string(), v.to_string());
5622            }
5623            self.client
5624                .get("/api/v1/open-interest/summary", Some(parameters))
5625        }
5626    }
5627
5628    // --- Premium ---
5629
5630    #[derive(Clone)]
5631    pub struct Premium {
5632        client: Client,
5633    }
5634
5635    impl Premium {
5636        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5637        pub fn from_client(client: Client) -> Self {
5638            Self { client }
5639        }
5640
5641        /// Get real-time premium (price difference) data across exchanges.
5642        pub fn get(&self, options: PremiumOptions) -> Result<PremiumResponse> {
5643            let mut parameters = BTreeMap::new();
5644            if let Some(v) = options.source_exchange {
5645                parameters.insert("source_exchange".to_string(), v.to_string());
5646            }
5647            if let Some(v) = options.target_exchange {
5648                parameters.insert("target_exchange".to_string(), v.to_string());
5649            }
5650            if let Some(v) = options.asset {
5651                parameters.insert("asset".to_string(), v.to_string());
5652            }
5653            if let Some(v) = options.source_quote {
5654                parameters.insert("source_quote".to_string(), v.to_string());
5655            }
5656            if let Some(v) = options.target_quote {
5657                parameters.insert("target_quote".to_string(), v.to_string());
5658            }
5659            if let Some(v) = options.source_market {
5660                parameters.insert("source_market".to_string(), v.to_string());
5661            }
5662            if let Some(v) = options.target_market {
5663                parameters.insert("target_market".to_string(), v.to_string());
5664            }
5665            if let Some(v) = options.premium_type {
5666                parameters.insert("premium_type".to_string(), v.to_string());
5667            }
5668            if let Some(v) = options.currency {
5669                parameters.insert("currency".to_string(), v.to_string());
5670            }
5671            if let Some(v) = options.conversion_base {
5672                parameters.insert("conversion_base".to_string(), v.to_string());
5673            }
5674            if let Some(v) = options.page {
5675                parameters.insert("page".to_string(), v.to_string());
5676            }
5677            if let Some(v) = options.limit {
5678                parameters.insert("limit".to_string(), v.to_string());
5679            }
5680            if let Some(v) = options.sort {
5681                parameters.insert("sort".to_string(), v.to_string());
5682            }
5683            if let Some(v) = options.key {
5684                parameters.insert("key".to_string(), v.to_string());
5685            }
5686            if let Some(v) = options.query {
5687                parameters.insert("query".to_string(), v.to_string());
5688            }
5689            if let Some(v) = options.only_transferable {
5690                parameters.insert("only_transferable".to_string(), v.to_string());
5691            }
5692            if let Some(v) = options.network {
5693                parameters.insert("network".to_string(), v.to_string());
5694            }
5695            if let Some(v) = options.min_sv {
5696                parameters.insert("min_sv".to_string(), v.to_string());
5697            }
5698            if let Some(v) = options.min_tv {
5699                parameters.insert("min_tv".to_string(), v.to_string());
5700            }
5701            if let Some(v) = options.token_include {
5702                parameters.insert("token_include".to_string(), v.to_string());
5703            }
5704            if let Some(v) = options.token_exclude {
5705                parameters.insert("token_exclude".to_string(), v.to_string());
5706            }
5707            self.client.get("/api/v1/premium", Some(parameters))
5708        }
5709
5710        /// Get supported source exchanges for premium data.
5711        pub fn exchanges(&self) -> Result<Vec<String>> {
5712            self.client.get("/api/v1/premium/exchanges", None)
5713        }
5714    }
5715
5716    // --- Telegram ---
5717
5718    #[derive(Clone)]
5719    pub struct Telegram {
5720        client: Client,
5721    }
5722
5723    impl Telegram {
5724        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5725        pub fn from_client(client: Client) -> Self {
5726            Self { client }
5727        }
5728
5729        /// Get Telegram channels
5730        pub fn channels(
5731            &self,
5732            options: TelegramChannelsOptions,
5733        ) -> Result<TelegramChannelsResponse> {
5734            let mut parameters = BTreeMap::new();
5735            if let Some(v) = options.page {
5736                parameters.insert("page".to_string(), v.to_string());
5737            }
5738            if let Some(v) = options.limit {
5739                parameters.insert("limit".to_string(), v.to_string());
5740            }
5741            if let Some(v) = options.category {
5742                parameters.insert("category".to_string(), v.to_string());
5743            }
5744            if let Some(v) = options.key {
5745                parameters.insert("key".to_string(), v.to_string());
5746            }
5747            if let Some(v) = options.sort {
5748                parameters.insert("sort".to_string(), v.to_string());
5749            }
5750            self.client
5751                .get("/api/v1/telegram/channels", Some(parameters))
5752        }
5753
5754        /// Get Telegram messages.
5755        pub fn messages(
5756            &self,
5757            options: TelegramMessagesOptions,
5758        ) -> Result<TelegramMessagesResponse> {
5759            let mut parameters = BTreeMap::new();
5760            if let Some(v) = options.channel {
5761                parameters.insert("channel".to_string(), v.to_string());
5762            }
5763            if let Some(v) = options.page {
5764                parameters.insert("page".to_string(), v.to_string());
5765            }
5766            if let Some(v) = options.limit {
5767                parameters.insert("limit".to_string(), v.to_string());
5768            }
5769            if let Some(v) = options.key {
5770                parameters.insert("key".to_string(), v.to_string());
5771            }
5772            if let Some(v) = options.sort {
5773                parameters.insert("sort".to_string(), v.to_string());
5774            }
5775            if let Some(v) = options.category {
5776                parameters.insert("category".to_string(), v.to_string());
5777            }
5778            if let Some(v) = options.search_query {
5779                parameters.insert("search_query".to_string(), v.to_string());
5780            }
5781            self.client
5782                .get("/api/v1/telegram/messages", Some(parameters))
5783        }
5784    }
5785
5786    // --- Ticker ---
5787
5788    #[derive(Clone)]
5789    pub struct Ticker {
5790        client: Client,
5791    }
5792
5793    impl Ticker {
5794        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5795        pub fn from_client(client: Client) -> Self {
5796            Self { client }
5797        }
5798
5799        /// Fetch the latest ticker for symbol from given exchange.
5800        pub fn get(
5801            &self,
5802            exchange: impl Into<String>,
5803            symbol: impl Into<String>,
5804            market: TickerMarket,
5805            options: TickerOptions,
5806        ) -> Result<TickerResponse> {
5807            let mut parameters = BTreeMap::new();
5808            parameters.insert("exchange".to_string(), exchange.into());
5809            parameters.insert("symbol".to_string(), symbol.into());
5810            parameters.insert("market".to_string(), market.to_string());
5811            if let Some(v) = options.currency {
5812                parameters.insert("currency".to_string(), v.to_string());
5813            }
5814            if let Some(v) = options.conversion_base {
5815                parameters.insert("conversion_base".to_string(), v.to_string());
5816            }
5817            self.client.get("/api/v1/ticker", Some(parameters))
5818        }
5819
5820        /// Get supported exchanges accepted by `/api/v1/ticker` endpoint.
5821        pub fn exchanges(&self, market: TickerExchangesMarket) -> Result<Vec<String>> {
5822            let mut parameters = BTreeMap::new();
5823            parameters.insert("market".to_string(), market.to_string());
5824            self.client
5825                .get("/api/v1/ticker/exchanges", Some(parameters))
5826        }
5827
5828        /// Get supported symbols accepted by `/api/v1/ticker` endpoint.
5829        pub fn symbols(
5830            &self,
5831            exchange: impl Into<String>,
5832            market: TickerSymbolsMarket,
5833        ) -> Result<Vec<String>> {
5834            let mut parameters = BTreeMap::new();
5835            parameters.insert("exchange".to_string(), exchange.into());
5836            parameters.insert("market".to_string(), market.to_string());
5837            self.client.get("/api/v1/ticker/symbols", Some(parameters))
5838        }
5839    }
5840
5841    // --- Token ---
5842
5843    #[derive(Clone)]
5844    pub struct Token {
5845        client: Client,
5846    }
5847
5848    impl Token {
5849        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5850        pub fn from_client(client: Client) -> Self {
5851            Self { client }
5852        }
5853
5854        /// Fetch latest token updates
5855        pub fn updates(&self, options: CexTokenUpdatesOptions) -> Result<CexTokenUpdatesResponse> {
5856            let mut parameters = BTreeMap::new();
5857            if let Some(v) = options.page {
5858                parameters.insert("page".to_string(), v.to_string());
5859            }
5860            if let Some(v) = options.limit {
5861                parameters.insert("limit".to_string(), v.to_string());
5862            }
5863            if let Some(v) = options.r#type {
5864                parameters.insert("type".to_string(), v.to_string());
5865            }
5866            self.client
5867                .get("/api/v1/cex/token/updates", Some(parameters))
5868        }
5869    }
5870
5871    // --- TradingFees ---
5872
5873    #[derive(Clone)]
5874    pub struct TradingFees {
5875        client: Client,
5876    }
5877
5878    impl TradingFees {
5879        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5880        pub fn from_client(client: Client) -> Self {
5881            Self { client }
5882        }
5883
5884        /// Get trading fees.
5885        pub fn fees(&self, options: CexFeesOptions) -> Result<Vec<CexFeesView>> {
5886            let mut parameters = BTreeMap::new();
5887            if let Some(v) = options.exchange {
5888                parameters.insert("exchange".to_string(), v.to_string());
5889            }
5890            if let Some(v) = options.symbol {
5891                parameters.insert("symbol".to_string(), v.to_string());
5892            }
5893            self.client.get("/api/v1/cex/fees", Some(parameters))
5894        }
5895
5896        /// Get supported exchanges accepted by `/api/v1/trading-fees` endpoint.
5897        pub fn exchanges(&self) -> Result<Vec<String>> {
5898            self.client.get("/api/v1/cex/fees/exchanges", None)
5899        }
5900
5901        /// Get supported symbols accepted by `/api/v1/trading-fees` endpoint.
5902        pub fn symbols(&self, exchange: impl Into<String>) -> Result<Vec<String>> {
5903            let mut parameters = BTreeMap::new();
5904            parameters.insert("exchange".to_string(), exchange.into());
5905            self.client
5906                .get("/api/v1/cex/fees/symbols", Some(parameters))
5907        }
5908    }
5909
5910    // --- WalletStatus ---
5911
5912    #[derive(Clone)]
5913    pub struct WalletStatus {
5914        client: Client,
5915    }
5916
5917    impl WalletStatus {
5918        /// Wraps an already-built client (e.g. from `ClientBuilder`).
5919        pub fn from_client(client: Client) -> Self {
5920            Self { client }
5921        }
5922
5923        /// Get the latest wallet status for asset from given exchange.
5924        pub fn get(
5925            &self,
5926            asset: impl Into<String>,
5927            options: WalletStatusOptions,
5928        ) -> Result<Vec<WalletStatusView>> {
5929            let mut parameters = BTreeMap::new();
5930            parameters.insert("asset".to_string(), asset.into());
5931            if let Some(v) = options.exchange {
5932                parameters.insert("exchange".to_string(), v.to_string());
5933            }
5934            self.client.get("/api/v1/wallet-status", Some(parameters))
5935        }
5936
5937        /// Get assets accepted by `/api/v1/wallet-status` endpoint.
5938        pub fn assets(&self, exchange: impl Into<String>) -> Result<Vec<String>> {
5939            let mut parameters = BTreeMap::new();
5940            parameters.insert("exchange".to_string(), exchange.into());
5941            self.client
5942                .get("/api/v1/wallet-status/assets", Some(parameters))
5943        }
5944
5945        /// Get exchanges accepted by `/api/v1/wallet-status` endpoint.
5946        pub fn exchanges(&self) -> Result<Vec<String>> {
5947            self.client.get("/api/v1/wallet-status/exchanges", None)
5948        }
5949    }
5950
5951    // --- Root client accessors ---
5952
5953    impl Client {
5954        /// Returns a handle to the `Announcements` endpoint group.
5955        pub fn announcements(&self) -> Announcements {
5956            Announcements::from_client(self.clone())
5957        }
5958
5959        /// Returns a handle to the `CexCandle` endpoint group.
5960        pub fn cex_candle(&self) -> CexCandle {
5961            CexCandle::from_client(self.clone())
5962        }
5963
5964        /// Returns a handle to the `CexSymbol` endpoint group.
5965        pub fn cex_symbol(&self) -> CexSymbol {
5966            CexSymbol::from_client(self.clone())
5967        }
5968
5969        /// Returns a handle to the `Forex` endpoint group.
5970        pub fn forex(&self) -> Forex {
5971            Forex::from_client(self.clone())
5972        }
5973
5974        /// Returns a handle to the `FundingRate` endpoint group.
5975        pub fn funding_rate(&self) -> FundingRate {
5976            FundingRate::from_client(self.clone())
5977        }
5978
5979        /// Returns a handle to the `IndexPrice` endpoint group.
5980        pub fn index_price(&self) -> IndexPrice {
5981            IndexPrice::from_client(self.clone())
5982        }
5983
5984        /// Returns a handle to the `Liquidation` endpoint group.
5985        pub fn liquidation(&self) -> Liquidation {
5986            Liquidation::from_client(self.clone())
5987        }
5988
5989        /// Returns a handle to the `Listing` endpoint group.
5990        pub fn listing(&self) -> Listing {
5991            Listing::from_client(self.clone())
5992        }
5993
5994        /// Returns a handle to the `MarginBorrow` endpoint group.
5995        pub fn margin_borrow(&self) -> MarginBorrow {
5996            MarginBorrow::from_client(self.clone())
5997        }
5998
5999        /// Returns a handle to the `NaverTrend` endpoint group.
6000        pub fn naver_trend(&self) -> NaverTrend {
6001            NaverTrend::from_client(self.clone())
6002        }
6003
6004        /// Returns a handle to the `OpenInterest` endpoint group.
6005        pub fn open_interest(&self) -> OpenInterest {
6006            OpenInterest::from_client(self.clone())
6007        }
6008
6009        /// Returns a handle to the `Premium` endpoint group.
6010        pub fn premium(&self) -> Premium {
6011            Premium::from_client(self.clone())
6012        }
6013
6014        /// Returns a handle to the `Telegram` endpoint group.
6015        pub fn telegram(&self) -> Telegram {
6016            Telegram::from_client(self.clone())
6017        }
6018
6019        /// Returns a handle to the `Ticker` endpoint group.
6020        pub fn ticker(&self) -> Ticker {
6021            Ticker::from_client(self.clone())
6022        }
6023
6024        /// Returns a handle to the `Token` endpoint group.
6025        pub fn token(&self) -> Token {
6026            Token::from_client(self.clone())
6027        }
6028
6029        /// Returns a handle to the `TradingFees` endpoint group.
6030        pub fn trading_fees(&self) -> TradingFees {
6031            TradingFees::from_client(self.clone())
6032        }
6033
6034        /// Returns a handle to the `WalletStatus` endpoint group.
6035        pub fn wallet_status(&self) -> WalletStatus {
6036            WalletStatus::from_client(self.clone())
6037        }
6038    }
6039}