1use crate::client::QueryPairs;
21
22pub(crate) trait ToQuery {
24 fn to_query(&self) -> QueryPairs;
25}
26
27fn push<T: ToString>(pairs: &mut QueryPairs, name: &'static str, value: &Option<T>) {
29 if let Some(value) = value {
30 pairs.push((name, value.to_string()));
31 }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum DiscoverTab {
37 Trending,
39 New,
41 Gainers,
43 Graduating,
45}
46
47impl DiscoverTab {
48 pub fn as_str(self) -> &'static str {
50 match self {
51 DiscoverTab::Trending => "trending",
52 DiscoverTab::New => "new",
53 DiscoverTab::Gainers => "gainers",
54 DiscoverTab::Graduating => "graduating",
55 }
56 }
57}
58
59impl std::fmt::Display for DiscoverTab {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 f.write_str(self.as_str())
62 }
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum TokenStatus {
68 Bonding,
70 Graduated,
72}
73
74impl TokenStatus {
75 pub fn as_str(self) -> &'static str {
77 match self {
78 TokenStatus::Bonding => "bonding",
79 TokenStatus::Graduated => "graduated",
80 }
81 }
82}
83
84impl std::fmt::Display for TokenStatus {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 f.write_str(self.as_str())
87 }
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92pub enum SortDirection {
93 Asc,
95 Desc,
97}
98
99impl SortDirection {
100 pub fn as_str(self) -> &'static str {
102 match self {
103 SortDirection::Asc => "asc",
104 SortDirection::Desc => "desc",
105 }
106 }
107}
108
109impl std::fmt::Display for SortDirection {
110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111 f.write_str(self.as_str())
112 }
113}
114
115#[derive(Debug, Clone, Default)]
117pub struct DiscoverParams {
118 pub tab: Option<DiscoverTab>,
120 pub network: Option<String>,
122 pub min_marketcap: Option<f64>,
124 pub min_volume: Option<f64>,
126 pub min_holders: Option<i64>,
128 pub max_age_secs: Option<i64>,
130 pub status: Option<TokenStatus>,
132 pub limit: Option<i64>,
134}
135
136impl DiscoverParams {
137 pub fn new() -> Self {
139 Self::default()
140 }
141
142 pub fn tab(mut self, tab: DiscoverTab) -> Self {
144 self.tab = Some(tab);
145 self
146 }
147
148 pub fn network(mut self, network: impl Into<String>) -> Self {
150 self.network = Some(network.into());
151 self
152 }
153
154 pub fn min_marketcap(mut self, min_marketcap: f64) -> Self {
156 self.min_marketcap = Some(min_marketcap);
157 self
158 }
159
160 pub fn min_volume(mut self, min_volume: f64) -> Self {
162 self.min_volume = Some(min_volume);
163 self
164 }
165
166 pub fn min_holders(mut self, min_holders: i64) -> Self {
168 self.min_holders = Some(min_holders);
169 self
170 }
171
172 pub fn max_age_secs(mut self, max_age_secs: i64) -> Self {
174 self.max_age_secs = Some(max_age_secs);
175 self
176 }
177
178 pub fn status(mut self, status: TokenStatus) -> Self {
180 self.status = Some(status);
181 self
182 }
183
184 pub fn limit(mut self, limit: i64) -> Self {
186 self.limit = Some(limit);
187 self
188 }
189}
190
191impl ToQuery for DiscoverParams {
192 fn to_query(&self) -> QueryPairs {
193 let mut pairs = QueryPairs::new();
194 push(&mut pairs, "tab", &self.tab.map(|t| t.as_str()));
195 push(&mut pairs, "network", &self.network);
196 push(&mut pairs, "minMarketcap", &self.min_marketcap);
197 push(&mut pairs, "minVolume", &self.min_volume);
198 push(&mut pairs, "minHolders", &self.min_holders);
199 push(&mut pairs, "maxAgeSecs", &self.max_age_secs);
200 push(&mut pairs, "status", &self.status.map(|s| s.as_str()));
201 push(&mut pairs, "limit", &self.limit);
202 pairs
203 }
204}
205
206#[derive(Debug, Clone, Default)]
209pub struct ListTokensParams {
210 pub order_type: Option<String>,
212 pub order_flag: Option<SortDirection>,
214 pub search_word: Option<String>,
216 pub network: Option<String>,
218 pub style: Option<String>,
220 pub include_nsfw: Option<bool>,
222 pub page_number: Option<i64>,
224 pub page_size: Option<i64>,
226}
227
228impl ListTokensParams {
229 pub fn new() -> Self {
231 Self::default()
232 }
233
234 pub fn order_type(mut self, order_type: impl Into<String>) -> Self {
236 self.order_type = Some(order_type.into());
237 self
238 }
239
240 pub fn order_flag(mut self, order_flag: SortDirection) -> Self {
242 self.order_flag = Some(order_flag);
243 self
244 }
245
246 pub fn search_word(mut self, search_word: impl Into<String>) -> Self {
248 self.search_word = Some(search_word.into());
249 self
250 }
251
252 pub fn network(mut self, network: impl Into<String>) -> Self {
254 self.network = Some(network.into());
255 self
256 }
257
258 pub fn style(mut self, style: impl Into<String>) -> Self {
260 self.style = Some(style.into());
261 self
262 }
263
264 pub fn include_nsfw(mut self, include_nsfw: bool) -> Self {
266 self.include_nsfw = Some(include_nsfw);
267 self
268 }
269
270 pub fn page_number(mut self, page_number: i64) -> Self {
272 self.page_number = Some(page_number);
273 self
274 }
275
276 pub fn page_size(mut self, page_size: i64) -> Self {
278 self.page_size = Some(page_size);
279 self
280 }
281}
282
283impl ToQuery for ListTokensParams {
284 fn to_query(&self) -> QueryPairs {
285 let mut pairs = QueryPairs::new();
286 push(&mut pairs, "orderType", &self.order_type);
287 push(
288 &mut pairs,
289 "orderFlag",
290 &self.order_flag.map(|f| f.as_str()),
291 );
292 push(&mut pairs, "searchWord", &self.search_word);
293 push(&mut pairs, "network", &self.network);
294 push(&mut pairs, "style", &self.style);
295 push(&mut pairs, "includeNsfw", &self.include_nsfw);
296 push(&mut pairs, "pageNumber", &self.page_number);
297 push(&mut pairs, "pageSize", &self.page_size);
298 pairs
299 }
300}
301
302#[derive(Debug, Clone, Default)]
305pub struct TokenDetailParams {
306 pub page_number: Option<i64>,
308 pub page_size: Option<i64>,
310}
311
312impl TokenDetailParams {
313 pub fn new() -> Self {
315 Self::default()
316 }
317
318 pub fn page_number(mut self, page_number: i64) -> Self {
320 self.page_number = Some(page_number);
321 self
322 }
323
324 pub fn page_size(mut self, page_size: i64) -> Self {
326 self.page_size = Some(page_size);
327 self
328 }
329}
330
331impl ToQuery for TokenDetailParams {
332 fn to_query(&self) -> QueryPairs {
333 let mut pairs = QueryPairs::new();
334 push(&mut pairs, "pageNumber", &self.page_number);
335 push(&mut pairs, "pageSize", &self.page_size);
336 pairs
337 }
338}
339
340#[derive(Debug, Clone, Default)]
343pub struct RecentTradesParams {
344 pub latest_trade_id: Option<i64>,
346 pub latest_token_id: Option<i64>,
348}
349
350impl RecentTradesParams {
351 pub fn new() -> Self {
353 Self::default()
354 }
355
356 pub fn latest_trade_id(mut self, latest_trade_id: i64) -> Self {
358 self.latest_trade_id = Some(latest_trade_id);
359 self
360 }
361
362 pub fn latest_token_id(mut self, latest_token_id: i64) -> Self {
364 self.latest_token_id = Some(latest_token_id);
365 self
366 }
367}
368
369impl ToQuery for RecentTradesParams {
370 fn to_query(&self) -> QueryPairs {
371 let mut pairs = QueryPairs::new();
372 push(&mut pairs, "latestTradeId", &self.latest_trade_id);
373 push(&mut pairs, "latestTokenId", &self.latest_token_id);
374 pairs
375 }
376}
377
378#[derive(Debug, Clone, Default)]
381pub struct TokenTradesParams {
382 pub limit: Option<i64>,
384 pub offset: Option<i64>,
386}
387
388impl TokenTradesParams {
389 pub fn new() -> Self {
391 Self::default()
392 }
393
394 pub fn limit(mut self, limit: i64) -> Self {
396 self.limit = Some(limit);
397 self
398 }
399
400 pub fn offset(mut self, offset: i64) -> Self {
402 self.offset = Some(offset);
403 self
404 }
405}
406
407impl ToQuery for TokenTradesParams {
408 fn to_query(&self) -> QueryPairs {
409 let mut pairs = QueryPairs::new();
410 push(&mut pairs, "limit", &self.limit);
411 push(&mut pairs, "offset", &self.offset);
412 pairs
413 }
414}
415
416#[derive(Debug, Clone)]
422pub struct ChartDataParams {
423 pub token_address: String,
425 pub interval: String,
427 pub from: i64,
429 pub to: i64,
431 pub first: Option<i64>,
433 pub dex: Option<String>,
435 pub count_back: Option<i64>,
437}
438
439impl ChartDataParams {
440 pub fn new(
442 token_address: impl Into<String>,
443 interval: impl Into<String>,
444 from: i64,
445 to: i64,
446 ) -> Self {
447 Self {
448 token_address: token_address.into(),
449 interval: interval.into(),
450 from,
451 to,
452 first: None,
453 dex: None,
454 count_back: None,
455 }
456 }
457
458 pub fn first(mut self, first: i64) -> Self {
460 self.first = Some(first);
461 self
462 }
463
464 pub fn dex(mut self, dex: impl Into<String>) -> Self {
466 self.dex = Some(dex.into());
467 self
468 }
469
470 pub fn count_back(mut self, count_back: i64) -> Self {
472 self.count_back = Some(count_back);
473 self
474 }
475}
476
477impl ToQuery for ChartDataParams {
478 fn to_query(&self) -> QueryPairs {
479 let mut pairs: QueryPairs = vec![
480 ("tokenAddress", self.token_address.clone()),
481 ("interval", self.interval.clone()),
482 ("from", self.from.to_string()),
483 ("to", self.to.to_string()),
484 ];
485 push(&mut pairs, "first", &self.first);
486 push(&mut pairs, "dex", &self.dex);
487 push(&mut pairs, "countBack", &self.count_back);
488 pairs
489 }
490}
491
492#[derive(Debug, Clone, Default)]
495pub struct TopHoldersParams {
496 pub from: Option<i64>,
498 pub to: Option<i64>,
500 pub network: Option<String>,
502}
503
504impl TopHoldersParams {
505 pub fn new() -> Self {
507 Self::default()
508 }
509
510 pub fn from(mut self, from: i64) -> Self {
512 self.from = Some(from);
513 self
514 }
515
516 pub fn to(mut self, to: i64) -> Self {
518 self.to = Some(to);
519 self
520 }
521
522 pub fn network(mut self, network: impl Into<String>) -> Self {
524 self.network = Some(network.into());
525 self
526 }
527}
528
529impl ToQuery for TopHoldersParams {
530 fn to_query(&self) -> QueryPairs {
531 let mut pairs = QueryPairs::new();
532 push(&mut pairs, "from", &self.from);
533 push(&mut pairs, "to", &self.to);
534 push(&mut pairs, "network", &self.network);
535 pairs
536 }
537}
538
539#[derive(Debug, Clone, Default)]
542pub struct SharesParams {
543 pub from: Option<i64>,
545 pub to: Option<i64>,
548 pub limit: Option<i64>,
551}
552
553impl SharesParams {
554 pub fn new() -> Self {
556 Self::default()
557 }
558
559 pub fn from(mut self, from: i64) -> Self {
561 self.from = Some(from);
562 self
563 }
564
565 pub fn to(mut self, to: i64) -> Self {
567 self.to = Some(to);
568 self
569 }
570
571 pub fn limit(mut self, limit: i64) -> Self {
573 self.limit = Some(limit);
574 self
575 }
576}
577
578impl ToQuery for SharesParams {
579 fn to_query(&self) -> QueryPairs {
580 let mut pairs = QueryPairs::new();
581 push(&mut pairs, "from", &self.from);
582 push(&mut pairs, "to", &self.to);
583 push(&mut pairs, "limit", &self.limit);
584 pairs
585 }
586}
587
588#[derive(Debug, Clone, Default)]
590pub struct RoundsParams {
591 pub limit: Option<i64>,
593 pub offset: Option<i64>,
595}
596
597impl RoundsParams {
598 pub fn new() -> Self {
600 Self::default()
601 }
602
603 pub fn limit(mut self, limit: i64) -> Self {
605 self.limit = Some(limit);
606 self
607 }
608
609 pub fn offset(mut self, offset: i64) -> Self {
611 self.offset = Some(offset);
612 self
613 }
614}
615
616impl ToQuery for RoundsParams {
617 fn to_query(&self) -> QueryPairs {
618 let mut pairs = QueryPairs::new();
619 push(&mut pairs, "limit", &self.limit);
620 push(&mut pairs, "offset", &self.offset);
621 pairs
622 }
623}
624
625#[cfg(test)]
626mod tests {
627 use super::*;
628
629 #[test]
630 fn omits_unset_parameters() {
631 let pairs = DiscoverParams::new().limit(5).to_query();
632 assert_eq!(pairs, vec![("limit", "5".to_string())]);
633 }
634
635 #[test]
636 fn encodes_enums_with_their_wire_values() {
637 let pairs = DiscoverParams::new()
638 .tab(DiscoverTab::Graduating)
639 .status(TokenStatus::Bonding)
640 .to_query();
641 assert_eq!(
642 pairs,
643 vec![
644 ("tab", "graduating".to_string()),
645 ("status", "bonding".to_string())
646 ]
647 );
648 }
649
650 #[test]
651 fn always_sends_the_required_chart_parameters() {
652 let pairs = ChartDataParams::new("0xabc", "5", 1, 2).to_query();
653 assert_eq!(
654 pairs,
655 vec![
656 ("tokenAddress", "0xabc".to_string()),
657 ("interval", "5".to_string()),
658 ("from", "1".to_string()),
659 ("to", "2".to_string()),
660 ]
661 );
662 }
663}