rig_onchain_kit/data/
mod.rs1use anyhow::{anyhow, Result};
2use rig_tool_macro::tool;
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Serialize, Deserialize)]
6pub struct Candlestick {
7 pub timestamp: u64,
8 pub open: f64,
9 pub high: f64,
10 pub low: f64,
11 pub close: f64,
12 pub volume: f64,
13}
14
15#[derive(Debug, Serialize, Deserialize)]
16pub struct TopToken {
17 pub name: String,
18 pub pubkey: String,
19 pub price: f64,
20 pub market_cap: f64,
21 pub volume_24h: f64,
22 pub price_change_24h: f64,
23}
24
25const API_BASE: &str = "https://api.listen-rs.com/v1/adapter";
26
27#[tool(description = "
28Fetch top tokens from the Listen API.
29
30Parameters:
31- limit (string): Optional number of tokens to return (default: 20)
32- min_volume (string): Optional minimum 24h volume filter
33- min_market_cap (string): Optional minimum market cap filter
34- timeframe (string): Optional timeframe in seconds
35- only_pumpfun_tokens (string): Optional boolean to filter only PumpFun tokens (default: \"true\")
36
37Use the min_market_cap of 100k unless specified otherwise.
38
39Returns a list of top tokens with their market data.
40")]
41pub async fn fetch_top_tokens(
42 limit: Option<String>,
43 min_volume: Option<String>,
44 min_market_cap: Option<String>,
45 timeframe: Option<String>,
46 only_pumpfun_tokens: Option<String>,
47) -> Result<Vec<TopToken>> {
48 let mut url = format!("{}/top-tokens", API_BASE);
49 let mut query_params = vec![];
50
51 if let Some(limit) = limit {
52 query_params.push(format!("limit={}", limit));
53 }
54 if let Some(min_volume) = min_volume {
55 query_params.push(format!("min_volume={}", min_volume));
56 }
57 if let Some(min_market_cap) = min_market_cap {
58 query_params.push(format!("min_market_cap={}", min_market_cap));
59 }
60 if let Some(timeframe) = timeframe {
61 query_params.push(format!("timeframe={}", timeframe));
62 }
63 if let Some(only_pumpfun) = only_pumpfun_tokens {
64 query_params.push(format!("only_pumpfun_tokens={}", only_pumpfun));
65 }
66
67 if !query_params.is_empty() {
68 url = format!("{}?{}", url, query_params.join("&"));
69 }
70
71 let response = reqwest::get(&url)
72 .await
73 .map_err(|e| anyhow!("Failed to fetch top tokens: {}", e))?;
74
75 let tokens = response
76 .json::<Vec<TopToken>>()
77 .await
78 .map_err(|e| anyhow!("Failed to parse response: {}", e))?;
79
80 Ok(tokens)
81}
82
83#[tool(description = "
84Fetch candlestick data for a token from the Listen API.
85
86Parameters:
87- mint (string): The token's mint/pubkey address
88- interval (string): The candlestick interval, one of:
89 * '15s' (15 seconds)
90 * '30s' (30 seconds)
91 * '1m' (1 minute)
92 * '5m' (5 minutes)
93 * '15m' (15 minutes)
94 * '30m' (30 minutes)
95 * '1h' (1 hour)
96 * '4h' (4 hours)
97 * '1d' (1 day)
98- limit (string): Optional number of candlesticks to return
99
100for tokens under 1M market cap, use the 30s interval, 200 limit
101
102for tokens over 1M market cap, use the 5m interval, 200 limit
103
104for tokens over 10M market cap, use the 15m interval, 200 limit
105
106Returns a list of candlesticks with OHLCV data.
107")]
108pub async fn fetch_candlesticks(
109 mint: String,
110 interval: String,
111 limit: Option<String>,
112) -> Result<Vec<Candlestick>> {
113 match interval.as_str() {
115 "15s" | "30s" | "1m" | "5m" | "15m" | "30m" | "1h" | "4h" | "1d" => {
116 ()
117 }
118 _ => return Err(anyhow!("Invalid interval: {}", interval)),
119 }
120
121 let mut url = format!(
122 "{}/candlesticks?mint={}&interval={}",
123 API_BASE, mint, interval
124 );
125
126 if let Some(limit) = limit {
127 url = format!("{}&limit={}", url, limit);
128 }
129
130 let response = reqwest::get(&url)
131 .await
132 .map_err(|e| anyhow!("Failed to fetch candlesticks: {}", e))?;
133
134 let candlesticks = response
135 .json::<Vec<Candlestick>>()
136 .await
137 .map_err(|e| anyhow!("Failed to parse response: {}", e))?;
138
139 Ok(candlesticks)
140}
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145
146 #[tokio::test]
147 async fn test_fetch_top_tokens() {
148 fetch_top_tokens(
149 Some("10".to_string()),
150 None,
151 None,
152 None,
153 Some("true".to_string()),
154 )
155 .await
156 .unwrap();
157 }
158
159 #[tokio::test]
160 async fn test_fetch_candlesticks() {
161 let candlesticks = fetch_candlesticks(
162 "So11111111111111111111111111111111111111112".to_string(),
163 "5m".to_string(),
164 Some("10".to_string()),
165 )
166 .await;
167 println!("{:?}", candlesticks);
168 }
169}