1use codec::{Compact, CompactAs, Decode, Encode};
2
3use core::{fmt, str::FromStr};
4
5#[cfg(feature = "serde")]
6use serde::{de, de::DeserializeOwned, ser, Deserialize, Serialize};
7
8#[cfg(all(feature = "std", feature = "type_info"))]
9use scale_info::TypeInfo;
10
11#[cfg(not(feature = "std"))]
12use alloc::{format, string::String};
13use sp_core::crypto::Ss58Codec;
14use sp_std::prelude::*;
15
16pub use frame_metadata;
18
19pub use sp_core;
20
21pub use sp_core::hashing;
22
23pub use sp_weights;
24
25pub use sp_runtime::MultiSignature;
26
27#[derive(
29 Clone, Copy, Debug, Encode, Decode, CompactAs, Default, PartialEq, Eq, PartialOrd, Ord,
30)]
31#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33#[cfg_attr(feature = "serde", serde(transparent))]
34pub struct OldWeight(pub u64);
35
36pub mod per_things {
38 use super::*;
39
40 #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord)]
41 #[cfg_attr(feature = "std", derive(Hash))]
42 #[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
43 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
44 pub struct Perbill(pub u32);
45
46 impl CompactAs for Perbill {
47 type As = u32;
48
49 fn encode_as(&self) -> &Self::As {
50 &self.0
51 }
52
53 fn decode_from(v: Self::As) -> Result<Self, codec::Error> {
54 Ok(Self(v))
55 }
56 }
57
58 impl From<Compact<Self>> for Perbill {
59 fn from(c: Compact<Self>) -> Self {
60 c.0
61 }
62 }
63
64 impl From<sp_arithmetic::per_things::Perbill> for Perbill {
65 fn from(p: sp_arithmetic::per_things::Perbill) -> Self {
66 Self(p.deconstruct())
67 }
68 }
69
70 #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord)]
71 #[cfg_attr(feature = "std", derive(Hash))]
72 #[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
73 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
74 pub struct PerU16(pub u16);
75
76 impl CompactAs for PerU16 {
77 type As = u16;
78
79 fn encode_as(&self) -> &Self::As {
80 &self.0
81 }
82
83 fn decode_from(v: Self::As) -> Result<Self, codec::Error> {
84 Ok(Self(v))
85 }
86 }
87
88 impl From<Compact<Self>> for PerU16 {
89 fn from(c: Compact<Self>) -> Self {
90 c.0
91 }
92 }
93
94 impl From<sp_arithmetic::per_things::PerU16> for PerU16 {
95 fn from(p: sp_arithmetic::per_things::PerU16) -> Self {
96 Self(p.deconstruct())
97 }
98 }
99
100 #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord)]
101 #[cfg_attr(feature = "std", derive(Hash))]
102 #[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
103 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
104 pub struct Permill(pub u32);
105
106 impl CompactAs for Permill {
107 type As = u32;
108
109 fn encode_as(&self) -> &Self::As {
110 &self.0
111 }
112
113 fn decode_from(v: Self::As) -> Result<Self, codec::Error> {
114 Ok(Self(v))
115 }
116 }
117
118 impl From<Compact<Self>> for Permill {
119 fn from(c: Compact<Self>) -> Self {
120 c.0
121 }
122 }
123
124 impl From<sp_arithmetic::per_things::Permill> for Permill {
125 fn from(p: sp_arithmetic::per_things::Permill) -> Self {
126 Self(p.deconstruct())
127 }
128 }
129
130 #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord)]
131 #[cfg_attr(feature = "std", derive(Hash))]
132 #[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
133 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
134 pub struct Percent(pub u8);
135
136 impl CompactAs for Percent {
137 type As = u8;
138
139 fn encode_as(&self) -> &Self::As {
140 &self.0
141 }
142
143 fn decode_from(v: Self::As) -> Result<Self, codec::Error> {
144 Ok(Self(v))
145 }
146 }
147
148 impl From<Compact<Self>> for Percent {
149 fn from(c: Compact<Self>) -> Self {
150 c.0
151 }
152 }
153
154 impl From<sp_arithmetic::per_things::Percent> for Percent {
155 fn from(p: sp_arithmetic::per_things::Percent) -> Self {
156 Self(p.deconstruct())
157 }
158 }
159}
160
161#[cfg(not(feature = "serde"))]
162pub trait AccountTraits: Clone + Encode + Decode + Default + FromStr {}
163
164#[cfg(not(feature = "serde"))]
165impl<T> AccountTraits for T where T: Clone + Encode + Decode + Default + FromStr {}
166
167#[cfg(feature = "serde")]
168pub trait AccountTraits:
169 Clone + Encode + Decode + Default + FromStr + ser::Serialize + DeserializeOwned
170{
171}
172
173#[cfg(feature = "serde")]
174impl<T> AccountTraits for T where
175 T: Clone + Encode + Decode + Default + FromStr + ser::Serialize + DeserializeOwned
176{
177}
178
179#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord)]
181#[cfg_attr(feature = "std", derive(Hash))]
182#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
183pub enum MultiAddress<AccountId: AccountTraits, AccountIndex: AccountTraits> {
184 Id(AccountId),
186 Index(#[codec(compact)] AccountIndex),
188 Raw(Vec<u8>),
190 Address32([u8; 32]),
192 Address20([u8; 20]),
194}
195
196#[cfg(feature = "serde")]
197impl<AccountId, AccountIndex> ser::Serialize for MultiAddress<AccountId, AccountIndex>
198where
199 AccountId: AccountTraits,
200 AccountIndex: AccountTraits,
201{
202 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
203 where
204 S: ser::Serializer,
205 {
206 match self {
207 Self::Id(account) => {
208 if serializer.is_human_readable() {
209 account.serialize(serializer)
210 } else {
211 serializer.serialize_newtype_variant("MultiAddress", 0, "Id", account)
212 }
213 }
214 Self::Index(index) => serializer.serialize_newtype_variant("MultiAddress", 1, "Index", index),
215 Self::Raw(data) => {
216 if serializer.is_human_readable() {
217 let h = hex::encode(data.as_slice());
218 serializer.serialize_newtype_variant("MultiAddress", 2, "Raw", &h)
219 } else {
220 serializer.serialize_newtype_variant("MultiAddress", 2, "Raw", data)
221 }
222 }
223 Self::Address32(address) => {
224 if serializer.is_human_readable() {
225 let h = hex::encode(&address[..]);
226 serializer.serialize_newtype_variant("MultiAddress", 3, "Address32", &h)
227 } else {
228 serializer.serialize_newtype_variant("MultiAddress", 3, "Address32", address)
229 }
230 }
231 Self::Address20(address) => {
232 if serializer.is_human_readable() {
233 let h = hex::encode(&address[..]);
234 serializer.serialize_newtype_variant("MultiAddress", 4, "Address20", &h)
235 } else {
236 serializer.serialize_newtype_variant("MultiAddress", 4, "Address20", address)
237 }
238 }
239 }
240 }
241}
242
243#[cfg(feature = "serde")]
244#[derive(Deserialize)]
245#[serde(field_identifier, rename_all = "PascalCase")]
246enum MultiAddressField {
247 Id,
248 Index,
249 Raw,
250 Address32,
251 Address20,
252}
253
254#[cfg(feature = "serde")]
255#[derive(Default)]
256struct MultiAddressVisitor<AccountId: AccountTraits, AccountIndex: AccountTraits> {
257 is_human_readable: bool,
258 _phantom: core::marker::PhantomData<(AccountId, AccountIndex)>,
259}
260
261#[cfg(feature = "serde")]
262impl<AccountId: AccountTraits, AccountIndex: AccountTraits>
263 MultiAddressVisitor<AccountId, AccountIndex>
264{
265 fn new(is_human_readable: bool) -> Self {
266 Self {
267 is_human_readable,
268 _phantom: Default::default(),
269 }
270 }
271}
272
273#[cfg(feature = "serde")]
274impl<'de, AccountId, AccountIndex> de::Visitor<'de> for MultiAddressVisitor<AccountId, AccountIndex>
275where
276 AccountId: AccountTraits,
277 AccountIndex: AccountTraits,
278{
279 type Value = MultiAddress<AccountId, AccountIndex>;
280
281 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
282 formatter.write_str("AccountId or MultiAddress")
283 }
284
285 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
286 where
287 E: de::Error,
288 {
289 let account = AccountId::from_str(v)
290 .map_err(|_e| de::Error::custom(format!("Failed to decode AccountId")))?;
291 Ok(MultiAddress::Id(account))
292 }
293
294 fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
295 where
296 V: de::MapAccess<'de>,
297 {
298 let mut address = None;
299 while let Some(key) = map.next_key()? {
300 match key {
301 MultiAddressField::Id => {
302 if address.is_some() {
303 return Err(de::Error::duplicate_field("Id"));
304 }
305 address = Some(MultiAddress::Id(map.next_value()?));
306 }
307 MultiAddressField::Index => {
308 if address.is_some() {
309 return Err(de::Error::duplicate_field("Index"));
310 }
311 address = Some(MultiAddress::Index(map.next_value()?));
312 }
313 MultiAddressField::Raw => {
314 if address.is_some() {
315 return Err(de::Error::duplicate_field("Raw"));
316 }
317 if self.is_human_readable {
318 let h: &str = map.next_value()?;
319 let off = if h.starts_with("0x") { 2 } else { 0 };
320 let data = hex::decode(&h[off..]).map_err(|e| de::Error::custom(e))?;
321 address = Some(MultiAddress::Raw(data));
322 } else {
323 address = Some(MultiAddress::Raw(map.next_value()?));
324 }
325 }
326 MultiAddressField::Address32 => {
327 if address.is_some() {
328 return Err(de::Error::duplicate_field("Address32"));
329 }
330 if self.is_human_readable {
331 let h: &str = map.next_value()?;
332 let mut data = [0u8; 32];
333 let off = if h.starts_with("0x") { 2 } else { 0 };
334 hex::decode_to_slice(&h[off..], &mut data).map_err(|e| de::Error::custom(e))?;
335 address = Some(MultiAddress::Address32(data));
336 } else {
337 address = Some(MultiAddress::Address32(map.next_value()?));
338 }
339 }
340 MultiAddressField::Address20 => {
341 if address.is_some() {
342 return Err(de::Error::duplicate_field("Address20"));
343 }
344 if self.is_human_readable {
345 let h: &str = map.next_value()?;
346 let mut data = [0u8; 20];
347 let off = if h.starts_with("0x") { 2 } else { 0 };
348 hex::decode_to_slice(&h[off..], &mut data).map_err(|e| de::Error::custom(e))?;
349 address = Some(MultiAddress::Address20(data));
350 } else {
351 address = Some(MultiAddress::Address20(map.next_value()?));
352 }
353 }
354 }
355 }
356 let address =
357 address.ok_or_else(|| de::Error::missing_field("Id, Index, Raw, Address32, or Address20"))?;
358 Ok(address)
359 }
360}
361
362#[cfg(feature = "serde")]
363impl<'de, AccountId, AccountIndex> Deserialize<'de> for MultiAddress<AccountId, AccountIndex>
364where
365 AccountId: AccountTraits,
366 AccountIndex: AccountTraits,
367{
368 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
369 where
370 D: de::Deserializer<'de>,
371 {
372 let visitor = MultiAddressVisitor::new(deserializer.is_human_readable());
373 if deserializer.is_human_readable() {
374 deserializer.deserialize_any(visitor)
375 } else {
376 deserializer.deserialize_enum(
377 "MultiAddress",
378 &["Id", "Index", "Raw", "Address32", "Address20"],
379 visitor,
380 )
381 }
382 }
383}
384
385impl<AccountId: AccountTraits, AccountIndex: AccountTraits> From<&AccountId>
386 for MultiAddress<AccountId, AccountIndex>
387{
388 fn from(other: &AccountId) -> Self {
389 Self::Id(other.clone())
390 }
391}
392
393impl<AccountId: AccountTraits, AccountIndex: AccountTraits> From<AccountId>
394 for MultiAddress<AccountId, AccountIndex>
395{
396 fn from(other: AccountId) -> Self {
397 Self::Id(other)
398 }
399}
400
401impl<AccountIndex: AccountTraits> From<sp_runtime::AccountId32>
402 for MultiAddress<AccountId, AccountIndex>
403{
404 fn from(other: sp_runtime::AccountId32) -> Self {
405 Self::Id(other.into())
406 }
407}
408
409impl<AccountId: AccountTraits, AccountIndex: AccountTraits>
410 From<sp_runtime::MultiAddress<AccountId, AccountIndex>>
411 for MultiAddress<AccountId, AccountIndex>
412{
413 fn from(other: sp_runtime::MultiAddress<AccountId, AccountIndex>) -> Self {
414 match other {
415 sp_runtime::MultiAddress::Id(v) => Self::Id(v),
416 sp_runtime::MultiAddress::Index(v) => Self::Index(v),
417 sp_runtime::MultiAddress::Raw(v) => Self::Raw(v),
418 sp_runtime::MultiAddress::Address32(v) => Self::Address32(v),
419 sp_runtime::MultiAddress::Address20(v) => Self::Address20(v),
420 }
421 }
422}
423
424impl<AccountId: AccountTraits, AccountIndex: AccountTraits>
425 From<&sp_runtime::MultiAddress<AccountId, AccountIndex>>
426 for MultiAddress<AccountId, AccountIndex>
427{
428 fn from(other: &sp_runtime::MultiAddress<AccountId, AccountIndex>) -> Self {
429 Self::from(other.clone())
430 }
431}
432
433#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)]
434#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
435pub struct AccountId(pub [u8; 32]);
436
437impl AccountId {
438 pub fn to_hex(&self) -> String {
439 format!("0x{}", hex::encode(&self.0))
440 }
441}
442
443impl FromStr for AccountId {
444 type Err = crate::Error;
445
446 fn from_str(s: &str) -> Result<Self, Self::Err> {
447 match s.len() {
448 66 if s.starts_with("0x") => {
449 let mut id = AccountId::default();
450 hex::decode_to_slice(&s[2..], &mut id.0)?;
451 Ok(id)
452 }
453 64 => {
454 let mut id = AccountId::default();
455 hex::decode_to_slice(&s[0..], &mut id.0)?;
456 Ok(id)
457 }
458 _ => Ok(AccountId::from_ss58check(s)?),
459 }
460 }
461}
462
463#[cfg(not(feature = "serde"))]
464impl AccountId {
465 pub fn to_ss58check(&self) -> String {
466 format!("0x{}", hex::encode(&self.0))
467 }
468}
469
470impl Ss58Codec for AccountId {}
471
472impl fmt::Display for AccountId {
473 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
474 write!(f, "{}", self.to_ss58check())
475 }
476}
477
478impl fmt::Debug for AccountId {
479 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
480 let ss58 = self.to_ss58check();
481 let h = hex::encode(&self.0);
482 write!(f, "0x{} ({}...)", h, &ss58[0..8])
483 }
484}
485
486#[cfg(feature = "serde")]
487impl Serialize for AccountId {
488 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
489 where
490 S: ser::Serializer,
491 {
492 if serializer.is_human_readable() {
493 let ss58 = self.to_ss58check();
494 serializer.serialize_str(&ss58)
495 } else {
496 self.0.serialize(serializer)
497 }
498 }
499}
500
501#[cfg(feature = "serde")]
502impl<'de> Deserialize<'de> for AccountId {
503 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
504 where
505 D: de::Deserializer<'de>,
506 {
507 if deserializer.is_human_readable() {
508 struct StringOrBytesVisitor;
509
510 impl<'de> de::Visitor<'de> for StringOrBytesVisitor {
511 type Value = AccountId;
512
513 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
514 formatter.write_str("a hex string or [u8; 32]")
515 }
516
517 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
518 where
519 E: de::Error,
520 {
521 Ok(AccountId::from_str(s).map_err(|e| de::Error::custom(e))?)
522 }
523
524 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
525 where
526 A: de::SeqAccess<'de>,
527 {
528 let mut id = AccountId::default();
529 for n in 0..32 {
530 id.0[n] = seq
531 .next_element()?
532 .ok_or_else(|| de::Error::invalid_length(n, &self))?;
533 }
534 Ok(id)
535 }
536 }
537 deserializer.deserialize_any(StringOrBytesVisitor)
538 } else {
539 Ok(Self(Deserialize::deserialize(deserializer)?))
540 }
541 }
542}
543
544impl<'a> TryFrom<&'a [u8]> for AccountId {
545 type Error = ();
546
547 fn try_from(x: &'a [u8]) -> Result<Self, ()> {
548 Ok(AccountId(x.try_into().map_err(|_| ())?))
549 }
550}
551
552impl AsMut<[u8; 32]> for AccountId {
553 fn as_mut(&mut self) -> &mut [u8; 32] {
554 &mut self.0
555 }
556}
557
558impl AsMut<[u8]> for AccountId {
559 fn as_mut(&mut self) -> &mut [u8] {
560 &mut self.0[..]
561 }
562}
563
564impl AsRef<[u8; 32]> for AccountId {
565 fn as_ref(&self) -> &[u8; 32] {
566 &self.0
567 }
568}
569
570impl AsRef<[u8]> for AccountId {
571 fn as_ref(&self) -> &[u8] {
572 &self.0[..]
573 }
574}
575
576impl sp_core::ByteArray for AccountId {
577 const LEN: usize = 32;
578}
579
580impl From<[u8; 32]> for AccountId {
581 fn from(p: [u8; 32]) -> Self {
582 Self(p)
583 }
584}
585
586impl From<sp_core::sr25519::Public> for AccountId {
587 fn from(p: sp_core::sr25519::Public) -> Self {
588 p.0.into()
589 }
590}
591
592impl From<sp_core::ed25519::Public> for AccountId {
593 fn from(p: sp_core::ed25519::Public) -> Self {
594 p.0.into()
595 }
596}
597
598impl From<sp_runtime::AccountId32> for AccountId {
599 fn from(id: sp_runtime::AccountId32) -> Self {
600 Self(*id.as_ref())
601 }
602}
603
604impl From<&sp_runtime::AccountId32> for AccountId {
605 fn from(id: &sp_runtime::AccountId32) -> Self {
606 Self(*id.as_ref())
607 }
608}
609
610impl From<AccountId> for sp_runtime::AccountId32 {
611 fn from(id: AccountId) -> Self {
612 Self::new(id.0)
613 }
614}
615
616impl From<&AccountId> for sp_runtime::AccountId32 {
617 fn from(id: &AccountId) -> Self {
618 Self::new(id.0)
619 }
620}
621
622pub type GenericAddress = MultiAddress<AccountId, u32>;
623
624#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)]
625#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
626#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
627#[cfg_attr(
628 feature = "utoipa",
629 schema(example = "0x0600000000000000000000000000000000000000000000000000000000000000")
630)]
631pub struct IdentityId(pub [u8; 32]);
632
633impl fmt::Display for IdentityId {
634 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
635 let h = hex::encode(&self.0);
636 write!(f, "0x{}", h)
637 }
638}
639
640impl fmt::Debug for IdentityId {
641 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
642 let h = hex::encode(&self.0);
643 write!(f, "0x{}", h)
644 }
645}
646
647#[cfg(feature = "serde")]
648impl Serialize for IdentityId {
649 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
650 where
651 S: ser::Serializer,
652 {
653 if serializer.is_human_readable() {
654 let h = format!("0x{}", hex::encode(&self.0));
655 serializer.serialize_str(&h)
656 } else {
657 self.0.serialize(serializer)
658 }
659 }
660}
661
662#[cfg(feature = "serde")]
663impl<'de> Deserialize<'de> for IdentityId {
664 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
665 where
666 D: de::Deserializer<'de>,
667 {
668 if deserializer.is_human_readable() {
669 struct StringOrBytesVisitor;
670
671 impl<'de> de::Visitor<'de> for StringOrBytesVisitor {
672 type Value = IdentityId;
673
674 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
675 formatter.write_str("a hex string or [u8; 32]")
676 }
677
678 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
679 where
680 E: de::Error,
681 {
682 let mut id = IdentityId::default();
683 let off = if s.starts_with("0x") { 2 } else { 0 };
684 hex::decode_to_slice(&s[off..], &mut id.0).map_err(|e| de::Error::custom(e))?;
685 Ok(id)
686 }
687
688 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
689 where
690 A: de::SeqAccess<'de>,
691 {
692 let mut id = IdentityId::default();
693 for n in 0..32 {
694 id.0[n] = seq
695 .next_element()?
696 .ok_or_else(|| de::Error::invalid_length(n, &self))?;
697 }
698 Ok(id)
699 }
700 }
701 deserializer.deserialize_any(StringOrBytesVisitor)
702 } else {
703 Ok(Self(Deserialize::deserialize(deserializer)?))
704 }
705 }
706}
707
708#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)]
709#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
710#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
711#[cfg_attr(
712 feature = "utoipa",
713 schema(example = "67e55044-10b1-426f-9247-bb680e5fe0c8")
714)]
715pub struct AssetId(pub [u8; 16]);
716
717impl AssetId {
718 pub fn as_uuid(&self) -> uuid::Uuid {
719 uuid::Uuid::from_bytes(self.0)
720 }
721}
722
723impl fmt::Display for AssetId {
724 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
725 self.as_uuid().fmt(f)
726 }
727}
728
729impl fmt::Debug for AssetId {
730 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
731 self.as_uuid().fmt(f)
732 }
733}
734
735impl From<uuid::Uuid> for AssetId {
736 fn from(uuid: uuid::Uuid) -> Self {
737 Self(uuid.into_bytes())
738 }
739}
740
741impl FromStr for AssetId {
742 type Err = uuid::Error;
743
744 fn from_str(uuid_str: &str) -> Result<Self, Self::Err> {
745 let uuid = uuid::Uuid::parse_str(uuid_str)?;
746 Ok(uuid.into())
747 }
748}
749
750impl TryFrom<&'_ str> for AssetId {
751 type Error = uuid::Error;
752
753 fn try_from(uuid_str: &'_ str) -> Result<Self, Self::Error> {
754 let uuid = uuid::Uuid::parse_str(uuid_str)?;
755 Ok(uuid.into())
756 }
757}
758
759#[cfg(feature = "serde")]
760impl Serialize for AssetId {
761 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
762 where
763 S: ser::Serializer,
764 {
765 self.as_uuid().serialize(serializer)
766 }
767}
768
769#[cfg(feature = "serde")]
770impl<'de> Deserialize<'de> for AssetId {
771 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
772 where
773 D: de::Deserializer<'de>,
774 {
775 let uuid: uuid::Uuid = Deserialize::deserialize(deserializer)?;
776 Ok(Self(uuid.into_bytes()))
777 }
778}
779
780#[cfg(test)]
781mod tests {
782 use super::*;
783 use serde_json::json;
784
785 #[test]
786 fn account_id_deserialize() {
787 let json_hex = json!("0x788b804aeea9afcf7042c6ee45ddc2a394f4e225918e3261a9b5ed5069037d09");
788 let json_ss58 = json!("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5");
789 let expected = AccountId::from_ss58check("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5")
790 .expect("AccountId");
791
792 let decoded: AccountId = serde_json::from_str(&json_hex.to_string()).expect("decode as json");
793 assert_eq!(decoded, expected);
794 let decoded: AccountId = serde_json::from_str(&json_ss58.to_string()).expect("decode as json");
795 assert_eq!(decoded, expected);
796 }
797
798 #[test]
799 fn account_id_roundtrip() {
800 let account = AccountId::from_ss58check("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5")
801 .expect("AccountId");
802 let data = serde_json::to_string(&account).expect("encode json");
803 let decoded: AccountId = serde_json::from_str(&data).expect("decode as json");
804 assert_eq!(decoded, account);
805 }
806
807 #[test]
808 fn asset_id_roundtrip() {
809 let asset: AssetId = "67e55044-10b1-426f-9247-bb680e5fe0c8"
810 .parse()
811 .expect("AssetId");
812 let data = serde_json::to_string(&asset).expect("encode json");
813 let decoded: AssetId = serde_json::from_str(&data).expect("decode as json");
814 assert_eq!(decoded, asset);
815 }
816
817 #[test]
818 fn asset_id_display() {
819 let str_id = "67e55044-10b1-426f-9247-bb680e5fe0c8";
820 let asset: AssetId = str_id.parse().expect("AssetId");
821 let display_id = format!("{asset}");
822 assert_eq!(display_id, str_id);
823 }
824
825 #[test]
826 fn multi_address_roundtrip() {
827 let account = AccountId::from_ss58check("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5")
828 .expect("AccountId");
829 let address = GenericAddress::Id(account);
831 let data = serde_json::to_string(&address).expect("encode json");
832 eprintln!("MultiAddress::Id = {data}");
833 let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
834 assert_eq!(decoded, address);
835 let address = GenericAddress::Index(1234);
837 let data = serde_json::to_string(&address).expect("encode json");
838 eprintln!("MultiAddress::Index = {data}");
839 let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
840 assert_eq!(decoded, address);
841 let address = GenericAddress::Raw(vec![0, 1, 2, 3, 4, 5]);
843 let data = serde_json::to_string(&address).expect("encode json");
844 eprintln!("MultiAddress::Raw = {data}");
845 let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
846 assert_eq!(decoded, address);
847 let address = GenericAddress::Address32([1; 32]);
849 let data = serde_json::to_string(&address).expect("encode json");
850 eprintln!("MultiAddress::Address32 = {data}");
851 let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
852 assert_eq!(decoded, address);
853 let address = GenericAddress::Address20([2; 20]);
855 let data = serde_json::to_string(&address).expect("encode json");
856 eprintln!("MultiAddress::Address20 = {data}");
857 let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
858 assert_eq!(decoded, address);
859 }
860}