asset_manager.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. use crate::{amount::AmountCents, asset::AssetId, Amount, Asset, Error};
  2. use std::{collections::HashMap, sync::Arc};
  3. /// Asset manager
  4. ///
  5. /// The Verax asset manager is a simple structure that holds the list of
  6. /// supported assets.
  7. ///
  8. /// The asset manager is used to convert from human readable amounts to an
  9. /// internal representation which is safe to use and operate.
  10. #[derive(Clone, Debug, Eq, PartialEq)]
  11. pub struct AssetManager {
  12. assets: Arc<HashMap<AssetId, AssetDefinition>>,
  13. asset_names: Arc<HashMap<Arc<str>, AssetDefinition>>,
  14. }
  15. /// The asset definition
  16. ///
  17. /// It is a simple structure that holds the asset id (an internal number), name
  18. /// (a human name) and the asset precision.
  19. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize)]
  20. pub struct AssetDefinition {
  21. /// The asset definition
  22. #[serde(flatten)]
  23. pub asset: Asset,
  24. #[serde(
  25. serialize_with = "crate::serialize_arc_str",
  26. deserialize_with = "crate::deserialize_arc_str"
  27. )]
  28. name: Arc<str>,
  29. }
  30. impl AssetManager {
  31. /// Creates a new instance of the asset manager
  32. pub fn new(assets: Vec<AssetDefinition>) -> Self {
  33. Self {
  34. assets: Arc::new(
  35. assets
  36. .iter()
  37. .map(|asset| (asset.asset.id, asset.clone()))
  38. .collect(),
  39. ),
  40. asset_names: Arc::new(
  41. assets
  42. .into_iter()
  43. .map(|asset| (asset.name.clone(), asset))
  44. .collect(),
  45. ),
  46. }
  47. }
  48. /// Get the name of an asset by their asset id
  49. pub fn get_name(&self, id: AssetId) -> Result<Arc<str>, Error> {
  50. self.assets
  51. .get(&id)
  52. .map(|asset| asset.name.clone())
  53. .ok_or(Error::AssetIdNotFound(id))
  54. }
  55. /// Get an asset definition by their id
  56. pub fn asset(&self, id: AssetId) -> Result<Asset, Error> {
  57. self.assets
  58. .get(&id)
  59. .map(|asset| asset.asset.clone())
  60. .ok_or(Error::AssetIdNotFound(id))
  61. }
  62. /// Get an asset definition by their human name
  63. pub fn human_amount_by_name(&self, name: &str, human_amount: &str) -> Result<Amount, Error> {
  64. Ok(self
  65. .asset_names
  66. .get(name)
  67. .map(|asset| Amount::from_human(asset.asset.clone(), human_amount))
  68. .ok_or(Error::AssetNotFound(name.to_owned()))??)
  69. }
  70. /// Get an Amount by their asset Id and cents
  71. pub fn amount_by_and_cents(&self, id: AssetId, cents: AmountCents) -> Result<Amount, Error> {
  72. self.asset(id).map(|asset| Amount::new(asset, cents))
  73. }
  74. }
  75. impl AssetDefinition {
  76. /// Creates a new asset definition
  77. pub fn new(id: u32, name: &str, precision: u8) -> Self {
  78. let name: Arc<str> = name.into();
  79. Self {
  80. asset: Asset {
  81. id,
  82. precision,
  83. name: name.clone(),
  84. },
  85. name,
  86. }
  87. }
  88. }