pragma_common/web3/
chain.rs

1use std::str::FromStr;
2
3use super::{Token, APT, AVAX, BNB, ETH, POL, SOL, SUI, USDC, USDT, WLD, XDAI};
4
5#[derive(Debug, thiserror::Error)]
6pub enum ChainError {
7    #[error("Unknown chain: {0}")]
8    UnknownChain(String),
9}
10
11#[derive(Debug, Copy, Hash, Eq, Clone, PartialEq, PartialOrd, Ord)]
12#[cfg_attr(
13    feature = "serde",
14    derive(serde::Serialize, serde::Deserialize),
15    serde(rename_all = "lowercase")
16)]
17#[cfg_attr(
18    feature = "borsh",
19    derive(borsh::BorshSerialize, borsh::BorshDeserialize)
20)]
21#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
22pub enum Chain {
23    Starknet,
24    Solana,
25    Sui,
26    Aptos,
27    // Evm chains
28    Ethereum,
29    Base,
30    Arbitrum,
31    Optimism,
32    ZkSync,
33    Polygon,
34    Bnb,
35    Avalanche,
36    Gnosis,
37    Worldchain,
38}
39
40impl Chain {
41    pub fn from_chain_id(id: u64) -> Option<Self> {
42        match id {
43            1 => Some(Self::Ethereum),
44            10 => Some(Self::Optimism),
45            137 => Some(Self::Polygon),
46            324 => Some(Self::ZkSync),
47            8453 => Some(Self::Base),
48            42161 => Some(Self::Arbitrum),
49            56 => Some(Self::Bnb),
50            43114 => Some(Self::Avalanche),
51            100 => Some(Self::Gnosis),
52            480 => Some(Self::Worldchain),
53            _ => None,
54        }
55    }
56
57    #[must_use]
58    pub const fn chain_id(&self) -> Option<u64> {
59        match self {
60            Self::Ethereum => Some(1),
61            Self::Optimism => Some(10),
62            Self::Polygon => Some(137),
63            Self::ZkSync => Some(324),
64            Self::Base => Some(8453),
65            Self::Arbitrum => Some(42161),
66            Self::Bnb => Some(56),
67            Self::Avalanche => Some(43114),
68            Self::Gnosis => Some(100),
69            Self::Worldchain => Some(480),
70            _ => None,
71        }
72    }
73
74    pub const fn is_evm(&self) -> bool {
75        matches!(
76            self,
77            Self::Ethereum
78                | Self::Optimism
79                | Self::Polygon
80                | Self::ZkSync
81                | Self::Base
82                | Self::Arbitrum
83                | Self::Bnb
84                | Self::Avalanche
85                | Self::Gnosis
86                | Self::Worldchain
87        )
88    }
89
90    #[must_use]
91    /// Returns the gas token for the chain
92    pub fn gas_token(&self) -> Token {
93        match self {
94            Self::Ethereum
95            | Self::Base
96            | Self::Optimism
97            | Self::Starknet
98            | Self::Arbitrum
99            | Self::ZkSync => ETH(),
100            Self::Solana => SOL(),
101            Self::Sui => SUI(),
102            Self::Aptos => APT(),
103            Self::Polygon => POL(),
104            Self::Bnb => BNB(),
105            Self::Avalanche => AVAX(),
106            Self::Gnosis => XDAI(),
107            Self::Worldchain => WLD(),
108        }
109    }
110
111    /// Returns the main stablecoin for the chain (or None if there is none)
112    pub fn usd_token(&self) -> Token {
113        match self {
114            Self::Polygon | Self::Optimism | Self::Arbitrum | Self::Gnosis | Self::Aptos => USDT(),
115            Self::Ethereum
116            | Self::Base
117            | Self::ZkSync
118            | Self::Bnb
119            | Self::Avalanche
120            | Self::Worldchain
121            | Self::Solana
122            | Self::Starknet
123            | Self::Sui => USDC(),
124        }
125    }
126}
127
128impl std::fmt::Display for Chain {
129    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130        write!(f, "{self:?}")
131    }
132}
133
134impl FromStr for Chain {
135    type Err = ChainError;
136
137    fn from_str(s: &str) -> Result<Self, Self::Err> {
138        match s.to_lowercase().as_str() {
139            "starknet" => Ok(Self::Starknet),
140            "solana" => Ok(Self::Solana),
141            "sui" => Ok(Self::Sui),
142            "aptos" => Ok(Self::Aptos),
143            "ethereum" => Ok(Self::Ethereum),
144            "base" => Ok(Self::Base),
145            "arbitrum" => Ok(Self::Arbitrum),
146            "optimism" => Ok(Self::Optimism),
147            "zksync" => Ok(Self::ZkSync),
148            "polygon" => Ok(Self::Polygon),
149            "bnb" => Ok(Self::Bnb),
150            "avalanche" => Ok(Self::Avalanche),
151            "gnosis" => Ok(Self::Gnosis),
152            "worldchain" => Ok(Self::Worldchain),
153            _ => Err(ChainError::UnknownChain(s.to_string())),
154        }
155    }
156}