283 lines
8.6 KiB
Rust
283 lines
8.6 KiB
Rust
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Serialize};
|
|
use uuid::Uuid;
|
|
|
|
/// Asset types representing different categories of digital assets
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub enum AssetType {
|
|
Artwork,
|
|
Token,
|
|
RealEstate,
|
|
Commodity,
|
|
Share,
|
|
Bond,
|
|
IntellectualProperty,
|
|
Other,
|
|
}
|
|
|
|
impl AssetType {
|
|
pub fn as_str(&self) -> &str {
|
|
match self {
|
|
AssetType::Artwork => "Artwork",
|
|
AssetType::Token => "Token",
|
|
AssetType::RealEstate => "Real Estate",
|
|
AssetType::Commodity => "Commodity",
|
|
AssetType::Share => "Share",
|
|
AssetType::Bond => "Bond",
|
|
AssetType::IntellectualProperty => "Intellectual Property",
|
|
AssetType::Other => "Other",
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Status of an asset
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub enum AssetStatus {
|
|
Active,
|
|
Locked,
|
|
ForSale,
|
|
Transferred,
|
|
Archived,
|
|
}
|
|
|
|
impl AssetStatus {
|
|
pub fn as_str(&self) -> &str {
|
|
match self {
|
|
AssetStatus::Active => "Active",
|
|
AssetStatus::Locked => "Locked",
|
|
AssetStatus::ForSale => "For Sale",
|
|
AssetStatus::Transferred => "Transferred",
|
|
AssetStatus::Archived => "Archived",
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Blockchain information for an asset
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct BlockchainInfo {
|
|
pub blockchain: String,
|
|
pub token_id: String,
|
|
pub contract_address: String,
|
|
pub owner_address: String,
|
|
pub transaction_hash: Option<String>,
|
|
pub block_number: Option<u64>,
|
|
pub timestamp: Option<DateTime<Utc>>,
|
|
}
|
|
|
|
/// Valuation history point for an asset
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ValuationPoint {
|
|
pub id: String,
|
|
pub date: DateTime<Utc>,
|
|
pub value: f64,
|
|
pub currency: String,
|
|
pub source: String,
|
|
pub notes: Option<String>,
|
|
}
|
|
|
|
/// Transaction history for an asset
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct AssetTransaction {
|
|
pub id: String,
|
|
pub transaction_type: String,
|
|
pub date: DateTime<Utc>,
|
|
pub from_address: Option<String>,
|
|
pub to_address: Option<String>,
|
|
pub amount: Option<f64>,
|
|
pub currency: Option<String>,
|
|
pub transaction_hash: Option<String>,
|
|
pub notes: Option<String>,
|
|
}
|
|
|
|
/// Main Asset model
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Asset {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub description: String,
|
|
pub asset_type: AssetType,
|
|
pub status: AssetStatus,
|
|
pub owner_id: String,
|
|
pub owner_name: String,
|
|
pub created_at: DateTime<Utc>,
|
|
pub updated_at: DateTime<Utc>,
|
|
pub blockchain_info: Option<BlockchainInfo>,
|
|
pub current_valuation: Option<f64>,
|
|
pub valuation_currency: Option<String>,
|
|
pub valuation_date: Option<DateTime<Utc>>,
|
|
pub valuation_history: Vec<ValuationPoint>,
|
|
pub transaction_history: Vec<AssetTransaction>,
|
|
pub metadata: serde_json::Value,
|
|
pub image_url: Option<String>,
|
|
pub external_url: Option<String>,
|
|
}
|
|
|
|
impl Asset {
|
|
/// Creates a new asset
|
|
pub fn new(
|
|
name: &str,
|
|
description: &str,
|
|
asset_type: AssetType,
|
|
owner_id: &str,
|
|
owner_name: &str,
|
|
) -> Self {
|
|
let now = Utc::now();
|
|
Self {
|
|
id: format!("asset-{}", Uuid::new_v4().to_string()[..8].to_string()),
|
|
name: name.to_string(),
|
|
description: description.to_string(),
|
|
asset_type,
|
|
status: AssetStatus::Active,
|
|
owner_id: owner_id.to_string(),
|
|
owner_name: owner_name.to_string(),
|
|
created_at: now,
|
|
updated_at: now,
|
|
blockchain_info: None,
|
|
current_valuation: None,
|
|
valuation_currency: None,
|
|
valuation_date: None,
|
|
valuation_history: Vec::new(),
|
|
transaction_history: Vec::new(),
|
|
metadata: serde_json::json!({}),
|
|
image_url: None,
|
|
external_url: None,
|
|
}
|
|
}
|
|
|
|
/// Adds blockchain information to the asset
|
|
pub fn add_blockchain_info(&mut self, blockchain_info: BlockchainInfo) {
|
|
self.blockchain_info = Some(blockchain_info);
|
|
self.updated_at = Utc::now();
|
|
}
|
|
|
|
/// Adds a valuation point to the asset's history
|
|
pub fn add_valuation(&mut self, value: f64, currency: &str, source: &str, notes: Option<String>) {
|
|
let valuation = ValuationPoint {
|
|
id: format!("val-{}", Uuid::new_v4().to_string()[..8].to_string()),
|
|
date: Utc::now(),
|
|
value,
|
|
currency: currency.to_string(),
|
|
source: source.to_string(),
|
|
notes,
|
|
};
|
|
|
|
self.current_valuation = Some(value);
|
|
self.valuation_currency = Some(currency.to_string());
|
|
self.valuation_date = Some(valuation.date);
|
|
self.valuation_history.push(valuation);
|
|
self.updated_at = Utc::now();
|
|
}
|
|
|
|
/// Adds a transaction to the asset's history
|
|
pub fn add_transaction(
|
|
&mut self,
|
|
transaction_type: &str,
|
|
from_address: Option<String>,
|
|
to_address: Option<String>,
|
|
amount: Option<f64>,
|
|
currency: Option<String>,
|
|
transaction_hash: Option<String>,
|
|
notes: Option<String>,
|
|
) {
|
|
let transaction = AssetTransaction {
|
|
id: format!("tx-{}", Uuid::new_v4().to_string()[..8].to_string()),
|
|
transaction_type: transaction_type.to_string(),
|
|
date: Utc::now(),
|
|
from_address,
|
|
to_address,
|
|
amount,
|
|
currency,
|
|
transaction_hash,
|
|
notes,
|
|
};
|
|
|
|
self.transaction_history.push(transaction);
|
|
self.updated_at = Utc::now();
|
|
}
|
|
|
|
/// Updates the status of the asset
|
|
pub fn update_status(&mut self, status: AssetStatus) {
|
|
self.status = status;
|
|
self.updated_at = Utc::now();
|
|
}
|
|
|
|
/// Gets the latest valuation point
|
|
pub fn latest_valuation(&self) -> Option<&ValuationPoint> {
|
|
self.valuation_history.last()
|
|
}
|
|
|
|
/// Gets the latest transaction
|
|
pub fn latest_transaction(&self) -> Option<&AssetTransaction> {
|
|
self.transaction_history.last()
|
|
}
|
|
|
|
/// Gets the valuation history sorted by date
|
|
pub fn sorted_valuation_history(&self) -> Vec<&ValuationPoint> {
|
|
let mut history = self.valuation_history.iter().collect::<Vec<_>>();
|
|
history.sort_by(|a, b| a.date.cmp(&b.date));
|
|
history
|
|
}
|
|
|
|
/// Gets the transaction history sorted by date
|
|
pub fn sorted_transaction_history(&self) -> Vec<&AssetTransaction> {
|
|
let mut history = self.transaction_history.iter().collect::<Vec<_>>();
|
|
history.sort_by(|a, b| a.date.cmp(&b.date));
|
|
history
|
|
}
|
|
}
|
|
|
|
/// Filter for assets
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct AssetFilter {
|
|
pub asset_type: Option<AssetType>,
|
|
pub status: Option<AssetStatus>,
|
|
pub owner_id: Option<String>,
|
|
pub min_valuation: Option<f64>,
|
|
pub max_valuation: Option<f64>,
|
|
pub valuation_currency: Option<String>,
|
|
pub search_query: Option<String>,
|
|
}
|
|
|
|
/// Statistics for assets
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct AssetStatistics {
|
|
pub total_assets: usize,
|
|
pub total_value: f64,
|
|
pub value_by_type: std::collections::HashMap<String, f64>,
|
|
pub assets_by_type: std::collections::HashMap<String, usize>,
|
|
pub assets_by_status: std::collections::HashMap<String, usize>,
|
|
}
|
|
|
|
impl AssetStatistics {
|
|
pub fn new(assets: &[Asset]) -> Self {
|
|
let mut total_value = 0.0;
|
|
let mut value_by_type = std::collections::HashMap::new();
|
|
let mut assets_by_type = std::collections::HashMap::new();
|
|
let mut assets_by_status = std::collections::HashMap::new();
|
|
|
|
for asset in assets {
|
|
if let Some(valuation) = asset.current_valuation {
|
|
total_value += valuation;
|
|
|
|
let asset_type = asset.asset_type.as_str().to_string();
|
|
*value_by_type.entry(asset_type.clone()).or_insert(0.0) += valuation;
|
|
*assets_by_type.entry(asset_type).or_insert(0) += 1;
|
|
} else {
|
|
let asset_type = asset.asset_type.as_str().to_string();
|
|
*assets_by_type.entry(asset_type).or_insert(0) += 1;
|
|
}
|
|
|
|
let status = asset.status.as_str().to_string();
|
|
*assets_by_status.entry(status).or_insert(0) += 1;
|
|
}
|
|
|
|
Self {
|
|
total_assets: assets.len(),
|
|
total_value,
|
|
value_by_type,
|
|
assets_by_type,
|
|
assets_by_status,
|
|
}
|
|
}
|
|
}
|