use core::fmt; use core::str::FromStr; use near_sdk::serde::{Deserialize, Serialize}; use near_sdk::{bs58, near}; use serde::de::Visitor; #[near(serializers=[borsh])] #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct SolAddress(pub [u8; 32]); impl SolAddress { pub const ZERO: Self = Self([0u8; 32]); pub fn is_zero(&self) -> bool { *self == Self::ZERO } } impl FromStr for SolAddress { type Err = String; fn from_str(s: &str) -> Result { let result = bs58::decode(s).into_vec().map_err(|err| err.to_string())?; Ok(Self( result .try_into() .map_err(|err| format!("Invalid length: {err:?}"))?, )) } } impl fmt::Display for SolAddress { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", bs58::encode(self.0).into_string()) } } impl<'de> Deserialize<'de> for SolAddress { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { struct Base58Visitor; impl Visitor<'_> for Base58Visitor { type Value = SolAddress; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a base58 string") } fn visit_str(self, s: &str) -> Result where E: serde::de::Error, { s.parse().map_err(serde::de::Error::custom) } } deserializer.deserialize_str(Base58Visitor) } } impl Serialize for SolAddress { fn serialize( &self, serializer: S, ) -> Result<::Ok, ::Error> where S: serde::Serializer, { serializer.serialize_str(&self.to_string()) } }