mithril_common/entities/
cardano_network.rs1use 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 =
163 CardanoNetwork::MainNet.compute_allow_unparsable_block(false).unwrap();
164 assert!(!allow_unparsable_block);
165
166 let allow_unparsable_block =
167 CardanoNetwork::MainNet.compute_allow_unparsable_block(true).unwrap();
168 assert!(!allow_unparsable_block);
169
170 let allow_unparsable_block = CardanoNetwork::TestNet(PREPROD_MAGIC_ID)
171 .compute_allow_unparsable_block(false)
172 .unwrap();
173 assert!(!allow_unparsable_block);
174
175 let allow_unparsable_block = CardanoNetwork::TestNet(PREPROD_MAGIC_ID)
176 .compute_allow_unparsable_block(true)
177 .unwrap();
178 assert!(!allow_unparsable_block);
179 }
180
181 #[test]
182 fn compute_allow_unparsable_block_should_return_value_passed_in_parameter_on_all_networks_other_than_mainnet_and_preprod()
183 {
184 let allow_unparsable_block = CardanoNetwork::TestNet(PREVIEW_MAGIC_ID)
185 .compute_allow_unparsable_block(false)
186 .unwrap();
187 assert!(!allow_unparsable_block);
188
189 let allow_unparsable_block = CardanoNetwork::TestNet(PREVIEW_MAGIC_ID)
190 .compute_allow_unparsable_block(true)
191 .unwrap();
192 assert!(allow_unparsable_block);
193
194 let allow_unparsable_block = CardanoNetwork::TestNet(TESTNET_MAGIC_ID)
195 .compute_allow_unparsable_block(false)
196 .unwrap();
197 assert!(!allow_unparsable_block);
198
199 let allow_unparsable_block = CardanoNetwork::TestNet(TESTNET_MAGIC_ID)
200 .compute_allow_unparsable_block(true)
201 .unwrap();
202 assert!(allow_unparsable_block);
203
204 let allow_unparsable_block = CardanoNetwork::DevNet(123)
205 .compute_allow_unparsable_block(false)
206 .unwrap();
207 assert!(!allow_unparsable_block);
208
209 let allow_unparsable_block = CardanoNetwork::DevNet(123)
210 .compute_allow_unparsable_block(true)
211 .unwrap();
212 assert!(allow_unparsable_block);
213 }
214
215 #[test]
216 fn network_to_string() {
217 fn assert_all_conversions_eq(network: CardanoNetwork, expected: &str) {
218 assert_eq!(network.to_string(), expected);
219 assert_eq!(String::from(network), expected);
220 assert_eq!(String::from(&network), expected);
221 }
222
223 assert_all_conversions_eq(CardanoNetwork::MainNet, "mainnet");
224 assert_all_conversions_eq(CardanoNetwork::DevNet(123456), "devnet");
225 assert_all_conversions_eq(CardanoNetwork::TestNet(TESTNET_MAGIC_ID), "testnet");
226 assert_all_conversions_eq(CardanoNetwork::TestNet(PREVIEW_MAGIC_ID), "preview");
227 assert_all_conversions_eq(CardanoNetwork::TestNet(PREPROD_MAGIC_ID), "preprod");
228 assert_all_conversions_eq(CardanoNetwork::TestNet(123456), "private");
229 }
230}