use crate::{amount::AmountCents, asset::AssetId, Amount, Asset, Error}; use std::{collections::HashMap, sync::Arc}; /// Asset manager /// /// The Verax asset manager is a simple structure that holds the list of /// supported assets. /// /// The asset manager is used to convert from human readable amounts to an /// internal representation which is safe to use and operate. #[derive(Clone, Debug, Eq, PartialEq)] pub struct AssetManager { assets: Arc>, asset_names: Arc, AssetDefinition>>, } /// The asset definition /// /// It is a simple structure that holds the asset id (an internal number), name /// (a human name) and the asset precision. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize)] pub struct AssetDefinition { /// The asset definition #[serde(flatten)] pub asset: Asset, #[serde( serialize_with = "crate::serialize_arc_str", deserialize_with = "crate::deserialize_arc_str" )] name: Arc, } impl AssetManager { /// Creates a new instance of the asset manager pub fn new(assets: Vec) -> Self { Self { assets: Arc::new( assets .iter() .map(|asset| (asset.asset.id, asset.clone())) .collect(), ), asset_names: Arc::new( assets .into_iter() .map(|asset| (asset.name.clone(), asset)) .collect(), ), } } /// Get the name of an asset by their asset id pub fn get_name(&self, id: AssetId) -> Result, Error> { self.assets .get(&id) .map(|asset| asset.name.clone()) .ok_or(Error::AssetIdNotFound(id)) } /// Get an asset definition by their id pub fn asset(&self, id: AssetId) -> Result { self.assets .get(&id) .map(|asset| asset.asset.clone()) .ok_or(Error::AssetIdNotFound(id)) } /// Get an asset definition by their human name pub fn human_amount_by_name(&self, name: &str, human_amount: &str) -> Result { Ok(self .asset_names .get(name) .map(|asset| Amount::from_human(asset.asset.clone(), human_amount)) .ok_or(Error::AssetNotFound(name.to_owned()))??) } /// Get an Amount by their asset Id and cents pub fn amount_by_and_cents(&self, id: AssetId, cents: AmountCents) -> Result { self.asset(id).map(|asset| Amount::new(asset, cents)) } } impl AssetDefinition { /// Creates a new asset definition pub fn new(id: u32, name: &str, precision: u8) -> Self { let name: Arc = name.into(); Self { asset: Asset { id, precision, name: name.clone(), }, name, } } }