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