price.rs•2.84 kB
//! Token price fetching operations
use anyhow::{Context, Result};
/// Get token price from CoinGecko API
pub async fn get_token_price(token: &str, currency: Option<&str>) -> Result<String> {
let currency = currency.unwrap_or("usd").to_lowercase();
let base_url = "https://api.coingecko.com/api/v3";
// For ETH, use special endpoint
if token.to_lowercase() == "eth" || token.to_lowercase() == "ethereum" {
let url = format!("{}/simple/price?ids=ethereum&vs_currencies={}", base_url, currency);
let response = reqwest::get(&url).await
.context("Failed to fetch price")?;
let json: serde_json::Value = response.json().await
.context("Failed to parse response")?;
let price = json["ethereum"][¤cy].as_f64()
.ok_or_else(|| anyhow::anyhow!("Price not found"))?;
return Ok(format!("ETH: {:.2} {}", price, currency.to_uppercase()));
}
// For other tokens, try to match by symbol or address
// First check if it's an address
if token.starts_with("0x") {
// Try to get price by contract address
let url = format!("{}/simple/token_price/ethereum?contract_addresses={}&vs_currencies={}",
base_url, token, currency);
let response = reqwest::get(&url).await
.context("Failed to fetch price")?;
let json: serde_json::Value = response.json().await
.context("Failed to parse response")?;
if let Some(price_obj) = json.as_object().and_then(|obj| {
obj.get(&token.to_lowercase())
}) {
if let Some(price) = price_obj[¤cy].as_f64() {
return Ok(format!("Token {}: {:.2} {}", token, price, currency.to_uppercase()));
}
}
return Err(anyhow::anyhow!("Price not found for token address: {}", token));
}
// Try to match by symbol (common tokens)
let symbol = token.to_lowercase();
let token_ids = match symbol.as_str() {
"usdc" => "usd-coin",
"usdt" => "tether",
"dai" => "dai",
"weth" => "weth",
"link" => "chainlink",
_ => return Err(anyhow::anyhow!("Token symbol not recognized: {}. Please use token address starting with 0x", token)),
};
let url = format!("{}/simple/price?ids={}&vs_currencies={}", base_url, token_ids, currency);
let response = reqwest::get(&url).await
.context("Failed to fetch price")?;
let json: serde_json::Value = response.json().await
.context("Failed to parse response")?;
let price = json[token_ids][¤cy].as_f64()
.ok_or_else(|| anyhow::anyhow!("Price not found"))?;
Ok(format!("{}: {:.2} {}", token.to_uppercase(), price, currency.to_uppercase()))
}