miden_objects/address/
network_id.rs

1use alloc::boxed::Box;
2use alloc::str::FromStr;
3use alloc::string::ToString;
4
5use bech32::Hrp;
6
7use crate::errors::NetworkIdError;
8
9// This is essentially a wrapper around [`bech32::Hrp`] but that type does not actually appear in
10// the public API since that crate does not have a stable release.
11
12/// The identifier of a Miden network.
13#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub enum NetworkId {
15    Mainnet,
16    Testnet,
17    Devnet,
18    // Box the [`CustomNetworkId`] to keep the stack size of network ID relatively small.
19    Custom(Box<CustomNetworkId>),
20}
21
22impl NetworkId {
23    const MAINNET: &str = "mm";
24    const TESTNET: &str = "mtst";
25    const DEVNET: &str = "mdev";
26
27    /// Constructs a new [`NetworkId`] from a string.
28    ///
29    /// # Errors
30    ///
31    /// Returns an error if:
32    /// - the string does not contain between 1 to 83 US-ASCII characters.
33    /// - each character is not in the range 33-126.
34    pub fn new(string: &str) -> Result<Self, NetworkIdError> {
35        Hrp::parse(string)
36            .map(Self::from_hrp)
37            .map_err(|source| NetworkIdError::NetworkIdParseError(source.to_string().into()))
38    }
39
40    /// Constructs a new [`NetworkId`] from an [`Hrp`].
41    ///
42    /// This method should not be made public to avoid having `bech32` types in the public API.
43    pub(crate) fn from_hrp(hrp: Hrp) -> Self {
44        match hrp.as_str() {
45            NetworkId::MAINNET => NetworkId::Mainnet,
46            NetworkId::TESTNET => NetworkId::Testnet,
47            NetworkId::DEVNET => NetworkId::Devnet,
48            _ => NetworkId::Custom(Box::new(CustomNetworkId::from_hrp(hrp))),
49        }
50    }
51
52    /// Returns the [`Hrp`] of this network ID.
53    ///
54    /// This method should not be made public to avoid having `bech32` types in the public API.
55    pub(crate) fn into_hrp(self) -> Hrp {
56        match self {
57            NetworkId::Mainnet => {
58                Hrp::parse(NetworkId::MAINNET).expect("mainnet hrp should be valid")
59            },
60            NetworkId::Testnet => {
61                Hrp::parse(NetworkId::TESTNET).expect("testnet hrp should be valid")
62            },
63            NetworkId::Devnet => Hrp::parse(NetworkId::DEVNET).expect("devnet hrp should be valid"),
64            NetworkId::Custom(custom) => custom.as_hrp(),
65        }
66    }
67
68    /// Returns the string representation of the network ID.
69    pub fn as_str(&self) -> &str {
70        match self {
71            NetworkId::Mainnet => NetworkId::MAINNET,
72            NetworkId::Testnet => NetworkId::TESTNET,
73            NetworkId::Devnet => NetworkId::DEVNET,
74            NetworkId::Custom(custom) => custom.as_str(),
75        }
76    }
77
78    /// Returns `true` if the network ID is the Miden mainnet, `false` otherwise.
79    pub fn is_mainnet(&self) -> bool {
80        matches!(self, NetworkId::Mainnet)
81    }
82
83    /// Returns `true` if the network ID is the Miden testnet, `false` otherwise.
84    pub fn is_testnet(&self) -> bool {
85        matches!(self, NetworkId::Testnet)
86    }
87
88    /// Returns `true` if the network ID is the Miden devnet, `false` otherwise.
89    pub fn is_devnet(&self) -> bool {
90        matches!(self, NetworkId::Devnet)
91    }
92}
93
94impl FromStr for NetworkId {
95    type Err = NetworkIdError;
96
97    /// Constructs a new [`NetworkId`] from a string.
98    ///
99    /// See [`NetworkId::new`] for details on errors.
100    fn from_str(string: &str) -> Result<Self, Self::Err> {
101        Self::new(string)
102    }
103}
104
105impl core::fmt::Display for NetworkId {
106    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107        f.write_str(self.as_str())
108    }
109}
110
111// CUSTOM NETWORK ID
112// ================================================================================================
113
114/// A wrapper around bech32 HRP(human-readable part) for custom network identifiers.
115#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
116pub struct CustomNetworkId {
117    hrp: Hrp,
118}
119
120impl CustomNetworkId {
121    /// Creates a new [`CustomNetworkId`] from a [`bech32::Hrp`].
122    pub(crate) fn from_hrp(hrp: Hrp) -> Self {
123        CustomNetworkId { hrp }
124    }
125
126    /// Converts this [`CustomNetworkId`] to a [`bech32::Hrp`].
127    pub(crate) fn as_hrp(&self) -> Hrp {
128        self.hrp
129    }
130
131    /// Returns the string representation of this custom HRP.
132    pub fn as_str(&self) -> &str {
133        self.hrp.as_str()
134    }
135}
136
137impl FromStr for CustomNetworkId {
138    type Err = NetworkIdError;
139
140    /// Creates a [`CustomNetworkId`] from a String.
141    /// # Errors
142    ///
143    /// Returns an error if the string is not a valid HRP according to bech32 rules
144    fn from_str(hrp_str: &str) -> Result<Self, Self::Err> {
145        Ok(CustomNetworkId {
146            hrp: Hrp::parse(hrp_str)
147                .map_err(|source| NetworkIdError::NetworkIdParseError(source.to_string().into()))?,
148        })
149    }
150}
151
152impl core::fmt::Display for CustomNetworkId {
153    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
154        f.write_str(self.as_str())
155    }
156}