1extern crate alloc;
2use alloc::vec::Vec;
3
4pub const MAINNET_GENESIS_HASH: &[u8] = &[
6 74u8, 88, 123, 241, 122, 64, 78, 53, 114, 116, 122, 221, 122, 171, 123, 190, 86, 232, 5, 165,
7 71, 156, 108, 67, 111, 7, 243, 111, 204, 141, 58, 225,
8];
9
10pub const TESTNET_ON_PASEO_GENESIS_HASH: &[u8] = &[
12 32, 60, 104, 56, 252, 120, 234, 54, 96, 162, 242, 152, 165, 141, 133, 149, 25, 199, 42, 94,
13 253, 192, 241, 148, 171, 214, 240, 213, 206, 24, 56, 224,
14];
15
16pub const TESTNET_ON_WESTEND_GENESIS_HASH: &[u8] = &[
18 225, 67, 242, 56, 3, 172, 80, 232, 246, 248, 230, 38, 149, 209, 206, 158, 78, 29, 104, 170, 54,
19 193, 205, 44, 253, 21, 52, 2, 19, 243, 66, 62,
20];
21
22#[derive(Debug, Clone, PartialEq)]
24pub enum DetectedChainType {
25 Unknown,
27 FrequencyMainNet,
29 FrequencyPaseoTestNet,
31 FrequencyWestendTestNet,
33}
34
35pub fn get_chain_type_by_genesis_hash(genesis_hash: &[u8]) -> DetectedChainType {
37 match genesis_hash {
38 MAINNET_GENESIS_HASH => DetectedChainType::FrequencyMainNet,
39 TESTNET_ON_PASEO_GENESIS_HASH => DetectedChainType::FrequencyPaseoTestNet,
40 TESTNET_ON_WESTEND_GENESIS_HASH => DetectedChainType::FrequencyWestendTestNet,
41 _ => DetectedChainType::Unknown,
42 }
43}
44
45pub fn to_abi_compatible_number<T: Into<u128>>(value: T) -> [u8; 32] {
47 let value_u128: u128 = value.into();
48 let bytes = value_u128.to_be_bytes();
49 let start_idx = 32 - bytes.len();
50 let mut result = [0u8; 32];
51 result[start_idx..].copy_from_slice(&bytes);
52 result
53}
54
55#[cfg(feature = "std")]
57pub mod as_hex {
58 use serde::{Deserializer, Serializer};
59
60 pub fn serialize<S>(bytes: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
62 where
63 S: Serializer,
64 {
65 impl_serde::serialize::serialize(bytes.as_slice(), serializer)
66 }
67
68 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error> {
70 impl_serde::serialize::deserialize(deserializer)
71 }
72}
73
74#[cfg(feature = "std")]
76pub mod as_hex_option {
77 use serde::{Deserializer, Serializer};
78
79 pub fn serialize<S>(bytes: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
81 where
82 S: Serializer,
83 {
84 match bytes {
85 Some(bytes) => impl_serde::serialize::serialize(bytes.as_slice(), serializer),
86 None => serializer.serialize_none(),
87 }
88 }
89
90 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
92 where
93 D: Deserializer<'de>,
94 {
95 impl_serde::serialize::deserialize(deserializer).map(Some)
96 }
97}
98#[cfg(feature = "std")]
100pub mod as_string {
101 use super::*;
102 use serde::{ser::Error, Deserialize, Deserializer, Serialize, Serializer};
103
104 pub fn serialize<S: Serializer>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> {
106 std::str::from_utf8(bytes)
107 .map_err(|e| S::Error::custom(format!("Debug buffer contains invalid UTF8: {e:?}")))?
108 .serialize(serializer)
109 }
110
111 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error> {
113 Ok(String::deserialize(deserializer)?.into_bytes())
114 }
115}
116
117#[cfg(feature = "std")]
119pub mod as_string_option {
120 use super::*;
121 use serde::{ser::Error, Deserialize, Deserializer, Serialize, Serializer};
122
123 pub fn serialize<S: Serializer>(
125 bytes: &Option<Vec<u8>>,
126 serializer: S,
127 ) -> Result<S::Ok, S::Error> {
128 match bytes {
129 Some(bytes) => std::str::from_utf8(bytes)
130 .map_err(|e| {
131 S::Error::custom(format!("Debug buffer contains invalid UTF8: {e:?}"))
132 })?
133 .serialize(serializer),
134 None => serializer.serialize_none(),
135 }
136 }
137
138 pub fn deserialize<'de, D: Deserializer<'de>>(
140 deserializer: D,
141 ) -> Result<Option<Vec<u8>>, D::Error> {
142 let bytes = String::deserialize(deserializer)?.into_bytes();
143 Ok(match bytes.len() {
144 0 => None,
145 _ => Some(bytes),
146 })
147 }
148}
149
150const PREFIX: &str = "<Bytes>";
151const POSTFIX: &str = "</Bytes>";
152
153pub fn wrap_binary_data(data: Vec<u8>) -> Vec<u8> {
156 let mut encapsuled = PREFIX.as_bytes().to_vec();
157 encapsuled.append(&mut data.clone());
158 encapsuled.append(&mut POSTFIX.as_bytes().to_vec());
159 encapsuled
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165 use impl_serde::serialize::from_hex;
166 use parity_scale_codec::{Decode, Encode};
167 use scale_info::TypeInfo;
168 use serde::{Deserialize, Serialize};
169 use sp_core::U256;
170
171 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
172 #[derive(Default, Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
173 struct TestAsHex {
174 #[cfg_attr(feature = "std", serde(with = "as_hex",))]
175 pub data: Vec<u8>,
176 }
177
178 #[test]
179 fn as_hex_can_serialize() {
180 let test_data = TestAsHex { data: vec![1, 2, 3, 4] };
181 let result = serde_json::to_string(&test_data);
182 assert!(result.is_ok());
183 assert_eq!("{\"data\":\"0x01020304\"}", result.unwrap());
184 }
185
186 #[test]
187 fn as_hex_can_deserialize() {
188 let result: Result<TestAsHex, serde_json::Error> =
189 serde_json::from_str("{\"data\":\"0x01020304\"}");
190 assert!(result.is_ok());
191 assert_eq!(vec![1, 2, 3, 4], result.unwrap().data);
192 }
193
194 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
195 #[derive(Default, Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
196 struct TestAsHexOption {
197 #[cfg_attr(
198 feature = "std",
199 serde(with = "as_hex_option", skip_serializing_if = "Option::is_none", default)
200 )]
201 pub data: Option<Vec<u8>>,
202 }
203
204 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
205 #[derive(Default, Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
206 struct TestAsHexOptionNull {
207 #[cfg_attr(feature = "std", serde(with = "as_hex_option", default))]
208 pub data: Option<Vec<u8>>,
209 }
210
211 #[test]
212 fn as_hex_option_can_serialize() {
213 let test_data = TestAsHexOption { data: Some(vec![1, 2, 3, 4]) };
214 let result = serde_json::to_string(&test_data);
215 assert!(result.is_ok());
216 assert_eq!("{\"data\":\"0x01020304\"}", result.unwrap());
217 }
218
219 #[test]
220 fn as_hex_option_can_deserialize() {
221 let result: Result<TestAsHexOption, serde_json::Error> =
222 serde_json::from_str("{\"data\":\"0x01020304\"}");
223 assert!(result.is_ok());
224 assert_eq!(Some(vec![1, 2, 3, 4]), result.unwrap().data);
225 }
226
227 #[test]
228 fn as_hex_option_can_serialize_nothing_with_skip() {
229 let test_data = TestAsHexOption { data: None };
230 let result = serde_json::to_string(&test_data);
231 assert!(result.is_ok());
232 assert_eq!("{}", result.unwrap());
233 }
234
235 #[test]
236 fn as_hex_option_can_serialize_nothing_as_null() {
237 let test_data = TestAsHexOptionNull { data: None };
238 let result = serde_json::to_string(&test_data);
239 assert!(result.is_ok());
240 assert_eq!("{\"data\":null}", result.unwrap());
241 }
242
243 #[test]
244 fn as_hex_option_can_deserialize_nothing() {
245 let result: Result<TestAsHexOption, serde_json::Error> = serde_json::from_str("{}");
246 assert!(result.is_ok());
247 assert_eq!(None, result.unwrap().data);
248 }
249
250 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
251 #[derive(Default, Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
252 struct TestAsString {
253 #[cfg_attr(feature = "std", serde(with = "as_string"))]
254 pub data: Vec<u8>,
255 }
256
257 #[test]
258 fn as_string_can_serialize() {
259 let test_data = TestAsString {
260 data: vec![
261 0xe8, 0x95, 0x99, 0x49, 0xdd, 0x9d, 0xcd, 0x99, 0xe0, 0xbc, 0x8d, 0x4c, 0xd0, 0xbc,
262 ],
263 };
264 let result = serde_json::to_string(&test_data);
265 assert!(result.is_ok());
266 assert_eq!("{\"data\":\"蕙Iݝ͙།Lм\"}", result.unwrap());
267 }
268
269 #[test]
270 fn as_string_can_deserialize() {
271 let result: Result<TestAsString, serde_json::Error> =
272 serde_json::from_str("{\"data\":\"蕙Iݝ͙།Lм\"}");
273 assert!(result.is_ok());
274 assert_eq!(
275 vec![
276 0xe8, 0x95, 0x99, 0x49, 0xdd, 0x9d, 0xcd, 0x99, 0xe0, 0xbc, 0x8d, 0x4c, 0xd0, 0xbc
277 ],
278 result.unwrap().data
279 );
280 }
281
282 #[test]
283 fn as_string_errors_for_bad_utf8_vec() {
284 let test_data = TestAsString { data: vec![0xc3, 0x28] };
285 let result = serde_json::to_string(&test_data);
286 assert!(result.is_err());
287 }
288
289 #[test]
290 fn as_string_errors_for_bad_utf8_str() {
291 let result: Result<TestAsString, serde_json::Error> =
292 serde_json::from_str("{\"data\":\"\\xa0\\xa1\"}");
293 assert!(result.is_err());
294 }
295
296 #[test]
297 fn get_chain_type_by_genesis_hash_with_mainnet_genesis_should_get_mainnet() {
298 let known_genesis =
300 from_hex("4a587bf17a404e3572747add7aab7bbe56e805a5479c6c436f07f36fcc8d3ae1").unwrap();
301
302 let detected = get_chain_type_by_genesis_hash(&known_genesis);
304
305 assert_eq!(detected, DetectedChainType::FrequencyMainNet);
307 }
308
309 #[test]
310 fn get_chain_type_by_genesis_hash_with_paseo_genesis_should_get_paseo() {
311 let known_genesis =
313 from_hex("203c6838fc78ea3660a2f298a58d859519c72a5efdc0f194abd6f0d5ce1838e0").unwrap();
314
315 let detected = get_chain_type_by_genesis_hash(&known_genesis);
317
318 assert_eq!(detected, DetectedChainType::FrequencyPaseoTestNet);
320 }
321
322 #[test]
323 fn abi_compatible_number_should_work_with_different_types() {
324 let u8_val: u8 = 42;
326 let coded_u8_val = to_abi_compatible_number(u8_val);
327 let u8_val: U256 = u8_val.into();
328 assert_eq!(
329 coded_u8_val.to_vec(),
330 sp_core::bytes::from_hex(&format!("0x{:064x}", u8_val)).unwrap()
331 );
332
333 let u16_val: u16 = 12345;
335 let coded_u16_val = to_abi_compatible_number(u16_val);
336 let u16_val: U256 = u16_val.into();
337 assert_eq!(
338 coded_u16_val.to_vec(),
339 sp_core::bytes::from_hex(&format!("0x{:064x}", u16_val)).unwrap()
340 );
341
342 let u32_val: u32 = 305419896;
344 let coded_u32_val = to_abi_compatible_number(u32_val);
345 let u32_val: U256 = u32_val.into();
346 assert_eq!(
347 coded_u32_val.to_vec(),
348 sp_core::bytes::from_hex(&format!("0x{:064x}", u32_val)).unwrap()
349 );
350
351 let u64_val: u64 = 1234567890123456789;
353 let coded_u64_val = to_abi_compatible_number(u64_val);
354 let u64_val: U256 = u64_val.into();
355 assert_eq!(
356 coded_u64_val.to_vec(),
357 sp_core::bytes::from_hex(&format!("0x{:064x}", u64_val)).unwrap()
358 );
359
360 let u128_val: u128 = 340282366920938463463374607431768211455; let coded_u128_val = to_abi_compatible_number(u128_val);
363 let u128_val: U256 = u128_val.into();
364 assert_eq!(
365 coded_u128_val.to_vec(),
366 sp_core::bytes::from_hex(&format!("0x{:064x}", u128_val)).unwrap()
367 );
368 }
369
370 #[test]
371 fn get_chain_type_by_genesis_hash_with_westend_genesis_should_get_westend() {
372 let known_genesis =
374 from_hex("e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e").unwrap();
375
376 let detected = get_chain_type_by_genesis_hash(&known_genesis);
378
379 assert_eq!(detected, DetectedChainType::FrequencyWestendTestNet);
381 }
382}