// heromodels/src/models/finance/asset.rs use heromodels_core::BaseModelData; use heromodels_derive::model; use rhai::{CustomType, TypeBuilder}; use serde::{Deserialize, Serialize}; /// AssetType defines the type of blockchain asset #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum AssetType { Erc20, // ERC-20 token standard Erc721, // ERC-721 NFT standard Erc1155, // ERC-1155 Multi-token standard Native, // Native blockchain asset (e.g., ETH, BTC) } impl Default for AssetType { fn default() -> Self { AssetType::Native } } /// Asset represents a digital asset or token #[derive(Debug, Clone, Serialize, Deserialize, CustomType, Default)] #[model] // Has base.Base in V spec pub struct Asset { pub base_data: BaseModelData, pub name: String, // Name of the asset pub description: String, // Description of the asset pub amount: f64, // Amount of the asset pub address: String, // Address of the asset on the blockchain or bank pub asset_type: AssetType, // Type of the asset pub decimals: u8, // Number of decimals of the asset } impl Asset { /// Create a new asset with default values pub fn new() -> Self { Self { base_data: BaseModelData::new(), name: String::new(), description: String::new(), amount: 0.0, address: String::new(), asset_type: AssetType::default(), decimals: 18, // Default for most tokens } } /// Set the name of the asset pub fn name(mut self, name: impl ToString) -> Self { self.name = name.to_string(); self } /// Set the description of the asset pub fn description(mut self, description: impl ToString) -> Self { self.description = description.to_string(); self } /// Set the amount of the asset pub fn amount(mut self, amount: f64) -> Self { self.amount = amount; self } /// Set the address of the asset on the blockchain pub fn address(mut self, address: impl ToString) -> Self { self.address = address.to_string(); self } /// Set the type of the asset pub fn asset_type(mut self, asset_type: AssetType) -> Self { self.asset_type = asset_type; self } /// Set the number of decimals of the asset pub fn decimals(mut self, decimals: u8) -> Self { self.decimals = decimals; self } /// Get the formatted amount with proper decimal places pub fn formatted_amount(&self) -> String { let factor = 10_f64.powi(self.decimals as i32); let formatted_amount = (self.amount * factor).round() / factor; format!("{:.1$}", formatted_amount, self.decimals as usize) } /// Transfer amount to another asset pub fn transfer_to(&mut self, target: &mut Asset, amount: f64) -> Result<(), &'static str> { if amount <= 0.0 { return Err("Transfer amount must be positive"); } if self.amount < amount { return Err("Insufficient balance for transfer"); } self.amount -= amount; target.amount += amount; Ok(()) } }