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