use alloc::{string::String, vec::Vec};
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Chain {
pub name: String,
#[serde(rename = "chain")]
pub currencu: String,
pub icon: Option<String>,
pub chain_id: Option<u64>,
pub rpc: Vec<ChainRpc>,
pub features: Option<Vec<Feature>>,
pub faucets: Option<Vec<String>>,
pub native_currency: Option<NativeCurrency>,
pub info_url: Option<String>,
pub short_name: Option<String>,
pub network_id: Option<u64>,
pub slip44: Option<u64>,
pub explorers: Option<Vec<Explorer>>,
pub tvl: Option<f64>,
pub chain_slug: Option<String>,
}
impl From<alloy_chains::NamedChain> for Chain {
fn from(named: alloy_chains::NamedChain) -> Self {
crate::CHAINS
.0
.iter()
.find(|chain| chain.chain_id == Some(named as u64))
.cloned()
.expect("Chain ID not found")
}
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Explorer {
pub name: String,
pub url: String,
pub icon: Option<String>,
pub standard: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NativeCurrency {
pub name: String,
pub symbol: String,
pub decimals: u8,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Feature {
pub name: String,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct ChainRpc {
pub url: String,
pub tracking: Option<Tracking>,
pub open_source: Option<bool>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Tracking {
r#None,
Yes,
Limited,
Unspecified,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_serde_chain_rpc() {
let json = r#"{"url":"https://rpc.example.com","tracking":"yes","open_source":true}"#;
let chain_rpc: ChainRpc = serde_json::from_str(json).unwrap();
assert_eq!(chain_rpc.url, "https://rpc.example.com");
assert_eq!(chain_rpc.tracking, Some(Tracking::Yes));
assert_eq!(chain_rpc.open_source, Some(true));
let serialized = serde_json::to_string(&chain_rpc).unwrap();
assert_eq!(serialized, json);
}
#[tokio::test]
#[cfg(feature = "online")]
async fn test_online_deserialize() {
let url = "https://chainlist.org/rpcs.json";
let response = reqwest::get(url).await.expect("Failed to fetch data");
let chains: alloc::vec::Vec<Chain> = response.json().await.expect("Failed to parse JSON");
assert!(!chains.is_empty(), "No chains found in the response");
}
}