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