solagent_plugin_birdeye/
lib.rs

1use anyhow::Result;
2use solagent_core::{IWallet, SolanaAgentKit};
3
4mod primitive;
5pub use primitive::*;
6
7/// Get overview of a token.
8///
9/// # Parameters
10///
11/// * `agent` - An instance of SolanaAgentKit (with .config.birdeye_api_key)
12///
13/// - `address`: Address of a token
14///
15/// # Returns
16///
17/// A `Result` TokenOverviewResponse
18pub async fn get_token_overview<W: IWallet>(agent: &SolanaAgentKit<W>, 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
42/// Get market data of single token
43///
44/// # Parameters
45///
46/// * `agent` - An instance of SolanaAgentKit
47///
48/// - `address`: Address of a token
49///
50/// # Returns
51///
52/// A `Result`
53pub async fn get_market_data<W: IWallet>(agent: &SolanaAgentKit<W>, address: &str) -> Result<MarketDataResponse> {
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::<MarketDataResponse>()
72        .await?;
73
74    Ok(resp)
75}
76
77/// Get Wallet Portfolio
78///
79/// # Parameters
80///
81/// * `agent` - An instance of SolanaAgentKit
82///
83/// - `address`: Address of a wallet
84///
85/// # Returns
86///
87/// A `WalletPortfolioResponse`
88pub async fn get_wallet_portfolio<W: IWallet>(
89    agent: &SolanaAgentKit<W>,
90    wallet_address: &str,
91) -> Result<WalletPortfolioResponse> {
92    let api_key = agent
93        .config
94        .birdeye_api_key
95        .as_ref()
96        .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
97
98    let client = reqwest::Client::new();
99    let url = format!("{}/v1/wallet/token_list", BIRDEYE_URL);
100
101    let response = client
102        .get(&url)
103        .query(&[("wallet", wallet_address)])
104        .header("accept", "application/json")
105        .header("X-API-KEY", api_key)
106        .header("x-chain", "solana")
107        .send()
108        .await?
109        .json::<WalletPortfolioResponse>()
110        .await?;
111
112    Ok(response)
113}
114
115/// Get top holder list of the given token
116///
117/// # Parameters
118///
119/// * `agent` - An instance of SolanaAgentKit (with .config.birdeye_api_key)
120///
121/// - `params`: Query Params
122///
123/// # Returns
124///
125/// A `Result` TokenHolderResponse
126pub async fn get_token_holders<W: IWallet>(
127    agent: &SolanaAgentKit<W>,
128    query_params: TokenHolderQueryParams,
129) -> Result<TokenHolderResponse> {
130    let api_key = agent
131        .config
132        .birdeye_api_key
133        .as_ref()
134        .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
135
136    let client = reqwest::Client::new();
137    let url = format!("{}/defi/v3/token/holder", BIRDEYE_URL);
138
139    let address = query_params.address;
140    let offset = query_params.offset.unwrap_or(0);
141    let limit = query_params.limit.unwrap_or(100);
142
143    let resp = client
144        .get(url)
145        .query(&[("address", address), ("offset", offset.to_string()), ("limit", limit.to_string())])
146        .header("X-API-KEY", api_key)
147        .header("accept", "application/json")
148        .header("x-chain", "solana")
149        .send()
150        .await?
151        .json::<TokenHolderResponse>()
152        .await?;
153
154    Ok(resp)
155}
156
157/// Get metadata of single token
158///
159/// # Parameters
160///
161/// * `agent` - An instance of SolanaAgentKit (with .config.birdeye_api_key)
162///
163/// - `address`: Address of a token
164///
165/// # Returns
166///
167/// A `Result` TokenMetadataResponse
168pub async fn get_token_metadata<W: IWallet>(agent: &SolanaAgentKit<W>, address: &str) -> Result<TokenMetadataResponse> {
169    let api_key = agent
170        .config
171        .birdeye_api_key
172        .as_ref()
173        .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
174
175    let client = reqwest::Client::new();
176    let url = format!("{}/defi/v3/token/meta-data/single", BIRDEYE_URL);
177
178    let resp = client
179        .get(url)
180        .query(&[("address", address)])
181        .header("X-API-KEY", api_key)
182        .header("accept", "application/json")
183        .header("x-chain", "solana")
184        .send()
185        .await?
186        .json::<TokenMetadataResponse>()
187        .await?;
188
189    Ok(resp)
190}
191
192/// Get price update of a token.
193///
194/// # Parameters
195///
196/// * `agent` - An instance of SolanaAgentKit (with .config.birdeye_api_key)
197///
198/// - `address`: Address of a token
199///
200/// # Returns
201///
202/// A `Result` TokenPriceResponse
203pub async fn get_token_price<W: IWallet>(agent: &SolanaAgentKit<W>, address: &str) -> Result<TokenPriceResponse> {
204    let api_key = agent
205        .config
206        .birdeye_api_key
207        .as_ref()
208        .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
209
210    let client = reqwest::Client::new();
211    let url = format!("{}/defi/price", BIRDEYE_URL);
212
213    let resp = client
214        .get(url)
215        .query(&[("address", address)])
216        .header("X-API-KEY", api_key)
217        .header("accept", "application/json")
218        .header("x-chain", "solana")
219        .send()
220        .await?
221        .json::<TokenPriceResponse>()
222        .await?;
223
224    Ok(resp)
225}
226
227/// Get price and volume updates of a token
228///
229/// # Parameters
230///
231/// * `agent` - An instance of SolanaAgentKit (with .config.birdeye_api_key)
232///
233/// - `query_params`: TokenPriceVolumeQueryParams
234///
235/// # Returns
236///
237/// A `Result` TokenPriceVolumeResponse
238pub async fn get_token_price_volume<W: IWallet>(
239    agent: &SolanaAgentKit<W>,
240    query_params: TokenPriceVolumeQueryParams,
241) -> Result<TokenPriceVolumeResponse> {
242    let api_key = agent
243        .config
244        .birdeye_api_key
245        .as_ref()
246        .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
247
248    let client = reqwest::Client::new();
249    let url = format!("{}/defi/price_volume/single", BIRDEYE_URL);
250
251    let address = query_params.address;
252    let vh = query_params.vh;
253
254    let resp = client
255        .get(url)
256        .query(&[("address", address), ("type", vh)])
257        .header("X-API-KEY", api_key)
258        .header("accept", "application/json")
259        .header("x-chain", "solana")
260        .send()
261        .await?
262        .json::<TokenPriceVolumeResponse>()
263        .await?;
264
265    Ok(resp)
266}
267
268/// Retrieve a dynamic and up-to-date list of trending tokens based on specified sorting criteria.
269///
270/// # Parameters
271///
272/// * `agent` - An instance of SolanaAgentKit (with .config.birdeye_api_key)
273///
274/// - `query_params`: TokenTrendingQueryParams
275///
276/// # Returns
277///
278/// A `Result` TokenTrendingResponse
279pub async fn get_token_trending<W: IWallet>(
280    agent: &SolanaAgentKit<W>,
281    query_params: TokenTrendingQueryParams,
282) -> Result<TokenTrendingResponse> {
283    let api_key = agent
284        .config
285        .birdeye_api_key
286        .as_ref()
287        .ok_or_else(|| anyhow::anyhow!("Missing Birdeye API key in agent.config.birdeye_api_key"))?;
288
289    let client = reqwest::Client::new();
290    let url = format!("{}/defi/token_trending", BIRDEYE_URL);
291
292    let sort_by = query_params.sort_by;
293    let sort_type = query_params.sort_type;
294    let offset = query_params.offset.unwrap_or(0);
295    let limit = query_params.limit.unwrap_or(20);
296
297    let resp = client
298        .get(url)
299        .query(&[
300            ("sort_by", sort_by),
301            ("sort_type", sort_type),
302            ("offset", offset.to_string()),
303            ("limit", limit.to_string()),
304        ])
305        .header("X-API-KEY", api_key)
306        .header("accept", "application/json")
307        .header("x-chain", "solana")
308        .send()
309        .await?
310        .json::<TokenTrendingResponse>()
311        .await?;
312
313    Ok(resp)
314}