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(feature = "utoipa", derive(utoipa::ToSchema))]
18pub enum Chain {
19 Starknet,
20 Solana,
21 Sui,
22 Aptos,
23 Ethereum,
25 Base,
26 Arbitrum,
27 Optimism,
28 ZkSync,
29 Polygon,
30 Bnb,
31 Avalanche,
32 Gnosis,
33 Worldchain,
34}
35
36impl Chain {
37 pub fn from_chain_id(id: u64) -> Option<Self> {
38 match id {
39 1 => Some(Self::Ethereum),
40 10 => Some(Self::Optimism),
41 137 => Some(Self::Polygon),
42 324 => Some(Self::ZkSync),
43 8453 => Some(Self::Base),
44 42161 => Some(Self::Arbitrum),
45 56 => Some(Self::Bnb),
46 43114 => Some(Self::Avalanche),
47 100 => Some(Self::Gnosis),
48 480 => Some(Self::Worldchain),
49 _ => None,
50 }
51 }
52
53 #[must_use]
54 pub const fn chain_id(&self) -> Option<u64> {
55 match self {
56 Self::Ethereum => Some(1),
57 Self::Optimism => Some(10),
58 Self::Polygon => Some(137),
59 Self::ZkSync => Some(324),
60 Self::Base => Some(8453),
61 Self::Arbitrum => Some(42161),
62 Self::Bnb => Some(56),
63 Self::Avalanche => Some(43114),
64 Self::Gnosis => Some(100),
65 Self::Worldchain => Some(480),
66 _ => None,
67 }
68 }
69
70 pub const fn is_evm(&self) -> bool {
71 matches!(
72 self,
73 Self::Ethereum
74 | Self::Optimism
75 | Self::Polygon
76 | Self::ZkSync
77 | Self::Base
78 | Self::Arbitrum
79 | Self::Bnb
80 | Self::Avalanche
81 | Self::Gnosis
82 | Self::Worldchain
83 )
84 }
85
86 #[must_use]
87 pub fn gas_token(&self) -> Token {
89 match self {
90 Self::Ethereum
91 | Self::Base
92 | Self::Optimism
93 | Self::Starknet
94 | Self::Arbitrum
95 | Self::ZkSync => ETH(),
96 Self::Solana => SOL(),
97 Self::Sui => SUI(),
98 Self::Aptos => APT(),
99 Self::Polygon => POL(),
100 Self::Bnb => BNB(),
101 Self::Avalanche => AVAX(),
102 Self::Gnosis => XDAI(),
103 Self::Worldchain => WLD(),
104 }
105 }
106
107 pub fn usd_token(&self) -> Token {
109 match self {
110 Self::Polygon | Self::Optimism | Self::Arbitrum | Self::Gnosis | Self::Aptos => USDT(),
111 Self::Ethereum
112 | Self::Base
113 | Self::ZkSync
114 | Self::Bnb
115 | Self::Avalanche
116 | Self::Worldchain
117 | Self::Solana
118 | Self::Starknet
119 | Self::Sui => USDC(),
120 }
121 }
122}
123
124impl std::fmt::Display for Chain {
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 write!(f, "{self:?}")
127 }
128}
129
130impl FromStr for Chain {
131 type Err = ChainError;
132
133 fn from_str(s: &str) -> Result<Self, Self::Err> {
134 match s.to_lowercase().as_str() {
135 "starknet" => Ok(Self::Starknet),
136 "solana" => Ok(Self::Solana),
137 "sui" => Ok(Self::Sui),
138 "aptos" => Ok(Self::Aptos),
139 "ethereum" => Ok(Self::Ethereum),
140 "base" => Ok(Self::Base),
141 "arbitrum" => Ok(Self::Arbitrum),
142 "optimism" => Ok(Self::Optimism),
143 "zksync" => Ok(Self::ZkSync),
144 "polygon" => Ok(Self::Polygon),
145 "bnb" => Ok(Self::Bnb),
146 "avalanche" => Ok(Self::Avalanche),
147 "gnosis" => Ok(Self::Gnosis),
148 "worldchain" => Ok(Self::Worldchain),
149 _ => Err(ChainError::UnknownChain(s.to_string())),
150 }
151 }
152}