polymesh-api-client 3.11.0

Polymesh API client core
Documentation
use serde::{de, ser, Deserialize, Serialize};

use alloc::format;
use core::{fmt, str::FromStr};
use sp_core::crypto::Ss58Codec;

use crate::basic_types::{AccountId, AccountTraits, AssetId, IdentityId, MultiAddress};

impl<AccountId, AccountIndex> ser::Serialize for MultiAddress<AccountId, AccountIndex>
where
  AccountId: AccountTraits,
  AccountIndex: AccountTraits,
{
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  where
    S: ser::Serializer,
  {
    match self {
      Self::Id(account) => {
        if serializer.is_human_readable() {
          account.serialize(serializer)
        } else {
          serializer.serialize_newtype_variant("MultiAddress", 0, "Id", account)
        }
      }
      Self::Index(index) => serializer.serialize_newtype_variant("MultiAddress", 1, "Index", index),
      Self::Raw(data) => {
        if serializer.is_human_readable() {
          let h = hex::encode(data.as_slice());
          serializer.serialize_newtype_variant("MultiAddress", 2, "Raw", &h)
        } else {
          serializer.serialize_newtype_variant("MultiAddress", 2, "Raw", data)
        }
      }
      Self::Address32(address) => {
        if serializer.is_human_readable() {
          let h = hex::encode(&address[..]);
          serializer.serialize_newtype_variant("MultiAddress", 3, "Address32", &h)
        } else {
          serializer.serialize_newtype_variant("MultiAddress", 3, "Address32", address)
        }
      }
      Self::Address20(address) => {
        if serializer.is_human_readable() {
          let h = hex::encode(&address[..]);
          serializer.serialize_newtype_variant("MultiAddress", 4, "Address20", &h)
        } else {
          serializer.serialize_newtype_variant("MultiAddress", 4, "Address20", address)
        }
      }
    }
  }
}

#[derive(Deserialize)]
#[serde(field_identifier, rename_all = "PascalCase")]
enum MultiAddressField {
  Id,
  Index,
  Raw,
  Address32,
  Address20,
}

#[derive(Default)]
struct MultiAddressVisitor<AccountId: AccountTraits, AccountIndex: AccountTraits> {
  is_human_readable: bool,
  _phantom: core::marker::PhantomData<(AccountId, AccountIndex)>,
}

impl<AccountId: AccountTraits, AccountIndex: AccountTraits>
  MultiAddressVisitor<AccountId, AccountIndex>
{
  fn new(is_human_readable: bool) -> Self {
    Self {
      is_human_readable,
      _phantom: Default::default(),
    }
  }
}

impl<'de, AccountId, AccountIndex> de::Visitor<'de> for MultiAddressVisitor<AccountId, AccountIndex>
where
  AccountId: AccountTraits,
  AccountIndex: AccountTraits,
{
  type Value = MultiAddress<AccountId, AccountIndex>;

  fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    formatter.write_str("AccountId or MultiAddress")
  }

  fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
  where
    E: de::Error,
  {
    let account = AccountId::from_str(v)
      .map_err(|_e| de::Error::custom(format!("Failed to decode AccountId")))?;
    Ok(MultiAddress::Id(account))
  }

  fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
  where
    V: de::MapAccess<'de>,
  {
    let mut address = None;
    while let Some(key) = map.next_key()? {
      match key {
        MultiAddressField::Id => {
          if address.is_some() {
            return Err(de::Error::duplicate_field("Id"));
          }
          address = Some(MultiAddress::Id(map.next_value()?));
        }
        MultiAddressField::Index => {
          if address.is_some() {
            return Err(de::Error::duplicate_field("Index"));
          }
          address = Some(MultiAddress::Index(map.next_value()?));
        }
        MultiAddressField::Raw => {
          if address.is_some() {
            return Err(de::Error::duplicate_field("Raw"));
          }
          if self.is_human_readable {
            let h: &str = map.next_value()?;
            let off = if h.starts_with("0x") { 2 } else { 0 };
            let data = hex::decode(&h[off..]).map_err(|e| de::Error::custom(e))?;
            address = Some(MultiAddress::Raw(data));
          } else {
            address = Some(MultiAddress::Raw(map.next_value()?));
          }
        }
        MultiAddressField::Address32 => {
          if address.is_some() {
            return Err(de::Error::duplicate_field("Address32"));
          }
          if self.is_human_readable {
            let h: &str = map.next_value()?;
            let mut data = [0u8; 32];
            let off = if h.starts_with("0x") { 2 } else { 0 };
            hex::decode_to_slice(&h[off..], &mut data).map_err(|e| de::Error::custom(e))?;
            address = Some(MultiAddress::Address32(data));
          } else {
            address = Some(MultiAddress::Address32(map.next_value()?));
          }
        }
        MultiAddressField::Address20 => {
          if address.is_some() {
            return Err(de::Error::duplicate_field("Address20"));
          }
          if self.is_human_readable {
            let h: &str = map.next_value()?;
            let mut data = [0u8; 20];
            let off = if h.starts_with("0x") { 2 } else { 0 };
            hex::decode_to_slice(&h[off..], &mut data).map_err(|e| de::Error::custom(e))?;
            address = Some(MultiAddress::Address20(data));
          } else {
            address = Some(MultiAddress::Address20(map.next_value()?));
          }
        }
      }
    }
    let address =
      address.ok_or_else(|| de::Error::missing_field("Id, Index, Raw, Address32, or Address20"))?;
    Ok(address)
  }
}

