hostbasket/actix_mvc_app/src/controllers/asset.rs

777 lines
36 KiB
Rust

use actix_web::{web, HttpResponse, Result};
use tera::{Context, Tera};
use chrono::{Utc, Duration};
use serde::Deserialize;
use crate::models::asset::{Asset, AssetType, AssetStatus, BlockchainInfo, ValuationPoint, AssetTransaction, AssetStatistics};
use crate::utils::render_template;
#[derive(Debug, Deserialize)]
pub struct AssetForm {
pub name: String,
pub description: String,
pub asset_type: String,
}
#[derive(Debug, Deserialize)]
pub struct ValuationForm {
pub value: f64,
pub currency: String,
pub source: String,
pub notes: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct TransactionForm {
pub transaction_type: String,
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>,
}
pub struct AssetController;
impl AssetController {
// Display the assets dashboard
pub async fn index(tmpl: web::Data<Tera>) -> Result<HttpResponse> {
let mut context = Context::new();
println!("DEBUG: Starting assets dashboard rendering");
let assets = Self::get_mock_assets();
println!("DEBUG: Generated {} mock assets", assets.len());
let stats = AssetStatistics::new(&assets);
println!("DEBUG: Generated asset statistics: {:?}", stats);
// Add active_page for navigation highlighting
context.insert("active_page", &"assets");
// Add stats
context.insert("stats", &serde_json::to_value(stats).unwrap());
println!("DEBUG: Added stats to context");
// Add recent assets
let recent_assets: Vec<serde_json::Map<String, serde_json::Value>> = assets
.iter()
.take(5)
.map(|a| Self::asset_to_json(a))
.collect();
context.insert("recent_assets", &recent_assets);
// Add assets by type
let asset_types = vec![
AssetType::NFT,
AssetType::Token,
AssetType::RealEstate,
AssetType::Commodity,
AssetType::Share,
AssetType::Bond,
AssetType::IntellectualProperty,
AssetType::Other,
];
let assets_by_type: Vec<serde_json::Map<String, serde_json::Value>> = asset_types
.iter()
.map(|asset_type| {
let mut map = serde_json::Map::new();
let type_str = asset_type.as_str();
let count = assets.iter().filter(|a| a.asset_type == *asset_type).count();
map.insert("type".to_string(), serde_json::Value::String(type_str.to_string()));
map.insert("count".to_string(), serde_json::Value::Number(serde_json::Number::from(count)));
map
})
.collect();
context.insert("assets_by_type", &assets_by_type);
println!("DEBUG: Rendering assets dashboard template");
let response = render_template(&tmpl, "assets/index.html", &context);
println!("DEBUG: Finished rendering assets dashboard template");
response
}
// Display the list of all assets
pub async fn list(tmpl: web::Data<Tera>) -> Result<HttpResponse> {
let mut context = Context::new();
println!("DEBUG: Starting assets list rendering");
let assets = Self::get_mock_assets();
println!("DEBUG: Generated {} mock assets", assets.len());
let assets_data: Vec<serde_json::Map<String, serde_json::Value>> = assets
.iter()
.map(|a| Self::asset_to_json(a))
.collect();
// Add active_page for navigation highlighting
context.insert("active_page", &"assets");
context.insert("assets", &assets_data);
context.insert("filter", &"all");
println!("DEBUG: Rendering assets list template");
let response = render_template(&tmpl, "assets/list.html", &context);
println!("DEBUG: Finished rendering assets list template");
response
}
// Display the list of user's assets
pub async fn my_assets(tmpl: web::Data<Tera>) -> Result<HttpResponse> {
let mut context = Context::new();
println!("DEBUG: Starting my assets rendering");
let assets = Self::get_mock_assets();
println!("DEBUG: Generated {} mock assets", assets.len());
let assets_data: Vec<serde_json::Map<String, serde_json::Value>> = assets
.iter()
.map(|a| Self::asset_to_json(a))
.collect();
// Add active_page for navigation highlighting
context.insert("active_page", &"assets");
context.insert("assets", &assets_data);
println!("DEBUG: Rendering my assets template");
let response = render_template(&tmpl, "assets/my_assets.html", &context);
println!("DEBUG: Finished rendering my assets template");
response
}
// Display a specific asset
pub async fn detail(tmpl: web::Data<Tera>, path: web::Path<String>) -> Result<HttpResponse> {
let asset_id = path.into_inner();
let mut context = Context::new();
println!("DEBUG: Starting asset detail rendering");
// Add active_page for navigation highlighting
context.insert("active_page", &"assets");
// Find the asset by ID
let assets = Self::get_mock_assets();
let asset = assets.iter().find(|a| a.id == asset_id);
match asset {
Some(asset) => {
println!("DEBUG: Found asset with ID {}", asset_id);
// Convert asset to JSON
let asset_json = Self::asset_to_json(asset);
context.insert("asset", &asset_json);
// Add valuation history for chart
let valuation_history: Vec<serde_json::Map<String, serde_json::Value>> = asset
.sorted_valuation_history()
.iter()
.map(|v| {
let mut map = serde_json::Map::new();
map.insert("date".to_string(), serde_json::Value::String(v.date.format("%Y-%m-%d").to_string()));
map.insert("value".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(v.value).unwrap()));
map.insert("currency".to_string(), serde_json::Value::String(v.currency.clone()));
map
})
.collect();
context.insert("valuation_history", &valuation_history);
println!("DEBUG: Rendering asset detail template");
let response = render_template(&tmpl, "assets/detail.html", &context);
println!("DEBUG: Finished rendering asset detail template");
response
},
None => {
println!("DEBUG: Asset not found with ID {}", asset_id);
Ok(HttpResponse::NotFound().finish())
}
}
}
// Display the create asset form
pub async fn create_form(tmpl: web::Data<Tera>) -> Result<HttpResponse> {
let mut context = Context::new();
println!("DEBUG: Starting create asset form rendering");
// Add active_page for navigation highlighting
context.insert("active_page", &"assets");
// Add asset types for dropdown
let asset_types = vec![
("NFT", "NFT"),
("Token", "Token"),
("RealEstate", "Real Estate"),
("Commodity", "Commodity"),
("Share", "Share"),
("Bond", "Bond"),
("IntellectualProperty", "Intellectual Property"),
("Other", "Other")
];
context.insert("asset_types", &asset_types);
println!("DEBUG: Rendering create asset form template");
let response = render_template(&tmpl, "assets/create.html", &context);
println!("DEBUG: Finished rendering create asset form template");
response
}
// Process the create asset form
pub async fn create(
_tmpl: web::Data<Tera>,
_form: web::Form<AssetForm>,
) -> Result<HttpResponse> {
println!("DEBUG: Processing create asset form");
// In a real application, we would save the asset to the database
// For now, we'll just redirect to the assets list
Ok(HttpResponse::Found().append_header(("Location", "/assets")).finish())
}
// Add a valuation to an asset
pub async fn add_valuation(
_tmpl: web::Data<Tera>,
path: web::Path<String>,
_form: web::Form<ValuationForm>,
) -> Result<HttpResponse> {
let asset_id = path.into_inner();
println!("DEBUG: Adding valuation to asset with ID {}", asset_id);
// In a real application, we would update the asset in the database
// For now, we'll just redirect to the asset detail page
Ok(HttpResponse::Found().append_header(("Location", format!("/assets/{}", asset_id))).finish())
}
// Add a transaction to an asset
pub async fn add_transaction(
_tmpl: web::Data<Tera>,
path: web::Path<String>,
_form: web::Form<TransactionForm>,
) -> Result<HttpResponse> {
let asset_id = path.into_inner();
println!("DEBUG: Adding transaction to asset with ID {}", asset_id);
// In a real application, we would update the asset in the database
// For now, we'll just redirect to the asset detail page
Ok(HttpResponse::Found().append_header(("Location", format!("/assets/{}", asset_id))).finish())
}
// Update the status of an asset
pub async fn update_status(
_tmpl: web::Data<Tera>,
path: web::Path<(String, String)>,
) -> Result<HttpResponse> {
let (asset_id, _status) = path.into_inner();
println!("DEBUG: Updating status of asset with ID {}", asset_id);
// In a real application, we would update the asset in the database
// For now, we'll just redirect to the asset detail page
Ok(HttpResponse::Found().append_header(("Location", format!("/assets/{}", asset_id))).finish())
}
// Test method to render a simple test page
pub async fn test(tmpl: web::Data<Tera>) -> Result<HttpResponse> {
println!("DEBUG: Starting test page rendering");
let mut context = Context::new();
let assets = Self::get_mock_assets();
println!("DEBUG: Generated {} mock assets for test", assets.len());
let stats = AssetStatistics::new(&assets);
println!("DEBUG: Generated asset statistics for test: {:?}", stats);
// Add active_page for navigation highlighting
context.insert("active_page", &"assets");
// Add stats
context.insert("stats", &serde_json::to_value(stats).unwrap());
println!("DEBUG: Added stats to context for test");
// Add recent assets
let recent_assets: Vec<serde_json::Map<String, serde_json::Value>> = assets
.iter()
.take(5)
.map(|a| Self::asset_to_json(a))
.collect();
context.insert("recent_assets", &recent_assets);
println!("DEBUG: Rendering test_base.html with full context");
let response = render_template(&tmpl, "test_base.html", &context);
println!("DEBUG: Finished rendering test_base.html");
response
}
// Helper method to convert Asset to a JSON object for templates
fn asset_to_json(asset: &Asset) -> serde_json::Map<String, serde_json::Value> {
let mut map = serde_json::Map::new();
map.insert("id".to_string(), serde_json::Value::String(asset.id.clone()));
map.insert("name".to_string(), serde_json::Value::String(asset.name.clone()));
map.insert("description".to_string(), serde_json::Value::String(asset.description.clone()));
map.insert("asset_type".to_string(), serde_json::Value::String(asset.asset_type.as_str().to_string()));
map.insert("status".to_string(), serde_json::Value::String(asset.status.as_str().to_string()));
map.insert("owner_id".to_string(), serde_json::Value::String(asset.owner_id.clone()));
map.insert("owner_name".to_string(), serde_json::Value::String(asset.owner_name.clone()));
map.insert("created_at".to_string(), serde_json::Value::String(asset.created_at.format("%Y-%m-%d").to_string()));
map.insert("updated_at".to_string(), serde_json::Value::String(asset.updated_at.format("%Y-%m-%d").to_string()));
// Add current valuation if available
if let Some(current_valuation) = asset.current_valuation {
map.insert("current_valuation".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(current_valuation).unwrap()));
if let Some(valuation_currency) = &asset.valuation_currency {
map.insert("valuation_currency".to_string(), serde_json::Value::String(valuation_currency.clone()));
}
if let Some(valuation_date) = asset.valuation_date {
map.insert("valuation_date".to_string(), serde_json::Value::String(valuation_date.format("%Y-%m-%d").to_string()));
}
}
// Add blockchain info if available
if let Some(blockchain_info) = &asset.blockchain_info {
let mut blockchain_map = serde_json::Map::new();
blockchain_map.insert("blockchain".to_string(), serde_json::Value::String(blockchain_info.blockchain.clone()));
blockchain_map.insert("token_id".to_string(), serde_json::Value::String(blockchain_info.token_id.clone()));
blockchain_map.insert("contract_address".to_string(), serde_json::Value::String(blockchain_info.contract_address.clone()));
blockchain_map.insert("owner_address".to_string(), serde_json::Value::String(blockchain_info.owner_address.clone()));
if let Some(transaction_hash) = &blockchain_info.transaction_hash {
blockchain_map.insert("transaction_hash".to_string(), serde_json::Value::String(transaction_hash.clone()));
}
if let Some(block_number) = blockchain_info.block_number {
blockchain_map.insert("block_number".to_string(), serde_json::Value::Number(serde_json::Number::from(block_number)));
}
if let Some(timestamp) = blockchain_info.timestamp {
blockchain_map.insert("timestamp".to_string(), serde_json::Value::String(timestamp.format("%Y-%m-%d").to_string()));
}
map.insert("blockchain_info".to_string(), serde_json::Value::Object(blockchain_map));
}
// Add valuation history
let valuation_history: Vec<serde_json::Value> = asset.valuation_history.iter()
.map(|v| {
let mut valuation_map = serde_json::Map::new();
valuation_map.insert("id".to_string(), serde_json::Value::String(v.id.clone()));
valuation_map.insert("date".to_string(), serde_json::Value::String(v.date.format("%Y-%m-%d").to_string()));
valuation_map.insert("value".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(v.value).unwrap()));
valuation_map.insert("currency".to_string(), serde_json::Value::String(v.currency.clone()));
valuation_map.insert("source".to_string(), serde_json::Value::String(v.source.clone()));
if let Some(notes) = &v.notes {
valuation_map.insert("notes".to_string(), serde_json::Value::String(notes.clone()));
}
serde_json::Value::Object(valuation_map)
})
.collect();
map.insert("valuation_history".to_string(), serde_json::Value::Array(valuation_history));
// Add transaction history
let transaction_history: Vec<serde_json::Value> = asset.transaction_history.iter()
.map(|t| {
let mut transaction_map = serde_json::Map::new();
transaction_map.insert("id".to_string(), serde_json::Value::String(t.id.clone()));
transaction_map.insert("transaction_type".to_string(), serde_json::Value::String(t.transaction_type.clone()));
transaction_map.insert("date".to_string(), serde_json::Value::String(t.date.format("%Y-%m-%d").to_string()));
if let Some(from_address) = &t.from_address {
transaction_map.insert("from_address".to_string(), serde_json::Value::String(from_address.clone()));
}
if let Some(to_address) = &t.to_address {
transaction_map.insert("to_address".to_string(), serde_json::Value::String(to_address.clone()));
}
if let Some(amount) = t.amount {
transaction_map.insert("amount".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(amount).unwrap()));
}
if let Some(currency) = &t.currency {
transaction_map.insert("currency".to_string(), serde_json::Value::String(currency.clone()));
}
if let Some(transaction_hash) = &t.transaction_hash {
transaction_map.insert("transaction_hash".to_string(), serde_json::Value::String(transaction_hash.clone()));
}
if let Some(notes) = &t.notes {
transaction_map.insert("notes".to_string(), serde_json::Value::String(notes.clone()));
}
serde_json::Value::Object(transaction_map)
})
.collect();
map.insert("transaction_history".to_string(), serde_json::Value::Array(transaction_history));
// Add image URL if available
if let Some(image_url) = &asset.image_url {
map.insert("image_url".to_string(), serde_json::Value::String(image_url.clone()));
}
// Add external URL if available
if let Some(external_url) = &asset.external_url {
map.insert("external_url".to_string(), serde_json::Value::String(external_url.clone()));
}
map
}
// Generate mock assets for testing
fn get_mock_assets() -> Vec<Asset> {
let now = Utc::now();
let mut assets = Vec::new();
// Create Tokenized Real Estate asset
let mut zanzibar_resort = Asset {
id: "asset-zanzibar-resort".to_string(),
name: "Zanzibar Coastal Resort".to_string(),
description: "A tokenized luxury eco-resort on the eastern coast of Zanzibar with 20 villas and sustainable energy infrastructure".to_string(),
asset_type: AssetType::RealEstate,
status: AssetStatus::Active,
owner_id: "entity-oceanview-holdings".to_string(),
owner_name: "OceanView Holdings Ltd.".to_string(),
created_at: now - Duration::days(120),
updated_at: now - Duration::days(5),
blockchain_info: None,
current_valuation: Some(3750000.0),
valuation_currency: Some("USD".to_string()),
valuation_date: Some(now - Duration::days(15)),
valuation_history: Vec::new(),
transaction_history: Vec::new(),
metadata: serde_json::json!({
"location": "East Coast, Zanzibar",
"property_size": "5.2 hectares",
"buildings": 22,
"tokenization_date": (now - Duration::days(120)).to_rfc3339(),
"total_tokens": 10000,
"token_price": 375.0
}),
image_url: Some("https://example.com/zanzibar_resort.jpg".to_string()),
external_url: Some("https://oceanviewholdings.zaz/resort".to_string()),
};
zanzibar_resort.add_blockchain_info(BlockchainInfo {
blockchain: "Ethereum".to_string(),
token_id: "ZRESORT".to_string(),
contract_address: "0x123456789abcdef123456789abcdef12345678ab".to_string(),
owner_address: "0xc3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4".to_string(),
transaction_hash: Some("0xabcdef123456789abcdef123456789abcdef123456789abcdef123456789abcd".to_string()),
block_number: Some(9876543),
timestamp: Some(now - Duration::days(120)),
});
zanzibar_resort.add_valuation(3500000.0, "USD", "ZAZ Property Registry", Some("Initial tokenization valuation".to_string()));
zanzibar_resort.add_valuation(3650000.0, "USD", "International Property Appraisers", Some("Independent third-party valuation".to_string()));
zanzibar_resort.add_valuation(3750000.0, "USD", "ZAZ Property Registry", Some("Updated valuation after infrastructure improvements".to_string()));
zanzibar_resort.add_transaction(
"Tokenization",
None,
Some("0xc3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4".to_string()),
Some(3500000.0),
Some("USD".to_string()),
Some("0xabcdef123456789abcdef123456789abcdef123456789abcdef123456789abcd".to_string()),
Some("Initial property tokenization under ZAZ Property Registry".to_string()),
);
zanzibar_resort.add_transaction(
"Token Sale",
Some("0xc3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4".to_string()),
Some("0x7a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string()),
Some(375000.0),
Some("USD".to_string()),
Some("0xdef123456789abcdef123456789abcdef123456789abcdef123456789abcdef".to_string()),
Some("Sale of 10% ownership tokens to Zanzibar Investment Collective".to_string()),
);
assets.push(zanzibar_resort);
// Create ZAZ Governance Token
let mut zaz_token = Asset {
id: "asset-zaz-governance".to_string(),
name: "ZAZ Governance Token".to_string(),
description: "Official governance token of the Zanzibar Autonomous Zone, used for voting on proposals and zone-wide decisions".to_string(),
asset_type: AssetType::Token,
status: AssetStatus::Active,
owner_id: "entity-zaz-foundation".to_string(),
owner_name: "Zanzibar Autonomous Zone Foundation".to_string(),
created_at: now - Duration::days(365),
updated_at: now - Duration::days(2),
blockchain_info: None,
current_valuation: Some(12500000.0),
valuation_currency: Some("USD".to_string()),
valuation_date: Some(now - Duration::days(3)),
valuation_history: Vec::new(),
transaction_history: Vec::new(),
metadata: serde_json::json!({
"total_supply": 10000000,
"circulating_supply": 7500000,
"governance_weight": 1.0,
"minimum_holding_for_proposals": 10000,
"launch_date": (now - Duration::days(365)).to_rfc3339()
}),
image_url: Some("https://example.com/zaz_token.png".to_string()),
external_url: Some("https://governance.zaz/token".to_string()),
};
zaz_token.add_blockchain_info(BlockchainInfo {
blockchain: "ThreeFold".to_string(),
token_id: "ZAZT".to_string(),
contract_address: "0xf6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1".to_string(),
owner_address: "0xe5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6".to_string(),
transaction_hash: None,
block_number: None,
timestamp: Some(now - Duration::days(365)),
});
zaz_token.add_valuation(8000000.0, "USD", "ZAZ Token Exchange", Some("Initial valuation at launch".to_string()));
zaz_token.add_valuation(10500000.0, "USD", "ZAZ Token Exchange", Some("Valuation after successful governance implementation".to_string()));
zaz_token.add_valuation(12500000.0, "USD", "ZAZ Token Exchange", Some("Current market valuation".to_string()));
zaz_token.add_transaction(
"Distribution",
Some("0xe5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6".to_string()),
Some("0x9a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string()),
Some(1000000.0),
Some("ZAZT".to_string()),
Some("0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()),
Some("Initial token distribution to founding members".to_string()),
);
zaz_token.add_transaction(
"Distribution",
Some("0xe5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6".to_string()),
Some("0x8b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c".to_string()),
Some(2500000.0),
Some("ZAZT".to_string()),
Some("0x234567890abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()),
Some("Public token sale for zone participants".to_string()),
);
assets.push(zaz_token);
// Create Spice Trade Venture Shares
let mut spice_trade_shares = Asset {
id: "asset-spice-trade-shares".to_string(),
name: "Zanzibar Spice Trade Ventures".to_string(),
description: "Equity shares in Zanzibar Spice Trade Ventures, a leading exporter of organic spices from the Zanzibar region".to_string(),
asset_type: AssetType::Share,
status: AssetStatus::Active,
owner_id: "entity-spice-trade".to_string(),
owner_name: "Zanzibar Spice Trade Ventures Ltd.".to_string(),
created_at: now - Duration::days(180),
updated_at: now - Duration::days(7),
blockchain_info: None,
current_valuation: Some(4250000.0),
valuation_currency: Some("USD".to_string()),
valuation_date: Some(now - Duration::days(7)),
valuation_history: Vec::new(),
transaction_history: Vec::new(),
metadata: serde_json::json!({
"total_shares": 1000000,
"share_type": "Common",
"business_sector": "Agriculture & Export",
"dividend_yield": 5.2,
"last_dividend_date": (now - Duration::days(30)).to_rfc3339(),
"incorporation_date": (now - Duration::days(180)).to_rfc3339()
}),
image_url: Some("https://example.com/spice_trade_logo.png".to_string()),
external_url: Some("https://spicetrade.zaz".to_string()),
};
spice_trade_shares.add_blockchain_info(BlockchainInfo {
blockchain: "Ethereum".to_string(),
token_id: "SPICE".to_string(),
contract_address: "0x3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4".to_string(),
owner_address: "0x6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string(),
transaction_hash: Some("0x789abcdef123456789abcdef123456789abcdef123456789abcdef123456789a".to_string()),
block_number: Some(7654321),
timestamp: Some(now - Duration::days(180)),
});
spice_trade_shares.add_valuation(3800000.0, "USD", "ZAZ Business Registry", Some("Initial company valuation at incorporation".to_string()));
spice_trade_shares.add_valuation(4000000.0, "USD", "ZAZ Business Registry", Some("Valuation after first export contracts".to_string()));
spice_trade_shares.add_valuation(4250000.0, "USD", "ZAZ Business Registry", Some("Current valuation after expansion to European markets".to_string()));
spice_trade_shares.add_transaction(
"Share Issuance",
None,
Some("0x6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string()),
Some(3800000.0),
Some("USD".to_string()),
Some("0x789abcdef123456789abcdef123456789abcdef123456789abcdef123456789a".to_string()),
Some("Initial share issuance at company formation".to_string()),
);
spice_trade_shares.add_transaction(
"Share Transfer",
Some("0x6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string()),
Some("0x7b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c".to_string()),
Some(950000.0),
Some("USD".to_string()),
Some("0x89abcdef123456789abcdef123456789abcdef123456789abcdef123456789ab".to_string()),
Some("Sale of 25% equity to East African Growth Partners".to_string()),
);
assets.push(spice_trade_shares);
// Create Sustainable Energy Patent
let mut tidal_energy_patent = Asset {
id: "asset-tidal-energy-patent".to_string(),
name: "Zanzibar Tidal Energy System Patent".to_string(),
description: "Patent for an innovative tidal energy harvesting system designed specifically for the coastal conditions of Zanzibar".to_string(),
asset_type: AssetType::IntellectualProperty,
status: AssetStatus::Active,
owner_id: "entity-zaz-energy-innovations".to_string(),
owner_name: "ZAZ Energy Innovations".to_string(),
created_at: now - Duration::days(210),
updated_at: now - Duration::days(30),
blockchain_info: None,
current_valuation: Some(2800000.0),
valuation_currency: Some("USD".to_string()),
valuation_date: Some(now - Duration::days(30)),
valuation_history: Vec::new(),
transaction_history: Vec::new(),
metadata: serde_json::json!({
"patent_number": "ZAZ-PAT-2024-0142",
"filing_date": (now - Duration::days(210)).to_rfc3339(),
"grant_date": (now - Duration::days(120)).to_rfc3339(),
"patent_type": "Utility",
"jurisdiction": "Zanzibar Autonomous Zone",
"inventors": ["Dr. Amina Juma", "Eng. Ibrahim Hassan", "Dr. Sarah Mbeki"]
}),
image_url: Some("https://example.com/tidal_energy_diagram.png".to_string()),
external_url: Some("https://patents.zaz/ZAZ-PAT-2024-0142".to_string()),
};
tidal_energy_patent.add_blockchain_info(BlockchainInfo {
blockchain: "Polygon".to_string(),
token_id: "TIDALIP".to_string(),
contract_address: "0x2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3".to_string(),
owner_address: "0x4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f".to_string(),
transaction_hash: Some("0x56789abcdef123456789abcdef123456789abcdef123456789abcdef12345678".to_string()),
block_number: Some(5432109),
timestamp: Some(now - Duration::days(120)),
});
tidal_energy_patent.add_valuation(1500000.0, "USD", "ZAZ IP Registry", Some("Initial patent valuation upon filing".to_string()));
tidal_energy_patent.add_valuation(2200000.0, "USD", "ZAZ IP Registry", Some("Valuation after successful prototype testing".to_string()));
tidal_energy_patent.add_valuation(2800000.0, "USD", "ZAZ IP Registry", Some("Current valuation after pilot implementation".to_string()));
tidal_energy_patent.add_transaction(
"Registration",
None,
Some("0x4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f".to_string()),
Some(1500000.0),
Some("USD".to_string()),
Some("0x56789abcdef123456789abcdef123456789abcdef123456789abcdef12345678".to_string()),
Some("Initial patent registration and tokenization".to_string()),
);
tidal_energy_patent.add_transaction(
"Licensing",
Some("0x4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f".to_string()),
Some("0x5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a".to_string()),
Some(450000.0),
Some("USD".to_string()),
Some("0x6789abcdef123456789abcdef123456789abcdef123456789abcdef123456789".to_string()),
Some("Licensing agreement with Coastal Energy Solutions".to_string()),
);
assets.push(tidal_energy_patent);
// Create Digital Art NFT
let mut zanzibar_heritage_nft = Asset {
id: "asset-heritage-nft".to_string(),
name: "Zanzibar Heritage Collection #1".to_string(),
description: "Limited edition digital art NFT showcasing Zanzibar's cultural heritage, created by renowned local artist Fatma Busaidy".to_string(),
asset_type: AssetType::NFT,
status: AssetStatus::Active,
owner_id: "entity-zaz-digital-arts".to_string(),
owner_name: "ZAZ Digital Arts Collective".to_string(),
created_at: now - Duration::days(90),
updated_at: now - Duration::days(10),
blockchain_info: None,
current_valuation: Some(15000.0),
valuation_currency: Some("USD".to_string()),
valuation_date: Some(now - Duration::days(10)),
valuation_history: Vec::new(),
transaction_history: Vec::new(),
metadata: serde_json::json!({
"artist": "Fatma Busaidy",
"edition": "1 of 10",
"medium": "Digital Mixed Media",
"dimensions": "4000x3000 px",
"creation_date": (now - Duration::days(95)).to_rfc3339(),
"authenticity_certificate": "ZAZ-ART-CERT-2024-089"
}),
image_url: Some("https://example.com/zanzibar_heritage_nft.jpg".to_string()),
external_url: Some("https://digitalarts.zaz/collections/heritage/1".to_string()),
};
zanzibar_heritage_nft.add_blockchain_info(BlockchainInfo {
blockchain: "Ethereum".to_string(),
token_id: "HERITAGE1".to_string(),
contract_address: "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d".to_string(),
owner_address: "0xb794f5ea0ba39494ce839613fffba74279579268".to_string(),
transaction_hash: Some("0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()),
block_number: Some(12345678),
timestamp: Some(now - Duration::days(90)),
});
zanzibar_heritage_nft.add_valuation(12000.0, "USD", "ZAZ NFT Marketplace", Some("Initial offering price".to_string()));
zanzibar_heritage_nft.add_valuation(13500.0, "USD", "ZAZ NFT Marketplace", Some("Valuation after artist exhibition".to_string()));
zanzibar_heritage_nft.add_valuation(15000.0, "USD", "ZAZ NFT Marketplace", Some("Current market valuation".to_string()));
zanzibar_heritage_nft.add_transaction(
"Minting",
None,
Some("0xb794f5ea0ba39494ce839613fffba74279579268".to_string()),
Some(0.0),
Some("ETH".to_string()),
Some("0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()),
Some("Initial NFT minting by artist".to_string()),
);
zanzibar_heritage_nft.add_transaction(
"Sale",
Some("0xb794f5ea0ba39494ce839613fffba74279579268".to_string()),
Some("0xa1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2".to_string()),
Some(12000.0),
Some("USD".to_string()),
Some("0x234567890abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()),
Some("Primary sale to ZAZ Digital Arts Collective".to_string()),
);
assets.push(zanzibar_heritage_nft);
assets
}
}