1use super::{U128, U256, U512, U64};
2use serde::{Deserialize, Serialize, Serializer};
3use std::{fmt, time::Duration};
4use strum::{AsRefStr, EnumCount, EnumIter, EnumString, VariantNames};
5
6#[doc(hidden)]
8pub use num_enum::{TryFromPrimitive, TryFromPrimitiveError};
9#[doc(hidden)]
10pub type ParseChainError = TryFromPrimitiveError<Chain>;
11
12#[derive(
32 Clone,
33 Copy,
34 Debug,
35 PartialEq,
36 Eq,
37 PartialOrd,
38 Ord,
39 Hash,
40 AsRefStr, VariantNames, EnumString, EnumIter, EnumCount, TryFromPrimitive, Deserialize,
47)]
48#[serde(rename_all = "snake_case")]
49#[strum(serialize_all = "kebab-case")]
50#[repr(u64)]
51pub enum Chain {
52 #[strum(to_string = "mainnet", serialize = "ethlive")]
53 #[serde(alias = "ethlive")]
54 Mainnet = 1,
55 Morden = 2,
56 Ropsten = 3,
57 Rinkeby = 4,
58 Goerli = 5,
59 Kovan = 42,
60 Holesky = 17000,
61 Sepolia = 11155111,
62
63 Optimism = 10,
64 OptimismKovan = 69,
65 OptimismGoerli = 420,
66 OptimismSepolia = 11155420,
67
68 Arbitrum = 42161,
69 ArbitrumTestnet = 421611,
70 ArbitrumGoerli = 421613,
71 ArbitrumSepolia = 421614,
72 ArbitrumNova = 42170,
73
74 Cronos = 25,
75 CronosTestnet = 338,
76
77 Rsk = 30,
78
79 #[strum(to_string = "bsc", serialize = "binance-smart-chain")]
80 #[serde(alias = "bsc")]
81 BinanceSmartChain = 56,
82 #[strum(to_string = "bsc-testnet", serialize = "binance-smart-chain-testnet")]
83 #[serde(alias = "bsc_testnet")]
84 BinanceSmartChainTestnet = 97,
85
86 Poa = 99,
87 Sokol = 77,
88
89 #[serde(alias = "scroll_sepolia", alias = "scroll_sepolia_testnet")]
90 ScrollSepolia = 534351,
91 Scroll = 534352,
92 ScrollAlphaTestnet = 534353,
93
94 Metis = 1088,
95
96 #[strum(to_string = "xdai", serialize = "gnosis", serialize = "gnosis-chain")]
97 #[serde(alias = "xdai", alias = "gnosis", alias = "gnosis_chain")]
98 Gnosis = 100,
99
100 Polygon = 137,
101 #[strum(to_string = "mumbai", serialize = "polygon-mumbai")]
102 #[serde(alias = "mumbai")]
103 PolygonMumbai = 80001,
104 #[strum(to_string = "amoy", serialize = "polygon-amoy")]
105 #[serde(alias = "amoy")]
106 PolygonAmoy = 80002,
107 #[strum(serialize = "polygon-zkevm", serialize = "zkevm")]
108 #[serde(alias = "zkevm", alias = "polygon_zkevm")]
109 PolygonZkEvm = 1101,
110 #[strum(serialize = "polygon-zkevm-testnet", serialize = "zkevm-testnet")]
111 #[serde(alias = "zkevm_testnet", alias = "polygon_zkevm_testnet")]
112 PolygonZkEvmTestnet = 1442,
113
114 Fantom = 250,
115 FantomTestnet = 4002,
116
117 Moonbeam = 1284,
118 MoonbeamDev = 1281,
119
120 Moonriver = 1285,
121
122 Moonbase = 1287,
123
124 Dev = 1337,
125 #[strum(to_string = "anvil-hardhat", serialize = "anvil", serialize = "hardhat")]
126 #[serde(alias = "anvil", alias = "hardhat")]
127 AnvilHardhat = 31337,
128
129 Evmos = 9001,
130 EvmosTestnet = 9000,
131
132 Chiado = 10200,
133
134 Oasis = 26863,
135
136 Emerald = 42262,
137 EmeraldTestnet = 42261,
138
139 FilecoinMainnet = 314,
140 FilecoinCalibrationTestnet = 314159,
141
142 Avalanche = 43114,
143 #[strum(to_string = "fuji", serialize = "avalanche-fuji")]
144 #[serde(alias = "fuji")]
145 AvalancheFuji = 43113,
146
147 Celo = 42220,
148 CeloAlfajores = 44787,
149 CeloBaklava = 62320,
150
151 Aurora = 1313161554,
152 AuroraTestnet = 1313161555,
153
154 Canto = 7700,
155 CantoTestnet = 740,
156
157 Boba = 288,
158
159 #[strum(to_string = "base")]
160 #[serde(alias = "base")]
161 Base = 8453,
162 #[strum(to_string = "base-goerli")]
163 #[serde(alias = "base_goerli")]
164 BaseGoerli = 84531,
165 #[strum(to_string = "base-sepolia")]
166 #[serde(alias = "base_sepolia")]
167 BaseSepolia = 84532,
168
169 Blast = 81457,
170 BlastSepolia = 168587773,
171
172 Linea = 59144,
173 LineaTestnet = 59140,
174
175 #[strum(to_string = "zksync")]
176 #[serde(alias = "zksync")]
177 ZkSync = 324,
178 #[strum(to_string = "zksync-testnet")]
179 #[serde(alias = "zksync_testnet")]
180 ZkSyncTestnet = 280,
181
182 #[strum(to_string = "mantle")]
183 #[serde(alias = "mantle")]
184 Mantle = 5000,
185 #[strum(to_string = "mantle-testnet")]
186 #[serde(alias = "mantle_testnet")]
187 MantleTestnet = 5001,
188
189 Viction = 88,
190
191 Zora = 7777777,
192 ZoraGoerli = 999,
193 ZoraSepolia = 999999999,
194
195 Mode = 34443,
196 ModeSepolia = 919,
197
198 Elastos = 20,
199}
200
201impl Default for Chain {
206 fn default() -> Self {
207 Self::Mainnet
208 }
209}
210
211macro_rules! impl_into_numeric {
212 ($($ty:ty)+) => {$(
213 impl From<Chain> for $ty {
214 fn from(chain: Chain) -> Self {
215 u64::from(chain).into()
216 }
217 }
218 )+};
219}
220
221macro_rules! impl_try_from_numeric {
222 ($($native:ty)+ ; $($primitive:ty)*) => {
223 $(
224 impl TryFrom<$native> for Chain {
225 type Error = ParseChainError;
226
227 fn try_from(value: $native) -> Result<Self, Self::Error> {
228 (value as u64).try_into()
229 }
230 }
231 )+
232
233 $(
234 impl TryFrom<$primitive> for Chain {
235 type Error = ParseChainError;
236
237 fn try_from(value: $primitive) -> Result<Self, Self::Error> {
238 if value.bits() > 64 {
239 return Err(ParseChainError { number: value.low_u64() })
242 }
243 value.low_u64().try_into()
244 }
245 }
246 )*
247 };
248}
249
250impl From<Chain> for u64 {
251 fn from(chain: Chain) -> Self {
252 chain as u64
253 }
254}
255
256impl_into_numeric!(u128 U64 U128 U256 U512);
257
258impl TryFrom<U64> for Chain {
259 type Error = ParseChainError;
260
261 fn try_from(value: U64) -> Result<Self, Self::Error> {
262 value.low_u64().try_into()
263 }
264}
265
266impl_try_from_numeric!(u8 u16 u32 usize; U128 U256 U512);
267
268impl fmt::Display for Chain {
269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270 f.pad(self.as_ref())
271 }
272}
273
274impl Serialize for Chain {
275 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
276 where
277 S: Serializer,
278 {
279 s.serialize_str(self.as_ref())
280 }
281}
282
283#[allow(clippy::match_like_matches_macro)]
286impl Chain {
287 pub const fn average_blocktime_hint(&self) -> Option<Duration> {
312 use Chain::*;
313
314 let ms = match self {
315 Mainnet => 12_000,
316 Arbitrum | ArbitrumTestnet | ArbitrumGoerli | ArbitrumSepolia | ArbitrumNova => 1_300,
317 Optimism | OptimismGoerli | OptimismSepolia => 2_000,
318 Polygon | PolygonMumbai | PolygonAmoy => 2_100,
319 Moonbeam | Moonriver => 12_500,
320 BinanceSmartChain | BinanceSmartChainTestnet => 3_000,
321 Avalanche | AvalancheFuji => 2_000,
322 Fantom | FantomTestnet => 1_200,
323 Cronos | CronosTestnet | Canto | CantoTestnet => 5_700,
324 Evmos | EvmosTestnet => 1_900,
325 Aurora | AuroraTestnet => 1_100,
326 Oasis => 5_500,
327 Emerald => 6_000,
328 Dev | AnvilHardhat => 200,
329 Celo | CeloAlfajores | CeloBaklava => 5_000,
330 FilecoinCalibrationTestnet | FilecoinMainnet => 30_000,
331 Scroll | ScrollSepolia | ScrollAlphaTestnet => 3_000,
332 Gnosis | Chiado => 5_000,
333 Viction => 2_000,
334 Mode | ModeSepolia => 2_000,
335 Elastos => 5_000,
336 Morden | Ropsten | Rinkeby | Goerli | Kovan | Sepolia | Holesky | Moonbase
338 | MoonbeamDev | OptimismKovan | Poa | Sokol | Rsk | EmeraldTestnet | Boba | Base
339 | BaseGoerli | BaseSepolia | Blast | BlastSepolia | ZkSync | ZkSyncTestnet
340 | PolygonZkEvm | PolygonZkEvmTestnet | Metis | Linea | LineaTestnet | Mantle
341 | MantleTestnet | Zora | ZoraGoerli | ZoraSepolia => return None,
342 };
343
344 Some(Duration::from_millis(ms))
345 }
346
347 pub const fn is_legacy(&self) -> bool {
358 use Chain::*;
359
360 match self {
361 OptimismKovan
363 | Fantom
364 | FantomTestnet
365 | BinanceSmartChain
366 | BinanceSmartChainTestnet
367 | ArbitrumTestnet
368 | Rsk
369 | Oasis
370 | Emerald
371 | EmeraldTestnet
372 | Celo
373 | CeloAlfajores
374 | CeloBaklava
375 | Boba
376 | ZkSync
377 | ZkSyncTestnet
378 | Mantle
379 | MantleTestnet
380 | PolygonZkEvm
381 | PolygonZkEvmTestnet
382 | Metis
383 | Viction
384 | Scroll
385 | ScrollSepolia
386 | Elastos => true,
387
388 Mainnet
390 | Goerli
391 | Sepolia
392 | Holesky
393 | Base
394 | BaseGoerli
395 | BaseSepolia
396 | Blast
397 | BlastSepolia
398 | Optimism
399 | OptimismGoerli
400 | OptimismSepolia
401 | Polygon
402 | PolygonMumbai
403 | PolygonAmoy
404 | Avalanche
405 | AvalancheFuji
406 | Arbitrum
407 | ArbitrumGoerli
408 | ArbitrumSepolia
409 | ArbitrumNova
410 | FilecoinMainnet
411 | Linea
412 | LineaTestnet
413 | FilecoinCalibrationTestnet
414 | Gnosis
415 | Chiado
416 | Mode
417 | ModeSepolia
418 | Zora
419 | ZoraGoerli
420 | ZoraSepolia => false,
421
422 Dev | AnvilHardhat | Morden | Ropsten | Rinkeby | Cronos | CronosTestnet | Kovan
424 | Sokol | Poa | Moonbeam | MoonbeamDev | Moonriver | Moonbase | Evmos
425 | EvmosTestnet | Aurora | AuroraTestnet | Canto | CantoTestnet | ScrollAlphaTestnet => {
426 false
427 }
428 }
429 }
430
431 pub const fn supports_push0(&self) -> bool {
436 match self {
437 Chain::Mainnet | Chain::Goerli | Chain::Sepolia | Chain::Gnosis | Chain::Chiado => true,
438 _ => false,
439 }
440 }
441
442 pub const fn etherscan_urls(&self) -> Option<(&'static str, &'static str)> {
462 use Chain::*;
463
464 let urls = match self {
465 Mainnet => ("https://api.etherscan.io/api", "https://etherscan.io"),
466 Ropsten => ("https://api-ropsten.etherscan.io/api", "https://ropsten.etherscan.io"),
467 Kovan => ("https://api-kovan.etherscan.io/api", "https://kovan.etherscan.io"),
468 Rinkeby => ("https://api-rinkeby.etherscan.io/api", "https://rinkeby.etherscan.io"),
469 Goerli => ("https://api-goerli.etherscan.io/api", "https://goerli.etherscan.io"),
470 Sepolia => ("https://api-sepolia.etherscan.io/api", "https://sepolia.etherscan.io"),
471 Holesky => ("https://api-holesky.etherscan.io/api", "https://holesky.etherscan.io"),
472
473 Polygon => ("https://api.polygonscan.com/api", "https://polygonscan.com"),
474 PolygonMumbai => {
475 ("https://api-testnet.polygonscan.com/api", "https://mumbai.polygonscan.com")
476 }
477 PolygonAmoy => ("https://rpc-amoy.polygon.technology", "https://www.oklink.com/amoy"),
478
479 PolygonZkEvm => {
480 ("https://api-zkevm.polygonscan.com/api", "https://zkevm.polygonscan.com")
481 }
482 PolygonZkEvmTestnet => (
483 "https://api-testnet-zkevm.polygonscan.com/api",
484 "https://testnet-zkevm.polygonscan.com",
485 ),
486
487 Avalanche => ("https://api.snowtrace.io/api", "https://snowtrace.io"),
488 AvalancheFuji => {
489 ("https://api-testnet.snowtrace.io/api", "https://testnet.snowtrace.io")
490 }
491
492 Optimism => {
493 ("https://api-optimistic.etherscan.io/api", "https://optimistic.etherscan.io")
494 }
495 OptimismGoerli => (
496 "https://api-goerli-optimistic.etherscan.io/api",
497 "https://goerli-optimism.etherscan.io",
498 ),
499 OptimismKovan => (
500 "https://api-kovan-optimistic.etherscan.io/api",
501 "https://kovan-optimistic.etherscan.io",
502 ),
503 OptimismSepolia => (
504 "https://api-sepolia-optimistic.etherscan.io/api",
505 "https://sepolia-optimism.etherscan.io",
506 ),
507
508 Fantom => ("https://api.ftmscan.com/api", "https://ftmscan.com"),
509 FantomTestnet => ("https://api-testnet.ftmscan.com/api", "https://testnet.ftmscan.com"),
510
511 BinanceSmartChain => ("https://api.bscscan.com/api", "https://bscscan.com"),
512 BinanceSmartChainTestnet => {
513 ("https://api-testnet.bscscan.com/api", "https://testnet.bscscan.com")
514 }
515
516 Arbitrum => ("https://api.arbiscan.io/api", "https://arbiscan.io"),
517 ArbitrumTestnet => {
518 ("https://api-testnet.arbiscan.io/api", "https://testnet.arbiscan.io")
519 }
520 ArbitrumGoerli => ("https://api-goerli.arbiscan.io/api", "https://goerli.arbiscan.io"),
521 ArbitrumSepolia => {
522 ("https://api-sepolia.arbiscan.io/api", "https://sepolia.arbiscan.io")
523 }
524 ArbitrumNova => ("https://api-nova.arbiscan.io/api", "https://nova.arbiscan.io/"),
525
526 Cronos => ("https://api.cronoscan.com/api", "https://cronoscan.com"),
527 CronosTestnet => {
528 ("https://api-testnet.cronoscan.com/api", "https://testnet.cronoscan.com")
529 }
530
531 Moonbeam => ("https://api-moonbeam.moonscan.io/api", "https://moonbeam.moonscan.io/"),
532 Moonbase => ("https://api-moonbase.moonscan.io/api", "https://moonbase.moonscan.io/"),
533 Moonriver => ("https://api-moonriver.moonscan.io/api", "https://moonriver.moonscan.io"),
534
535 Gnosis => ("https://api.gnosisscan.io/api", "https://gnosisscan.io"),
536
537 Scroll => ("https://api.scrollscan.com/api", "https://scrollscan.com"),
538 ScrollSepolia => {
539 ("https://api-sepolia.scrollscan.com/api", "https://sepolia.scrollscan.com")
540 }
541 ScrollAlphaTestnet => {
542 ("https://alpha-blockscout.scroll.io/api", "https://alpha-blockscout.scroll.io/")
543 }
544
545 Metis => (
546 "https://api.routescan.io/v2/network/mainnet/evm/1088/etherscan/api",
547 "https://explorer.metis.io/",
548 ),
549
550 Chiado => {
551 ("https://blockscout.chiadochain.net/api", "https://blockscout.chiadochain.net")
552 }
553
554 FilecoinCalibrationTestnet => (
555 "https://api.calibration.node.glif.io/rpc/v1",
556 "https://calibration.filfox.info/en",
557 ),
558
559 Sokol => ("https://blockscout.com/poa/sokol/api", "https://blockscout.com/poa/sokol"),
560
561 Poa => ("https://blockscout.com/poa/core/api", "https://blockscout.com/poa/core"),
562
563 Rsk => ("https://blockscout.com/rsk/mainnet/api", "https://blockscout.com/rsk/mainnet"),
564
565 Oasis => ("https://scan.oasischain.io/api", "https://scan.oasischain.io/"),
566
567 Emerald => {
568 ("https://explorer.emerald.oasis.dev/api", "https://explorer.emerald.oasis.dev/")
569 }
570 EmeraldTestnet => (
571 "https://testnet.explorer.emerald.oasis.dev/api",
572 "https://testnet.explorer.emerald.oasis.dev/",
573 ),
574
575 Aurora => ("https://api.aurorascan.dev/api", "https://aurorascan.dev"),
576 AuroraTestnet => {
577 ("https://testnet.aurorascan.dev/api", "https://testnet.aurorascan.dev")
578 }
579
580 Evmos => ("https://evm.evmos.org/api", "https://evm.evmos.org/"),
581 EvmosTestnet => ("https://evm.evmos.dev/api", "https://evm.evmos.dev/"),
582
583 Celo => ("https://explorer.celo.org/mainnet/api", "https://explorer.celo.org/mainnet"),
584 CeloAlfajores => {
585 ("https://explorer.celo.org/alfajores/api", "https://explorer.celo.org/alfajores")
586 }
587 CeloBaklava => {
588 ("https://explorer.celo.org/baklava/api", "https://explorer.celo.org/baklava")
589 }
590
591 Canto => ("https://evm.explorer.canto.io/api", "https://evm.explorer.canto.io/"),
592 CantoTestnet => (
593 "https://testnet-explorer.canto.neobase.one/api",
594 "https://testnet-explorer.canto.neobase.one/",
595 ),
596
597 Boba => ("https://api.bobascan.com/api", "https://bobascan.com"),
598
599 Base => ("https://api.basescan.org/api", "https://basescan.org"),
600
601 BaseGoerli => ("https://api-goerli.basescan.org/api", "https://goerli.basescan.org"),
602 BaseSepolia => ("https://api-sepolia.basescan.org/api", "https://sepolia.basescan.org"),
603
604 Blast => (
605 "https://api.routescan.io/v2/network/mainnet/evm/81457/etherscan",
606 "https://blastscan.io",
607 ),
608 BlastSepolia => (
609 "https://api.routescan.io/v2/network/testnet/evm/168587773/etherscan",
610 "https://testnet.blastscan.io",
611 ),
612
613 ZkSync => {
614 ("https://zksync2-mainnet-explorer.zksync.io/", "https://explorer.zksync.io/")
615 }
616 ZkSyncTestnet => (
617 "https://zksync2-testnet-explorer.zksync.dev/",
618 "https://goerli.explorer.zksync.io/",
619 ),
620 Linea => ("https://api.lineascan.build/api", "https://lineascan.build/"),
621 LineaTestnet => {
622 ("https://explorer.goerli.linea.build/api", "https://explorer.goerli.linea.build/")
623 }
624 Mantle => ("https://explorer.mantle.xyz/api", "https://explorer.mantle.xyz"),
625 MantleTestnet => {
626 ("https://explorer.testnet.mantle.xyz/api", "https://explorer.testnet.mantle.xyz")
627 }
628
629 Zora => ("https://explorer.zora.energy/api", "https://explorer.zora.energy"),
630 ZoraGoerli => {
631 ("https://testnet.explorer.zora.energy/api", "https://testnet.explorer.zora.energy")
632 }
633 ZoraSepolia => {
634 ("https://sepolia.explorer.zora.energy/api", "https://sepolia.explorer.zora.energy")
635 }
636
637 AnvilHardhat | Dev | Morden | MoonbeamDev | FilecoinMainnet => {
638 return None;
641 }
642 Viction => ("https://www.vicscan.xyz/api", "https://www.vicscan.xyz"),
643
644 Mode => ("https://explorer.mode.network/api", "https://explorer.mode.network"),
645 ModeSepolia => (
646 "https://sepolia.explorer.mode.network/api",
647 "https://sepolia.explorer.mode.network",
648 ),
649 Elastos => ("https://api.elastos.io/eth", "https://esc.elastos.io/"),
650 };
651
652 Some(urls)
653 }
654
655 pub const fn etherscan_api_key_name(&self) -> Option<&'static str> {
666 use Chain::*;
667
668 let api_key_name = match self {
669 Mainnet
670 | Morden
671 | Ropsten
672 | Kovan
673 | Rinkeby
674 | Goerli
675 | Holesky
676 | Optimism
677 | OptimismGoerli
678 | OptimismKovan
679 | OptimismSepolia
680 | BinanceSmartChain
681 | BinanceSmartChainTestnet
682 | Arbitrum
683 | ArbitrumTestnet
684 | ArbitrumGoerli
685 | ArbitrumSepolia
686 | ArbitrumNova
687 | Cronos
688 | CronosTestnet
689 | Aurora
690 | AuroraTestnet
691 | Celo
692 | CeloAlfajores
693 | CeloBaklava
694 | Base
695 | Linea
696 | Mantle
697 | MantleTestnet
698 | BaseGoerli
699 | BaseSepolia
700 | Blast
701 | BlastSepolia
702 | Gnosis
703 | Scroll
704 | ScrollSepolia => "ETHERSCAN_API_KEY",
705
706 Avalanche | AvalancheFuji => "SNOWTRACE_API_KEY",
707
708 Polygon | PolygonMumbai | PolygonZkEvm | PolygonZkEvmTestnet | PolygonAmoy => {
709 "POLYGONSCAN_API_KEY"
710 }
711
712 Fantom | FantomTestnet => "FTMSCAN_API_KEY",
713
714 Moonbeam | Moonbase | MoonbeamDev | Moonriver => "MOONSCAN_API_KEY",
715
716 Canto | CantoTestnet | Zora | ZoraGoerli | ZoraSepolia | Mode | ModeSepolia => {
717 "BLOCKSCOUT_API_KEY"
718 }
719
720 Boba => "BOBASCAN_API_KEY",
721
722 ScrollAlphaTestnet
724 | Metis
725 | Chiado
726 | Sepolia
727 | Rsk
728 | Sokol
729 | Poa
730 | Oasis
731 | Emerald
732 | EmeraldTestnet
733 | Evmos
734 | EvmosTestnet
735 | AnvilHardhat
736 | Dev
737 | ZkSync
738 | ZkSyncTestnet
739 | FilecoinMainnet
740 | LineaTestnet
741 | Viction
742 | FilecoinCalibrationTestnet
743 | Elastos => return None,
744 };
745
746 Some(api_key_name)
747 }
748
749 pub fn etherscan_api_key(&self) -> Option<String> {
762 self.etherscan_api_key_name().and_then(|name| std::env::var(name).ok())
763 }
764}
765
766#[cfg(test)]
767mod tests {
768 use super::*;
769 use strum::IntoEnumIterator;
770
771 #[test]
772 fn default() {
773 assert_eq!(serde_json::to_string(&Chain::default()).unwrap(), "\"mainnet\"");
774 }
775
776 #[test]
777 fn enum_iter() {
778 assert_eq!(Chain::COUNT, Chain::iter().size_hint().0);
779 }
780
781 #[test]
782 fn roundtrip_string() {
783 for chain in Chain::iter() {
784 let chain_string = chain.to_string();
785 assert_eq!(chain_string, format!("{chain}"));
786 assert_eq!(chain_string.as_str(), chain.as_ref());
787 assert_eq!(serde_json::to_string(&chain).unwrap(), format!("\"{chain_string}\""));
788
789 assert_eq!(chain_string.parse::<Chain>().unwrap(), chain);
790 }
791 }
792
793 #[test]
794 fn roundtrip_serde() {
795 for chain in Chain::iter() {
796 let chain_string = serde_json::to_string(&chain).unwrap();
797 let chain_string = chain_string.replace('-', "_");
798 assert_eq!(serde_json::from_str::<'_, Chain>(&chain_string).unwrap(), chain);
799 }
800 }
801
802 #[test]
803 fn aliases() {
804 use Chain::*;
805
806 const ALIASES: &[(Chain, &[&str])] = &[
808 (Mainnet, &["ethlive"]),
809 (BinanceSmartChain, &["bsc", "binance-smart-chain"]),
810 (BinanceSmartChainTestnet, &["bsc-testnet", "binance-smart-chain-testnet"]),
811 (Gnosis, &["gnosis", "gnosis-chain"]),
812 (PolygonMumbai, &["mumbai"]),
813 (PolygonZkEvm, &["zkevm", "polygon-zkevm"]),
814 (PolygonZkEvmTestnet, &["zkevm-testnet", "polygon-zkevm-testnet"]),
815 (AnvilHardhat, &["anvil", "hardhat"]),
816 (AvalancheFuji, &["fuji"]),
817 (ZkSync, &["zksync"]),
818 (Mantle, &["mantle"]),
819 (MantleTestnet, &["mantle-testnet"]),
820 (Viction, &["viction"]),
821 (Base, &["base"]),
822 (BaseGoerli, &["base-goerli"]),
823 (BaseSepolia, &["base-sepolia"]),
824 ];
825
826 for &(chain, aliases) in ALIASES {
827 for &alias in aliases {
828 assert_eq!(alias.parse::<Chain>().unwrap(), chain);
829 let s = alias.to_string().replace('-', "_");
830 assert_eq!(serde_json::from_str::<Chain>(&format!("\"{s}\"")).unwrap(), chain);
831 }
832 }
833 }
834
835 #[test]
836 fn serde_to_string_match() {
837 for chain in Chain::iter() {
838 let chain_serde = serde_json::to_string(&chain).unwrap();
839 let chain_string = format!("\"{chain}\"");
840 assert_eq!(chain_serde, chain_string);
841 }
842 }
843}