alloy_chains/
named.rs

1use alloy_primitives::{Address, address};
2use core::{cmp::Ordering, fmt, time::Duration};
3use num_enum::TryFromPrimitiveError;
4
5#[allow(unused_imports)]
6use alloc::string::String;
7
8// When adding a new chain:
9//   1. add new variant to the NamedChain enum;
10//   2. add extra information in the last `impl` block (explorer URLs, block time) when applicable;
11//   3. (optional) add aliases:
12//     - Strum (in kebab-case): `#[strum(to_string = "<main>", serialize = "<aliasX>", ...)]`
13//      `to_string = "<main>"` must be present and will be used in `Display`, `Serialize`
14//      and `FromStr`, while `serialize = "<aliasX>"` will be appended to `FromStr`.
15//      More info: <https://docs.rs/strum/latest/strum/additional_attributes/index.html#attributes-on-variants>
16//     - Serde (in snake_case): `#[cfg_attr(feature = "serde", serde(alias = "<aliasX>", ...))]`
17//      Aliases are appended to the `Deserialize` implementation.
18//      More info: <https://serde.rs/variant-attrs.html>
19//     - Add a test at the bottom of the file
20//   4. run `cargo test --all-features` to update the JSON bindings and schema.
21//   5. run `cargo +nightly fmt --all` to properly format the code.
22
23// We don't derive Serialize because it is manually implemented using AsRef<str> and it would break
24// a lot of things since Serialize is `kebab-case` vs Deserialize `snake_case`. This means that the
25// NamedChain type is not "round-trippable", because the Serialize and Deserialize implementations
26// do not use the same case style.
27
28/// An Ethereum EIP-155 chain.
29#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
30#[derive(strum::IntoStaticStr)] // Into<&'static str>, AsRef<str>, fmt::Display and serde::Serialize
31#[derive(strum::VariantNames)] // NamedChain::VARIANTS
32#[derive(strum::VariantArray)] // NamedChain::VARIANTS
33#[derive(strum::EnumString)] // FromStr, TryFrom<&str>
34#[derive(strum::EnumIter)] // NamedChain::iter
35#[derive(strum::EnumCount)] // NamedChain::COUNT
36#[derive(num_enum::TryFromPrimitive)] // TryFrom<u64>
37#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
38#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
39#[strum(serialize_all = "kebab-case")]
40#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
41#[repr(u64)]
42#[allow(missing_docs)]
43#[non_exhaustive]
44pub enum NamedChain {
45    #[strum(to_string = "mainnet", serialize = "ethlive")]
46    #[cfg_attr(feature = "serde", serde(alias = "ethlive"))]
47    Mainnet = 1,
48    Morden = 2,
49    Ropsten = 3,
50    Rinkeby = 4,
51    Goerli = 5,
52    Kovan = 42,
53    Holesky = 17000,
54    Hoodi = 560048,
55    Sepolia = 11155111,
56
57    #[cfg_attr(feature = "serde", serde(alias = "odyssey"))]
58    Odyssey = 911867,
59
60    Optimism = 10,
61    #[cfg_attr(feature = "serde", serde(alias = "optimism-kovan"))]
62    OptimismKovan = 69,
63    #[cfg_attr(feature = "serde", serde(alias = "optimism-goerli"))]
64    OptimismGoerli = 420,
65    #[cfg_attr(feature = "serde", serde(alias = "optimism-sepolia"))]
66    OptimismSepolia = 11155420,
67
68    #[strum(to_string = "bob")]
69    #[cfg_attr(feature = "serde", serde(alias = "bob"))]
70    Bob = 60808,
71    #[strum(to_string = "bob-sepolia")]
72    #[cfg_attr(feature = "serde", serde(alias = "bob-sepolia"))]
73    BobSepolia = 808813,
74
75    #[cfg_attr(feature = "serde", serde(alias = "arbitrum_one", alias = "arbitrum-one"))]
76    Arbitrum = 42161,
77    ArbitrumTestnet = 421611,
78    #[cfg_attr(feature = "serde", serde(alias = "arbitrum-goerli"))]
79    ArbitrumGoerli = 421613,
80    #[cfg_attr(feature = "serde", serde(alias = "arbitrum-sepolia"))]
81    ArbitrumSepolia = 421614,
82    #[cfg_attr(feature = "serde", serde(alias = "arbitrum-nova"))]
83    ArbitrumNova = 42170,
84
85    Cronos = 25,
86    CronosTestnet = 338,
87
88    Rsk = 30,
89    RskTestnet = 31,
90
91    #[strum(to_string = "telos")]
92    #[cfg_attr(feature = "serde", serde(alias = "telos", alias = "telos_evm"))]
93    TelosEvm = 40,
94    #[strum(to_string = "telos-testnet")]
95    #[cfg_attr(
96        feature = "serde",
97        serde(alias = "telos_testnet", alias = "telos-evm-testnet", alias = "telos_evm_testnet")
98    )]
99    TelosEvmTestnet = 41,
100
101    #[strum(to_string = "crab")]
102    #[cfg_attr(feature = "serde", serde(alias = "crab"))]
103    Crab = 44,
104    #[strum(to_string = "darwinia")]
105    #[cfg_attr(feature = "serde", serde(alias = "darwinia"))]
106    Darwinia = 46,
107    #[strum(to_string = "koi")]
108    #[cfg_attr(feature = "serde", serde(alias = "koi"))]
109    Koi = 701,
110
111    /// Note the correct name for BSC should be `BNB Smart Chain` due to the rebranding: <https://www.bnbchain.org/en/blog/bsc-is-now-bnb-chain-the-infrastructure-for-the-metafi-universe>
112    /// We keep `Binance Smart Chain` for backward compatibility, and the enum could be renamed in
113    /// the future release.
114    #[strum(to_string = "bsc", serialize = "binance-smart-chain", serialize = "bnb-smart-chain")]
115    #[cfg_attr(
116        feature = "serde",
117        serde(alias = "bsc", alias = "bnb-smart-chain", alias = "binance-smart-chain")
118    )]
119    BinanceSmartChain = 56,
120    #[strum(
121        to_string = "bsc-testnet",
122        serialize = "binance-smart-chain-testnet",
123        serialize = "bnb-smart-chain-testnet"
124    )]
125    #[cfg_attr(
126        feature = "serde",
127        serde(
128            alias = "bsc_testnet",
129            alias = "bsc-testnet",
130            alias = "bnb-smart-chain-testnet",
131            alias = "binance-smart-chain-testnet"
132        )
133    )]
134    BinanceSmartChainTestnet = 97,
135
136    Poa = 99,
137    Sokol = 77,
138
139    Scroll = 534352,
140    #[cfg_attr(
141        feature = "serde",
142        serde(alias = "scroll_sepolia_testnet", alias = "scroll-sepolia")
143    )]
144    ScrollSepolia = 534351,
145
146    Metis = 1088,
147
148    #[cfg_attr(feature = "serde", serde(alias = "conflux-espace-testnet"))]
149    CfxTestnet = 71,
150    #[cfg_attr(feature = "serde", serde(alias = "conflux-espace"))]
151    Cfx = 1030,
152
153    #[strum(to_string = "xdai", serialize = "gnosis", serialize = "gnosis-chain")]
154    #[cfg_attr(feature = "serde", serde(alias = "xdai", alias = "gnosis", alias = "gnosis-chain"))]
155    Gnosis = 100,
156
157    Polygon = 137,
158    #[strum(to_string = "mumbai", serialize = "polygon-mumbai")]
159    #[cfg_attr(feature = "serde", serde(alias = "mumbai", alias = "polygon-mumbai"))]
160    PolygonMumbai = 80001,
161    #[strum(to_string = "amoy", serialize = "polygon-amoy")]
162    #[cfg_attr(feature = "serde", serde(alias = "amoy", alias = "polygon-amoy"))]
163    PolygonAmoy = 80002,
164    #[strum(serialize = "polygon-zkevm", serialize = "zkevm")]
165    #[cfg_attr(
166        feature = "serde",
167        serde(alias = "zkevm", alias = "polygon_zkevm", alias = "polygon-zkevm")
168    )]
169    PolygonZkEvm = 1101,
170    #[strum(serialize = "polygon-zkevm-testnet", serialize = "zkevm-testnet")]
171    #[cfg_attr(
172        feature = "serde",
173        serde(
174            alias = "zkevm-testnet",
175            alias = "polygon_zkevm_testnet",
176            alias = "polygon-zkevm-testnet"
177        )
178    )]
179    PolygonZkEvmTestnet = 1442,
180
181    Fantom = 250,
182    FantomTestnet = 4002,
183
184    Moonbeam = 1284,
185    MoonbeamDev = 1281,
186
187    Moonriver = 1285,
188
189    Moonbase = 1287,
190
191    Dev = 1337,
192    #[strum(to_string = "anvil-hardhat", serialize = "anvil", serialize = "hardhat")]
193    #[cfg_attr(
194        feature = "serde",
195        serde(alias = "anvil", alias = "hardhat", alias = "anvil-hardhat")
196    )]
197    AnvilHardhat = 31337,
198
199    #[strum(to_string = "gravity-alpha-mainnet")]
200    #[cfg_attr(feature = "serde", serde(alias = "gravity-alpha-mainnet"))]
201    GravityAlphaMainnet = 1625,
202    #[strum(to_string = "gravity-alpha-testnet-sepolia")]
203    #[cfg_attr(feature = "serde", serde(alias = "gravity-alpha-testnet-sepolia"))]
204    GravityAlphaTestnetSepolia = 13505,
205
206    Evmos = 9001,
207    EvmosTestnet = 9000,
208
209    Chiado = 10200,
210
211    Oasis = 26863,
212
213    Emerald = 42262,
214    EmeraldTestnet = 42261,
215
216    FilecoinMainnet = 314,
217    FilecoinCalibrationTestnet = 314159,
218
219    Avalanche = 43114,
220    #[strum(to_string = "fuji", serialize = "avalanche-fuji")]
221    #[cfg_attr(feature = "serde", serde(alias = "fuji"))]
222    AvalancheFuji = 43113,
223
224    Celo = 42220,
225    CeloAlfajores = 44787,
226    CeloBaklava = 62320,
227
228    Aurora = 1313161554,
229    AuroraTestnet = 1313161555,
230
231    Canto = 7700,
232    CantoTestnet = 740,
233
234    Boba = 288,
235
236    Base = 8453,
237    #[cfg_attr(feature = "serde", serde(alias = "base-goerli"))]
238    BaseGoerli = 84531,
239    #[cfg_attr(feature = "serde", serde(alias = "base-sepolia"))]
240    BaseSepolia = 84532,
241    #[cfg_attr(feature = "serde", serde(alias = "syndr"))]
242    Syndr = 404,
243    #[cfg_attr(feature = "serde", serde(alias = "syndr-sepolia"))]
244    SyndrSepolia = 444444,
245
246    Shimmer = 148,
247
248    Ink = 57073,
249    #[cfg_attr(feature = "serde", serde(alias = "ink_sepolia_testnet", alias = "ink-sepolia"))]
250    InkSepolia = 763373,
251
252    #[strum(to_string = "fraxtal")]
253    #[cfg_attr(feature = "serde", serde(alias = "fraxtal"))]
254    Fraxtal = 252,
255    #[strum(to_string = "fraxtal-testnet")]
256    #[cfg_attr(feature = "serde", serde(alias = "fraxtal-testnet"))]
257    FraxtalTestnet = 2522,
258
259    Blast = 81457,
260    #[cfg_attr(feature = "serde", serde(alias = "blast-sepolia"))]
261    BlastSepolia = 168587773,
262
263    Linea = 59144,
264    #[cfg_attr(feature = "serde", serde(alias = "linea-goerli"))]
265    LineaGoerli = 59140,
266    #[cfg_attr(feature = "serde", serde(alias = "linea-sepolia"))]
267    LineaSepolia = 59141,
268
269    #[strum(to_string = "zksync")]
270    #[cfg_attr(feature = "serde", serde(alias = "zksync"))]
271    ZkSync = 324,
272    #[strum(to_string = "zksync-testnet")]
273    #[cfg_attr(feature = "serde", serde(alias = "zksync_testnet", alias = "zksync-testnet"))]
274    ZkSyncTestnet = 300,
275
276    #[strum(to_string = "mantle")]
277    #[cfg_attr(feature = "serde", serde(alias = "mantle"))]
278    Mantle = 5000,
279    #[strum(to_string = "mantle-testnet")]
280    #[cfg_attr(feature = "serde", serde(alias = "mantle-testnet"))]
281    MantleTestnet = 5001,
282    #[strum(to_string = "mantle-sepolia")]
283    #[cfg_attr(feature = "serde", serde(alias = "mantle-sepolia"))]
284    MantleSepolia = 5003,
285
286    #[strum(to_string = "xai")]
287    #[cfg_attr(feature = "serde", serde(alias = "xai"))]
288    Xai = 660279,
289    #[strum(to_string = "xai-sepolia")]
290    #[cfg_attr(feature = "serde", serde(alias = "xai-sepolia"))]
291    XaiSepolia = 37714555429,
292
293    #[strum(to_string = "happychain-testnet")]
294    #[cfg_attr(feature = "serde", serde(alias = "happychain-testnet"))]
295    HappychainTestnet = 216,
296
297    Viction = 88,
298
299    Zora = 7777777,
300    #[cfg_attr(feature = "serde", serde(alias = "zora-sepolia"))]
301    ZoraSepolia = 999999999,
302
303    Pgn = 424,
304    #[cfg_attr(feature = "serde", serde(alias = "pgn-sepolia"))]
305    PgnSepolia = 58008,
306
307    Mode = 34443,
308    #[cfg_attr(feature = "serde", serde(alias = "mode-sepolia"))]
309    ModeSepolia = 919,
310
311    Elastos = 20,
312
313    #[cfg_attr(
314        feature = "serde",
315        serde(alias = "kakarot-sepolia", alias = "kakarot-starknet-sepolia")
316    )]
317    KakarotSepolia = 920637907288165,
318
319    #[cfg_attr(feature = "serde", serde(alias = "etherlink"))]
320    Etherlink = 42793,
321
322    #[cfg_attr(feature = "serde", serde(alias = "etherlink-testnet"))]
323    EtherlinkTestnet = 128123,
324
325    Degen = 666666666,
326
327    #[strum(to_string = "opbnb-mainnet")]
328    #[cfg_attr(
329        feature = "serde",
330        serde(rename = "opbnb_mainnet", alias = "opbnb-mainnet", alias = "op-bnb-mainnet")
331    )]
332    OpBNBMainnet = 204,
333    #[strum(to_string = "opbnb-testnet")]
334    #[cfg_attr(
335        feature = "serde",
336        serde(rename = "opbnb_testnet", alias = "opbnb-testnet", alias = "op-bnb-testnet")
337    )]
338    OpBNBTestnet = 5611,
339
340    Ronin = 2020,
341
342    #[cfg_attr(feature = "serde", serde(alias = "ronin-testnet"))]
343    RoninTestnet = 2021,
344
345    Taiko = 167000,
346    #[cfg_attr(feature = "serde", serde(alias = "taiko-hekla"))]
347    TaikoHekla = 167009,
348
349    #[strum(to_string = "autonomys-nova-testnet")]
350    #[cfg_attr(
351        feature = "serde",
352        serde(rename = "autonomys_nova_testnet", alias = "autonomys-nova-testnet")
353    )]
354    AutonomysNovaTestnet = 490000,
355
356    Flare = 14,
357    #[cfg_attr(feature = "serde", serde(alias = "flare-coston2"))]
358    FlareCoston2 = 114,
359
360    #[strum(to_string = "acala")]
361    #[cfg_attr(feature = "serde", serde(alias = "acala"))]
362    Acala = 787,
363    #[strum(to_string = "acala-mandala-testnet")]
364    #[cfg_attr(feature = "serde", serde(alias = "acala-mandala-testnet"))]
365    AcalaMandalaTestnet = 595,
366    #[strum(to_string = "acala-testnet")]
367    #[cfg_attr(feature = "serde", serde(alias = "acala-testnet"))]
368    AcalaTestnet = 597,
369
370    #[strum(to_string = "karura")]
371    #[cfg_attr(feature = "serde", serde(alias = "karura"))]
372    Karura = 686,
373    #[strum(to_string = "karura-testnet")]
374    #[cfg_attr(feature = "serde", serde(alias = "karura-testnet"))]
375    KaruraTestnet = 596,
376    #[strum(to_string = "pulsechain")]
377    #[cfg_attr(feature = "serde", serde(alias = "pulsechain"))]
378    Pulsechain = 369,
379    #[strum(to_string = "pulsechain-testnet")]
380    #[cfg_attr(feature = "serde", serde(alias = "pulsechain-testnet"))]
381    PulsechainTestnet = 943,
382
383    #[strum(to_string = "immutable")]
384    #[cfg_attr(feature = "serde", serde(alias = "immutable"))]
385    Immutable = 13371,
386    #[strum(to_string = "immutable-testnet")]
387    #[cfg_attr(feature = "serde", serde(alias = "immutable-testnet"))]
388    ImmutableTestnet = 13473,
389
390    #[strum(to_string = "soneium")]
391    #[cfg_attr(feature = "serde", serde(alias = "soneium"))]
392    Soneium = 1868,
393
394    #[strum(to_string = "soneium-minato-testnet")]
395    #[cfg_attr(feature = "serde", serde(alias = "soneium-minato-testnet"))]
396    SoneiumMinatoTestnet = 1946,
397
398    #[cfg_attr(feature = "serde", serde(alias = "worldchain"))]
399    World = 480,
400    #[strum(to_string = "world-sepolia")]
401    #[cfg_attr(feature = "serde", serde(alias = "worldchain-sepolia", alias = "world-sepolia"))]
402    WorldSepolia = 4801,
403    Iotex = 4689,
404    Core = 1116,
405    Merlin = 4200,
406    Bitlayer = 200901,
407    Vana = 1480,
408    Zeta = 7000,
409    Kaia = 8217,
410    Story = 1514,
411    Sei = 1329,
412
413    Unichain = 130,
414    #[strum(to_string = "unichain-sepolia")]
415    #[cfg_attr(feature = "serde", serde(alias = "unichain-sepolia"))]
416    UnichainSepolia = 1301,
417
418    #[strum(to_string = "apechain")]
419    #[cfg_attr(feature = "serde", serde(alias = "apechain"))]
420    ApeChain = 33139,
421    #[strum(to_string = "curtis", serialize = "apechain-testnet")]
422    #[cfg_attr(feature = "serde", serde(alias = "apechain-testnet", alias = "curtis"))]
423    Curtis = 33111,
424
425    #[strum(to_string = "sonic-blaze")]
426    #[cfg_attr(feature = "serde", serde(alias = "sonic-blaze"))]
427    SonicBlaze = 57054,
428    #[strum(to_string = "sonic-testnet")]
429    #[cfg_attr(feature = "serde", serde(alias = "sonic-testnet"))]
430    SonicTestnet = 64165,
431    #[strum(to_string = "sonic")]
432    #[cfg_attr(feature = "serde", serde(alias = "sonic"))]
433    Sonic = 146,
434
435    #[strum(to_string = "treasure")]
436    #[cfg_attr(feature = "serde", serde(alias = "treasure"))]
437    Treasure = 61166,
438
439    #[strum(to_string = "treasure-topaz", serialize = "treasure-topaz-testnet")]
440    #[cfg_attr(
441        feature = "serde",
442        serde(alias = "treasure-topaz-testnet", alias = "treasure-topaz")
443    )]
444    TreasureTopaz = 978658,
445
446    #[strum(to_string = "berachain-bepolia", serialize = "berachain-bepolia-testnet")]
447    #[cfg_attr(
448        feature = "serde",
449        serde(alias = "berachain-bepolia-testnet", alias = "berachain-bepolia")
450    )]
451    BerachainBepolia = 80069,
452
453    Berachain = 80094,
454
455    #[strum(to_string = "superposition-testnet")]
456    #[cfg_attr(feature = "serde", serde(alias = "superposition-testnet"))]
457    SuperpositionTestnet = 98985,
458
459    #[strum(to_string = "superposition")]
460    #[cfg_attr(feature = "serde", serde(alias = "superposition"))]
461    Superposition = 55244,
462
463    #[strum(serialize = "monad-testnet")]
464    #[cfg_attr(feature = "serde", serde(alias = "monad-testnet"))]
465    MonadTestnet = 10143,
466
467    #[strum(to_string = "hyperliquid")]
468    #[cfg_attr(feature = "serde", serde(alias = "hyperliquid"))]
469    Hyperliquid = 999,
470
471    #[strum(to_string = "abstract")]
472    #[cfg_attr(feature = "serde", serde(alias = "abstract"))]
473    Abstract = 2741,
474
475    #[strum(to_string = "abstract-testnet")]
476    #[cfg_attr(feature = "serde", serde(alias = "abstract-testnet"))]
477    AbstractTestnet = 11124,
478
479    #[strum(to_string = "corn")]
480    #[cfg_attr(feature = "serde", serde(alias = "corn"))]
481    Corn = 21000000,
482
483    #[strum(to_string = "corn-testnet")]
484    #[cfg_attr(feature = "serde", serde(alias = "corn-testnet"))]
485    CornTestnet = 21000001,
486
487    #[strum(to_string = "sophon")]
488    #[cfg_attr(feature = "serde", serde(alias = "sophon"))]
489    Sophon = 50104,
490
491    #[strum(to_string = "sophon-testnet")]
492    #[cfg_attr(feature = "serde", serde(alias = "sophon-testnet"))]
493    SophonTestnet = 531050104,
494
495    #[strum(to_string = "lens")]
496    #[cfg_attr(feature = "serde", serde(alias = "lens"))]
497    Lens = 232,
498
499    #[strum(to_string = "lens-testnet")]
500    #[cfg_attr(feature = "serde", serde(alias = "lens-testnet"))]
501    LensTestnet = 37111,
502
503    #[strum(to_string = "injective")]
504    #[cfg_attr(feature = "serde", serde(alias = "injective"))]
505    Injective = 1776,
506
507    #[strum(to_string = "injective-testnet")]
508    #[cfg_attr(feature = "serde", serde(alias = "injective-testnet"))]
509    InjectiveTestnet = 1439,
510
511    #[strum(to_string = "katana")]
512    #[cfg_attr(feature = "serde", serde(alias = "katana"))]
513    Katana = 747474,
514
515    #[strum(to_string = "lisk")]
516    #[cfg_attr(feature = "serde", serde(alias = "lisk"))]
517    Lisk = 1135,
518
519    #[strum(to_string = "fuse")]
520    #[cfg_attr(feature = "serde", serde(alias = "fuse"))]
521    Fuse = 122,
522    #[strum(to_string = "fluent-devnet")]
523    #[cfg_attr(feature = "serde", serde(alias = "fluent-devnet"))]
524    FluentDevnet = 20993,
525
526    #[strum(to_string = "fluent-testnet")]
527    #[cfg_attr(feature = "serde", serde(alias = "fluent-testnet"))]
528    FluentTestnet = 20994,
529}
530
531// This must be implemented manually so we avoid a conflict with `TryFromPrimitive` where it treats
532// the `#[default]` attribute as its own `#[num_enum(default)]`
533impl Default for NamedChain {
534    #[inline]
535    fn default() -> Self {
536        Self::Mainnet
537    }
538}
539
540macro_rules! impl_into_numeric {
541    ($($t:ty)+) => {$(
542        impl From<NamedChain> for $t {
543            #[inline]
544            fn from(chain: NamedChain) -> Self {
545                chain as $t
546            }
547        }
548    )+};
549}
550
551impl_into_numeric!(u64 i64 u128 i128);
552#[cfg(target_pointer_width = "64")]
553impl_into_numeric!(usize isize);
554
555macro_rules! impl_try_from_numeric {
556    ($($native:ty)+) => {
557        $(
558            impl TryFrom<$native> for NamedChain {
559                type Error = TryFromPrimitiveError<NamedChain>;
560
561                #[inline]
562                fn try_from(value: $native) -> Result<Self, Self::Error> {
563                    (value as u64).try_into()
564                }
565            }
566        )+
567    };
568}
569
570impl_try_from_numeric!(u8 i8 u16 i16 u32 i32 usize isize);
571
572impl fmt::Display for NamedChain {
573    #[inline]
574    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575        self.as_str().fmt(f)
576    }
577}
578
579impl AsRef<str> for NamedChain {
580    #[inline]
581    fn as_ref(&self) -> &str {
582        self.as_str()
583    }
584}
585
586impl PartialEq<u64> for NamedChain {
587    #[inline]
588    fn eq(&self, other: &u64) -> bool {
589        (*self as u64) == *other
590    }
591}
592
593impl PartialOrd<u64> for NamedChain {
594    #[inline]
595    fn partial_cmp(&self, other: &u64) -> Option<Ordering> {
596        (*self as u64).partial_cmp(other)
597    }
598}
599
600#[cfg(feature = "serde")]
601impl serde::Serialize for NamedChain {
602    #[inline]
603    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
604        s.serialize_str(self.as_ref())
605    }
606}
607
608#[cfg(feature = "rlp")]
609impl alloy_rlp::Encodable for NamedChain {
610    #[inline]
611    fn encode(&self, out: &mut dyn alloy_rlp::BufMut) {
612        (*self as u64).encode(out)
613    }
614
615    #[inline]
616    fn length(&self) -> usize {
617        (*self as u64).length()
618    }
619}
620
621#[cfg(feature = "rlp")]
622impl alloy_rlp::Decodable for NamedChain {
623    #[inline]
624    fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
625        let n = u64::decode(buf)?;
626        Self::try_from(n).map_err(|_| alloy_rlp::Error::Overflow)
627    }
628}
629
630#[cfg(feature = "arbitrary")]
631impl<'a> arbitrary::Arbitrary<'a> for NamedChain {
632    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
633        use strum::{EnumCount, VariantArray};
634        let idx = u.choose_index(NamedChain::COUNT)?;
635        Ok(NamedChain::VARIANTS[idx])
636    }
637}
638
639// NB: all utility functions *should* be explicitly exhaustive (not use `_` matcher) so we don't
640//     forget to update them when adding a new `NamedChain` variant.
641#[allow(clippy::match_like_matches_macro)]
642#[deny(unreachable_patterns, unused_variables)]
643impl NamedChain {
644    /// Returns the string representation of the chain.
645    #[inline]
646    pub fn as_str(&self) -> &'static str {
647        self.into()
648    }
649
650    /// Returns `true` if this chain is Ethereum or an Ethereum testnet.
651    pub const fn is_ethereum(&self) -> bool {
652        use NamedChain::*;
653
654        matches!(self, Mainnet | Morden | Ropsten | Rinkeby | Goerli | Kovan | Holesky | Sepolia)
655    }
656
657    /// Returns true if the chain contains Optimism configuration.
658    pub const fn is_optimism(self) -> bool {
659        use NamedChain::*;
660
661        matches!(
662            self,
663            Optimism
664                | OptimismGoerli
665                | OptimismKovan
666                | OptimismSepolia
667                | Base
668                | BaseGoerli
669                | BaseSepolia
670                | Fraxtal
671                | FraxtalTestnet
672                | Ink
673                | InkSepolia
674                | Mode
675                | ModeSepolia
676                | Pgn
677                | PgnSepolia
678                | Zora
679                | ZoraSepolia
680                | BlastSepolia
681                | OpBNBMainnet
682                | OpBNBTestnet
683                | Soneium
684                | SoneiumMinatoTestnet
685                | Odyssey
686                | World
687                | WorldSepolia
688                | Unichain
689                | UnichainSepolia
690                | HappychainTestnet
691                | Lisk
692                | Celo
693                | Katana
694        )
695    }
696
697    /// Returns true if the chain contains Polygon configuration.
698    pub const fn is_polygon(self) -> bool {
699        use NamedChain::*;
700
701        matches!(self, Polygon | PolygonAmoy | PolygonZkEvm | PolygonMumbai | PolygonZkEvmTestnet)
702    }
703
704    /// Returns true if the chain contains Arbitrum configuration.
705    pub const fn is_arbitrum(self) -> bool {
706        use NamedChain::*;
707
708        matches!(self, Arbitrum | ArbitrumTestnet | ArbitrumGoerli | ArbitrumSepolia | ArbitrumNova)
709    }
710
711    /// Returns true if the chain contains Elastic Network configuration.
712    pub const fn is_elastic(self) -> bool {
713        use NamedChain::*;
714
715        matches!(
716            self,
717            ZkSync
718                | ZkSyncTestnet
719                | Abstract
720                | AbstractTestnet
721                | Sophon
722                | SophonTestnet
723                | Lens
724                | LensTestnet
725        )
726    }
727
728    /// Returns the chain's average blocktime, if applicable.
729    ///
730    /// It can be beneficial to know the average blocktime to adjust the polling of an HTTP provider
731    /// for example.
732    ///
733    /// **Note:** this is not an accurate average, but is rather a sensible default derived from
734    /// blocktime charts such as [Etherscan's](https://etherscan.com/chart/blocktime)
735    /// or [Polygonscan's](https://polygonscan.com/chart/blocktime).
736    ///
737    /// # Examples
738    ///
739    /// ```
740    /// use alloy_chains::NamedChain;
741    /// use std::time::Duration;
742    ///
743    /// assert_eq!(NamedChain::Mainnet.average_blocktime_hint(), Some(Duration::from_millis(12_000)),);
744    /// assert_eq!(NamedChain::Optimism.average_blocktime_hint(), Some(Duration::from_millis(2_000)),);
745    /// ```
746    pub const fn average_blocktime_hint(self) -> Option<Duration> {
747        use NamedChain::*;
748
749        Some(Duration::from_millis(match self {
750            Mainnet | Taiko | TaikoHekla => 12_000,
751
752            Arbitrum
753            | ArbitrumTestnet
754            | ArbitrumGoerli
755            | ArbitrumSepolia
756            | GravityAlphaMainnet
757            | GravityAlphaTestnetSepolia
758            | Xai
759            | XaiSepolia
760            | Syndr
761            | SyndrSepolia
762            | ArbitrumNova
763            | ApeChain
764            | Curtis
765            | SuperpositionTestnet
766            | Superposition => 260,
767
768            Optimism | OptimismGoerli | OptimismSepolia | Base | BaseGoerli | BaseSepolia
769            | Blast | BlastSepolia | Fraxtal | FraxtalTestnet | Zora | ZoraSepolia | Mantle
770            | MantleSepolia | Mode | ModeSepolia | Pgn | PgnSepolia | HappychainTestnet
771            | Soneium | SoneiumMinatoTestnet | Bob | BobSepolia => 2_000,
772
773            Ink | InkSepolia | Odyssey => 1_000,
774
775            Viction => 2_000,
776
777            Polygon | PolygonMumbai | PolygonAmoy => 2_100,
778
779            Acala | AcalaMandalaTestnet | AcalaTestnet | Karura | KaruraTestnet | Moonbeam
780            | Moonriver => 12_500,
781
782            BinanceSmartChain | BinanceSmartChainTestnet => 750,
783
784            Avalanche | AvalancheFuji => 2_000,
785
786            Fantom | FantomTestnet => 1_200,
787
788            Cronos | CronosTestnet | Canto | CantoTestnet => 5_700,
789
790            Evmos | EvmosTestnet => 1_900,
791
792            Aurora | AuroraTestnet => 1_100,
793
794            Oasis => 5_500,
795
796            Emerald | Darwinia | Crab | Koi => 6_000,
797
798            Dev | AnvilHardhat => 200,
799
800            Celo | CeloAlfajores | CeloBaklava => 5_000,
801
802            FilecoinCalibrationTestnet | FilecoinMainnet => 30_000,
803
804            Scroll | ScrollSepolia => 3_000,
805
806            Shimmer => 5_000,
807
808            Gnosis | Chiado => 5_000,
809
810            Elastos => 5_000,
811
812            Etherlink => 5_000,
813
814            EtherlinkTestnet => 5_000,
815
816            Degen => 600,
817
818            Cfx | CfxTestnet => 500,
819
820            OpBNBMainnet | OpBNBTestnet | AutonomysNovaTestnet => 1_000,
821
822            Ronin | RoninTestnet => 3_000,
823
824            Flare => 1_800,
825
826            FlareCoston2 => 2_500,
827
828            Pulsechain => 10000,
829            PulsechainTestnet => 10101,
830
831            Immutable | ImmutableTestnet => 2_000,
832
833            World | WorldSepolia => 2_000,
834
835            Iotex => 5_000,
836            Core => 3_000,
837            Merlin => 3_000,
838            Bitlayer => 3_000,
839            Vana => 6_000,
840            Zeta => 6_000,
841            Kaia => 1_000,
842            Story => 2_500,
843            Sei => 500,
844
845            Sonic => 1_000,
846
847            TelosEvm | TelosEvmTestnet => 500,
848
849            UnichainSepolia | Unichain => 1_000,
850
851            BerachainBepolia | Berachain => 2_000,
852
853            MonadTestnet => 500,
854
855            Hyperliquid => 2_000,
856
857            Abstract | AbstractTestnet => 1_000,
858            ZkSync | ZkSyncTestnet => 1_000,
859            Sophon | SophonTestnet => 1_000,
860            Lens | LensTestnet => 1_000,
861            Rsk | RskTestnet => 25_000,
862            Injective | InjectiveTestnet => 700,
863            Katana => 1_000,
864            Lisk => 2_000,
865            Fuse => 5_000,
866            FluentDevnet => 3_000,
867            FluentTestnet => 1_000,
868
869            Morden | Ropsten | Rinkeby | Goerli | Kovan | Sepolia | Holesky | Hoodi
870            | MantleTestnet | Moonbase | MoonbeamDev | OptimismKovan | Poa | Sokol
871            | EmeraldTestnet | Boba | PolygonZkEvm | PolygonZkEvmTestnet | Metis | Linea
872            | LineaGoerli | LineaSepolia | KakarotSepolia | SonicBlaze | SonicTestnet
873            | Treasure | TreasureTopaz | Corn | CornTestnet => return None,
874        }))
875    }
876
877    /// Returns whether the chain implements EIP-1559 (with the type 2 EIP-2718 transaction type).
878    ///
879    /// # Examples
880    ///
881    /// ```
882    /// use alloy_chains::NamedChain;
883    ///
884    /// assert!(!NamedChain::Mainnet.is_legacy());
885    /// assert!(NamedChain::Fantom.is_legacy());
886    /// ```
887    pub const fn is_legacy(self) -> bool {
888        use NamedChain::*;
889
890        match self {
891            // Known legacy chains / non EIP-1559 compliant.
892            CeloAlfajores | CeloBaklava | Elastos | Emerald | EmeraldTestnet | Fantom
893            | FantomTestnet | MantleTestnet | OptimismKovan | PolygonZkEvm
894            | PolygonZkEvmTestnet | Ronin | RoninTestnet | Rsk | RskTestnet | Shimmer
895            | Treasure | TreasureTopaz | Viction | Sophon | SophonTestnet => true,
896
897            // Known EIP-1559 chains.
898            Mainnet
899            | Goerli
900            | Sepolia
901            | Holesky
902            | Hoodi
903            | Odyssey
904            | Acala
905            | AcalaMandalaTestnet
906            | AcalaTestnet
907            | ArbitrumTestnet
908            | Base
909            | BaseGoerli
910            | BaseSepolia
911            | Boba
912            | Metis
913            | Oasis
914            | Blast
915            | BlastSepolia
916            | Celo
917            | Fraxtal
918            | FraxtalTestnet
919            | Optimism
920            | OptimismGoerli
921            | OptimismSepolia
922            | Bob
923            | BobSepolia
924            | Polygon
925            | PolygonMumbai
926            | PolygonAmoy
927            | Avalanche
928            | AvalancheFuji
929            | Arbitrum
930            | ArbitrumGoerli
931            | ArbitrumSepolia
932            | ArbitrumNova
933            | GravityAlphaMainnet
934            | GravityAlphaTestnetSepolia
935            | Xai
936            | XaiSepolia
937            | HappychainTestnet
938            | Syndr
939            | SyndrSepolia
940            | FilecoinMainnet
941            | Linea
942            | LineaGoerli
943            | LineaSepolia
944            | FilecoinCalibrationTestnet
945            | Gnosis
946            | Chiado
947            | Zora
948            | ZoraSepolia
949            | Ink
950            | InkSepolia
951            | Mantle
952            | MantleSepolia
953            | Mode
954            | ModeSepolia
955            | Pgn
956            | PgnSepolia
957            | KakarotSepolia
958            | Etherlink
959            | EtherlinkTestnet
960            | Degen
961            | OpBNBMainnet
962            | OpBNBTestnet
963            | Taiko
964            | TaikoHekla
965            | AutonomysNovaTestnet
966            | Flare
967            | FlareCoston2
968            | Scroll
969            | ScrollSepolia
970            | Darwinia
971            | Cfx
972            | CfxTestnet
973            | Crab
974            | Pulsechain
975            | PulsechainTestnet
976            | Koi
977            | Immutable
978            | ImmutableTestnet
979            | Soneium
980            | SoneiumMinatoTestnet
981            | Sonic
982            | World
983            | WorldSepolia
984            | Unichain
985            | UnichainSepolia
986            | ApeChain
987            | BerachainBepolia
988            | Berachain
989            | Curtis
990            | SuperpositionTestnet
991            | Superposition
992            | MonadTestnet
993            | Hyperliquid
994            | Corn
995            | CornTestnet
996            | ZkSync
997            | ZkSyncTestnet
998            | AbstractTestnet
999            | Abstract
1000            | Lens
1001            | LensTestnet
1002            | BinanceSmartChain
1003            | BinanceSmartChainTestnet
1004            | Karura
1005            | KaruraTestnet
1006            | TelosEvm
1007            | TelosEvmTestnet
1008            | FluentDevnet
1009            | FluentTestnet => false,
1010
1011            // Unknown / not applicable, default to false for backwards compatibility.
1012            Dev | AnvilHardhat | Morden | Ropsten | Rinkeby | Cronos | CronosTestnet | Kovan
1013            | Sokol | Poa | Moonbeam | MoonbeamDev | Moonriver | Moonbase | Evmos
1014            | EvmosTestnet | Aurora | AuroraTestnet | Canto | CantoTestnet | Iotex | Core
1015            | Merlin | Bitlayer | SonicBlaze | SonicTestnet | Vana | Zeta | Kaia | Story | Sei
1016            | Injective | InjectiveTestnet | Katana | Lisk | Fuse => false,
1017        }
1018    }
1019
1020    /// Returns whether the chain supports the [Shanghai hardfork][ref].
1021    ///
1022    /// [ref]: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md
1023    pub const fn supports_shanghai(self) -> bool {
1024        use NamedChain::*;
1025
1026        matches!(
1027            self,
1028            Mainnet
1029                | Goerli
1030                | Sepolia
1031                | Holesky
1032                | Hoodi
1033                | AnvilHardhat
1034                | Optimism
1035                | OptimismGoerli
1036                | OptimismSepolia
1037                | Bob
1038                | BobSepolia
1039                | Odyssey
1040                | Base
1041                | BaseGoerli
1042                | BaseSepolia
1043                | Blast
1044                | BlastSepolia
1045                | Fraxtal
1046                | FraxtalTestnet
1047                | Ink
1048                | InkSepolia
1049                | Gnosis
1050                | Chiado
1051                | ZoraSepolia
1052                | Mantle
1053                | MantleSepolia
1054                | Mode
1055                | ModeSepolia
1056                | PolygonMumbai
1057                | Polygon
1058                | Arbitrum
1059                | ArbitrumNova
1060                | ArbitrumSepolia
1061                | GravityAlphaMainnet
1062                | GravityAlphaTestnetSepolia
1063                | Xai
1064                | XaiSepolia
1065                | Syndr
1066                | SyndrSepolia
1067                | Etherlink
1068                | EtherlinkTestnet
1069                | Scroll
1070                | ScrollSepolia
1071                | HappychainTestnet
1072                | Shimmer
1073                | BinanceSmartChain
1074                | BinanceSmartChainTestnet
1075                | OpBNBMainnet
1076                | OpBNBTestnet
1077                | KakarotSepolia
1078                | Taiko
1079                | TaikoHekla
1080                | Avalanche
1081                | AvalancheFuji
1082                | AutonomysNovaTestnet
1083                | Acala
1084                | AcalaMandalaTestnet
1085                | AcalaTestnet
1086                | Karura
1087                | KaruraTestnet
1088                | Darwinia
1089                | Crab
1090                | Cfx
1091                | CfxTestnet
1092                | Pulsechain
1093                | PulsechainTestnet
1094                | Koi
1095                | Immutable
1096                | ImmutableTestnet
1097                | Soneium
1098                | SoneiumMinatoTestnet
1099                | World
1100                | WorldSepolia
1101                | Iotex
1102                | Unichain
1103                | UnichainSepolia
1104                | ApeChain
1105                | Curtis
1106                | SuperpositionTestnet
1107                | Superposition
1108                | MonadTestnet
1109                | Corn
1110                | CornTestnet
1111                | Rsk
1112                | RskTestnet
1113                | Berachain
1114                | BerachainBepolia
1115                | Injective
1116                | InjectiveTestnet
1117                | FluentDevnet
1118                | FluentTestnet
1119        )
1120    }
1121
1122    #[doc(hidden)]
1123    #[deprecated(since = "0.1.3", note = "use `supports_shanghai` instead")]
1124    pub const fn supports_push0(self) -> bool {
1125        self.supports_shanghai()
1126    }
1127
1128    /// Returns whether the chain is a testnet.
1129    pub const fn is_testnet(self) -> bool {
1130        use NamedChain::*;
1131
1132        match self {
1133            // Ethereum testnets.
1134            Goerli | Holesky | Kovan | Sepolia | Morden | Ropsten | Rinkeby | Hoodi => true,
1135
1136            // Other testnets.
1137            ArbitrumGoerli
1138            | ArbitrumSepolia
1139            | ArbitrumTestnet
1140            | SyndrSepolia
1141            | AuroraTestnet
1142            | AvalancheFuji
1143            | Odyssey
1144            | BaseGoerli
1145            | BaseSepolia
1146            | BlastSepolia
1147            | BinanceSmartChainTestnet
1148            | CantoTestnet
1149            | CronosTestnet
1150            | CeloAlfajores
1151            | CeloBaklava
1152            | EmeraldTestnet
1153            | EvmosTestnet
1154            | FantomTestnet
1155            | FilecoinCalibrationTestnet
1156            | FraxtalTestnet
1157            | HappychainTestnet
1158            | LineaGoerli
1159            | LineaSepolia
1160            | InkSepolia
1161            | MantleTestnet
1162            | MantleSepolia
1163            | MoonbeamDev
1164            | OptimismGoerli
1165            | OptimismKovan
1166            | OptimismSepolia
1167            | BobSepolia
1168            | PolygonMumbai
1169            | PolygonAmoy
1170            | PolygonZkEvmTestnet
1171            | ScrollSepolia
1172            | Shimmer
1173            | ZkSyncTestnet
1174            | ZoraSepolia
1175            | ModeSepolia
1176            | PgnSepolia
1177            | KakarotSepolia
1178            | EtherlinkTestnet
1179            | OpBNBTestnet
1180            | RoninTestnet
1181            | TaikoHekla
1182            | AutonomysNovaTestnet
1183            | FlareCoston2
1184            | AcalaMandalaTestnet
1185            | AcalaTestnet
1186            | KaruraTestnet
1187            | CfxTestnet
1188            | PulsechainTestnet
1189            | GravityAlphaTestnetSepolia
1190            | XaiSepolia
1191            | Koi
1192            | ImmutableTestnet
1193            | SoneiumMinatoTestnet
1194            | WorldSepolia
1195            | UnichainSepolia
1196            | Curtis
1197            | TreasureTopaz
1198            | SonicBlaze
1199            | SonicTestnet
1200            | BerachainBepolia
1201            | SuperpositionTestnet
1202            | MonadTestnet
1203            | RskTestnet
1204            | TelosEvmTestnet
1205            | AbstractTestnet
1206            | LensTestnet
1207            | SophonTestnet
1208            | InjectiveTestnet
1209            | FluentDevnet
1210            | FluentTestnet
1211            | CornTestnet => true,
1212
1213            // Dev chains.
1214            Dev | AnvilHardhat => true,
1215
1216            // Mainnets.
1217            Mainnet | Optimism | Arbitrum | ArbitrumNova | Blast | Syndr | Cronos | Rsk
1218            | BinanceSmartChain | Poa | Sokol | Scroll | Metis | Gnosis | Polygon
1219            | PolygonZkEvm | Fantom | Moonbeam | Moonriver | Moonbase | Evmos | Chiado | Oasis
1220            | Emerald | FilecoinMainnet | Avalanche | Celo | Aurora | Canto | Boba | Base
1221            | Fraxtal | Ink | Linea | ZkSync | Mantle | GravityAlphaMainnet | Xai | Zora | Pgn
1222            | Mode | Viction | Elastos | Degen | OpBNBMainnet | Ronin | Taiko | Flare | Acala
1223            | Karura | Darwinia | Cfx | Crab | Pulsechain | Etherlink | Immutable | World
1224            | Iotex | Core | Merlin | Bitlayer | ApeChain | Vana | Zeta | Kaia | Treasure | Bob
1225            | Soneium | Sonic | Superposition | Berachain | Unichain | TelosEvm | Story | Sei
1226            | Hyperliquid | Abstract | Sophon | Lens | Corn | Katana | Lisk | Fuse | Injective => {
1227                false
1228            }
1229        }
1230    }
1231
1232    /// Returns the symbol of the chain's native currency.
1233    pub const fn native_currency_symbol(self) -> Option<&'static str> {
1234        use NamedChain::*;
1235
1236        Some(match self {
1237            Mainnet | Goerli | Holesky | Kovan | Sepolia | Morden | Ropsten | Rinkeby | Scroll
1238            | ScrollSepolia | Taiko | TaikoHekla | Unichain | UnichainSepolia
1239            | SuperpositionTestnet | Superposition | Abstract | ZkSync | ZkSyncTestnet | Katana
1240            | Lisk => "ETH",
1241
1242            Mantle | MantleSepolia => "MNT",
1243
1244            GravityAlphaMainnet | GravityAlphaTestnetSepolia => "G",
1245
1246            Xai | XaiSepolia => "XAI",
1247
1248            HappychainTestnet => "HAPPY",
1249
1250            BinanceSmartChain | BinanceSmartChainTestnet | OpBNBMainnet | OpBNBTestnet => "BNB",
1251
1252            Etherlink | EtherlinkTestnet => "XTZ",
1253
1254            Degen => "DEGEN",
1255
1256            Ronin | RoninTestnet => "RON",
1257
1258            Shimmer => "SMR",
1259
1260            Flare => "FLR",
1261
1262            FlareCoston2 => "C2FLR",
1263
1264            Darwinia => "RING",
1265
1266            Crab => "CRAB",
1267
1268            Koi => "KRING",
1269
1270            Cfx | CfxTestnet => "CFX",
1271            Pulsechain | PulsechainTestnet => "PLS",
1272
1273            Immutable => "IMX",
1274            ImmutableTestnet => "tIMX",
1275
1276            World | WorldSepolia => "WRLD",
1277
1278            Iotex => "IOTX",
1279            Core => "CORE",
1280            Merlin => "BTC",
1281            Bitlayer => "BTC",
1282            Vana => "VANA",
1283            Zeta => "ZETA",
1284            Kaia => "KAIA",
1285            Story => "IP",
1286            Sei => "SEI",
1287            ApeChain | Curtis => "APE",
1288
1289            Treasure | TreasureTopaz => "MAGIC",
1290
1291            BerachainBepolia | Berachain => "BERA",
1292
1293            Sonic | SonicBlaze => "S",
1294
1295            TelosEvm | TelosEvmTestnet => "TLOS",
1296
1297            Hyperliquid => "HYPE",
1298
1299            Polygon | PolygonMumbai | PolygonZkEvm | PolygonZkEvmTestnet | PolygonAmoy => "POL",
1300
1301            Corn | CornTestnet => "BTCN",
1302
1303            Sophon | SophonTestnet => "SOPH",
1304
1305            LensTestnet => "GRASS",
1306            Lens => "GHO",
1307
1308            Rsk => "RBTC",
1309            RskTestnet => "tRBTC",
1310
1311            Injective => "INJ",
1312            InjectiveTestnet => "INJ",
1313
1314            _ => return None,
1315        })
1316    }
1317
1318    /// Returns the chain's blockchain explorer and its API (Etherscan and Etherscan-like) URLs.
1319    ///
1320    /// Returns `(API_URL, BASE_URL)`.
1321    ///
1322    /// All URLs have no trailing `/`
1323    ///
1324    /// # Examples
1325    ///
1326    /// ```
1327    /// use alloy_chains::NamedChain;
1328    ///
1329    /// assert_eq!(
1330    ///     NamedChain::Mainnet.etherscan_urls(),
1331    ///     Some(("https://api.etherscan.io/v2/api?chainid=1", "https://etherscan.io"))
1332    /// );
1333    /// assert_eq!(
1334    ///     NamedChain::Avalanche.etherscan_urls(),
1335    ///     Some(("https://api.etherscan.io/v2/api?chainid=43114", "https://snowtrace.io"))
1336    /// );
1337    /// assert_eq!(NamedChain::AnvilHardhat.etherscan_urls(), None);
1338    /// ```
1339    pub const fn etherscan_urls(self) -> Option<(&'static str, &'static str)> {
1340        use NamedChain::*;
1341
1342        Some(match self {
1343            Mainnet => ("https://api.etherscan.io/v2/api?chainid=1", "https://etherscan.io"),
1344            Ropsten => ("https://api-ropsten.etherscan.io/api", "https://ropsten.etherscan.io"),
1345            Kovan => ("https://api-kovan.etherscan.io/api", "https://kovan.etherscan.io"),
1346            Rinkeby => ("https://api-rinkeby.etherscan.io/api", "https://rinkeby.etherscan.io"),
1347            Goerli => ("https://api-goerli.etherscan.io/api", "https://goerli.etherscan.io"),
1348            Sepolia => {
1349                ("https://api.etherscan.io/v2/api?chainid=11155111", "https://sepolia.etherscan.io")
1350            }
1351            Holesky => {
1352                ("https://api.etherscan.io/v2/api?chainid=17000", "https://holesky.etherscan.io")
1353            }
1354            Hoodi => {
1355                ("https://api.etherscan.io/v2/api?chainid=560048", "https://hoodi.etherscan.io")
1356            }
1357
1358            Polygon => ("https://api.etherscan.io/v2/api?chainid=137", "https://polygonscan.com"),
1359            PolygonMumbai => {
1360                ("https://api-testnet.polygonscan.com/api", "https://mumbai.polygonscan.com")
1361            }
1362            PolygonAmoy => {
1363                ("https://api.etherscan.io/v2/api?chainid=80002", "https://amoy.polygonscan.com")
1364            }
1365
1366            PolygonZkEvm => {
1367                ("https://api.etherscan.io/v2/api?chainid=1101", "https://zkevm.polygonscan.com")
1368            }
1369            PolygonZkEvmTestnet => (
1370                "https://api-testnet-zkevm.polygonscan.com/api",
1371                "https://testnet-zkevm.polygonscan.com",
1372            ),
1373
1374            Avalanche => ("https://api.etherscan.io/v2/api?chainid=43114", "https://snowtrace.io"),
1375            AvalancheFuji => {
1376                ("https://api.etherscan.io/v2/api?chainid=43113", "https://testnet.snowtrace.io")
1377            }
1378
1379            Optimism => {
1380                ("https://api.etherscan.io/v2/api?chainid=10", "https://optimistic.etherscan.io")
1381            }
1382            OptimismGoerli => (
1383                "https://api-goerli-optimistic.etherscan.io/api",
1384                "https://goerli-optimism.etherscan.io",
1385            ),
1386            OptimismKovan => (
1387                "https://api-kovan-optimistic.etherscan.io/api",
1388                "https://kovan-optimistic.etherscan.io",
1389            ),
1390            OptimismSepolia => (
1391                "https://api.etherscan.io/v2/api?chainid=11155420",
1392                "https://sepolia-optimism.etherscan.io",
1393            ),
1394
1395            Bob => ("https://explorer.gobob.xyz/api", "https://explorer.gobob.xyz"),
1396            BobSepolia => (
1397                "https://bob-sepolia.explorer.gobob.xyz/api",
1398                "https://bob-sepolia.explorer.gobob.xyz",
1399            ),
1400
1401            Fantom => ("https://api.ftmscan.com/api", "https://ftmscan.com"),
1402            FantomTestnet => ("https://api-testnet.ftmscan.com/api", "https://testnet.ftmscan.com"),
1403
1404            BinanceSmartChain => {
1405                ("https://api.etherscan.io/v2/api?chainid=52", "https://bscscan.com")
1406            }
1407            BinanceSmartChainTestnet => {
1408                ("https://api.etherscan.io/v2/api?chainid=97", "https://testnet.bscscan.com")
1409            }
1410
1411            OpBNBMainnet => {
1412                ("https://api.etherscan.io/v2/api?chainid=204", "https://opbnb.bscscan.com")
1413            }
1414            OpBNBTestnet => (
1415                "https://api.etherscan.io/v2/api?chainid=5611",
1416                "https://opbnb-testnet.bscscan.com",
1417            ),
1418
1419            Arbitrum => ("https://api.etherscan.io/v2/api?chainid=42161", "https://arbiscan.io"),
1420            ArbitrumTestnet => {
1421                ("https://api-testnet.arbiscan.io/api", "https://testnet.arbiscan.io")
1422            }
1423            ArbitrumGoerli => ("https://api-goerli.arbiscan.io/api", "https://goerli.arbiscan.io"),
1424            ArbitrumSepolia => {
1425                ("https://api.etherscan.io/v2/api?chainid=421614", "https://sepolia.arbiscan.io")
1426            }
1427            ArbitrumNova => {
1428                ("https://api.etherscan.io/v2/api?chainid=42170", "https://nova.arbiscan.io")
1429            }
1430
1431            GravityAlphaMainnet => {
1432                ("https://explorer.gravity.xyz/api", "https://explorer.gravity.xyz")
1433            }
1434            GravityAlphaTestnetSepolia => {
1435                ("https://explorer-sepolia.gravity.xyz/api", "https://explorer-sepolia.gravity.xyz")
1436            }
1437            HappychainTestnet => {
1438                ("https://explorer.testnet.happy.tech/api", "https://explorer.testnet.happy.tech")
1439            }
1440
1441            XaiSepolia => (
1442                "https://api.etherscan.io/v2/api?chainid=37714555429",
1443                "https://sepolia.xaiscan.io",
1444            ),
1445            Xai => ("https://api.etherscan.io/v2/api?chainid=660279", "https://xaiscan.io"),
1446
1447            Syndr => ("https://explorer.syndr.com/api", "https://explorer.syndr.com"),
1448            SyndrSepolia => {
1449                ("https://sepolia-explorer.syndr.com/api", "https://sepolia-explorer.syndr.com")
1450            }
1451
1452            Cronos => ("https://api.etherscan.io/v2/api?chainid=25", "https://cronoscan.com"),
1453            CronosTestnet => {
1454                ("https://api-testnet.cronoscan.com/api", "https://testnet.cronoscan.com")
1455            }
1456
1457            Moonbeam => {
1458                ("https://api.etherscan.io/v2/api?chainid=1284", "https://moonbeam.moonscan.io")
1459            }
1460            Moonbase => {
1461                ("https://api.etherscan.io/v2/api?chainid=1287", "https://moonbase.moonscan.io")
1462            }
1463            Moonriver => {
1464                ("https://api.etherscan.io/v2/api?chainid=1285", "https://moonriver.moonscan.io")
1465            }
1466
1467            Gnosis => ("https://api.etherscan.io/v2/api?chainid=100", "https://gnosisscan.io"),
1468
1469            Scroll => ("https://api.etherscan.io/v2/api?chainid=534352", "https://scrollscan.com"),
1470            ScrollSepolia => {
1471                ("https://api.etherscan.io/v2/api?chainid=534351", "https://sepolia.scrollscan.com")
1472            }
1473
1474            Ink => ("https://explorer.inkonchain.com/api/v2", "https://explorer.inkonchain.com"),
1475            InkSepolia => (
1476                "https://explorer-sepolia.inkonchain.com/api/v2",
1477                "https://explorer-sepolia.inkonchain.com",
1478            ),
1479
1480            Shimmer => {
1481                ("https://explorer.evm.shimmer.network/api", "https://explorer.evm.shimmer.network")
1482            }
1483
1484            Metis => (
1485                "https://api.routescan.io/v2/network/mainnet/evm/1088/etherscan",
1486                "https://explorer.metis.io",
1487            ),
1488
1489            Chiado => {
1490                ("https://blockscout.chiadochain.net/api", "https://blockscout.chiadochain.net")
1491            }
1492
1493            FilecoinCalibrationTestnet => (
1494                "https://api.calibration.node.glif.io/rpc/v1",
1495                "https://calibration.filfox.info/en",
1496            ),
1497
1498            Sokol => ("https://blockscout.com/poa/sokol/api", "https://blockscout.com/poa/sokol"),
1499
1500            Poa => ("https://blockscout.com/poa/core/api", "https://blockscout.com/poa/core"),
1501
1502            Rsk => ("https://blockscout.com/rsk/mainnet/api", "https://blockscout.com/rsk/mainnet"),
1503            RskTestnet => (
1504                "https://rootstock-testnet.blockscout.com/api",
1505                "https://rootstock-testnet.blockscout.com",
1506            ),
1507
1508            Oasis => ("https://scan.oasischain.io/api", "https://scan.oasischain.io"),
1509
1510            Emerald => {
1511                ("https://explorer.emerald.oasis.dev/api", "https://explorer.emerald.oasis.dev")
1512            }
1513            EmeraldTestnet => (
1514                "https://testnet.explorer.emerald.oasis.dev/api",
1515                "https://testnet.explorer.emerald.oasis.dev",
1516            ),
1517
1518            Aurora => ("https://api.aurorascan.dev/api", "https://aurorascan.dev"),
1519            AuroraTestnet => {
1520                ("https://testnet.aurorascan.dev/api", "https://testnet.aurorascan.dev")
1521            }
1522
1523            Evmos => ("https://evm.evmos.org/api", "https://evm.evmos.org"),
1524            EvmosTestnet => ("https://evm.evmos.dev/api", "https://evm.evmos.dev"),
1525
1526            Celo => ("https://api.etherscan.io/v2/api?chainid=42220", "https://celoscan.io"),
1527            CeloAlfajores => {
1528                ("https://api.etherscan.io/v2/api?chainid=44787", "https://alfajores.celoscan.io")
1529            }
1530            CeloBaklava => {
1531                ("https://explorer.celo.org/baklava/api", "https://explorer.celo.org/baklava")
1532            }
1533
1534            Canto => ("https://evm.explorer.canto.io/api", "https://evm.explorer.canto.io"),
1535            CantoTestnet => (
1536                "https://testnet-explorer.canto.neobase.one/api",
1537                "https://testnet-explorer.canto.neobase.one",
1538            ),
1539
1540            Boba => ("https://api.bobascan.com/api", "https://bobascan.com"),
1541
1542            Base => ("https://api.etherscan.io/v2/api?chainid=8453", "https://basescan.org"),
1543            BaseGoerli => ("https://api-goerli.basescan.org/api", "https://goerli.basescan.org"),
1544            BaseSepolia => {
1545                ("https://api.etherscan.io/v2/api?chainid=84532", "https://sepolia.basescan.org")
1546            }
1547
1548            Fraxtal => ("https://api.etherscan.io/v2/api?chainid=252", "https://fraxscan.com"),
1549            FraxtalTestnet => {
1550                ("https://api.etherscan.io/v2/api?chainid=2522", "https://holesky.fraxscan.com")
1551            }
1552
1553            Blast => ("https://api.etherscan.io/v2/api?chainid=81457", "https://blastscan.io"),
1554            BlastSepolia => (
1555                "https://api.etherscan.io/v2/api?chainid=168587773",
1556                "https://sepolia.blastscan.io",
1557            ),
1558
1559            ZkSync => ("https://api.etherscan.io/v2/api?chainid=324", "https://era.zksync.network"),
1560            ZkSyncTestnet => (
1561                "https://api.etherscan.io/v2/api?chainid=300",
1562                "https://sepolia-era.zksync.network",
1563            ),
1564
1565            Linea => ("https://api.etherscan.io/v2/api?chainid=59144", "https://lineascan.build"),
1566            LineaGoerli => {
1567                ("https://explorer.goerli.linea.build/api", "https://explorer.goerli.linea.build")
1568            }
1569            LineaSepolia => {
1570                ("https://api.etherscan.io/v2/api?chainid=59141", "https://sepolia.lineascan.build")
1571            }
1572
1573            Mantle => {
1574                ("https://api.etherscan.io/v2/api?chainid=5000", "https://explorer.mantle.xyz")
1575            }
1576            MantleTestnet => {
1577                ("https://explorer.testnet.mantle.xyz/api", "https://explorer.testnet.mantle.xyz")
1578            }
1579            MantleSepolia => (
1580                "https://api.etherscan.io/v2/api?chainid=5003",
1581                "https://explorer.sepolia.mantle.xyz",
1582            ),
1583
1584            Viction => ("https://www.vicscan.xyz/api", "https://www.vicscan.xyz"),
1585
1586            Zora => ("https://explorer.zora.energy/api", "https://explorer.zora.energy"),
1587            ZoraSepolia => {
1588                ("https://sepolia.explorer.zora.energy/api", "https://sepolia.explorer.zora.energy")
1589            }
1590
1591            Pgn => {
1592                ("https://explorer.publicgoods.network/api", "https://explorer.publicgoods.network")
1593            }
1594
1595            PgnSepolia => (
1596                "https://explorer.sepolia.publicgoods.network/api",
1597                "https://explorer.sepolia.publicgoods.network",
1598            ),
1599
1600            Mode => ("https://explorer.mode.network/api", "https://explorer.mode.network"),
1601            ModeSepolia => (
1602                "https://sepolia.explorer.mode.network/api",
1603                "https://sepolia.explorer.mode.network",
1604            ),
1605
1606            Elastos => ("https://esc.elastos.io/api", "https://esc.elastos.io"),
1607            KakarotSepolia => {
1608                ("https://sepolia.kakarotscan.org/api", "https://sepolia.kakarotscan.org")
1609            }
1610            Etherlink => ("https://explorer.etherlink.com/api", "https://explorer.etherlink.com"),
1611            EtherlinkTestnet => (
1612                "https://testnet-explorer.etherlink.com/api",
1613                "https://testnet-explorer.etherlink.com",
1614            ),
1615            Degen => ("https://explorer.degen.tips/api", "https://explorer.degen.tips"),
1616            Ronin => ("https://skynet-api.roninchain.com/ronin", "https://app.roninchain.com"),
1617            RoninTestnet => (
1618                "https://api-gateway.skymavis.com/rpc/testnet",
1619                "https://saigon-app.roninchain.com",
1620            ),
1621            Taiko => ("https://api.etherscan.io/v2/api?chainid=167000", "https://taikoscan.io"),
1622            TaikoHekla => {
1623                ("https://api.etherscan.io/v2/api?chainid=167009", "https://hekla.taikoscan.io")
1624            }
1625            Flare => {
1626                ("https://flare-explorer.flare.network/api", "https://flare-explorer.flare.network")
1627            }
1628            FlareCoston2 => (
1629                "https://coston2-explorer.flare.network/api",
1630                "https://coston2-explorer.flare.network",
1631            ),
1632            Acala => ("https://blockscout.acala.network/api", "https://blockscout.acala.network"),
1633            AcalaMandalaTestnet => (
1634                "https://blockscout.mandala.aca-staging.network/api",
1635                "https://blockscout.mandala.aca-staging.network",
1636            ),
1637            AcalaTestnet => (
1638                "https://blockscout.acala-testnet.aca-staging.network/api",
1639                "https://blockscout.acala-testnet.aca-staging.network",
1640            ),
1641            Karura => {
1642                ("https://blockscout.karura.network/api", "https://blockscout.karura.network")
1643            }
1644            KaruraTestnet => (
1645                "https://blockscout.karura-testnet.aca-staging.network/api",
1646                "https://blockscout.karura-testnet.aca-staging.network",
1647            ),
1648
1649            Darwinia => {
1650                ("https://explorer.darwinia.network/api", "https://explorer.darwinia.network")
1651            }
1652            Crab => {
1653                ("https://crab-scan.darwinia.network/api", "https://crab-scan.darwinia.network")
1654            }
1655            Koi => ("https://koi-scan.darwinia.network/api", "https://koi-scan.darwinia.network"),
1656            Cfx => ("https://evmapi.confluxscan.net/api", "https://evm.confluxscan.io"),
1657            CfxTestnet => {
1658                ("https://evmapi-testnet.confluxscan.net/api", "https://evmtestnet.confluxscan.io")
1659            }
1660            Pulsechain => ("https://api.scan.pulsechain.com", "https://scan.pulsechain.com"),
1661            PulsechainTestnet => (
1662                "https://api.scan.v4.testnet.pulsechain.com",
1663                "https://scan.v4.testnet.pulsechain.com",
1664            ),
1665
1666            Immutable => ("https://explorer.immutable.com/api", "https://explorer.immutable.com"),
1667            ImmutableTestnet => (
1668                "https://explorer.testnet.immutable.com/api",
1669                "https://explorer.testnet.immutable.com",
1670            ),
1671            Soneium => ("https://soneium.blockscout.com/api", "https://soneium.blockscout.com"),
1672            SoneiumMinatoTestnet => (
1673                "https://soneium-minato.blockscout.com/api",
1674                "https://soneium-minato.blockscout.com",
1675            ),
1676            Odyssey => {
1677                ("https://odyssey-explorer.ithaca.xyz/api", "https://odyssey-explorer.ithaca.xyz")
1678            }
1679            World => ("https://api.etherscan.io/v2/api?chainid=480", "https://worldscan.org"),
1680            WorldSepolia => {
1681                ("https://api.etherscan.io/v2/api?chainid=4801", "https://sepolia.worldscan.org")
1682            }
1683            Unichain => ("https://api.etherscan.io/v2/api?chainid=130", "https://uniscan.xyz"),
1684            UnichainSepolia => {
1685                ("https://api.etherscan.io/v2/api?chainid=1301", "https://sepolia.uniscan.xyz")
1686            }
1687            Core => ("https://openapi.coredao.org/api", "https://scan.coredao.org"),
1688            Merlin => ("https://scan.merlinchain.io/api", "https://scan.merlinchain.io"),
1689            Bitlayer => ("https://api.btrscan.com/scan/api", "https://www.btrscan.com"),
1690            Vana => ("https://api.vanascan.io/api", "https://vanascan.io"),
1691            Zeta => ("https://zetachain.blockscout.com/api", "https://zetachain.blockscout.com"),
1692            Kaia => ("https://mainnet-oapi.kaiascan.io/api", "https://kaiascan.io"),
1693            Story => ("https://www.storyscan.xyz/api/v2", "https://www.storyscan.xyz"),
1694
1695            ApeChain => ("https://api.etherscan.io/v2/api?chainid=33139", "https://apescan.io"),
1696            Curtis => {
1697                ("https://api.etherscan.io/v2/api?chainid=33111", "https://curtis.apescan.io")
1698            }
1699            SonicBlaze => {
1700                ("https://api.etherscan.io/v2/api?chainid=57054", "https://testnet.sonicscan.org")
1701            }
1702            SonicTestnet => (
1703                "https://api.routescan.io/v2/network/testnet/evm/64165/etherscan/api",
1704                "https://scan.soniclabs.com",
1705            ),
1706            Sonic => ("https://api.etherscan.io/v2/api?chainid=146", "https://sonicscan.org"),
1707            Treasure => ("https://block-explorer.treasurescan.io/api", "https://treasurescan.io"),
1708            TreasureTopaz => (
1709                "https://block-explorer.topaz.treasurescan.io/api",
1710                "https://topaz.treasurescan.io",
1711            ),
1712            BerachainBepolia => {
1713                ("https://api.etherscan.io/v2/api?chainid=80069", "https://testnet.berascan.com")
1714            }
1715            Berachain => ("https://api.etherscan.io/v2/api?chainid=80094", "https://berascan.com"),
1716            SuperpositionTestnet => (
1717                "https://testnet-explorer.superposition.so/api",
1718                "https://testnet-explorer.superposition.so",
1719            ),
1720            Superposition => {
1721                ("https://explorer.superposition.so/api", "https://explorer.superposition.so")
1722            }
1723            MonadTestnet => {
1724                ("https://api.etherscan.io/v2/api?chainid=10143", "https://testnet.monadscan.com")
1725            }
1726            TelosEvm => ("https://api.teloscan.io/api", "https://teloscan.io"),
1727            TelosEvmTestnet => {
1728                ("https://api.testnet.teloscan.io/api", "https://testnet.teloscan.io")
1729            }
1730            Hyperliquid => {
1731                ("https://api.etherscan.io/v2/api?chainid=999", "https://hyperevmscan.io")
1732            }
1733            Abstract => ("https://api.etherscan.io/v2/api?chainid=2741", "https://abscan.org"),
1734            AbstractTestnet => {
1735                ("https://api.etherscan.io/v2/api?chainid=11124", "https://sepolia.abscan.org")
1736            }
1737            Corn => (
1738                "https://api.routescan.io/v2/network/mainnet/evm/21000000/etherscan/api",
1739                "https://cornscan.io",
1740            ),
1741            CornTestnet => (
1742                "https://api.routescan.io/v2/network/testnet/evm/21000001/etherscan/api",
1743                "https://testnet.cornscan.io",
1744            ),
1745            // TODO: add hoodi etherscan when live
1746            AnvilHardhat | Dev | Morden | MoonbeamDev | FilecoinMainnet | AutonomysNovaTestnet
1747            | Iotex | Sei => {
1748                return None;
1749            }
1750            Sophon => ("https://api.etherscan.io/v2/api?chainid=50104", "https://sophscan.xyz"),
1751            SophonTestnet => (
1752                "https://api.etherscan.io/v2/api?chainid=531050104",
1753                "https://testnet.sophscan.xyz",
1754            ),
1755            Lens => ("https://explorer-api.lens.xyz", "https://explorer.lens.xyz"),
1756            LensTestnet => (
1757                "https://block-explorer-api.staging.lens.zksync.dev",
1758                "https://explorer.testnet.lens.xyz",
1759            ),
1760            Katana => ("https://explorer.katanarpc.com/api", "https://explorer.katanarpc.com"),
1761            Lisk => ("https://blockscout.lisk.com/api", "https://blockscout.lisk.com"),
1762            Fuse => ("https://explorer.fuse.io/api", "https://explorer.fuse.io"),
1763            Injective => (
1764                "https://blockscout-api.injective.network/api",
1765                "https://blockscout.injective.network",
1766            ),
1767            InjectiveTestnet => (
1768                "https://testnet.blockscout-api.injective.network/api",
1769                "https://testnet.blockscout.injective.network",
1770            ),
1771            FluentDevnet => {
1772                ("https://blockscout.dev.gblend.xyz/api", "https://blockscout.dev.gblend.xyz")
1773            }
1774            FluentTestnet => {
1775                ("https://testnet.fluentscan.xyz/api", "https://testnet.fluentscan.xyz")
1776            }
1777        })
1778    }
1779
1780    /// Returns the chain's blockchain explorer's API key environment variable's default name.
1781    ///
1782    /// # Examples
1783    ///
1784    /// ```
1785    /// use alloy_chains::NamedChain;
1786    ///
1787    /// assert_eq!(NamedChain::Mainnet.etherscan_api_key_name(), Some("ETHERSCAN_API_KEY"));
1788    /// assert_eq!(NamedChain::AnvilHardhat.etherscan_api_key_name(), None);
1789    /// ```
1790    pub const fn etherscan_api_key_name(self) -> Option<&'static str> {
1791        use NamedChain::*;
1792
1793        let api_key_name = match self {
1794            Mainnet
1795            | Morden
1796            | Ropsten
1797            | Kovan
1798            | Rinkeby
1799            | Goerli
1800            | Holesky
1801            | Hoodi
1802            | Optimism
1803            | OptimismGoerli
1804            | OptimismKovan
1805            | OptimismSepolia
1806            | BinanceSmartChain
1807            | BinanceSmartChainTestnet
1808            | OpBNBMainnet
1809            | OpBNBTestnet
1810            | Arbitrum
1811            | ArbitrumTestnet
1812            | ArbitrumGoerli
1813            | ArbitrumSepolia
1814            | ArbitrumNova
1815            | Syndr
1816            | SyndrSepolia
1817            | Cronos
1818            | CronosTestnet
1819            | Aurora
1820            | AuroraTestnet
1821            | Celo
1822            | CeloAlfajores
1823            | Base
1824            | Linea
1825            | LineaSepolia
1826            | Mantle
1827            | MantleTestnet
1828            | MantleSepolia
1829            | Xai
1830            | XaiSepolia
1831            | BaseGoerli
1832            | BaseSepolia
1833            | Fraxtal
1834            | FraxtalTestnet
1835            | Blast
1836            | BlastSepolia
1837            | Gnosis
1838            | Scroll
1839            | ScrollSepolia
1840            | Taiko
1841            | TaikoHekla
1842            | Unichain
1843            | UnichainSepolia
1844            | MonadTestnet
1845            | ApeChain
1846            | Abstract
1847            | AbstractTestnet
1848            | ZkSyncTestnet
1849            | ZkSync
1850            | Hyperliquid
1851            | Sophon
1852            | SophonTestnet => "ETHERSCAN_API_KEY",
1853
1854            Avalanche | AvalancheFuji => "SNOWTRACE_API_KEY",
1855
1856            Polygon | PolygonMumbai | PolygonAmoy | PolygonZkEvm | PolygonZkEvmTestnet => {
1857                "POLYGONSCAN_API_KEY"
1858            }
1859
1860            Fantom | FantomTestnet => "FTMSCAN_API_KEY",
1861
1862            Moonbeam | Moonbase | MoonbeamDev | Moonriver => "MOONSCAN_API_KEY",
1863
1864            Acala | AcalaMandalaTestnet | AcalaTestnet | Canto | CantoTestnet | CeloBaklava
1865            | Etherlink | EtherlinkTestnet | Flare | FlareCoston2 | KakarotSepolia | Karura
1866            | KaruraTestnet | Mode | ModeSepolia | Pgn | PgnSepolia | Shimmer | Zora
1867            | ZoraSepolia | Darwinia | Crab | Koi | Immutable | ImmutableTestnet | Soneium
1868            | SoneiumMinatoTestnet | World | WorldSepolia | Curtis | Ink | InkSepolia
1869            | SuperpositionTestnet | Superposition | Vana | Story | Katana | Lisk | Fuse
1870            | Injective | InjectiveTestnet => "BLOCKSCOUT_API_KEY",
1871
1872            Boba => "BOBASCAN_API_KEY",
1873
1874            Core => "CORESCAN_API_KEY",
1875            Merlin => "MERLINSCAN_API_KEY",
1876            Bitlayer => "BITLAYERSCAN_API_KEY",
1877            Zeta => "ZETASCAN_API_KEY",
1878            Kaia => "KAIASCAN_API_KEY",
1879            Sonic => "SONICSCAN_API_KEY",
1880            Berachain | BerachainBepolia => "BERASCAN_API_KEY",
1881            Corn | CornTestnet => "ROUTESCAN_API_KEY",
1882            // Explicitly exhaustive. See NB above.
1883            Metis
1884            | Chiado
1885            | Odyssey
1886            | Sepolia
1887            | Rsk
1888            | RskTestnet
1889            | Sokol
1890            | Poa
1891            | Oasis
1892            | Emerald
1893            | EmeraldTestnet
1894            | Evmos
1895            | EvmosTestnet
1896            | AnvilHardhat
1897            | Dev
1898            | GravityAlphaMainnet
1899            | GravityAlphaTestnetSepolia
1900            | Bob
1901            | BobSepolia
1902            | FilecoinMainnet
1903            | LineaGoerli
1904            | FilecoinCalibrationTestnet
1905            | Viction
1906            | Elastos
1907            | Degen
1908            | Ronin
1909            | RoninTestnet
1910            | Cfx
1911            | CfxTestnet
1912            | Pulsechain
1913            | PulsechainTestnet
1914            | AutonomysNovaTestnet
1915            | Iotex
1916            | HappychainTestnet
1917            | SonicBlaze
1918            | SonicTestnet
1919            | Treasure
1920            | TreasureTopaz
1921            | TelosEvm
1922            | TelosEvmTestnet
1923            | Lens
1924            | LensTestnet
1925            | Sei
1926            | FluentDevnet
1927            | FluentTestnet => return None,
1928        };
1929
1930        Some(api_key_name)
1931    }
1932
1933    /// Returns the chain's blockchain explorer's API key, from the environment variable with the
1934    /// name specified in [`etherscan_api_key_name`](NamedChain::etherscan_api_key_name).
1935    ///
1936    /// # Examples
1937    ///
1938    /// ```
1939    /// use alloy_chains::NamedChain;
1940    ///
1941    /// let chain = NamedChain::Mainnet;
1942    /// unsafe {
1943    ///     std::env::set_var(chain.etherscan_api_key_name().unwrap(), "KEY");
1944    /// }
1945    /// assert_eq!(chain.etherscan_api_key().as_deref(), Some("KEY"));
1946    /// ```
1947    #[cfg(feature = "std")]
1948    pub fn etherscan_api_key(self) -> Option<String> {
1949        self.etherscan_api_key_name().and_then(|name| std::env::var(name).ok())
1950    }
1951
1952    /// Returns the address of the public DNS node list for the given chain.
1953    ///
1954    /// See also <https://github.com/ethereum/discv4-dns-lists>.
1955    pub fn public_dns_network_protocol(self) -> Option<String> {
1956        use NamedChain::*;
1957
1958        const DNS_PREFIX: &str = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@";
1959        if let Mainnet | Goerli | Sepolia | Ropsten | Rinkeby | Holesky | Hoodi = self {
1960            // `{DNS_PREFIX}all.{self.lower()}.ethdisco.net`
1961            let mut s = String::with_capacity(DNS_PREFIX.len() + 32);
1962            s.push_str(DNS_PREFIX);
1963            s.push_str("all.");
1964            let chain_str = self.as_ref();
1965            s.push_str(chain_str);
1966            let l = s.len();
1967            s[l - chain_str.len()..].make_ascii_lowercase();
1968            s.push_str(".ethdisco.net");
1969
1970            Some(s)
1971        } else {
1972            None
1973        }
1974    }
1975
1976    /// Returns the address of the most popular wrapped native token address for this chain, if it
1977    /// exists.
1978    ///
1979    /// Example:
1980    ///
1981    /// ```
1982    /// use alloy_chains::NamedChain;
1983    /// use alloy_primitives::address;
1984    ///
1985    /// let chain = NamedChain::Mainnet;
1986    /// assert_eq!(
1987    ///     chain.wrapped_native_token(),
1988    ///     Some(address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"))
1989    /// );
1990    /// ```
1991    pub const fn wrapped_native_token(self) -> Option<Address> {
1992        use NamedChain::*;
1993
1994        let addr = match self {
1995            Mainnet => address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
1996            Optimism => address!("4200000000000000000000000000000000000006"),
1997            BinanceSmartChain => address!("bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c"),
1998            OpBNBMainnet => address!("4200000000000000000000000000000000000006"),
1999            Arbitrum => address!("82af49447d8a07e3bd95bd0d56f35241523fbab1"),
2000            Base => address!("4200000000000000000000000000000000000006"),
2001            Linea => address!("e5d7c2a44ffddf6b295a15c148167daaaf5cf34f"),
2002            Mantle => address!("deaddeaddeaddeaddeaddeaddeaddeaddead1111"),
2003            Blast => address!("4300000000000000000000000000000000000004"),
2004            Gnosis => address!("e91d153e0b41518a2ce8dd3d7944fa863463a97d"),
2005            Scroll => address!("5300000000000000000000000000000000000004"),
2006            Taiko => address!("a51894664a773981c6c112c43ce576f315d5b1b6"),
2007            Avalanche => address!("b31f66aa3c1e785363f0875a1b74e27b85fd66c7"),
2008            Polygon => address!("0d500b1d8e8ef31e21c99d1db9a6444d3adf1270"),
2009            Fantom => address!("21be370d5312f44cb42ce377bc9b8a0cef1a4c83"),
2010            Iotex => address!("a00744882684c3e4747faefd68d283ea44099d03"),
2011            Core => address!("40375C92d9FAf44d2f9db9Bd9ba41a3317a2404f"),
2012            Merlin => address!("F6D226f9Dc15d9bB51182815b320D3fBE324e1bA"),
2013            Bitlayer => address!("ff204e2681a6fa0e2c3fade68a1b28fb90e4fc5f"),
2014            ApeChain => address!("48b62137EdfA95a428D35C09E44256a739F6B557"),
2015            Vana => address!("00EDdD9621Fb08436d0331c149D1690909a5906d"),
2016            Zeta => address!("5F0b1a82749cb4E2278EC87F8BF6B618dC71a8bf"),
2017            Kaia => address!("19aac5f612f524b754ca7e7c41cbfa2e981a4432"),
2018            Story => address!("1514000000000000000000000000000000000000"),
2019            Treasure => address!("263d8f36bb8d0d9526255e205868c26690b04b88"),
2020            Superposition => address!("1fB719f10b56d7a85DCD32f27f897375fB21cfdd"),
2021            Sonic => address!("039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38"),
2022            Berachain => address!("6969696969696969696969696969696969696969"),
2023            Hyperliquid => address!("5555555555555555555555555555555555555555"),
2024            Abstract => address!("3439153EB7AF838Ad19d56E1571FBD09333C2809"),
2025            Sei => address!("E30feDd158A2e3b13e9badaeABaFc5516e95e8C7"),
2026            ZkSync => address!("5aea5775959fbc2557cc8789bc1bf90a239d9a91"),
2027            Sophon => address!("f1f9e08a0818594fde4713ae0db1e46672ca960e"),
2028            Rsk => address!("967f8799af07df1534d48a95a5c9febe92c53ae0"),
2029            _ => return None,
2030        };
2031
2032        Some(addr)
2033    }
2034}
2035
2036#[cfg(test)]
2037mod tests {
2038    use super::*;
2039    use strum::{EnumCount, IntoEnumIterator};
2040
2041    #[allow(unused_imports)]
2042    use alloc::string::ToString;
2043
2044    #[test]
2045    #[cfg(feature = "serde")]
2046    fn default() {
2047        assert_eq!(serde_json::to_string(&NamedChain::default()).unwrap(), "\"mainnet\"");
2048    }
2049
2050    #[test]
2051    fn enum_iter() {
2052        assert_eq!(NamedChain::COUNT, NamedChain::iter().size_hint().0);
2053    }
2054
2055    #[test]
2056    fn roundtrip_string() {
2057        for chain in NamedChain::iter() {
2058            let chain_string = chain.to_string();
2059            assert_eq!(chain_string, format!("{chain}"));
2060            assert_eq!(chain_string.as_str(), chain.as_ref());
2061            #[cfg(feature = "serde")]
2062            assert_eq!(serde_json::to_string(&chain).unwrap(), format!("\"{chain_string}\""));
2063
2064            assert_eq!(chain_string.parse::<NamedChain>().unwrap(), chain);
2065        }
2066    }
2067
2068    #[test]
2069    #[cfg(feature = "serde")]
2070    fn roundtrip_serde() {
2071        for chain in NamedChain::iter() {
2072            let chain_string = serde_json::to_string(&chain).unwrap();
2073            let chain_string = chain_string.replace('-', "_");
2074            assert_eq!(serde_json::from_str::<'_, NamedChain>(&chain_string).unwrap(), chain);
2075        }
2076    }
2077
2078    #[test]
2079    #[cfg(feature = "arbitrary")]
2080    fn test_arbitrary_named_chain() {
2081        use arbitrary::{Arbitrary, Unstructured};
2082        let data = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 255];
2083        let mut unstructured = Unstructured::new(&data);
2084
2085        for _ in 0..10 {
2086            let _chain = NamedChain::arbitrary(&mut unstructured).unwrap();
2087        }
2088    }
2089
2090    #[test]
2091    fn aliases() {
2092        use NamedChain::*;
2093
2094        // kebab-case
2095        const ALIASES: &[(NamedChain, &[&str])] = &[
2096            (Mainnet, &["ethlive"]),
2097            (BinanceSmartChain, &["bsc", "bnb-smart-chain", "binance-smart-chain"]),
2098            (
2099                BinanceSmartChainTestnet,
2100                &["bsc-testnet", "bnb-smart-chain-testnet", "binance-smart-chain-testnet"],
2101            ),
2102            (Gnosis, &["gnosis", "gnosis-chain"]),
2103            (PolygonMumbai, &["mumbai"]),
2104            (PolygonZkEvm, &["zkevm", "polygon-zkevm"]),
2105            (PolygonZkEvmTestnet, &["zkevm-testnet", "polygon-zkevm-testnet"]),
2106            (AnvilHardhat, &["anvil", "hardhat"]),
2107            (AvalancheFuji, &["fuji"]),
2108            (ZkSync, &["zksync"]),
2109            (ZkSyncTestnet, &["zksync-testnet"]),
2110            (Mantle, &["mantle"]),
2111            (MantleTestnet, &["mantle-testnet"]),
2112            (MantleSepolia, &["mantle-sepolia"]),
2113            (GravityAlphaMainnet, &["gravity-alpha-mainnet"]),
2114            (GravityAlphaTestnetSepolia, &["gravity-alpha-testnet-sepolia"]),
2115            (Bob, &["bob"]),
2116            (BobSepolia, &["bob-sepolia"]),
2117            (HappychainTestnet, &["happychain-testnet"]),
2118            (Xai, &["xai"]),
2119            (XaiSepolia, &["xai-sepolia"]),
2120            (Base, &["base"]),
2121            (BaseGoerli, &["base-goerli"]),
2122            (BaseSepolia, &["base-sepolia"]),
2123            (Fraxtal, &["fraxtal"]),
2124            (FraxtalTestnet, &["fraxtal-testnet"]),
2125            (Ink, &["ink"]),
2126            (InkSepolia, &["ink-sepolia"]),
2127            (BlastSepolia, &["blast-sepolia"]),
2128            (Syndr, &["syndr"]),
2129            (SyndrSepolia, &["syndr-sepolia"]),
2130            (LineaGoerli, &["linea-goerli"]),
2131            (LineaSepolia, &["linea-sepolia"]),
2132            (AutonomysNovaTestnet, &["autonomys-nova-testnet"]),
2133            (Immutable, &["immutable"]),
2134            (ImmutableTestnet, &["immutable-testnet"]),
2135            (Soneium, &["soneium"]),
2136            (SoneiumMinatoTestnet, &["soneium-minato-testnet"]),
2137            (ApeChain, &["apechain"]),
2138            (Curtis, &["apechain-testnet", "curtis"]),
2139            (Treasure, &["treasure"]),
2140            (TreasureTopaz, &["treasure-topaz-testnet", "treasure-topaz"]),
2141            (BerachainBepolia, &["berachain-bepolia-testnet", "berachain-bepolia"]),
2142            (SuperpositionTestnet, &["superposition-testnet"]),
2143            (Superposition, &["superposition"]),
2144            (Hyperliquid, &["hyperliquid"]),
2145            (Abstract, &["abstract"]),
2146            (AbstractTestnet, &["abstract-testnet"]),
2147            (Sophon, &["sophon"]),
2148            (SophonTestnet, &["sophon-testnet"]),
2149            (Lens, &["lens"]),
2150            (LensTestnet, &["lens-testnet"]),
2151            (Katana, &["katana"]),
2152            (Lisk, &["lisk"]),
2153            (Fuse, &["fuse"]),
2154            (FluentDevnet, &["fluent-devnet"]),
2155            (FluentTestnet, &["fluent-testnet"]),
2156            (Injective, &["injective"]),
2157            (InjectiveTestnet, &["injective-testnet"]),
2158        ];
2159
2160        for &(chain, aliases) in ALIASES {
2161            for &alias in aliases {
2162                let named = alias.parse::<NamedChain>().expect(alias);
2163                assert_eq!(named, chain);
2164
2165                #[cfg(feature = "serde")]
2166                {
2167                    assert_eq!(
2168                        serde_json::from_str::<NamedChain>(&format!("\"{alias}\"")).unwrap(),
2169                        chain
2170                    );
2171
2172                    assert_eq!(
2173                        serde_json::from_str::<NamedChain>(&format!("\"{named}\"")).unwrap(),
2174                        chain
2175                    );
2176                }
2177            }
2178        }
2179    }
2180
2181    #[test]
2182    #[cfg(feature = "serde")]
2183    fn serde_to_string_match() {
2184        for chain in NamedChain::iter() {
2185            let chain_serde = serde_json::to_string(&chain).unwrap();
2186            let chain_string = format!("\"{chain}\"");
2187            assert_eq!(chain_serde, chain_string);
2188        }
2189    }
2190
2191    #[test]
2192    fn test_dns_network() {
2193        let s = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net";
2194        assert_eq!(NamedChain::Mainnet.public_dns_network_protocol().unwrap(), s);
2195    }
2196
2197    #[test]
2198    fn ensure_no_trailing_etherscan_url_separator() {
2199        for chain in NamedChain::iter() {
2200            if let Some((api, base)) = chain.etherscan_urls() {
2201                assert!(!api.ends_with('/'), "{chain:?} api url has trailing /");
2202                assert!(!base.ends_with('/'), "{chain:?} base url has trailing /");
2203            }
2204        }
2205    }
2206}