impl<'de, AccountId, AccountIndex> Deserialize<'de> for MultiAddress<AccountId, AccountIndex>
where
  AccountId: AccountTraits,
  AccountIndex: AccountTraits,
{
  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  where
    D: de::Deserializer<'de>,
  {
    let visitor = MultiAddressVisitor::new(deserializer.is_human_readable());
    if deserializer.is_human_readable() {
      deserializer.deserialize_any(visitor)
    } else {
      deserializer.deserialize_enum(
        "MultiAddress",
        &["Id", "Index", "Raw", "Address32", "Address20"],
        visitor,
      )
    }
  }
}

impl Serialize for AccountId {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  where
    S: ser::Serializer,
  {
    if serializer.is_human_readable() {
      let ss58 = self.to_ss58check();
      serializer.serialize_str(&ss58)
    } else {
      self.0.serialize(serializer)
    }
  }
}

impl<'de> Deserialize<'de> for AccountId {
  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  where
    D: de::Deserializer<'de>,
  {
    if deserializer.is_human_readable() {
      struct StringOrBytesVisitor;

      impl<'de> de::Visitor<'de> for StringOrBytesVisitor {
        type Value = AccountId;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
          formatter.write_str("a hex string or [u8; 32]")
        }

        fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
        where
          E: de::Error,
        {
          Ok(AccountId::from_str(s).map_err(|e| de::Error::custom(e))?)
        }

        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
        where
          A: de::SeqAccess<'de>,
        {
          let mut id = AccountId::default();
          for n in 0..32 {
            id.0[n] = seq
              .next_element()?
              .ok_or_else(|| de::Error::invalid_length(n, &self))?;
          }
          Ok(id)
        }
      }
      deserializer.deserialize_any(StringOrBytesVisitor)
    } else {
      Ok(Self(Deserialize::deserialize(deserializer)?))
    }
  }
}

impl Serialize for IdentityId {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  where
    S: ser::Serializer,
  {
    if serializer.is_human_readable() {
      let h = format!("0x{}", hex::encode(&self.0));
      serializer.serialize_str(&h)
    } else {
      self.0.serialize(serializer)
    }
  }
}

impl<'de> Deserialize<'de> for IdentityId {
  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  where
    D: de::Deserializer<'de>,
  {
    if deserializer.is_human_readable() {
      struct StringOrBytesVisitor;

      impl<'de> de::Visitor<'de> for StringOrBytesVisitor {
        type Value = IdentityId;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
          formatter.write_str("a hex string or [u8; 32]")
        }

        fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
        where
          E: de::Error,
        {
          let mut id = IdentityId::default();
          let off = if s.starts_with("0x") { 2 } else { 0 };
          hex::decode_to_slice(&s[off..], &mut id.0).map_err(|e| de::Error::custom(e))?;
          Ok(id)
        }

        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
        where
          A: de::SeqAccess<'de>,
        {
          let mut id = IdentityId::default();
          for n in 0..32 {
            id.0[n] = seq
              .next_element()?
              .ok_or_else(|| de::Error::invalid_length(n, &self))?;
          }
          Ok(id)
        }
      }
      deserializer.deserialize_any(StringOrBytesVisitor)
    } else {
      Ok(Self(Deserialize::deserialize(deserializer)?))
    }
  }
}

impl Serialize for AssetId {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  where
    S: ser::Serializer,
  {
    self.as_uuid().serialize(serializer)
  }
}

impl<'de> Deserialize<'de> for AssetId {
  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  where
    D: de::Deserializer<'de>,
  {
    let uuid: uuid::Uuid = Deserialize::deserialize(deserializer)?;
    Ok(Self(uuid.into_bytes()))
  }
}