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 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 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 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}