1use anyhow::Result;
2use solagent_core::SolanaAgentKit;
3
4mod primitive;
5pub use primitive::*;
6
7pub async fn get_token_overview(agent: &SolanaAgentKit, address: &str) -> Result<TokenOverviewResponse> {
19 let api_key = agent
20 .config
21 .birdeye_api_key
22 .as_ref()
23 .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
24
25 let client = reqwest::Client::new();
26 let url = format!("{}/defi/token_overview", BIRDEYE_URL);
27
28 let resp = client
29 .get(url)
30 .query(&[("address", address)])
31 .header("X-API-KEY", api_key)
32 .header("accept", "application/json")
33 .header("x-chain", "solana")
34 .send()
35 .await?
36 .json::<TokenOverviewResponse>()
37 .await?;
38
39 Ok(resp)
40}
41
42pub async fn get_market_data(agent: &SolanaAgentKit, address: &str) -> Result<TokenMarketDataResponse> {
54 let api_key = agent
55 .config
56 .birdeye_api_key
57 .as_ref()
58 .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
59
60 let client = reqwest::Client::new();
61 let url = format!("{}/defi/v3/token/market-data", BIRDEYE_URL);
62
63 let resp = client
64 .get(url)
65 .query(&[("address", address)])
66 .header("X-API-KEY", api_key)
67 .header("accept", "application/json")
68 .header("x-chain", "solana")
69 .send()
70 .await?
71 .json::<TokenMarketDataResponse>()
72 .await?;
73
74 Ok(resp)
75}
76
77pub async fn get_wallet_portfolio(agent: &SolanaAgentKit, wallet_address: &str) -> Result<WalletPortfolioResponse> {
89 let api_key = agent
90 .config
91 .birdeye_api_key
92 .as_ref()
93 .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
94
95 let client = reqwest::Client::new();
96 let url = format!("{}/v1/wallet/token_list", BIRDEYE_URL);
97
98 let response = client
99 .get(&url)
100 .query(&[("wallet", wallet_address)])
101 .header("accept", "application/json")
102 .header("X-API-KEY", api_key)
103 .header("x-chain", "solana")
104 .send()
105 .await?
106 .json::<WalletPortfolioResponse>()
107 .await?;
108
109 Ok(response)
110}
111
112pub async fn get_token_holders(
124 agent: &SolanaAgentKit,
125 query_params: TokenHolderQueryParams,
126) -> Result<TokenHolderResponse> {
127 let api_key = agent
128 .config
129 .birdeye_api_key
130 .as_ref()
131 .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
132
133 let client = reqwest::Client::new();
134 let url = format!("{}/defi/v3/token/holder", BIRDEYE_URL);
135
136 let address = query_params.address;
137 let offset = query_params.offset.unwrap_or(0);
138 let limit = query_params.limit.unwrap_or(100);
139
140 let resp = client
141 .get(url)
142 .query(&[("address", address), ("offset", offset.to_string()), ("limit", limit.to_string())])
143 .header("X-API-KEY", api_key)
144 .header("accept", "application/json")
145 .header("x-chain", "solana")
146 .send()
147 .await?
148 .json::<TokenHolderResponse>()
149 .await?;
150
151 Ok(resp)
152}
153
154pub async fn get_token_metadata(agent: &SolanaAgentKit, address: &str) -> Result<TokenMetadataResponse> {
166 let api_key = agent
167 .config
168 .birdeye_api_key
169 .as_ref()
170 .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
171
172 let client = reqwest::Client::new();
173 let url = format!("{}/defi/v3/token/meta-data/single", BIRDEYE_URL);
174
175 let resp = client
176 .get(url)
177 .query(&[("address", address)])
178 .header("X-API-KEY", api_key)
179 .header("accept", "application/json")
180 .header("x-chain", "solana")
181 .send()
182 .await?
183 .json::<TokenMetadataResponse>()
184 .await?;
185
186 Ok(resp)
187}
188
189pub async fn get_token_price(agent: &SolanaAgentKit, address: &str) -> Result<TokenPriceResponse> {
201 let api_key = agent
202 .config
203 .birdeye_api_key
204 .as_ref()
205 .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
206
207 let client = reqwest::Client::new();
208 let url = format!("{}/defi/price", BIRDEYE_URL);
209
210 let resp = client
211 .get(url)
212 .query(&[("address", address)])
213 .header("X-API-KEY", api_key)
214 .header("accept", "application/json")
215 .header("x-chain", "solana")
216 .send()
217 .await?
218 .json::<TokenPriceResponse>()
219 .await?;
220
221 Ok(resp)
222}
223
224pub async fn get_token_price_volume(
236 agent: &SolanaAgentKit,
237 query_params: TokenPriceVolumeQueryParams,
238) -> Result<TokenPriceVolumeResponse> {
239 let api_key = agent
240 .config
241 .birdeye_api_key
242 .as_ref()
243 .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
244
245 let client = reqwest::Client::new();
246 let url = format!("{}/defi/price_volume/single", BIRDEYE_URL);
247
248 let address = query_params.address;
249 let vh = query_params.vh;
250
251 let resp = client
252 .get(url)
253 .query(&[("address", address), ("type", vh)])
254 .header("X-API-KEY", api_key)
255 .header("accept", "application/json")
256 .header("x-chain", "solana")
257 .send()
258 .await?
259 .json::<TokenPriceVolumeResponse>()
260 .await?;
261
262 Ok(resp)
263}
264
265pub async fn get_token_trending(
277 agent: &SolanaAgentKit,
278 query_params: TokenTrendingQueryParams,
279) -> Result<TokenTrendingResponse> {
280 let api_key = agent
281 .config
282 .birdeye_api_key
283 .as_ref()
284 .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
285
286 let client = reqwest::Client::new();
287 let url = format!("{}/defi/token_trending", BIRDEYE_URL);
288
289 let sort_by = query_params.sort_by;
290 let sort_type = query_params.sort_type;
291 let offset = query_params.offset.unwrap_or(0);
292 let limit = query_params.limit.unwrap_or(20);
293
294 let resp = client
295 .get(url)
296 .query(&[
297 ("sort_by", sort_by),
298 ("sort_type", sort_type),
299 ("offset", offset.to_string()),
300 ("limit", limit.to_string()),
301 ])
302 .header("X-API-KEY", api_key)
303 .header("accept", "application/json")
304 .header("x-chain", "solana")
305 .send()
306 .await?
307 .json::<TokenTrendingResponse>()
308 .await?;
309
310 Ok(resp)
311}
312
313pub async fn get_token_mintburn_tx(
325 agent: &SolanaAgentKit,
326 query_params: TokenMintOrBurnQueryParams,
327) -> Result<TokenMintOrBurnResponse> {
328 let api_key = agent
329 .config
330 .birdeye_api_key
331 .as_ref()
332 .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
333
334 let client = reqwest::Client::new();
335 let url = format!("{}/defi/v3/token/mint-burn-txs", BIRDEYE_URL);
336
337 let address = query_params.address;
338 let tx_type = query_params.tx_type;
339 let offset = query_params.offset.unwrap_or(0);
340 let limit = query_params.limit.unwrap_or(20);
341
342 let resp = client
343 .get(url)
344 .query(&[
345 ("address", address),
346 ("type", tx_type),
347 ("sort_by", "block_time".to_string()),
348 ("sort_type", "desc".to_string()),
349 ("offset", offset.to_string()),
350 ("limit", limit.to_string()),
351 ])
352 .header("X-API-KEY", api_key)
353 .header("accept", "application/json")
354 .header("x-chain", "solana")
355 .send()
356 .await?
357 .json::<TokenMintOrBurnResponse>()
358 .await?;
359
360 Ok(resp)
361}
362
363pub async fn search_token_or_market_data(
375 agent: &SolanaAgentKit,
376 query_params: TokenOrMarketQueryParams,
377) -> Result<TokenOrMarketResponse> {
378 let api_key = agent
379 .config
380 .birdeye_api_key
381 .as_ref()
382 .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
383
384 let client = reqwest::Client::new();
385 let url = format!("{}/defi/v3/search", BIRDEYE_URL);
386
387 let keyword = query_params.keyword;
388 let target = query_params.target;
389 let offset = query_params.offset.unwrap_or(0);
390 let limit = query_params.limit.unwrap_or(20);
391
392 let resp = client
393 .get(url)
394 .query(&[
395 ("chain", "solana".to_string()),
396 ("keyworkd", keyword),
397 ("target", target),
398 ("sort_by", "volume_24h_usd".to_string()),
399 ("sort_type", "desc".to_string()),
400 ("offset", offset.to_string()),
401 ("limit", limit.to_string()),
402 ])
403 .header("X-API-KEY", api_key)
404 .header("accept", "application/json")
405 .send()
406 .await?
407 .json::<TokenOrMarketResponse>()
408 .await?;
409
410 Ok(resp)
411}