solana_commons/
spl_token.rs

1use serde::Deserialize;
2use serde_repr::Deserialize_repr;
3use solana_program::pubkey::Pubkey;
4use thiserror::Error;
5
6use crate::deserialize_pubkey;
7
8const TOKEN_LIST_URL: &str = "https://raw.githubusercontent.com/solana-labs/token-list/main/src/tokens/solana.tokenlist.json";
9
10#[derive(Debug, Deserialize)]
11pub struct TokenListWrapper {
12    tokens: Vec<TokenInfo>,
13}
14
15#[derive(Debug, Deserialize_repr)]
16#[repr(u8)]
17pub enum ClusterSlug {
18    MainnetBeta = 101,
19    Testnet = 102,
20    Devnet = 103,
21}
22
23#[derive(Debug, Deserialize)]
24#[serde(rename_all = "camelCase")]
25pub struct TokenInfo {
26    #[serde(rename = "chainId")]
27    pub cluster_slug: ClusterSlug,
28    #[serde(deserialize_with = "deserialize_pubkey")]
29    pub address: Pubkey,
30    pub name: String,
31    pub decimals: u32,
32    pub symbol: String,
33}
34
35#[derive(Debug, Error)]
36pub enum TokenListError {
37    #[error("network error")]
38    Network(#[from] reqwest::Error),
39    #[error("malformed API response")]
40    Deserialize(#[from] serde_json::Error),
41}
42
43pub async fn fetch_token_list() -> Result<Vec<TokenInfo>, TokenListError> {
44    let wrapper = reqwest::get(TOKEN_LIST_URL)
45        .await?
46        .json::<TokenListWrapper>()
47        .await?;
48    Ok(wrapper.tokens)
49}