use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use crate::{Error, IconFetcher, IconQuery, IconResult, IconSource};
#[derive(Clone)]
pub struct Blockscout;
#[async_trait::async_trait]
impl IconSource for Blockscout {
fn name(&self) -> &'static str {
"blockscout"
}
fn url(&self, query: &IconQuery) -> Option<String> {
match query {
IconQuery::ERC20(network_id, address) => {
if *network_id != 1 {
return None;
}
Some(format!(
"https://eth.blockscout.com/api/v2/tokens/{}",
address.to_lowercase()
))
}
_ => None,
}
}
async fn fetch(&self, fetcher: &IconFetcher, query: &IconQuery) -> Result<IconResult, Error> {
let Some(url) = self.url(query) else {
return Ok(IconResult::Unsupported);
};
let Some(metadata) = fetcher.fetch_json::<BlockscoutAssetMetadata>(&url).await? else {
return Ok(IconResult::NotFound);
};
let Some(icon_url) = metadata.icon_url else {
return Ok(IconResult::NotFound);
};
fetcher.fetch_image_url(&icon_url).await
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BlockscoutAssetMetadata {
pub icon_url: Option<String>,
#[serde(flatten)]
pub other: HashMap<String, serde_json::Value>,
}