starknet_devnet_types/
chain_id.rs1use std::fmt::Display;
2use std::str::FromStr;
3
4use starknet_rs_core::chain_id::{MAINNET, SEPOLIA};
5use starknet_rs_core::utils::{cairo_short_string_to_felt, parse_cairo_short_string};
6use starknet_types_core::felt::Felt;
7
8use crate::error::ConversionError;
9
10#[derive(Clone, Copy, Debug)]
11pub enum ChainId {
12 Mainnet,
13 Testnet,
14 Custom(Felt),
15}
16
17impl ChainId {
18 const TESTNET: Felt = Felt::from_raw([
23 398700013197595345,
24 18446744073709551615,
25 18446744073709548950,
26 3753493103916128178,
27 ]);
28
29 pub const fn goerli_legacy_id() -> Felt {
30 Self::TESTNET
31 }
32
33 pub fn to_felt(&self) -> Felt {
34 Felt::from(self)
35 }
36}
37
38impl Display for ChainId {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 let felt = Felt::from(self);
41 let str = parse_cairo_short_string(&felt).map_err(|_| std::fmt::Error)?;
42 f.write_str(&str)
43 }
44}
45
46impl FromStr for ChainId {
47 type Err = ConversionError;
48
49 fn from_str(s: &str) -> Result<Self, Self::Err> {
50 let uppercase_chain_id_str = s.to_ascii_uppercase();
51 let chain_id = match uppercase_chain_id_str.as_str() {
52 "MAINNET" => ChainId::Mainnet,
53 "TESTNET" => ChainId::Testnet,
54 _ => {
55 let felt = cairo_short_string_to_felt(&uppercase_chain_id_str)
56 .map_err(|err| ConversionError::OutOfRangeError(err.to_string()))?;
57 ChainId::Custom(felt)
58 }
59 };
60
61 Ok(chain_id)
62 }
63}
64
65impl From<ChainId> for Felt {
66 fn from(value: ChainId) -> Self {
67 match value {
68 ChainId::Mainnet => MAINNET,
69 ChainId::Testnet => SEPOLIA,
70 ChainId::Custom(felt) => felt,
71 }
72 }
73}
74
75impl From<&ChainId> for Felt {
76 fn from(value: &ChainId) -> Self {
77 match value {
78 ChainId::Mainnet => MAINNET,
79 ChainId::Testnet => SEPOLIA,
80 ChainId::Custom(felt) => *felt,
81 }
82 }
83}
84
85impl From<Felt> for ChainId {
86 fn from(value: Felt) -> Self {
87 if value == MAINNET {
88 ChainId::Mainnet
89 } else if value == SEPOLIA {
90 ChainId::Testnet
91 } else {
92 ChainId::Custom(value)
93 }
94 }
95}
96
97impl From<ChainId> for starknet_api::core::ChainId {
98 fn from(value: ChainId) -> Self {
99 match value {
100 ChainId::Mainnet => Self::Mainnet,
101 ChainId::Testnet => Self::Sepolia,
102 ChainId::Custom(_) => Self::Other(format!("{value}")),
103 }
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::ChainId;
110
111 #[test]
112 fn check_conversion_to_starknet_api() {
113 let t = ChainId::Testnet;
114 let sat: starknet_api::core::ChainId = t.into();
115
116 assert_eq!(t.to_felt().to_hex_string(), sat.as_hex());
117 }
118
119 #[test]
120 fn test_display() {
121 assert_eq!(format!("{}", ChainId::Mainnet), "SN_MAIN");
122 assert_eq!(format!("{}", ChainId::Testnet), "SN_SEPOLIA");
123 }
124}