polymesh_api_client/
basic_types.rs

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
16// Re-export some basic crates.
17pub 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// Re-impl `OldWeight`
28#[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
36// Re-impl `per_things` to support serde
37pub 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// Re-impl MultiAddress to support serde
180#[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  /// It's an account ID (pubkey).
185  Id(AccountId),
186  /// It's an account index.
187  Index(#[codec(compact)] AccountIndex),
188  /// It's some arbitrary raw bytes.
189  Raw(Vec<u8>),
190  /// It's a 32 byte representation.
191  Address32([u8; 32]),
192  /// Its a 20 byte representation.
193  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))]
627pub struct IdentityId(
628  #[cfg_attr(
629    feature = "utoipa",
630    schema(example = "0x0600000000000000000000000000000000000000000000000000000000000000")
631  )]
632  pub [u8; 32],
633);
634
635impl fmt::Display for IdentityId {
636  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
637    let h = hex::encode(&self.0);
638    write!(f, "0x{}", h)
639  }
640}
641
642impl fmt::Debug for IdentityId {
643  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
644    let h = hex::encode(&self.0);
645    write!(f, "0x{}", h)
646  }
647}
648
649#[cfg(feature = "serde")]
650impl Serialize for IdentityId {
651  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
652  where
653    S: ser::Serializer,
654  {
655    if serializer.is_human_readable() {
656      let h = format!("0x{}", hex::encode(&self.0));
657      serializer.serialize_str(&h)
658    } else {
659      self.0.serialize(serializer)
660    }
661  }
662}
663
664#[cfg(feature = "serde")]
665impl<'de> Deserialize<'de> for IdentityId {
666  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
667  where
668    D: de::Deserializer<'de>,
669  {
670    if deserializer.is_human_readable() {
671      struct StringOrBytesVisitor;
672
673      impl<'de> de::Visitor<'de> for StringOrBytesVisitor {
674        type Value = IdentityId;
675
676        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
677          formatter.write_str("a hex string or [u8; 32]")
678        }
679
680        fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
681        where
682          E: de::Error,
683        {
684          let mut id = IdentityId::default();
685          let off = if s.starts_with("0x") { 2 } else { 0 };
686          hex::decode_to_slice(&s[off..], &mut id.0).map_err(|e| de::Error::custom(e))?;
687          Ok(id)
688        }
689
690        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
691        where
692          A: de::SeqAccess<'de>,
693        {
694          let mut id = IdentityId::default();
695          for n in 0..32 {
696            id.0[n] = seq
697              .next_element()?
698              .ok_or_else(|| de::Error::invalid_length(n, &self))?;
699          }
700          Ok(id)
701        }
702      }
703      deserializer.deserialize_any(StringOrBytesVisitor)
704    } else {
705      Ok(Self(Deserialize::deserialize(deserializer)?))
706    }
707  }
708}
709
710#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)]
711#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
712#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
713pub struct AssetId(
714  #[cfg_attr(
715    feature = "utoipa",
716    schema(example = "67e55044-10b1-426f-9247-bb680e5fe0c8")
717  )]
718  pub [u8; 16],
719);
720
721impl AssetId {
722  pub fn as_uuid(&self) -> uuid::Uuid {
723    uuid::Uuid::from_bytes(self.0)
724  }
725}
726
727impl fmt::Display for AssetId {
728  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
729    self.as_uuid().fmt(f)
730  }
731}
732
733impl fmt::Debug for AssetId {
734  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
735    self.as_uuid().fmt(f)
736  }
737}
738
739impl From<uuid::Uuid> for AssetId {
740  fn from(uuid: uuid::Uuid) -> Self {
741    Self(uuid.into_bytes())
742  }
743}
744
745impl FromStr for AssetId {
746  type Err = uuid::Error;
747
748  fn from_str(uuid_str: &str) -> Result<Self, Self::Err> {
749    let uuid = uuid::Uuid::parse_str(uuid_str)?;
750    Ok(uuid.into())
751  }
752}
753
754impl TryFrom<&'_ str> for AssetId {
755  type Error = uuid::Error;
756
757  fn try_from(uuid_str: &'_ str) -> Result<Self, Self::Error> {
758    let uuid = uuid::Uuid::parse_str(uuid_str)?;
759    Ok(uuid.into())
760  }
761}
762
763#[cfg(feature = "serde")]
764impl Serialize for AssetId {
765  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
766  where
767    S: ser::Serializer,
768  {
769    self.as_uuid().serialize(serializer)
770  }
771}
772
773#[cfg(feature = "serde")]
774impl<'de> Deserialize<'de> for AssetId {
775  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
776  where
777    D: de::Deserializer<'de>,
778  {
779    let uuid: uuid::Uuid = Deserialize::deserialize(deserializer)?;
780    Ok(Self(uuid.into_bytes()))
781  }
782}
783
784#[cfg(test)]
785mod tests {
786  use super::*;
787  use serde_json::json;
788
789  #[test]
790  fn account_id_deserialize() {
791    let json_hex = json!("0x788b804aeea9afcf7042c6ee45ddc2a394f4e225918e3261a9b5ed5069037d09");
792    let json_ss58 = json!("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5");
793    let expected = AccountId::from_ss58check("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5")
794      .expect("AccountId");
795
796    let decoded: AccountId = serde_json::from_str(&json_hex.to_string()).expect("decode as json");
797    assert_eq!(decoded, expected);
798    let decoded: AccountId = serde_json::from_str(&json_ss58.to_string()).expect("decode as json");
799    assert_eq!(decoded, expected);
800  }
801
802  #[test]
803  fn account_id_roundtrip() {
804    let account = AccountId::from_ss58check("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5")
805      .expect("AccountId");
806    let data = serde_json::to_string(&account).expect("encode json");
807    let decoded: AccountId = serde_json::from_str(&data).expect("decode as json");
808    assert_eq!(decoded, account);
809  }
810
811  #[test]
812  fn asset_id_roundtrip() {
813    let asset: AssetId = "67e55044-10b1-426f-9247-bb680e5fe0c8"
814      .parse()
815      .expect("AssetId");
816    let data = serde_json::to_string(&asset).expect("encode json");
817    let decoded: AssetId = serde_json::from_str(&data).expect("decode as json");
818    assert_eq!(decoded, asset);
819  }
820
821  #[test]
822  fn asset_id_display() {
823    let str_id = "67e55044-10b1-426f-9247-bb680e5fe0c8";
824    let asset: AssetId = str_id.parse().expect("AssetId");
825    let display_id = format!("{asset}");
826    assert_eq!(display_id, str_id);
827  }
828
829  #[test]
830  fn multi_address_roundtrip() {
831    let account = AccountId::from_ss58check("5Enm3VfZioxHVBpZgJcACv7pZPZZeYWymvrZ9cxkXhNHJWe5")
832      .expect("AccountId");
833    // Round-trip test MultiAddress::Id variant.
834    let address = GenericAddress::Id(account);
835    let data = serde_json::to_string(&address).expect("encode json");
836    eprintln!("MultiAddress::Id = {data}");
837    let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
838    assert_eq!(decoded, address);
839    // Round-trip test MultiAddress::Index variant.
840    let address = GenericAddress::Index(1234);
841    let data = serde_json::to_string(&address).expect("encode json");
842    eprintln!("MultiAddress::Index = {data}");
843    let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
844    assert_eq!(decoded, address);
845    // Round-trip test MultiAddress::Raw variant.
846    let address = GenericAddress::Raw(vec![0, 1, 2, 3, 4, 5]);
847    let data = serde_json::to_string(&address).expect("encode json");
848    eprintln!("MultiAddress::Raw = {data}");
849    let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
850    assert_eq!(decoded, address);
851    // Round-trip test MultiAddress::Address32 variant.
852    let address = GenericAddress::Address32([1; 32]);
853    let data = serde_json::to_string(&address).expect("encode json");
854    eprintln!("MultiAddress::Address32 = {data}");
855    let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
856    assert_eq!(decoded, address);
857    // Round-trip test MultiAddress::Address20 variant.
858    let address = GenericAddress::Address20([2; 20]);
859    let data = serde_json::to_string(&address).expect("encode json");
860    eprintln!("MultiAddress::Address20 = {data}");
861    let decoded: GenericAddress = serde_json::from_str(&data).expect("decode as json");
862    assert_eq!(decoded, address);
863  }
864}