use std::{collections::HashMap, str::FromStr}; use hypersdk::{Address, hypercore::PrivateKeySigner}; #[derive(Debug)] pub struct PrivateKey(pub PrivateKeySigner, pub String); impl FromStr for PrivateKey { type Err = ::Err; fn from_str(s: &str) -> Result { Ok(Self(s.parse()?, s.to_string())) } } impl std::fmt::Display for PrivateKey { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.1.fmt(f) } } impl<'de> serde::Deserialize<'de> for PrivateKey { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { let s = String::deserialize(deserializer)?; s.parse().map_err(serde::de::Error::custom) } } impl serde::Serialize for PrivateKey { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { serializer.serialize_str(&self.to_string()) } } #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct Account { pub address: Address, pub private_key: PrivateKey, } #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] pub struct AccountList { pub active: String, #[serde(flatten)] pub accounts: HashMap, } impl AccountList { pub async fn new() -> tokio::io::Result { let path = crate::store::pulse_accounts_file()?; if !path.exists() { let default = Self::default(); tokio::fs::create_dir_all(path.parent().unwrap()).await?; tokio::fs::write(&path, default.to_string()?).await?; return Ok(default); } let output = tokio::fs::read_to_string(path).await?; Self::from_str(&output) } pub fn from_str(s: &str) -> tokio::io::Result { toml::from_str(s) .map_err(|v| tokio::io::Error::new(std::io::ErrorKind::InvalidInput, v.to_string())) } pub fn to_string(&self) -> tokio::io::Result { toml::to_string(self) .map_err(|v| tokio::io::Error::new(std::io::ErrorKind::Other, v.to_string())) } pub fn get_active<'a>(&'a self) -> Option<&'a Account> { self.accounts.get(&self.active) } } impl Account { pub fn get_truncated_address(&self) -> String { let s = format!("{:x}", self.address); if s.len() <= 6 { return format!("INVALID"); } let first: String = s.chars().take(4).collect(); let last: String = s .chars() .rev() .take(4) .collect::>() .into_iter() .rev() .collect(); format!("{}..{}", first, last) } }