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