solana_commons/
spl_token.rs1use 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}