mithril_common/entities/
cardano_network.rs
1use serde::{Deserialize, Serialize};
2use std::fmt::Display;
3use thiserror::Error;
4
5use crate::{MagicId, StdResult};
6
7const MAINNET_MAGIC_ID: MagicId = 764824073;
8const TESTNET_MAGIC_ID: MagicId = 1097911063;
9const PREPROD_MAGIC_ID: MagicId = 1;
10const PREVIEW_MAGIC_ID: MagicId = 2;
11
12#[derive(Error, Debug)]
13pub enum CardanoNetworkError {
14 #[error("parse from code error: '{0}'")]
15 ParseFromCode(String),
16}
17
18#[allow(clippy::enum_variant_names)]
20#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, Hash, Eq, PartialOrd)]
21pub enum CardanoNetwork {
22 MainNet,
24
25 TestNet(MagicId),
27
28 DevNet(MagicId),
30}
31
32impl CardanoNetwork {
33 pub fn from_code(
35 network_code: String,
36 network_magic: Option<u64>,
37 ) -> Result<CardanoNetwork, CardanoNetworkError> {
38 match network_code.to_lowercase().as_str() {
39 "mainnet" => Ok(CardanoNetwork::MainNet),
40 "testnet" => Ok(CardanoNetwork::TestNet(TESTNET_MAGIC_ID)),
41 "preview" => Ok(CardanoNetwork::TestNet(PREVIEW_MAGIC_ID)),
42 "preprod" => Ok(CardanoNetwork::TestNet(PREPROD_MAGIC_ID)),
43 "private" => {
44 if let Some(magic) = network_magic {
45 Ok(CardanoNetwork::TestNet(magic))
46 } else {
47 Err(CardanoNetworkError::ParseFromCode(
48 "no NETWORK MAGIC number given for test network".to_string(),
49 ))
50 }
51 }
52 "devnet" => {
53 if let Some(magic) = network_magic {
54 Ok(CardanoNetwork::DevNet(magic))
55 } else {
56 Err(CardanoNetworkError::ParseFromCode(
57 "no NETWORK MAGIC number given for devnet network".to_string(),
58 ))
59 }
60 }
61 what => Err(CardanoNetworkError::ParseFromCode(format!(
62 "could not parse network '{what}', the only recognized networks are: mainnet, devnet, testnet, preview, preprod and private"
63 ))),
64 }
65 }
66
67 pub fn code(&self) -> MagicId {
69 match *self {
70 CardanoNetwork::MainNet => MAINNET_MAGIC_ID,
71 CardanoNetwork::DevNet(magic_id) => magic_id,
72 CardanoNetwork::TestNet(magic_id) => magic_id,
73 }
74 }
75
76 pub fn compute_allow_unparsable_block(&self, allow_unparsable_block: bool) -> StdResult<bool> {
78 let allow_unparsable_block = match self {
79 CardanoNetwork::MainNet => false,
80 CardanoNetwork::TestNet(id) if *id == PREPROD_MAGIC_ID => false,
81 _ => allow_unparsable_block,
82 };
83
84 Ok(allow_unparsable_block)
85 }
86}
87
88impl Display for CardanoNetwork {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 match *self {
91 CardanoNetwork::MainNet => write!(f, "mainnet"),
92 CardanoNetwork::DevNet(_) => write!(f, "devnet"),
93 CardanoNetwork::TestNet(magic_id) => match magic_id {
94 TESTNET_MAGIC_ID => write!(f, "testnet"),
95 PREVIEW_MAGIC_ID => write!(f, "preview"),
96 PREPROD_MAGIC_ID => write!(f, "preprod"),
97 _ => write!(f, "private"),
98 },
99 }
100 }
101}
102
103impl From<CardanoNetwork> for String {
104 fn from(network: CardanoNetwork) -> Self {
105 network.to_string()
106 }
107}
108
109impl From<&CardanoNetwork> for String {
110 fn from(network: &CardanoNetwork) -> Self {
111 network.to_string()
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn test_cardano_network_from_code() {
121 assert_eq!(
122 CardanoNetwork::from_code("mainnet".to_string(), None).unwrap(),
123 CardanoNetwork::MainNet
124 );
125 assert_eq!(
126 CardanoNetwork::from_code("mainnet".to_string(), Some(123)).unwrap(),
127 CardanoNetwork::MainNet
128 );
129 assert_eq!(
130 CardanoNetwork::from_code("preview".to_string(), None).unwrap(),
131 CardanoNetwork::TestNet(PREVIEW_MAGIC_ID)
132 );
133 assert_eq!(
134 CardanoNetwork::from_code("preview".to_string(), Some(123)).unwrap(),
135 CardanoNetwork::TestNet(PREVIEW_MAGIC_ID)
136 );
137 assert_eq!(
138 CardanoNetwork::from_code("preprod".to_string(), None).unwrap(),
139 CardanoNetwork::TestNet(PREPROD_MAGIC_ID)
140 );
141 assert_eq!(
142 CardanoNetwork::from_code("preprod".to_string(), Some(123)).unwrap(),
143 CardanoNetwork::TestNet(PREPROD_MAGIC_ID)
144 );
145 assert_eq!(
146 CardanoNetwork::from_code("testnet".to_string(), None).unwrap(),
147 CardanoNetwork::TestNet(TESTNET_MAGIC_ID)
148 );
149 assert_eq!(
150 CardanoNetwork::from_code("testnet".to_string(), Some(123)).unwrap(),
151 CardanoNetwork::TestNet(TESTNET_MAGIC_ID)
152 );
153 assert_eq!(
154 CardanoNetwork::from_code("private".to_string(), Some(123)).unwrap(),
155 CardanoNetwork::TestNet(123)
156 );
157 assert!(CardanoNetwork::from_code("private".to_string(), None).is_err());
158 }
159
160 #[test]
161 fn compute_allow_unparsable_block_should_always_return_false_on_mainnet_and_preprod() {
162 let allow_unparsable_block = CardanoNetwork::MainNet
163 .compute_allow_unparsable_block(false)
164 .unwrap();
165 assert!(!allow_unparsable_block);
166
167 let allow_unparsable_block = CardanoNetwork::MainNet
168 .compute_allow_unparsable_block(true)
169 .unwrap();
170 assert!(!allow_unparsable_block);
171
172 let allow_unparsable_block = CardanoNetwork::TestNet(PREPROD_MAGIC_ID)
173 .compute_allow_unparsable_block(false)
174 .unwrap();
175 assert!(!allow_unparsable_block);
176
177 let allow_unparsable_block = CardanoNetwork::TestNet(PREPROD_MAGIC_ID)
178 .compute_allow_unparsable_block(true)
179 .unwrap();
180 assert!(!allow_unparsable_block);
181 }
182
183 #[test]
184 fn compute_allow_unparsable_block_should_return_value_passed_in_parameter_on_all_networks_other_than_mainnet_and_preprod(
185 ) {
186 let allow_unparsable_block = CardanoNetwork::TestNet(PREVIEW_MAGIC_ID)
187 .compute_allow_unparsable_block(false)
188 .unwrap();
189 assert!(!allow_unparsable_block);
190
191 let allow_unparsable_block = CardanoNetwork::TestNet(PREVIEW_MAGIC_ID)
192 .compute_allow_unparsable_block(true)
193 .unwrap();
194 assert!(allow_unparsable_block);
195
196 let allow_unparsable_block = CardanoNetwork::TestNet(TESTNET_MAGIC_ID)
197 .compute_allow_unparsable_block(false)
198 .unwrap();
199 assert!(!allow_unparsable_block);
200
201 let allow_unparsable_block = CardanoNetwork::TestNet(TESTNET_MAGIC_ID)
202 .compute_allow_unparsable_block(true)
203 .unwrap();
204 assert!(allow_unparsable_block);
205
206 let allow_unparsable_block = CardanoNetwork::DevNet(123)
207 .compute_allow_unparsable_block(false)
208 .unwrap();
209 assert!(!allow_unparsable_block);
210
211 let allow_unparsable_block = CardanoNetwork::DevNet(123)
212 .compute_allow_unparsable_block(true)
213 .unwrap();
214 assert!(allow_unparsable_block);
215 }
216
217 #[test]
218 fn network_to_string() {
219 fn assert_all_conversions_eq(network: CardanoNetwork, expected: &str) {
220 assert_eq!(network.to_string(), expected);
221 assert_eq!(String::from(network), expected);
222 assert_eq!(String::from(&network), expected);
223 }
224
225 assert_all_conversions_eq(CardanoNetwork::MainNet, "mainnet");
226 assert_all_conversions_eq(CardanoNetwork::DevNet(123456), "devnet");
227 assert_all_conversions_eq(CardanoNetwork::TestNet(TESTNET_MAGIC_ID), "testnet");
228 assert_all_conversions_eq(CardanoNetwork::TestNet(PREVIEW_MAGIC_ID), "preview");
229 assert_all_conversions_eq(CardanoNetwork::TestNet(PREPROD_MAGIC_ID), "preprod");
230 assert_all_conversions_eq(CardanoNetwork::TestNet(123456), "private");
231 }
232}