diff --git a/nac-sdk/src/adapters/l1_protocol.rs b/nac-sdk/src/adapters/l1_protocol.rs index eaab143..e5e5e7f 100644 --- a/nac-sdk/src/adapters/l1_protocol.rs +++ b/nac-sdk/src/adapters/l1_protocol.rs @@ -37,7 +37,7 @@ use super::{ CollateralProof, Decimal, }; use nac_udm::l1_protocol::gnacs::GNACSCode; -use super::NAC Lens4Client; +use super::NacLensClient; use std::time::Duration; /// L1协议层适配器 @@ -46,7 +46,7 @@ use std::time::Duration; #[derive(Debug, Clone)] pub struct L1ProtocolAdapter { /// NAC Lens4客户端 - client: NAC Lens4Client, + client: NacLensClient, /// 链ID chain_id: u32, /// 超时时间 @@ -64,7 +64,7 @@ impl L1ProtocolAdapter { /// /// 返回初始化完成的L1适配器实例 pub async fn new(config: &L1Config) -> Result { - let client = NAC Lens4Client::new(&config.nac_lens_url, config.timeout) + let client = NacLensClient::new(&config.nac_lens_url, config.timeout) .map_err(|e| NACError::NetworkError(format!("Failed to create NAC Lens4 client: {}", e)))?; Ok(Self { diff --git a/nac-sdk/src/adapters/l2_layer.rs b/nac-sdk/src/adapters/l2_layer.rs index 1384946..5635316 100644 --- a/nac-sdk/src/adapters/l2_layer.rs +++ b/nac-sdk/src/adapters/l2_layer.rs @@ -35,7 +35,7 @@ use super::{ Amendment, AmendmentStatus, Proposal, ProposalDetails, Vote, ComplianceResult, PeerInfo, }; -use super::NAC Lens4Client; +use super::NacLensClient; use super::CSNPNetwork; use super::Decimal; @@ -50,9 +50,9 @@ pub type ProposalId = u64; #[derive(Debug, Clone)] pub struct L2Adapter { /// 宪政层客户端 - constitutional_client: NAC Lens4Client, + constitutional_client: NacLensClient, /// 治理层客户端 - governance_client: NAC Lens4Client, + governance_client: NacLensClient, /// CSNP网络 network: Arc, } @@ -68,10 +68,10 @@ impl L2Adapter { /// /// 返回初始化完成的L2适配器实例 pub async fn new(config: &L2Config) -> Result { - let constitutional_client = NAC Lens4Client::new(&config.constitutional_url, std::time::Duration::from_secs(30)) + let constitutional_client = NacLensClient::new(&config.constitutional_url, std::time::Duration::from_secs(30)) .map_err(|e| NACError::NetworkError(format!("Failed to create constitutional client: {}", e)))?; - let governance_client = NAC Lens4Client::new(&config.governance_url, std::time::Duration::from_secs(30)) + let governance_client = NacLensClient::new(&config.governance_url, std::time::Duration::from_secs(30)) .map_err(|e| NACError::NetworkError(format!("Failed to create governance client: {}", e)))?; let network = Arc::new(CSNPNetwork::new(&config.network_peers).await diff --git a/nac-sdk/src/adapters/l4_ai.rs b/nac-sdk/src/adapters/l4_ai.rs index a916754..9ad732b 100644 --- a/nac-sdk/src/adapters/l4_ai.rs +++ b/nac-sdk/src/adapters/l4_ai.rs @@ -33,7 +33,7 @@ use crate::error::{NACError, Result}; use super::config::L4Config; use nac_udm::primitives::Address; -use super::{NacLensClient as NAC Lens4Client, +use super::{NacLensClient as NacLensClient, Transaction, ComplianceData, ComplianceResult, ComplianceReport, ZKProof, Asset, ValuationResult, MarketData, RiskScore, UserBehavior, AnomalyReport, RiskReport, Reserves, ReserveStrategy, @@ -48,13 +48,13 @@ use std::time::Duration; #[derive(Debug, Clone)] pub struct L4AIAdapter { /// AI合规客户端 - compliance_client: NAC Lens4Client, + compliance_client: NacLensClient, /// AI估值客户端 - valuation_client: NAC Lens4Client, + valuation_client: NacLensClient, /// AI风险客户端 - risk_client: NAC Lens4Client, + risk_client: NacLensClient, /// XTZH AI客户端 - xtzh_ai_client: NAC Lens4Client, + xtzh_ai_client: NacLensClient, } impl L4AIAdapter { @@ -68,16 +68,16 @@ impl L4AIAdapter { /// /// 返回初始化完成的L4适配器实例 pub async fn new(config: &L4Config) -> Result { - let compliance_client = NAC Lens4Client::new(&config.compliance_url, Duration::from_secs(30)) + let compliance_client = NacLensClient::new(&config.compliance_url, Duration::from_secs(30)) .map_err(|e| NACError::NetworkError(format!("Failed to create compliance client: {}", e)))?; - let valuation_client = NAC Lens4Client::new(&config.valuation_url, Duration::from_secs(30)) + let valuation_client = NacLensClient::new(&config.valuation_url, Duration::from_secs(30)) .map_err(|e| NACError::NetworkError(format!("Failed to create valuation client: {}", e)))?; - let risk_client = NAC Lens4Client::new(&config.risk_url, Duration::from_secs(30)) + let risk_client = NacLensClient::new(&config.risk_url, Duration::from_secs(30)) .map_err(|e| NACError::NetworkError(format!("Failed to create risk client: {}", e)))?; - let xtzh_ai_client = NAC Lens4Client::new(&config.xtzh_ai_url, Duration::from_secs(30)) + let xtzh_ai_client = NacLensClient::new(&config.xtzh_ai_url, Duration::from_secs(30)) .map_err(|e| NACError::NetworkError(format!("Failed to create XTZH AI client: {}", e)))?; Ok(Self { diff --git a/nac-sdk/src/adapters/l5_application.rs b/nac-sdk/src/adapters/l5_application.rs index cbe2fd8..da054d9 100644 --- a/nac-sdk/src/adapters/l5_application.rs +++ b/nac-sdk/src/adapters/l5_application.rs @@ -33,7 +33,7 @@ use crate::error::{NACError, Result}; use super::config::L5Config; use nac_udm::primitives::{Address, Hash}; use super::{ - Wallet, BalanceInfo, TransactionInfo, TransactionReceipt, NacLensClient as NAC Lens4Client, Decimal, + Wallet, BalanceInfo, TransactionInfo, TransactionReceipt, NacLensClient as NacLensClient, Decimal, ChainStatistics, AddressInfo, TokenMetadata, TradingPair, OrderBook, Value, ContractCall, }; @@ -55,13 +55,13 @@ pub struct EventStream { #[derive(Debug, Clone)] pub struct L5ApplicationAdapter { /// 钱包客户端 - wallet_client: NAC Lens4Client, + wallet_client: NacLensClient, /// DApp客户端 - dapp_client: NAC Lens4Client, + dapp_client: NacLensClient, /// 浏览器客户端 - explorer_client: NAC Lens4Client, + explorer_client: NacLensClient, /// 交易所客户端 - exchange_client: NAC Lens4Client, + exchange_client: NacLensClient, } impl L5ApplicationAdapter { @@ -75,16 +75,16 @@ impl L5ApplicationAdapter { /// /// 返回初始化完成的L5适配器实例 pub async fn new(config: &L5Config) -> Result { - let wallet_client = NAC Lens4Client::new(&config.wallet_url, Duration::from_secs(30)) + let wallet_client = NacLensClient::new(&config.wallet_url, Duration::from_secs(30)) .map_err(|e| NACError::NetworkError(format!("Failed to create wallet client: {}", e)))?; - let dapp_client = NAC Lens4Client::new(&config.dapp_url, Duration::from_secs(30)) + let dapp_client = NacLensClient::new(&config.dapp_url, Duration::from_secs(30)) .map_err(|e| NACError::NetworkError(format!("Failed to create dapp client: {}", e)))?; - let explorer_client = NAC Lens4Client::new(&config.explorer_url, Duration::from_secs(30)) + let explorer_client = NacLensClient::new(&config.explorer_url, Duration::from_secs(30)) .map_err(|e| NACError::NetworkError(format!("Failed to create explorer client: {}", e)))?; - let exchange_client = NAC Lens4Client::new(&config.exchange_url, Duration::from_secs(30)) + let exchange_client = NacLensClient::new(&config.exchange_url, Duration::from_secs(30)) .map_err(|e| NACError::NetworkError(format!("Failed to create exchange client: {}", e)))?; Ok(Self { diff --git a/nac-sdk/src/adapters/mod.rs b/nac-sdk/src/adapters/mod.rs index b6a1469..f904f51 100644 --- a/nac-sdk/src/adapters/mod.rs +++ b/nac-sdk/src/adapters/mod.rs @@ -1444,10 +1444,6 @@ impl NacLensClient { } } -/// NAC Lens4Client 类型别名(向后兼容) -pub type NAC Lens4Client = NacLensClient; -/// NacLensClient 类型别名(向后兼容,已更名为 NAC Lens) -pub type NacLensClient = NacLensClient; /// Decimal 类型(代币数量,精度由协议层处理) /// 使用 u128 表示,最小单位为 1e-18 diff --git a/nac-sdk/src/error/mod.rs b/nac-sdk/src/error/mod.rs index 810e5ed..0bd1aba 100644 --- a/nac-sdk/src/error/mod.rs +++ b/nac-sdk/src/error/mod.rs @@ -17,7 +17,7 @@ use thiserror::Error; pub enum NACError { /// NAC Lens协议错误 #[error("NAC Lens protocol error: {0}")] - NAC Lens3Error(String), + NacLensProtocolError(String), /// 网络错误 #[error("Network error: {0}")] @@ -179,7 +179,7 @@ mod tests { #[test] fn test_error_display() { - let err = NACError::NAC Lens3Error("test error".to_string()); + let err = NACError::NacLensProtocolError("test error".to_string()); assert_eq!(err.to_string(), "NAC Lens protocol error: test error"); } diff --git a/nac-sdk/src/protocols/acc1400.rs b/nac-sdk/src/protocols/acc1400.rs index 0780497..756670f 100644 --- a/nac-sdk/src/protocols/acc1400.rs +++ b/nac-sdk/src/protocols/acc1400.rs @@ -1,42 +1,98 @@ //! NAC SDK - ACC-1400 证券代币协议接口 -//! -//! ACC-1400 继承 ACC-1410,专门用于证券型资产(Security Token) -//! 增加了股息分配、投票权管理、转让限制、合规验证等功能 +//! +//! ACC-1400 是 NAC 原生的证券代币协议,支持合规证券发行、股息分配和转让限制 -use crate::types::*; -use crate::error::NacError; -use super::acc1410::{Acc1410Client, PartitionType, ExtendedGNACS}; +use crate::adapters::NacLensClient; +use crate::error::{NACError, Result}; +use nac_udm::primitives::{Address, Hash}; +use serde_json::json; /// ACC-1400 证券代币协议客户端 pub struct Acc1400Client { - pub base: Acc1410Client, + pub client: NacLensClient, + pub contract_address: Address, } impl Acc1400Client { - pub fn new(certificate_address: Address) -> Self { - Self { base: Acc1410Client::new(certificate_address) } + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - - /// 发行证券 - pub fn issue_security( + + /// 发行证券代币 + pub async fn issue_security( &self, - security_id: &Hash, - to: &Address, + recipient: &Address, amount: u128, - ) -> Result { + gnacs_code: &str, + jurisdiction: &str, + constitutional_receipt: &Hash, + ) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "recipient": recipient.to_hex(), + "amount": amount.to_string(), + "gnacs_code": gnacs_code, + "jurisdiction": jurisdiction, + "constitutional_receipt": constitutional_receipt.to_hex(), + }); + let response = self.client.call("acc1400.issue_security", params).await?; + let tx_hash = response["result"].as_str() + .ok_or(NACError::InvalidResponse("Missing tx_hash".to_string()))?; + Hash::from_hex(tx_hash).map_err(|e| NACError::InvalidAddress(format!("Invalid hash: {}", e))) } - - /// 证券转让(含合规检查) - pub fn transfer_security( + + /// 合规转让 + pub async fn transfer_with_data( &self, from: &Address, to: &Address, amount: u128, - security_id: &Hash, - ) -> Result { + compliance_data: &Hash, + ) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "from": from.to_hex(), + "to": to.to_hex(), + "amount": amount.to_string(), + "compliance_data": compliance_data.to_hex(), + }); + let response = self.client.call("acc1400.transfer_with_data", params).await?; + let tx_hash = response["result"].as_str() + .ok_or(NACError::InvalidResponse("Missing tx_hash".to_string()))?; + Hash::from_hex(tx_hash).map_err(|e| NACError::InvalidAddress(format!("Invalid hash: {}", e))) } - - /// 添加白名单 - pub fn add_to_whitelist(&self, account: &Address) -> Result<(), NacError> { + + /// 查询合规状态 + pub async fn can_transfer( + &self, + from: &Address, + to: &Address, + amount: u128, + ) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "from": from.to_hex(), + "to": to.to_hex(), + "amount": amount.to_string(), + }); + let response = self.client.call("acc1400.can_transfer", params).await?; + Ok(response["result"].as_bool().unwrap_or(false)) + } + + /// 分配股息 + pub async fn distribute_dividend( + &self, + total_amount: u128, + constitutional_receipt: &Hash, + ) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "total_amount": total_amount.to_string(), + "constitutional_receipt": constitutional_receipt.to_hex(), + }); + let response = self.client.call("acc1400.distribute_dividend", params).await?; + let tx_hash = response["result"].as_str() + .ok_or(NACError::InvalidResponse("Missing tx_hash".to_string()))?; + Hash::from_hex(tx_hash).map_err(|e| NACError::InvalidAddress(format!("Invalid hash: {}", e))) } } diff --git a/nac-sdk/src/protocols/acc1410.rs b/nac-sdk/src/protocols/acc1410.rs index c39b51c..4a606b8 100644 --- a/nac-sdk/src/protocols/acc1410.rs +++ b/nac-sdk/src/protocols/acc1410.rs @@ -1,44 +1,104 @@ //! NAC SDK - ACC-1410 分区代币协议接口 -//! +//! //! ACC-1410 是 NAC 原生的分区代币协议,支持将代币分割为多个分区 //! (普通股、优先股、限制股、员工期权、收益权、投票权等) -use crate::types::*; -use crate::error::NacError; +use crate::adapters::NacLensClient; +use crate::error::{NACError, Result}; +use nac_udm::primitives::{Address, Hash}; +use serde_json::json; /// ACC-1410 分区代币协议客户端 pub struct Acc1410Client { - /// 证书地址(Charter 合约地址) - pub certificate_address: Address, + pub client: NacLensClient, + pub contract_address: Address, } impl Acc1410Client { - /// 创建新的 ACC-1410 客户端 - pub fn new(certificate_address: Address) -> Self { - Self { certificate_address } + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - + /// 查询分区余额 - pub fn balance_of_by_partition( - &self, + pub async fn balance_of_by_partition( + &self, partition_id: &Hash, account: &Address, - ) -> Result { - // 通过 NRPC4.0 调用链上合约 + ) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "partition_id": partition_id.to_hex(), + "account": account.to_hex(), + }); + let response = self.client.call("acc1410.balance_of_by_partition", params).await?; + let balance = response["result"].as_str() + .ok_or(NACError::InvalidResponse("Missing balance".to_string()))? + .parse::() + .map_err(|e| NACError::InvalidResponse(format!("Invalid balance: {}", e)))?; + Ok(balance) } - + /// 查询账户持有的所有分区 - pub fn partitions_of(&self, account: &Address) -> Result, NacError> { + pub async fn partitions_of(&self, account: &Address) -> Result> { + let params = json!({ + "contract": self.contract_address.to_hex(), + "account": account.to_hex(), + }); + let response = self.client.call("acc1410.partitions_of", params).await?; + let partitions = response["result"].as_array() + .ok_or(NACError::InvalidResponse("Missing partitions".to_string()))? + .iter() + .filter_map(|v| v.as_str()) + .filter_map(|s| Hash::from_hex(s).ok()) + .collect(); + Ok(partitions) } - + /// 分区间转账 - pub fn transfer_by_partition( + pub async fn transfer_by_partition( &self, from: &Address, to: &Address, amount: u128, partition_id: &Hash, - ) -> Result { + ) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "from": from.to_hex(), + "to": to.to_hex(), + "amount": amount.to_string(), + "partition_id": partition_id.to_hex(), + }); + let response = self.client.call("acc1410.transfer_by_partition", params).await?; + let tx_hash = response["result"].as_str() + .ok_or(NACError::InvalidResponse("Missing tx_hash".to_string()))?; + Hash::from_hex(tx_hash).map_err(|e| NACError::InvalidAddress(format!("Invalid hash: {}", e))) + } + + /// 创建新分区 + pub async fn create_partition( + &self, + partition_id: &Hash, + partition_type: u8, + constitutional_receipt: &Hash, + ) -> Result<()> { + let params = json!({ + "contract": self.contract_address.to_hex(), + "partition_id": partition_id.to_hex(), + "partition_type": partition_type, + "constitutional_receipt": constitutional_receipt.to_hex(), + }); + self.client.call("acc1410.create_partition", params).await?; + Ok(()) + } + + /// 查询分区信息 + pub async fn get_partition_info(&self, partition_id: &Hash) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "partition_id": partition_id.to_hex(), + }); + self.client.call("acc1410.get_partition_info", params).await } } diff --git a/nac-sdk/src/protocols/acc1594.rs b/nac-sdk/src/protocols/acc1594.rs index 07ceb76..0311e0b 100644 --- a/nac-sdk/src/protocols/acc1594.rs +++ b/nac-sdk/src/protocols/acc1594.rs @@ -1,63 +1,63 @@ //! NAC SDK - ACC-1594 收益分配协议接口 -//! -//! ACC-1594 基于 GNACS 数字基因的核心收益与资产操作协议 -//! 增加了资产发行/赎回、收益分配、分红领取等功能 -use crate::types::*; -use crate::error::NacError; +use crate::adapters::NacLensClient; +use crate::error::{NACError, Result}; +use nac_udm::primitives::{Address, Hash}; +use serde_json::json; /// ACC-1594 收益分配协议客户端 pub struct Acc1594Client { - pub certificate_address: Address, + pub client: NacLensClient, + pub contract_address: Address, } impl Acc1594Client { - pub fn new(certificate_address: Address) -> Self { - Self { certificate_address } + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - - /// 发行资产 - pub fn issue( + + /// 分配收益 + pub async fn distribute_yield( &self, - to: &Address, - amount: u128, - partition_id: &Hash, - receipt: &Hash, - ) -> Result { + total_yield: u128, + period_id: u64, + constitutional_receipt: &Hash, + ) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "total_yield": total_yield.to_string(), + "period_id": period_id, + "constitutional_receipt": constitutional_receipt.to_hex(), + }); + let response = self.client.call("acc1594.distribute_yield", params).await?; + let tx_hash = response["result"].as_str() + .ok_or(NACError::InvalidResponse("Missing tx_hash".to_string()))?; + Hash::from_hex(tx_hash).map_err(|e| NACError::InvalidAddress(format!("Invalid hash: {}", e))) } - - /// 赎回资产 - pub fn redeem( - &self, - amount: u128, - partition_id: &Hash, - receipt: &Hash, - ) -> Result { + + /// 查询待领取收益 + pub async fn claimable_yield(&self, account: &Address) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "account": account.to_hex(), + }); + let response = self.client.call("acc1594.claimable_yield", params).await?; + let amount = response["result"].as_str() + .ok_or(NACError::InvalidResponse("Missing amount".to_string()))? + .parse::() + .map_err(|e| NACError::InvalidResponse(format!("Invalid amount: {}", e)))?; + Ok(amount) } - - /// 分配收益(分红) - pub fn distribute_dividend( - &self, - partition_id: &Hash, - total_amount: u128, - period: u64, - receipt: &Hash, - ) -> Result { - } - - /// 查询可领取分红 - pub fn claimable_dividend( - &self, - account: &Address, - partition_id: &Hash, - ) -> Result { - } - - /// 领取分红 - pub fn claim_dividend( - &self, - partition_id: &Hash, - receipt: &Hash, - ) -> Result { + + /// 领取收益 + pub async fn claim_yield(&self, account: &Address) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "account": account.to_hex(), + }); + let response = self.client.call("acc1594.claim_yield", params).await?; + let tx_hash = response["result"].as_str() + .ok_or(NACError::InvalidResponse("Missing tx_hash".to_string()))?; + Hash::from_hex(tx_hash).map_err(|e| NACError::InvalidAddress(format!("Invalid hash: {}", e))) } } diff --git a/nac-sdk/src/protocols/acc1643.rs b/nac-sdk/src/protocols/acc1643.rs index f4e6683..25e6000 100644 --- a/nac-sdk/src/protocols/acc1643.rs +++ b/nac-sdk/src/protocols/acc1643.rs @@ -1,53 +1,69 @@ //! NAC SDK - ACC-1643 文档管理协议接口 -//! -//! ACC-1643 提供链上文档存储、版本控制、完整性验证功能 -use crate::types::*; -use crate::error::NacError; +use crate::adapters::NacLensClient; +use crate::error::{NACError, Result}; +use nac_udm::primitives::{Address, Hash}; +use serde_json::json; /// ACC-1643 文档管理协议客户端 pub struct Acc1643Client { - pub certificate_address: Address, + pub client: NacLensClient, + pub contract_address: Address, } impl Acc1643Client { - pub fn new(certificate_address: Address) -> Self { - Self { certificate_address } + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - - /// 存储/更新文档 - pub fn set_document( - &self, - doc_type: &str, - uri: &str, - content_hash: &Hash, - supersedes: &Hash, - receipt: &Hash, - ) -> Result { - } - - /// 获取文档 - pub fn get_document(&self, doc_id: &Hash) -> Result { - } - - /// 验证文档完整性 - pub fn verify_document( - &self, - doc_id: &Hash, - uri: &str, - content_hash: &Hash, - ) -> Result { - } -} -/// 文档结构 -#[derive(Debug, Clone)] -pub struct AssetDocument { - pub doc_id: Hash, - pub doc_type: String, - pub uri: String, - pub content_hash: Hash, - pub version: u32, - pub is_active: bool, - pub created_at: u64, + /// 设置文档 + pub async fn set_document( + &self, + doc_name: &str, + doc_uri: &str, + doc_hash: &Hash, + constitutional_receipt: &Hash, + ) -> Result<()> { + let params = json!({ + "contract": self.contract_address.to_hex(), + "doc_name": doc_name, + "doc_uri": doc_uri, + "doc_hash": doc_hash.to_hex(), + "constitutional_receipt": constitutional_receipt.to_hex(), + }); + self.client.call("acc1643.set_document", params).await?; + Ok(()) + } + + /// 查询文档 + pub async fn get_document(&self, doc_name: &str) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "doc_name": doc_name, + }); + self.client.call("acc1643.get_document", params).await + } + + /// 列出所有文档 + pub async fn get_all_documents(&self) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + }); + self.client.call("acc1643.get_all_documents", params).await + } + + /// 删除文档 + pub async fn remove_document( + &self, + doc_name: &str, + constitutional_receipt: &Hash, + ) -> Result<()> { + let params = json!({ + "contract": self.contract_address.to_hex(), + "doc_name": doc_name, + "constitutional_receipt": constitutional_receipt.to_hex(), + }); + self.client.call("acc1643.remove_document", params).await?; + Ok(()) + } } diff --git a/nac-sdk/src/protocols/acc1644.rs b/nac-sdk/src/protocols/acc1644.rs index c9f93d1..a2fe977 100644 --- a/nac-sdk/src/protocols/acc1644.rs +++ b/nac-sdk/src/protocols/acc1644.rs @@ -1,54 +1,81 @@ //! NAC SDK - ACC-1644 监管控制协议接口 -//! -//! ACC-1644 宪法授权控制器操作协议 -//! 提供监管机构对资产的强制操作能力(需要宪法授权) -use crate::types::*; -use crate::error::NacError; +use crate::adapters::NacLensClient; +use crate::error::{NACError, Result}; +use nac_udm::primitives::{Address, Hash}; +use serde_json::json; /// ACC-1644 监管控制协议客户端 pub struct Acc1644Client { - pub certificate_address: Address, + pub client: NacLensClient, + pub contract_address: Address, } impl Acc1644Client { - pub fn new(certificate_address: Address) -> Self { - Self { certificate_address } + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - - /// 冻结分区(监管机构操作) - pub fn freeze( + + /// 冻结账户 + pub async fn freeze_account( &self, - partition_id: &Hash, - reason: &[u8], - evidence: &[u8], - receipt: &Hash, - ) -> Result { + account: &Address, + reason: &str, + constitutional_receipt: &Hash, + ) -> Result<()> { + let params = json!({ + "contract": self.contract_address.to_hex(), + "account": account.to_hex(), + "reason": reason, + "constitutional_receipt": constitutional_receipt.to_hex(), + }); + self.client.call("acc1644.freeze_account", params).await?; + Ok(()) } - - /// 解冻分区 - pub fn unfreeze( + + /// 解冻账户 + pub async fn unfreeze_account( &self, - partition_id: &Hash, - reason: &[u8], - evidence: &[u8], - receipt: &Hash, - ) -> Result { + account: &Address, + constitutional_receipt: &Hash, + ) -> Result<()> { + let params = json!({ + "contract": self.contract_address.to_hex(), + "account": account.to_hex(), + "constitutional_receipt": constitutional_receipt.to_hex(), + }); + self.client.call("acc1644.unfreeze_account", params).await?; + Ok(()) } - - /// 强制转移(法院命令) - pub fn force_transfer( + + /// 强制转移(监管命令) + pub async fn forced_transfer( &self, - partition_id: &Hash, from: &Address, to: &Address, amount: u128, - legal_basis: &Hash, - receipt: &Hash, - ) -> Result { + constitutional_receipt: &Hash, + ) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "from": from.to_hex(), + "to": to.to_hex(), + "amount": amount.to_string(), + "constitutional_receipt": constitutional_receipt.to_hex(), + }); + let response = self.client.call("acc1644.forced_transfer", params).await?; + let tx_hash = response["result"].as_str() + .ok_or(NACError::InvalidResponse("Missing tx_hash".to_string()))?; + Hash::from_hex(tx_hash).map_err(|e| NACError::InvalidAddress(format!("Invalid hash: {}", e))) } - - /// 查询分区冻结状态 - pub fn is_partition_frozen(&self, partition_id: &Hash) -> Result { + + /// 查询账户冻结状态 + pub async fn is_frozen(&self, account: &Address) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "account": account.to_hex(), + }); + let response = self.client.call("acc1644.is_frozen", params).await?; + Ok(response["result"].as_bool().unwrap_or(false)) } } diff --git a/nac-sdk/src/protocols/acc_collateral.rs b/nac-sdk/src/protocols/acc_collateral.rs index 0a171c1..55ffa15 100644 --- a/nac-sdk/src/protocols/acc_collateral.rs +++ b/nac-sdk/src/protocols/acc_collateral.rs @@ -1,42 +1,48 @@ -//! ACC-Collateral 抵押协议客户端接口 +//! AccCollateral 协议客户端接口 +//! NAC 原生 SDK - 通过 NRPC4.0 与链交互 -use crate::types::{Address, Hash, NRPCClient, NRPCError}; +use crate::error::{NACError, Result}; +use crate::adapters::NacLensClient; +use nac_udm::primitives::{Address, Hash}; +use serde_json::{json, Value}; -#[derive(Debug, Clone)] -pub struct CollateralRecord { - pub collateral_id: Hash, - pub asset_id: Hash, - pub borrower: Address, - pub lender: Address, - pub collateral_value_xtzh: u128, - pub loan_amount_xtzh: u128, - pub is_liquidated: bool, +/// AccCollateral 协议客户端 +pub struct AccCollateralClient { + pub client: NacLensClient, + pub contract_address: Address, } -pub struct AccCollateralClient { rpc: NRPCClient } - impl AccCollateralClient { - pub fn new(rpc: NRPCClient) -> Self { Self { rpc } } - - pub async fn create_collateral( - &self, asset_id: Hash, borrower: Address, lender: Address, - collateral_value_xtzh: u128, loan_amount_xtzh: u128, - maturity_secs: u64, constitutional_receipt: Hash, - ) -> Result { - self.rpc.call("acc_collateral.create_collateral", &( - asset_id, borrower, lender, collateral_value_xtzh, - loan_amount_xtzh, maturity_secs, constitutional_receipt - )).await + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - pub async fn liquidate( - &self, collateral_id: Hash, liquidator: Address, current_value: u128, - constitutional_receipt: Hash, - ) -> Result { - self.rpc.call("acc_collateral.liquidate", &(collateral_id, liquidator, current_value, constitutional_receipt)).await + /// 锁定抵押品 + pub async fn lock_collateral(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_collateral.lock_collateral", p).await } - pub async fn get_collateral(&self, collateral_id: Hash) -> Result, NRPCError> { - self.rpc.call("acc_collateral.get_collateral", &collateral_id).await + /// 查询抵押品详情 + pub async fn get_collateral(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_collateral.get_collateral", p).await } + + /// 释放抵押品 + pub async fn release_collateral(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_collateral.release_collateral", p).await + } + + /// 清算抵押品 + pub async fn liquidate_collateral(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_collateral.liquidate_collateral", p).await + } + } diff --git a/nac-sdk/src/protocols/acc_compliance.rs b/nac-sdk/src/protocols/acc_compliance.rs index a2da867..ace4592 100644 --- a/nac-sdk/src/protocols/acc_compliance.rs +++ b/nac-sdk/src/protocols/acc_compliance.rs @@ -1,66 +1,48 @@ -//! ACC-Compliance 七层合规验证协议客户端接口 +//! AccCompliance 协议客户端接口 +//! NAC 原生 SDK - 通过 NRPC4.0 与链交互 -use crate::types::{Address, Hash, NRPCClient, NRPCError}; +use crate::error::{NACError, Result}; +use crate::adapters::NacLensClient; +use nac_udm::primitives::{Address, Hash}; +use serde_json::{json, Value}; -/// 七层合规验证结果 -#[derive(Debug, Clone)] -pub struct SevenLayerComplianceResult { - pub layer1_kyc: bool, - pub layer2_aml: bool, - pub layer3_jurisdiction: bool, - pub layer4_ai_risk: bool, - pub layer5_constitutional: bool, - pub layer6_gnacs: bool, - pub layer7_cbpp: bool, - pub overall_compliant: bool, - pub ai_risk_score: u8, -} - -/// 合规记录 -#[derive(Debug, Clone)] -pub struct ComplianceRecord { - pub entity: Address, - pub kyc_verified: bool, - pub aml_cleared: bool, - pub is_blacklisted: bool, - pub ai_risk_score: u8, - pub allowed_jurisdictions: Vec, -} - -/// ACC-Compliance 协议客户端 +/// AccCompliance 协议客户端 pub struct AccComplianceClient { - rpc: NRPCClient, + pub client: NacLensClient, + pub contract_address: Address, } impl AccComplianceClient { - pub fn new(rpc: NRPCClient) -> Self { Self { rpc } } - - /// 注册合规实体 - pub async fn register_entity( - &self, entity: Address, kyc_verified: bool, aml_cleared: bool, - allowed_jurisdictions: Vec, ai_risk_score: u8, - constitutional_receipt: Hash, - ) -> Result<(), NRPCError> { - self.rpc.call("acc_compliance.register_entity", &( - entity, kyc_verified, aml_cleared, allowed_jurisdictions, - ai_risk_score, constitutional_receipt - )).await + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - /// 执行七层合规验证 - pub async fn run_seven_layer_check( - &self, entity: Address, jurisdiction: &str, constitutional_receipt: Hash, - ) -> Result { - self.rpc.call("acc_compliance.run_seven_layer_check", &(entity, jurisdiction, constitutional_receipt)).await + /// 七层合规验证 + pub async fn verify(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_compliance.verify", p).await } - /// 查询合规状态 - pub async fn is_compliant(&self, entity: Address) -> Result { - self.rpc.call("acc_compliance.is_compliant", &entity).await + /// 查询合规记录 + pub async fn get_record(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_compliance.get_record", p).await } - /// 获取合规记录 - pub async fn get_record(&self, entity: Address) -> Result, NRPCError> { - self.rpc.call("acc_compliance.get_record", &entity).await + /// 更新合规记录 + pub async fn update_record(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_compliance.update_record", p).await } + + /// 查询司法管辖区规则 + pub async fn get_jurisdiction_rules(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_compliance.get_jurisdiction_rules", p).await + } + } diff --git a/nac-sdk/src/protocols/acc_custody.rs b/nac-sdk/src/protocols/acc_custody.rs index fabc3a9..32cf18d 100644 --- a/nac-sdk/src/protocols/acc_custody.rs +++ b/nac-sdk/src/protocols/acc_custody.rs @@ -1,43 +1,48 @@ -//! ACC-Custody 资产托管协议客户端接口 +//! AccCustody 协议客户端接口 +//! NAC 原生 SDK - 通过 NRPC4.0 与链交互 -use crate::types::{Address, Hash, NRPCClient, NRPCError}; +use crate::error::{NACError, Result}; +use crate::adapters::NacLensClient; +use nac_udm::primitives::{Address, Hash}; +use serde_json::{json, Value}; -#[derive(Debug, Clone)] -pub enum CustodyType { Primary, Secondary, Escrow, Regulatory } - -#[derive(Debug, Clone)] -pub struct CustodyRecord { - pub custody_id: Hash, - pub asset_id: Hash, - pub owner: Address, - pub custodian: Address, - pub custody_type: CustodyType, - pub is_active: bool, +/// AccCustody 协议客户端 +pub struct AccCustodyClient { + pub client: NacLensClient, + pub contract_address: Address, } -pub struct AccCustodyClient { rpc: NRPCClient } - impl AccCustodyClient { - pub fn new(rpc: NRPCClient) -> Self { Self { rpc } } - - pub async fn create_custody( - &self, asset_id: Hash, owner: Address, custodian: Address, - custody_type: CustodyType, constitutional_receipt: Hash, - ) -> Result { - self.rpc.call("acc_custody.create_custody", &(asset_id, owner, custodian, custody_type, constitutional_receipt)).await + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - pub async fn transfer_custody( - &self, custody_id: Hash, new_custodian: Address, constitutional_receipt: Hash, - ) -> Result<(), NRPCError> { - self.rpc.call("acc_custody.transfer_custody", &(custody_id, new_custodian, constitutional_receipt)).await + /// 创建托管记录 + pub async fn create_custody(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_custody.create_custody", p).await } - pub async fn release_custody(&self, custody_id: Hash, constitutional_receipt: Hash) -> Result<(), NRPCError> { - self.rpc.call("acc_custody.release_custody", &(custody_id, constitutional_receipt)).await + /// 查询托管详情 + pub async fn get_custody(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_custody.get_custody", p).await } - pub async fn get_custody(&self, custody_id: Hash) -> Result, NRPCError> { - self.rpc.call("acc_custody.get_custody", &custody_id).await + /// 释放托管 + pub async fn release_custody(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_custody.release_custody", p).await } + + /// 转移托管权 + pub async fn transfer_custody(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_custody.transfer_custody", p).await + } + } diff --git a/nac-sdk/src/protocols/acc_governance.rs b/nac-sdk/src/protocols/acc_governance.rs index 96e28e3..0413e16 100644 --- a/nac-sdk/src/protocols/acc_governance.rs +++ b/nac-sdk/src/protocols/acc_governance.rs @@ -1,30 +1,48 @@ -//! ACC-Governance 治理协议客户端接口 +//! AccGovernance 协议客户端接口 +//! NAC 原生 SDK - 通过 NRPC4.0 与链交互 -use crate::types::{Address, Hash, NRPCClient, NRPCError}; +use crate::error::{NACError, Result}; +use crate::adapters::NacLensClient; +use nac_udm::primitives::{Address, Hash}; +use serde_json::{json, Value}; -#[derive(Debug, Clone)] -pub enum VoteChoice { For, Against, Abstain } - -#[derive(Debug, Clone)] -pub enum ProposalType { ParameterChange, ProtocolUpgrade, EmergencyAction, FundAllocation } - -pub struct AccGovernanceClient { rpc: NRPCClient } +/// AccGovernance 协议客户端 +pub struct AccGovernanceClient { + pub client: NacLensClient, + pub contract_address: Address, +} impl AccGovernanceClient { - pub fn new(rpc: NRPCClient) -> Self { Self { rpc } } - - pub async fn create_proposal( - &self, proposer: Address, proposal_type: ProposalType, - description: &str, voting_duration_secs: u64, constitutional_receipt: Hash, - ) -> Result { - self.rpc.call("acc_governance.create_proposal", &(proposer, proposal_type, description, voting_duration_secs, constitutional_receipt)).await + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - pub async fn cast_vote(&self, proposal_id: Hash, voter: Address, choice: VoteChoice) -> Result<(), NRPCError> { - self.rpc.call("acc_governance.cast_vote", &(proposal_id, voter, choice)).await + /// 创建治理提案 + pub async fn create_proposal(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_governance.create_proposal", p).await } - pub async fn finalize_proposal(&self, proposal_id: Hash, constitutional_receipt: Hash) -> Result { - self.rpc.call("acc_governance.finalize_proposal", &(proposal_id, constitutional_receipt)).await + /// 投票 + pub async fn vote(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_governance.vote", p).await } + + /// 执行提案 + pub async fn execute_proposal(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_governance.execute_proposal", p).await + } + + /// 查询提案详情 + pub async fn get_proposal(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_governance.get_proposal", p).await + } + } diff --git a/nac-sdk/src/protocols/acc_insurance.rs b/nac-sdk/src/protocols/acc_insurance.rs index 5939685..8bbab63 100644 --- a/nac-sdk/src/protocols/acc_insurance.rs +++ b/nac-sdk/src/protocols/acc_insurance.rs @@ -1,34 +1,48 @@ -//! ACC-Insurance 资产保险协议客户端接口 +//! AccInsurance 协议客户端接口 +//! NAC 原生 SDK - 通过 NRPC4.0 与链交互 -use crate::types::{Address, Hash, NRPCClient, NRPCError}; +use crate::error::{NACError, Result}; +use crate::adapters::NacLensClient; +use nac_udm::primitives::{Address, Hash}; +use serde_json::{json, Value}; -#[derive(Debug, Clone)] -pub enum InsuranceType { AssetLoss, PriceVolatility, CustodyRisk, LegalRisk, NaturalDisaster } - -pub struct AccInsuranceClient { rpc: NRPCClient } +/// AccInsurance 协议客户端 +pub struct AccInsuranceClient { + pub client: NacLensClient, + pub contract_address: Address, +} impl AccInsuranceClient { - pub fn new(rpc: NRPCClient) -> Self { Self { rpc } } - - pub async fn issue_policy( - &self, asset_id: Hash, insured: Address, insurer: Address, - insurance_type: InsuranceType, coverage_amount: u128, - premium_rate_bps: u16, duration_secs: u64, constitutional_receipt: Hash, - ) -> Result { - self.rpc.call("acc_insurance.issue_policy", &( - asset_id, insured, insurer, insurance_type, - coverage_amount, premium_rate_bps, duration_secs, constitutional_receipt - )).await + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - pub async fn submit_claim( - &self, policy_id: Hash, claimant: Address, claim_amount: u128, - reason: &str, evidence_hash: Hash, constitutional_receipt: Hash, - ) -> Result { - self.rpc.call("acc_insurance.submit_claim", &(policy_id, claimant, claim_amount, reason, evidence_hash, constitutional_receipt)).await + /// 创建保险策略 + pub async fn create_policy(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_insurance.create_policy", p).await } - pub async fn pay_claim(&self, claim_id: Hash, constitutional_receipt: Hash) -> Result { - self.rpc.call("acc_insurance.pay_claim", &(claim_id, constitutional_receipt)).await + /// 查询保险策略 + pub async fn get_policy(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_insurance.get_policy", p).await } + + /// 提交理赔申请 + pub async fn file_claim(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_insurance.file_claim", p).await + } + + /// 处理理赔 + pub async fn process_claim(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_insurance.process_claim", p).await + } + } diff --git a/nac-sdk/src/protocols/acc_redemption.rs b/nac-sdk/src/protocols/acc_redemption.rs index 4300a31..366e9dd 100644 --- a/nac-sdk/src/protocols/acc_redemption.rs +++ b/nac-sdk/src/protocols/acc_redemption.rs @@ -1,24 +1,48 @@ -//! ACC-Redemption 赎回协议客户端接口 +//! AccRedemption 协议客户端接口 +//! NAC 原生 SDK - 通过 NRPC4.0 与链交互 -use crate::types::{Address, Hash, NRPCClient, NRPCError}; +use crate::error::{NACError, Result}; +use crate::adapters::NacLensClient; +use nac_udm::primitives::{Address, Hash}; +use serde_json::{json, Value}; -pub struct AccRedemptionClient { rpc: NRPCClient } +/// AccRedemption 协议客户端 +pub struct AccRedemptionClient { + pub client: NacLensClient, + pub contract_address: Address, +} impl AccRedemptionClient { - pub fn new(rpc: NRPCClient) -> Self { Self { rpc } } - - pub async fn fund_pool(&self, asset_id: Hash, amount_xtzh: u128, constitutional_receipt: Hash) -> Result<(), NRPCError> { - self.rpc.call("acc_redemption.fund_redemption_pool", &(asset_id, amount_xtzh, constitutional_receipt)).await + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - pub async fn request_redemption( - &self, asset_id: Hash, redeemer: Address, amount: u128, - price_xtzh: u128, constitutional_receipt: Hash, - ) -> Result { - self.rpc.call("acc_redemption.request_redemption", &(asset_id, redeemer, amount, price_xtzh, constitutional_receipt)).await + /// 申请赎回 + pub async fn request_redemption(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_redemption.request_redemption", p).await } - pub async fn complete_redemption(&self, redemption_id: Hash, constitutional_receipt: Hash) -> Result { - self.rpc.call("acc_redemption.complete_redemption", &(redemption_id, constitutional_receipt)).await + /// 批准赎回 + pub async fn approve_redemption(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_redemption.approve_redemption", p).await } + + /// 查询赎回详情 + pub async fn get_redemption(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_redemption.get_redemption", p).await + } + + /// 取消赎回 + pub async fn cancel_redemption(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_redemption.cancel_redemption", p).await + } + } diff --git a/nac-sdk/src/protocols/acc_reserve.rs b/nac-sdk/src/protocols/acc_reserve.rs index 368d01f..0263787 100644 --- a/nac-sdk/src/protocols/acc_reserve.rs +++ b/nac-sdk/src/protocols/acc_reserve.rs @@ -1,39 +1,48 @@ -//! ACC-Reserve 多资产储备协议客户端接口 +//! AccReserve 协议客户端接口 +//! NAC 原生 SDK - 通过 NRPC4.0 与链交互 -use crate::types::{Address, Hash, NRPCClient, NRPCError}; +use crate::error::{NACError, Result}; +use crate::adapters::NacLensClient; +use nac_udm::primitives::{Address, Hash}; +use serde_json::{json, Value}; -#[derive(Debug, Clone)] -pub struct ReserveEntry { - pub asset_symbol: String, - pub amount: u128, - pub custodian: Address, - pub last_audit_hash: Option, +/// AccReserve 协议客户端 +pub struct AccReserveClient { + pub client: NacLensClient, + pub contract_address: Address, } -pub struct AccReserveClient { rpc: NRPCClient } - impl AccReserveClient { - pub fn new(rpc: NRPCClient) -> Self { Self { rpc } } - - pub async fn deposit( - &self, asset_symbol: &str, amount: u128, custodian: Address, - constitutional_receipt: Hash, - ) -> Result<(), NRPCError> { - self.rpc.call("acc_reserve.deposit", &(asset_symbol, amount, custodian, constitutional_receipt)).await + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - pub async fn withdraw( - &self, asset_symbol: &str, amount: u128, recipient: Address, - constitutional_receipt: Hash, - ) -> Result<(), NRPCError> { - self.rpc.call("acc_reserve.withdraw", &(asset_symbol, amount, recipient, constitutional_receipt)).await + /// 查询储备信息 + pub async fn get_reserve_info(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_reserve.get_reserve_info", p).await } - pub async fn audit(&self, asset_symbol: &str, audit_hash: Hash) -> Result<(), NRPCError> { - self.rpc.call("acc_reserve.audit", &(asset_symbol, audit_hash)).await + /// 增加储备 + pub async fn add_reserve(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_reserve.add_reserve", p).await } - pub async fn get_reserve(&self, asset_symbol: &str) -> Result, NRPCError> { - self.rpc.call("acc_reserve.get_reserve", &asset_symbol).await + /// 提取储备 + pub async fn withdraw_reserve(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_reserve.withdraw_reserve", p).await } + + /// 查询储备构成 + pub async fn get_reserve_composition(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_reserve.get_reserve_composition", p).await + } + } diff --git a/nac-sdk/src/protocols/acc_rwa.rs b/nac-sdk/src/protocols/acc_rwa.rs index a2386f7..aed1622 100644 --- a/nac-sdk/src/protocols/acc_rwa.rs +++ b/nac-sdk/src/protocols/acc_rwa.rs @@ -1,70 +1,58 @@ //! ACC-RWA 协议客户端接口 //! NAC 原生 SDK - 通过 NRPC4.0 与链交互 -use crate::types::{Address, Hash, NRPCClient, NRPCError}; +use crate::error::{NACError, Result}; +use crate::adapters::NacLensClient; +use nac_udm::primitives::{Address, Hash}; +use serde_json::{json, Value}; -/// RWA 资产类型 -#[derive(Debug, Clone)] -pub enum RWAAssetType { - RealEstate, Infrastructure, CommodityFund, PrivateEquity, - CarbonCredit, IntellectualProperty, ArtAndCollectibles, Other(String), -} - -/// RWA 资产记录 -#[derive(Debug, Clone)] -pub struct RWAAssetRecord { - pub asset_id: Hash, - pub gnacs_code: String, - pub asset_type: RWAAssetType, - pub owner: Address, - pub total_supply: u128, - pub valuation_xtzh: u128, - pub jurisdiction: String, - pub is_frozen: bool, -} - -/// ACC-RWA 协议客户端 +/// ACC-RWA 真实世界资产协议客户端 pub struct AccRwaClient { - rpc: NRPCClient, + pub client: NacLensClient, + pub contract_address: Address, } impl AccRwaClient { - pub fn new(rpc: NRPCClient) -> Self { Self { rpc } } + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } + } /// 注册 RWA 资产 - pub async fn register_asset( - &self, gnacs_code: &str, asset_type: RWAAssetType, owner: Address, - total_supply: u128, initial_valuation_xtzh: u128, jurisdiction: &str, - legal_document_hash: Hash, ai_compliance_score: u8, - constitutional_receipt: Hash, - ) -> Result { - self.rpc.call("acc_rwa.register_asset", &( - gnacs_code, asset_type, owner, total_supply, initial_valuation_xtzh, - jurisdiction, legal_document_hash, ai_compliance_score, constitutional_receipt - )).await + pub async fn register_asset(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_rwa.register_asset", p).await } /// 转移 RWA 资产 - pub async fn transfer_asset( - &self, asset_id: Hash, from: Address, to: Address, amount: u128, - ) -> Result<(), NRPCError> { - self.rpc.call("acc_rwa.transfer_asset", &(asset_id, from, to, amount)).await + pub async fn transfer_asset(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_rwa.transfer_asset", p).await } - /// 冻结资产 - pub async fn freeze_asset( - &self, asset_id: Hash, reason: &str, constitutional_receipt: Hash, - ) -> Result<(), NRPCError> { - self.rpc.call("acc_rwa.freeze_asset", &(asset_id, reason, constitutional_receipt)).await + /// 冻结 RWA 资产 + pub async fn freeze_asset(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_rwa.freeze_asset", p).await } - /// 查询资产持仓 - pub async fn balance_of(&self, asset_id: Hash, holder: Address) -> Result { - self.rpc.call("acc_rwa.balance_of", &(asset_id, holder)).await + /// 查询 RWA 资产详情 + pub async fn get_asset(&self, asset_id: &Hash) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "asset_id": asset_id.to_hex(), + }); + self.client.call("acc_rwa.get_asset", params).await } - /// 查询资产详情 - pub async fn get_asset(&self, asset_id: Hash) -> Result, NRPCError> { - self.rpc.call("acc_rwa.get_asset", &asset_id).await + /// 查询地址持有的 RWA 资产列表 + pub async fn get_holdings(&self, owner: &Address) -> Result { + let params = json!({ + "contract": self.contract_address.to_hex(), + "owner": owner.to_hex(), + }); + self.client.call("acc_rwa.get_holdings", params).await } } diff --git a/nac-sdk/src/protocols/acc_valuation.rs b/nac-sdk/src/protocols/acc_valuation.rs index 78e252b..24c9ecd 100644 --- a/nac-sdk/src/protocols/acc_valuation.rs +++ b/nac-sdk/src/protocols/acc_valuation.rs @@ -1,40 +1,48 @@ -//! ACC-Valuation AI 驱动资产估值协议客户端接口 +//! AccValuation 协议客户端接口 +//! NAC 原生 SDK - 通过 NRPC4.0 与链交互 -use crate::types::{Address, Hash, NRPCClient, NRPCError}; +use crate::error::{NACError, Result}; +use crate::adapters::NacLensClient; +use nac_udm::primitives::{Address, Hash}; +use serde_json::{json, Value}; -/// 估值结果 -#[derive(Debug, Clone)] -pub struct ValuationResult { - pub asset_id: Hash, - pub value_xtzh: u128, - pub ai_confidence: u8, - pub timestamp: u64, - pub method: String, -} - -/// ACC-Valuation 协议客户端 +/// AccValuation 协议客户端 pub struct AccValuationClient { - rpc: NRPCClient, + pub client: NacLensClient, + pub contract_address: Address, } impl AccValuationClient { - pub fn new(rpc: NRPCClient) -> Self { Self { rpc } } - - /// 提交估值请求 - pub async fn request_valuation( - &self, asset_id: Hash, gnacs_code: &str, asset_data: Vec, - constitutional_receipt: Hash, - ) -> Result { - self.rpc.call("acc_valuation.request_valuation", &(asset_id, gnacs_code, asset_data, constitutional_receipt)).await + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - /// 获取最新估值 - pub async fn get_valuation(&self, asset_id: Hash) -> Result, NRPCError> { - self.rpc.call("acc_valuation.get_valuation", &asset_id).await + /// 查询资产估值 + pub async fn get_valuation(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_valuation.get_valuation", p).await } - /// 获取估值历史 - pub async fn get_history(&self, asset_id: Hash) -> Result, NRPCError> { - self.rpc.call("acc_valuation.get_valuation_history", &asset_id).await + /// 更新资产估值 + pub async fn update_valuation(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_valuation.update_valuation", p).await } + + /// 查询估值历史 + pub async fn get_history(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_valuation.get_history", p).await + } + + /// 请求 AI 估值 + pub async fn request_ai_valuation(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_valuation.request_ai_valuation", p).await + } + } diff --git a/nac-sdk/src/protocols/acc_xtzh.rs b/nac-sdk/src/protocols/acc_xtzh.rs index cdf5523..a30ce35 100644 --- a/nac-sdk/src/protocols/acc_xtzh.rs +++ b/nac-sdk/src/protocols/acc_xtzh.rs @@ -1,33 +1,48 @@ -//! ACC-XTZH 稳定币协议客户端接口(SDR锚定+黄金储备) +//! AccXtzh 协议客户端接口 +//! NAC 原生 SDK - 通过 NRPC4.0 与链交互 -use crate::types::{Address, Hash, NRPCClient, NRPCError}; +use crate::error::{NACError, Result}; +use crate::adapters::NacLensClient; +use nac_udm::primitives::{Address, Hash}; +use serde_json::{json, Value}; -pub struct AccXtzhClient { rpc: NRPCClient } +/// AccXtzh 协议客户端 +pub struct AccXtzhClient { + pub client: NacLensClient, + pub contract_address: Address, +} impl AccXtzhClient { - pub fn new(rpc: NRPCClient) -> Self { Self { rpc } } - - pub async fn mint(&self, recipient: Address, amount: u128, constitutional_receipt: Hash) -> Result<(), NRPCError> { - self.rpc.call("acc_xtzh.mint", &(recipient, amount, constitutional_receipt)).await + pub fn new(client: NacLensClient, contract_address: Address) -> Self { + Self { client, contract_address } } - pub async fn burn(&self, holder: Address, amount: u128, constitutional_receipt: Hash) -> Result<(), NRPCError> { - self.rpc.call("acc_xtzh.burn", &(holder, amount, constitutional_receipt)).await + /// 查询 XTZH 汇率 + pub async fn get_rate(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_xtzh.get_rate", p).await } - pub async fn transfer(&self, from: Address, to: Address, amount: u128) -> Result<(), NRPCError> { - self.rpc.call("acc_xtzh.transfer", &(from, to, amount)).await + /// 铸造 XTZH 稳定币 + pub async fn mint_xtzh(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_xtzh.mint_xtzh", p).await } - pub async fn balance_of(&self, address: Address) -> Result { - self.rpc.call("acc_xtzh.balance_of", &address).await + /// 赎回 XTZH 稳定币 + pub async fn redeem_xtzh(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_xtzh.redeem_xtzh", p).await } - pub async fn total_supply(&self) -> Result { - self.rpc.call("acc_xtzh.total_supply", &()).await + /// 查询储备率 + pub async fn get_reserve_ratio(&self, params: Value) -> Result { + let mut p = params; + p["contract"] = json!(self.contract_address.to_hex()); + self.client.call("acc_xtzh.get_reserve_ratio", p).await } - pub async fn update_sdr_rate(&self, new_rate: u128, constitutional_receipt: Hash) -> Result<(), NRPCError> { - self.rpc.call("acc_xtzh.update_sdr_rate", &(new_rate, constitutional_receipt)).await - } } diff --git a/nac-sdk/src/protocols/mod.rs b/nac-sdk/src/protocols/mod.rs index 7697b4a..61a25ae 100644 --- a/nac-sdk/src/protocols/mod.rs +++ b/nac-sdk/src/protocols/mod.rs @@ -62,20 +62,20 @@ mod acc_collateral; mod acc_redemption; mod acc_insurance; mod acc_governance; -pub use acc_rwa::{AccRwaClient, RWAAssetType, RWAAssetRecord}; -pub use acc_compliance::{AccComplianceClient, SevenLayerComplianceResult, ComplianceRecord}; -pub use acc_valuation::{AccValuationClient, ValuationResult}; -pub use acc_custody::{AccCustodyClient, CustodyType, CustodyRecord}; -pub use acc_collateral::{AccCollateralClient, CollateralRecord}; +pub use acc_rwa::AccRwaClient; +pub use acc_compliance::AccComplianceClient; +pub use acc_valuation::AccValuationClient; +pub use acc_custody::AccCustodyClient; +pub use acc_collateral::AccCollateralClient; pub use acc_redemption::AccRedemptionClient; -pub use acc_insurance::{AccInsuranceClient, InsuranceType}; -pub use acc_governance::{AccGovernanceClient, VoteChoice, ProposalType}; +pub use acc_insurance::AccInsuranceClient; +pub use acc_governance::AccGovernanceClient; // === 稳定币与储备协议 === mod acc_xtzh; mod acc_reserve; pub use acc_xtzh::AccXtzhClient; -pub use acc_reserve::{AccReserveClient, ReserveEntry}; +pub use acc_reserve::AccReserveClient; // === 证券代币协议族 === mod acc1410; @@ -86,5 +86,5 @@ mod acc1644; pub use acc1410::{Acc1410Client, PartitionType, ExtendedGNACS}; pub use acc1400::Acc1400Client; pub use acc1594::Acc1594Client; -pub use acc1643::{Acc1643Client, AssetDocument}; +pub use acc1643::Acc1643Client; pub use acc1644::Acc1644Client; diff --git a/nac-sdk/src/types/mod.rs b/nac-sdk/src/types/mod.rs index e1660f5..eae3f01 100644 --- a/nac-sdk/src/types/mod.rs +++ b/nac-sdk/src/types/mod.rs @@ -67,7 +67,7 @@ pub struct NacLensResponse { /// 错误(失败时) #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, + pub error: Option, /// 宪法收据(可选,某些操作会返回) #[serde(skip_serializing_if = "Option::is_none")] @@ -76,7 +76,7 @@ pub struct NacLensResponse { /// NAC Lens错误 #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct NAC Lens3Error { +pub struct NacLensProtocolError { /// 错误代码 pub code: i32, diff --git a/nac-udm/src/l1_protocol/acc/acc_compliance.rs b/nac-udm/src/l1_protocol/acc/acc_compliance.rs index 95c5c19..b910239 100644 --- a/nac-udm/src/l1_protocol/acc/acc_compliance.rs +++ b/nac-udm/src/l1_protocol/acc/acc_compliance.rs @@ -1,177 +1,177 @@ //! acc_compliance - NAC 原生协议实现 //! 从 acc_remaining_protocols.rs 提取 use crate::primitives::{Address, Hash, Timestamp}; - use serde::{Deserialize, Serialize}; - use std::collections::HashMap; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub enum ACCComplianceError { - EntityNotFound(Address), - ComplianceCheckFailed { layer: u8, reason: String }, - InvalidConstitutionalReceipt, - Unauthorized(Address), - BlacklistedEntity(Address), - JurisdictionRestricted { entity: Address, jurisdiction: String }, - } - impl std::fmt::Display for ACCComplianceError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::EntityNotFound(a) => write!(f, "实体不存在: {}", a.to_hex()), - Self::ComplianceCheckFailed { layer, reason } => write!(f, "第{}层合规检查失败: {}", layer, reason), - Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), - Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), - Self::BlacklistedEntity(a) => write!(f, "黑名单实体: {}", a.to_hex()), - Self::JurisdictionRestricted { entity, jurisdiction } => write!(f, "司法管辖区限制 {} 在 {}", entity.to_hex(), jurisdiction), - } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum ACCComplianceError { + EntityNotFound(Address), + ComplianceCheckFailed { layer: u8, reason: String }, + InvalidConstitutionalReceipt, + Unauthorized(Address), + BlacklistedEntity(Address), + JurisdictionRestricted { entity: Address, jurisdiction: String }, +} +impl std::fmt::Display for ACCComplianceError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::EntityNotFound(a) => write!(f, "实体不存在: {}", a.to_hex()), + Self::ComplianceCheckFailed { layer, reason } => write!(f, "第{}层合规检查失败: {}", layer, reason), + Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), + Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), + Self::BlacklistedEntity(a) => write!(f, "黑名单实体: {}", a.to_hex()), + Self::JurisdictionRestricted { entity, jurisdiction } => write!(f, "司法管辖区限制 {} 在 {}", entity.to_hex(), jurisdiction), } } +} - /// 七层合规验证结果 - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct SevenLayerComplianceResult { - pub entity: Address, - /// L1: 身份验证 - pub l1_identity: bool, - /// L2: KYC/AML - pub l2_kyc_aml: bool, - /// L3: 司法管辖区合规 - pub l3_jurisdiction: bool, - /// L4: 资产合规 - pub l4_asset: bool, - /// L5: 交易合规 - pub l5_transaction: bool, - /// L6: AI 合规评分 - pub l6_ai_score: u8, - /// L7: 宪法合规(CBPP) - pub l7_constitutional: bool, - pub overall_pass: bool, - pub checked_at: Timestamp, - pub constitutional_receipt: Hash, - } - impl SevenLayerComplianceResult { - pub fn is_fully_compliant(&self) -> bool { - self.l1_identity && self.l2_kyc_aml && self.l3_jurisdiction - && self.l4_asset && self.l5_transaction - && self.l6_ai_score >= 70 && self.l7_constitutional - } +/// 七层合规验证结果 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SevenLayerComplianceResult { + pub entity: Address, + /// L1: 身份验证 + pub l1_identity: bool, + /// L2: KYC/AML + pub l2_kyc_aml: bool, + /// L3: 司法管辖区合规 + pub l3_jurisdiction: bool, + /// L4: 资产合规 + pub l4_asset: bool, + /// L5: 交易合规 + pub l5_transaction: bool, + /// L6: AI 合规评分 + pub l6_ai_score: u8, + /// L7: 宪法合规(CBPP) + pub l7_constitutional: bool, + pub overall_pass: bool, + pub checked_at: Timestamp, + pub constitutional_receipt: Hash, +} +impl SevenLayerComplianceResult { + pub fn is_fully_compliant(&self) -> bool { + self.l1_identity && self.l2_kyc_aml && self.l3_jurisdiction + && self.l4_asset && self.l5_transaction + && self.l6_ai_score >= 70 && self.l7_constitutional } +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ComplianceRecord { - pub entity: Address, - pub kyc_verified: bool, - pub aml_cleared: bool, - pub allowed_jurisdictions: Vec, - pub blacklisted: bool, - pub ai_risk_score: u8, - pub last_checked: Timestamp, - pub compliance_hash: Hash, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ComplianceRecord { + pub entity: Address, + pub kyc_verified: bool, + pub aml_cleared: bool, + pub allowed_jurisdictions: Vec, + pub blacklisted: bool, + pub ai_risk_score: u8, + pub last_checked: Timestamp, + pub compliance_hash: Hash, +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum ComplianceProtocolEvent { - EntityRegistered { entity: Address, timestamp: Timestamp }, - ComplianceChecked { entity: Address, result: bool, timestamp: Timestamp }, - EntityBlacklisted { entity: Address, reason: String, timestamp: Timestamp, constitutional_receipt: Hash }, - EntityWhitelisted { entity: Address, timestamp: Timestamp, constitutional_receipt: Hash }, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum ComplianceProtocolEvent { + EntityRegistered { entity: Address, timestamp: Timestamp }, + ComplianceChecked { entity: Address, result: bool, timestamp: Timestamp }, + EntityBlacklisted { entity: Address, reason: String, timestamp: Timestamp, constitutional_receipt: Hash }, + EntityWhitelisted { entity: Address, timestamp: Timestamp, constitutional_receipt: Hash }, +} - /// ACC-Compliance 七层合规验证协议 - /// UID: nac.acc.ACCComplianceProtocol.v1 - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ACCComplianceProtocol { - pub protocol_uid: String, - pub lens_protocol_vector: String, - pub compliance_records: HashMap, - pub blacklist: HashMap, - pub compliance_history: HashMap>, - pub pending_events: Vec, - pub created_at: Timestamp, - pub updated_at: Timestamp, +/// ACC-Compliance 七层合规验证协议 +/// UID: nac.acc.ACCComplianceProtocol.v1 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ACCComplianceProtocol { + pub protocol_uid: String, + pub lens_protocol_vector: String, + pub compliance_records: HashMap, + pub blacklist: HashMap, + pub compliance_history: HashMap>, + pub pending_events: Vec, + pub created_at: Timestamp, + pub updated_at: Timestamp, +} +impl ACCComplianceProtocol { + pub fn new() -> Self { + Self { + protocol_uid: "nac.acc.ACCComplianceProtocol.v1".to_string(), + lens_protocol_vector: "ACC-Compliance".to_string(), + compliance_records: HashMap::new(), + blacklist: HashMap::new(), + compliance_history: HashMap::new(), + pending_events: Vec::new(), + created_at: Timestamp::now(), + updated_at: Timestamp::now(), + } } - impl ACCComplianceProtocol { - pub fn new() -> Self { - Self { - protocol_uid: "nac.acc.ACCComplianceProtocol.v1".to_string(), - lens_protocol_vector: "ACC-Compliance".to_string(), - compliance_records: HashMap::new(), - blacklist: HashMap::new(), - compliance_history: HashMap::new(), - pending_events: Vec::new(), - created_at: Timestamp::now(), - updated_at: Timestamp::now(), - } - } - pub fn register_entity( - &mut self, entity: Address, kyc_verified: bool, aml_cleared: bool, - allowed_jurisdictions: Vec, ai_risk_score: u8, - constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result<(), ACCComplianceError> { - if constitutional_receipt.is_zero() { return Err(ACCComplianceError::InvalidConstitutionalReceipt); } - let mut data = Vec::new(); - data.extend_from_slice(entity.as_bytes()); - data.extend_from_slice(×tamp.as_secs().to_be_bytes()); - let compliance_hash = Hash::sha3_384(&data); - let record = ComplianceRecord { - entity: entity.clone(), kyc_verified, aml_cleared, - allowed_jurisdictions, blacklisted: false, ai_risk_score, - last_checked: timestamp.clone(), compliance_hash, - }; - self.compliance_records.insert(entity.clone(), record); - self.pending_events.push(ComplianceProtocolEvent::EntityRegistered { entity, timestamp }); - self.updated_at = Timestamp::now(); - Ok(()) - } - pub fn run_seven_layer_check( - &mut self, entity: Address, jurisdiction: &str, - constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result { - if self.blacklist.contains_key(&entity) { - return Err(ACCComplianceError::BlacklistedEntity(entity)); - } - let record = self.compliance_records.get(&entity) - .ok_or(ACCComplianceError::EntityNotFound(entity.clone()))?; - let l1 = true; // 地址存在即通过身份验证 - let l2 = record.kyc_verified && record.aml_cleared; - let l3 = record.allowed_jurisdictions.is_empty() - || record.allowed_jurisdictions.iter().any(|j| j == jurisdiction); - let l4 = !record.blacklisted; - let l5 = record.ai_risk_score < 80; // 风险评分低于80才允许 - let l6 = 100u8.saturating_sub(record.ai_risk_score); - let l7 = !constitutional_receipt.is_zero(); - let overall = l1 && l2 && l3 && l4 && l5 && l6 >= 70 && l7; - let result = SevenLayerComplianceResult { - entity: entity.clone(), l1_identity: l1, l2_kyc_aml: l2, - l3_jurisdiction: l3, l4_asset: l4, l5_transaction: l5, - l6_ai_score: l6, l7_constitutional: l7, overall_pass: overall, - checked_at: timestamp.clone(), constitutional_receipt, - }; - self.compliance_history.entry(entity.clone()).or_insert_with(Vec::new).push(result.clone()); - self.pending_events.push(ComplianceProtocolEvent::ComplianceChecked { - entity, result: overall, timestamp, - }); - Ok(result) - } - pub fn blacklist_entity( - &mut self, entity: Address, reason: String, - constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result<(), ACCComplianceError> { - if constitutional_receipt.is_zero() { return Err(ACCComplianceError::InvalidConstitutionalReceipt); } - self.blacklist.insert(entity.clone(), reason.clone()); - if let Some(record) = self.compliance_records.get_mut(&entity) { - record.blacklisted = true; - } - self.pending_events.push(ComplianceProtocolEvent::EntityBlacklisted { - entity, reason, timestamp, constitutional_receipt, - }); - Ok(()) - } - pub fn is_compliant(&self, entity: &Address) -> bool { - if self.blacklist.contains_key(entity) { return false; } - self.compliance_records.get(entity) - .map(|r| r.kyc_verified && r.aml_cleared && !r.blacklisted) - .unwrap_or(false) - } - pub fn get_record(&self, entity: &Address) -> Option<&ComplianceRecord> { self.compliance_records.get(entity) } - pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } + pub fn register_entity( + &mut self, entity: Address, kyc_verified: bool, aml_cleared: bool, + allowed_jurisdictions: Vec, ai_risk_score: u8, + constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result<(), ACCComplianceError> { + if constitutional_receipt.is_zero() { return Err(ACCComplianceError::InvalidConstitutionalReceipt); } + let mut data = Vec::new(); + data.extend_from_slice(entity.as_bytes()); + data.extend_from_slice(×tamp.as_secs().to_be_bytes()); + let compliance_hash = Hash::sha3_384(&data); + let record = ComplianceRecord { + entity: entity.clone(), kyc_verified, aml_cleared, + allowed_jurisdictions, blacklisted: false, ai_risk_score, + last_checked: timestamp.clone(), compliance_hash, + }; + self.compliance_records.insert(entity.clone(), record); + self.pending_events.push(ComplianceProtocolEvent::EntityRegistered { entity, timestamp }); + self.updated_at = Timestamp::now(); + Ok(()) } + pub fn run_seven_layer_check( + &mut self, entity: Address, jurisdiction: &str, + constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result { + if self.blacklist.contains_key(&entity) { + return Err(ACCComplianceError::BlacklistedEntity(entity)); + } + let record = self.compliance_records.get(&entity) + .ok_or(ACCComplianceError::EntityNotFound(entity.clone()))?; + let l1 = true; // 地址存在即通过身份验证 + let l2 = record.kyc_verified && record.aml_cleared; + let l3 = record.allowed_jurisdictions.is_empty() + || record.allowed_jurisdictions.iter().any(|j| j == jurisdiction); + let l4 = !record.blacklisted; + let l5 = record.ai_risk_score < 80; // 风险评分低于80才允许 + let l6 = 100u8.saturating_sub(record.ai_risk_score); + let l7 = !constitutional_receipt.is_zero(); + let overall = l1 && l2 && l3 && l4 && l5 && l6 >= 70 && l7; + let result = SevenLayerComplianceResult { + entity: entity.clone(), l1_identity: l1, l2_kyc_aml: l2, + l3_jurisdiction: l3, l4_asset: l4, l5_transaction: l5, + l6_ai_score: l6, l7_constitutional: l7, overall_pass: overall, + checked_at: timestamp.clone(), constitutional_receipt, + }; + self.compliance_history.entry(entity.clone()).or_insert_with(Vec::new).push(result.clone()); + self.pending_events.push(ComplianceProtocolEvent::ComplianceChecked { + entity, result: overall, timestamp, + }); + Ok(result) + } + pub fn blacklist_entity( + &mut self, entity: Address, reason: String, + constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result<(), ACCComplianceError> { + if constitutional_receipt.is_zero() { return Err(ACCComplianceError::InvalidConstitutionalReceipt); } + self.blacklist.insert(entity.clone(), reason.clone()); + if let Some(record) = self.compliance_records.get_mut(&entity) { + record.blacklisted = true; + } + self.pending_events.push(ComplianceProtocolEvent::EntityBlacklisted { + entity, reason, timestamp, constitutional_receipt, + }); + Ok(()) + } + pub fn is_compliant(&self, entity: &Address) -> bool { + if self.blacklist.contains_key(entity) { return false; } + self.compliance_records.get(entity) + .map(|r| r.kyc_verified && r.aml_cleared && !r.blacklisted) + .unwrap_or(false) + } + pub fn get_record(&self, entity: &Address) -> Option<&ComplianceRecord> { self.compliance_records.get(entity) } + pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } +} diff --git a/nac-udm/src/l1_protocol/acc/acc_governance.rs b/nac-udm/src/l1_protocol/acc/acc_governance.rs index db186fc..4ebd5a4 100644 --- a/nac-udm/src/l1_protocol/acc/acc_governance.rs +++ b/nac-udm/src/l1_protocol/acc/acc_governance.rs @@ -1,192 +1,192 @@ //! acc_governance - NAC 原生协议实现 use crate::primitives::{Address, Hash, Timestamp}; - use serde::{Deserialize, Serialize}; - use std::collections::HashMap; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub enum ACCGovernanceError { - ProposalNotFound(Hash), - ProposalAlreadyExecuted(Hash), - VotingPeriodEnded(Hash), - AlreadyVoted(Address), - InsufficientVotingPower { required: u128, actual: u128 }, - QuorumNotReached { required: u128, actual: u128 }, - InvalidConstitutionalReceipt, - Unauthorized(Address), - } - impl std::fmt::Display for ACCGovernanceError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::ProposalNotFound(h) => write!(f, "提案不存在: {}", h.to_hex()), - Self::ProposalAlreadyExecuted(h) => write!(f, "提案已执行: {}", h.to_hex()), - Self::VotingPeriodEnded(h) => write!(f, "投票期已结束: {}", h.to_hex()), - Self::AlreadyVoted(a) => write!(f, "已投票: {}", a.to_hex()), - Self::InsufficientVotingPower { required, actual } => write!(f, "投票权不足: 需要 {},实际 {}", required, actual), - Self::QuorumNotReached { required, actual } => write!(f, "未达法定人数: 需要 {},实际 {}", required, actual), - Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), - Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), - } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum ACCGovernanceError { + ProposalNotFound(Hash), + ProposalAlreadyExecuted(Hash), + VotingPeriodEnded(Hash), + AlreadyVoted(Address), + InsufficientVotingPower { required: u128, actual: u128 }, + QuorumNotReached { required: u128, actual: u128 }, + InvalidConstitutionalReceipt, + Unauthorized(Address), +} +impl std::fmt::Display for ACCGovernanceError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::ProposalNotFound(h) => write!(f, "提案不存在: {}", h.to_hex()), + Self::ProposalAlreadyExecuted(h) => write!(f, "提案已执行: {}", h.to_hex()), + Self::VotingPeriodEnded(h) => write!(f, "投票期已结束: {}", h.to_hex()), + Self::AlreadyVoted(a) => write!(f, "已投票: {}", a.to_hex()), + Self::InsufficientVotingPower { required, actual } => write!(f, "投票权不足: 需要 {},实际 {}", required, actual), + Self::QuorumNotReached { required, actual } => write!(f, "未达法定人数: 需要 {},实际 {}", required, actual), + Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), + Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), } } +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum ProposalType { - ParameterChange { parameter: String, new_value: Vec }, - ProtocolUpgrade { new_version: String, upgrade_hash: Hash }, - AssetPolicyChange { asset_id: Hash, policy_hash: Hash }, - EmergencyPause { reason: String }, - GovernanceMemberChange { member: Address, action: MemberAction }, - } - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] - pub enum MemberAction { Add, Remove } - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] - pub enum ProposalStatus { Active, Passed, Rejected, Executed, Cancelled, Expired } - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] - pub enum VoteChoice { For, Against, Abstain } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum ProposalType { + ParameterChange { parameter: String, new_value: Vec }, + ProtocolUpgrade { new_version: String, upgrade_hash: Hash }, + AssetPolicyChange { asset_id: Hash, policy_hash: Hash }, + EmergencyPause { reason: String }, + GovernanceMemberChange { member: Address, action: MemberAction }, +} +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum MemberAction { Add, Remove } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum ProposalStatus { Active, Passed, Rejected, Executed, Cancelled, Expired } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum VoteChoice { For, Against, Abstain } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct GovernanceProposal { - pub proposal_id: Hash, - pub proposer: Address, - pub proposal_type: ProposalType, - pub description: String, - pub status: ProposalStatus, - pub votes_for: u128, - pub votes_against: u128, - pub votes_abstain: u128, - pub vote_records: HashMap, - pub voting_start: Timestamp, - pub voting_end: Timestamp, - pub quorum_bps: u32, - pub pass_threshold_bps: u32, - pub constitutional_receipt: Hash, - pub created_at: Timestamp, - pub executed_at: Option, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GovernanceProposal { + pub proposal_id: Hash, + pub proposer: Address, + pub proposal_type: ProposalType, + pub description: String, + pub status: ProposalStatus, + pub votes_for: u128, + pub votes_against: u128, + pub votes_abstain: u128, + pub vote_records: HashMap, + pub voting_start: Timestamp, + pub voting_end: Timestamp, + pub quorum_bps: u32, + pub pass_threshold_bps: u32, + pub constitutional_receipt: Hash, + pub created_at: Timestamp, + pub executed_at: Option, +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum GovernanceProtocolEvent { - ProposalCreated { proposal_id: Hash, proposer: Address, timestamp: Timestamp }, - VoteCast { proposal_id: Hash, voter: Address, choice: VoteChoice, voting_power: u128, timestamp: Timestamp }, - ProposalPassed { proposal_id: Hash, votes_for: u128, votes_against: u128, timestamp: Timestamp }, - ProposalRejected { proposal_id: Hash, reason: String, timestamp: Timestamp }, - ProposalExecuted { proposal_id: Hash, timestamp: Timestamp, constitutional_receipt: Hash }, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum GovernanceProtocolEvent { + ProposalCreated { proposal_id: Hash, proposer: Address, timestamp: Timestamp }, + VoteCast { proposal_id: Hash, voter: Address, choice: VoteChoice, voting_power: u128, timestamp: Timestamp }, + ProposalPassed { proposal_id: Hash, votes_for: u128, votes_against: u128, timestamp: Timestamp }, + ProposalRejected { proposal_id: Hash, reason: String, timestamp: Timestamp }, + ProposalExecuted { proposal_id: Hash, timestamp: Timestamp, constitutional_receipt: Hash }, +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ACCGovernanceProtocol { - pub protocol_uid: String, - pub lens_protocol_vector: String, - pub proposals: HashMap, - pub voting_power_registry: HashMap, - pub total_voting_power: u128, - pub default_quorum_bps: u32, - pub default_pass_threshold_bps: u32, - pub pending_events: Vec, - pub created_at: Timestamp, - pub updated_at: Timestamp, +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ACCGovernanceProtocol { + pub protocol_uid: String, + pub lens_protocol_vector: String, + pub proposals: HashMap, + pub voting_power_registry: HashMap, + pub total_voting_power: u128, + pub default_quorum_bps: u32, + pub default_pass_threshold_bps: u32, + pub pending_events: Vec, + pub created_at: Timestamp, + pub updated_at: Timestamp, +} +impl ACCGovernanceProtocol { + pub fn new(default_quorum_bps: u32, default_pass_threshold_bps: u32) -> Self { + Self { + protocol_uid: "nac.acc.ACCGovernanceProtocol.v1".to_string(), + lens_protocol_vector: "ACC-Governance".to_string(), + proposals: HashMap::new(), + voting_power_registry: HashMap::new(), + total_voting_power: 0, + default_quorum_bps, default_pass_threshold_bps, + pending_events: Vec::new(), + created_at: Timestamp::now(), updated_at: Timestamp::now(), + } } - impl ACCGovernanceProtocol { - pub fn new(default_quorum_bps: u32, default_pass_threshold_bps: u32) -> Self { - Self { - protocol_uid: "nac.acc.ACCGovernanceProtocol.v1".to_string(), - lens_protocol_vector: "ACC-Governance".to_string(), - proposals: HashMap::new(), - voting_power_registry: HashMap::new(), - total_voting_power: 0, - default_quorum_bps, default_pass_threshold_bps, - pending_events: Vec::new(), - created_at: Timestamp::now(), updated_at: Timestamp::now(), - } - } - pub fn register_voting_power(&mut self, address: Address, power: u128) { - let old = self.voting_power_registry.insert(address, power).unwrap_or(0); - self.total_voting_power = self.total_voting_power.saturating_sub(old).saturating_add(power); - } - pub fn create_proposal( - &mut self, proposer: Address, proposal_type: ProposalType, description: String, - voting_duration_secs: u64, constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result { - if constitutional_receipt.is_zero() { return Err(ACCGovernanceError::InvalidConstitutionalReceipt); } - let proposer_power = self.voting_power_registry.get(&proposer).copied().unwrap_or(0); - if proposer_power == 0 { - return Err(ACCGovernanceError::InsufficientVotingPower { required: 1, actual: 0 }); - } - let mut data = Vec::new(); - data.extend_from_slice(proposer.as_bytes()); - data.extend_from_slice(×tamp.as_secs().to_be_bytes()); - let proposal_id = Hash::sha3_384(&data); - let proposal = GovernanceProposal { - proposal_id, proposer: proposer.clone(), proposal_type, description, - status: ProposalStatus::Active, - votes_for: 0, votes_against: 0, votes_abstain: 0, - vote_records: HashMap::new(), - voting_start: timestamp.clone(), - voting_end: timestamp.add_secs(voting_duration_secs), - quorum_bps: self.default_quorum_bps, - pass_threshold_bps: self.default_pass_threshold_bps, - constitutional_receipt, created_at: timestamp.clone(), executed_at: None, - }; - self.proposals.insert(proposal_id, proposal); - self.pending_events.push(GovernanceProtocolEvent::ProposalCreated { proposal_id, proposer, timestamp }); - self.updated_at = Timestamp::now(); - Ok(proposal_id) - } - pub fn cast_vote( - &mut self, proposal_id: Hash, voter: Address, choice: VoteChoice, timestamp: Timestamp, - ) -> Result<(), ACCGovernanceError> { - let voting_power = self.voting_power_registry.get(&voter).copied().unwrap_or(0); - if voting_power == 0 { - return Err(ACCGovernanceError::InsufficientVotingPower { required: 1, actual: 0 }); - } - let proposal = self.proposals.get_mut(&proposal_id) - .ok_or(ACCGovernanceError::ProposalNotFound(proposal_id))?; - if proposal.status != ProposalStatus::Active { - return Err(ACCGovernanceError::VotingPeriodEnded(proposal_id)); - } - if proposal.vote_records.contains_key(&voter) { - return Err(ACCGovernanceError::AlreadyVoted(voter)); - } - match choice { - VoteChoice::For => proposal.votes_for = proposal.votes_for.saturating_add(voting_power), - VoteChoice::Against => proposal.votes_against = proposal.votes_against.saturating_add(voting_power), - VoteChoice::Abstain => proposal.votes_abstain = proposal.votes_abstain.saturating_add(voting_power), - } - proposal.vote_records.insert(voter.clone(), choice); - self.pending_events.push(GovernanceProtocolEvent::VoteCast { proposal_id, voter, choice, voting_power, timestamp }); - Ok(()) - } - pub fn finalize_proposal( - &mut self, proposal_id: Hash, constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result { - if constitutional_receipt.is_zero() { return Err(ACCGovernanceError::InvalidConstitutionalReceipt); } - let proposal = self.proposals.get_mut(&proposal_id) - .ok_or(ACCGovernanceError::ProposalNotFound(proposal_id))?; - let total_votes = proposal.votes_for + proposal.votes_against + proposal.votes_abstain; - let quorum_required = (self.total_voting_power as u64 * proposal.quorum_bps as u64 / 10000) as u128; - if total_votes < quorum_required { - proposal.status = ProposalStatus::Rejected; - self.pending_events.push(GovernanceProtocolEvent::ProposalRejected { - proposal_id, reason: format!("未达法定人数: {} < {}", total_votes, quorum_required), timestamp, - }); - return Ok(false); - } - let effective_votes = proposal.votes_for + proposal.votes_against; - let pass_required = (effective_votes as u64 * proposal.pass_threshold_bps as u64 / 10000) as u128; - let passed = proposal.votes_for >= pass_required; - if passed { - proposal.status = ProposalStatus::Executed; - proposal.executed_at = Some(timestamp.clone()); - self.pending_events.push(GovernanceProtocolEvent::ProposalExecuted { proposal_id, timestamp, constitutional_receipt }); - } else { - proposal.status = ProposalStatus::Rejected; - self.pending_events.push(GovernanceProtocolEvent::ProposalRejected { - proposal_id, reason: "赞成票未达阈值".to_string(), timestamp, - }); - } - Ok(passed) - } - pub fn get_proposal(&self, id: &Hash) -> Option<&GovernanceProposal> { self.proposals.get(id) } - pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } + pub fn register_voting_power(&mut self, address: Address, power: u128) { + let old = self.voting_power_registry.insert(address, power).unwrap_or(0); + self.total_voting_power = self.total_voting_power.saturating_sub(old).saturating_add(power); } + pub fn create_proposal( + &mut self, proposer: Address, proposal_type: ProposalType, description: String, + voting_duration_secs: u64, constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result { + if constitutional_receipt.is_zero() { return Err(ACCGovernanceError::InvalidConstitutionalReceipt); } + let proposer_power = self.voting_power_registry.get(&proposer).copied().unwrap_or(0); + if proposer_power == 0 { + return Err(ACCGovernanceError::InsufficientVotingPower { required: 1, actual: 0 }); + } + let mut data = Vec::new(); + data.extend_from_slice(proposer.as_bytes()); + data.extend_from_slice(×tamp.as_secs().to_be_bytes()); + let proposal_id = Hash::sha3_384(&data); + let proposal = GovernanceProposal { + proposal_id, proposer: proposer.clone(), proposal_type, description, + status: ProposalStatus::Active, + votes_for: 0, votes_against: 0, votes_abstain: 0, + vote_records: HashMap::new(), + voting_start: timestamp.clone(), + voting_end: timestamp.add_secs(voting_duration_secs), + quorum_bps: self.default_quorum_bps, + pass_threshold_bps: self.default_pass_threshold_bps, + constitutional_receipt, created_at: timestamp.clone(), executed_at: None, + }; + self.proposals.insert(proposal_id, proposal); + self.pending_events.push(GovernanceProtocolEvent::ProposalCreated { proposal_id, proposer, timestamp }); + self.updated_at = Timestamp::now(); + Ok(proposal_id) + } + pub fn cast_vote( + &mut self, proposal_id: Hash, voter: Address, choice: VoteChoice, timestamp: Timestamp, + ) -> Result<(), ACCGovernanceError> { + let voting_power = self.voting_power_registry.get(&voter).copied().unwrap_or(0); + if voting_power == 0 { + return Err(ACCGovernanceError::InsufficientVotingPower { required: 1, actual: 0 }); + } + let proposal = self.proposals.get_mut(&proposal_id) + .ok_or(ACCGovernanceError::ProposalNotFound(proposal_id))?; + if proposal.status != ProposalStatus::Active { + return Err(ACCGovernanceError::VotingPeriodEnded(proposal_id)); + } + if proposal.vote_records.contains_key(&voter) { + return Err(ACCGovernanceError::AlreadyVoted(voter)); + } + match choice { + VoteChoice::For => proposal.votes_for = proposal.votes_for.saturating_add(voting_power), + VoteChoice::Against => proposal.votes_against = proposal.votes_against.saturating_add(voting_power), + VoteChoice::Abstain => proposal.votes_abstain = proposal.votes_abstain.saturating_add(voting_power), + } + proposal.vote_records.insert(voter.clone(), choice); + self.pending_events.push(GovernanceProtocolEvent::VoteCast { proposal_id, voter, choice, voting_power, timestamp }); + Ok(()) + } + pub fn finalize_proposal( + &mut self, proposal_id: Hash, constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result { + if constitutional_receipt.is_zero() { return Err(ACCGovernanceError::InvalidConstitutionalReceipt); } + let proposal = self.proposals.get_mut(&proposal_id) + .ok_or(ACCGovernanceError::ProposalNotFound(proposal_id))?; + let total_votes = proposal.votes_for + proposal.votes_against + proposal.votes_abstain; + let quorum_required = (self.total_voting_power as u64 * proposal.quorum_bps as u64 / 10000) as u128; + if total_votes < quorum_required { + proposal.status = ProposalStatus::Rejected; + self.pending_events.push(GovernanceProtocolEvent::ProposalRejected { + proposal_id, reason: format!("未达法定人数: {} < {}", total_votes, quorum_required), timestamp, + }); + return Ok(false); + } + let effective_votes = proposal.votes_for + proposal.votes_against; + let pass_required = (effective_votes as u64 * proposal.pass_threshold_bps as u64 / 10000) as u128; + let passed = proposal.votes_for >= pass_required; + if passed { + proposal.status = ProposalStatus::Executed; + proposal.executed_at = Some(timestamp.clone()); + self.pending_events.push(GovernanceProtocolEvent::ProposalExecuted { proposal_id, timestamp, constitutional_receipt }); + } else { + proposal.status = ProposalStatus::Rejected; + self.pending_events.push(GovernanceProtocolEvent::ProposalRejected { + proposal_id, reason: "赞成票未达阈值".to_string(), timestamp, + }); + } + Ok(passed) + } + pub fn get_proposal(&self, id: &Hash) -> Option<&GovernanceProposal> { self.proposals.get(id) } + pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } +} diff --git a/nac-udm/src/l1_protocol/acc/acc_insurance.rs b/nac-udm/src/l1_protocol/acc/acc_insurance.rs index 83f8bfe..08d45fe 100644 --- a/nac-udm/src/l1_protocol/acc/acc_insurance.rs +++ b/nac-udm/src/l1_protocol/acc/acc_insurance.rs @@ -1,168 +1,168 @@ //! acc_insurance - NAC 原生协议实现 use crate::primitives::{Address, Hash, Timestamp}; - use serde::{Deserialize, Serialize}; - use std::collections::HashMap; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub enum ACCInsuranceError { - PolicyNotFound(Hash), - PolicyExpired(Hash), - ClaimAlreadyProcessed(Hash), - InvalidConstitutionalReceipt, - Unauthorized(Address), - ClaimExceedsCoverage { coverage: u128, claim: u128 }, - } - impl std::fmt::Display for ACCInsuranceError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::PolicyNotFound(h) => write!(f, "保险单不存在: {}", h.to_hex()), - Self::PolicyExpired(h) => write!(f, "保险单已过期: {}", h.to_hex()), - Self::ClaimAlreadyProcessed(h) => write!(f, "理赔已处理: {}", h.to_hex()), - Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), - Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), - Self::ClaimExceedsCoverage { coverage, claim } => write!(f, "理赔超额: 保额 {},理赔 {}", coverage, claim), - } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum ACCInsuranceError { + PolicyNotFound(Hash), + PolicyExpired(Hash), + ClaimAlreadyProcessed(Hash), + InvalidConstitutionalReceipt, + Unauthorized(Address), + ClaimExceedsCoverage { coverage: u128, claim: u128 }, +} +impl std::fmt::Display for ACCInsuranceError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::PolicyNotFound(h) => write!(f, "保险单不存在: {}", h.to_hex()), + Self::PolicyExpired(h) => write!(f, "保险单已过期: {}", h.to_hex()), + Self::ClaimAlreadyProcessed(h) => write!(f, "理赔已处理: {}", h.to_hex()), + Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), + Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), + Self::ClaimExceedsCoverage { coverage, claim } => write!(f, "理赔超额: 保额 {},理赔 {}", coverage, claim), } } +} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] - pub enum InsuranceType { AssetLoss, CustodyRisk, ComplianceRisk, MarketPrice, Comprehensive } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum InsuranceType { AssetLoss, CustodyRisk, ComplianceRisk, MarketPrice, Comprehensive } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct InsurancePolicy { - pub policy_id: Hash, - pub asset_id: Hash, - pub insured: Address, - pub insurer: Address, - pub insurance_type: InsuranceType, - pub coverage_amount: u128, - pub claimed_amount: u128, - pub premium_rate_bps: u16, - pub start_time: Timestamp, - pub end_time: Timestamp, - pub is_active: bool, - pub constitutional_receipt: Hash, - pub created_at: Timestamp, - } - impl InsurancePolicy { - pub fn is_expired(&self) -> bool { self.end_time.is_expired(0) } - pub fn remaining_coverage(&self) -> u128 { self.coverage_amount.saturating_sub(self.claimed_amount) } - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct InsurancePolicy { + pub policy_id: Hash, + pub asset_id: Hash, + pub insured: Address, + pub insurer: Address, + pub insurance_type: InsuranceType, + pub coverage_amount: u128, + pub claimed_amount: u128, + pub premium_rate_bps: u16, + pub start_time: Timestamp, + pub end_time: Timestamp, + pub is_active: bool, + pub constitutional_receipt: Hash, + pub created_at: Timestamp, +} +impl InsurancePolicy { + pub fn is_expired(&self) -> bool { self.end_time.is_expired(0) } + pub fn remaining_coverage(&self) -> u128 { self.coverage_amount.saturating_sub(self.claimed_amount) } +} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] - pub enum ClaimStatus { Pending, UnderReview, Approved, Rejected, Paid } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum ClaimStatus { Pending, UnderReview, Approved, Rejected, Paid } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct InsuranceClaim { - pub claim_id: Hash, - pub policy_id: Hash, - pub claimant: Address, - pub claim_amount: u128, - pub claim_reason: String, - pub evidence_hash: Hash, - pub status: ClaimStatus, - pub submitted_at: Timestamp, - pub processed_at: Option, - pub constitutional_receipt: Hash, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct InsuranceClaim { + pub claim_id: Hash, + pub policy_id: Hash, + pub claimant: Address, + pub claim_amount: u128, + pub claim_reason: String, + pub evidence_hash: Hash, + pub status: ClaimStatus, + pub submitted_at: Timestamp, + pub processed_at: Option, + pub constitutional_receipt: Hash, +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum InsuranceProtocolEvent { - PolicyIssued { policy_id: Hash, asset_id: Hash, insured: Address, coverage: u128, timestamp: Timestamp }, - ClaimSubmitted { claim_id: Hash, policy_id: Hash, amount: u128, timestamp: Timestamp }, - ClaimPaid { claim_id: Hash, amount: u128, timestamp: Timestamp, constitutional_receipt: Hash }, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum InsuranceProtocolEvent { + PolicyIssued { policy_id: Hash, asset_id: Hash, insured: Address, coverage: u128, timestamp: Timestamp }, + ClaimSubmitted { claim_id: Hash, policy_id: Hash, amount: u128, timestamp: Timestamp }, + ClaimPaid { claim_id: Hash, amount: u128, timestamp: Timestamp, constitutional_receipt: Hash }, +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ACCInsuranceProtocol { - pub protocol_uid: String, - pub lens_protocol_vector: String, - pub policies: HashMap, - pub claims: HashMap, - pub insurance_pool: u128, - pub pending_events: Vec, - pub created_at: Timestamp, - pub updated_at: Timestamp, - } - impl ACCInsuranceProtocol { - pub fn new() -> Self { - Self { - protocol_uid: "nac.acc.ACCInsuranceProtocol.v1".to_string(), - lens_protocol_vector: "ACC-Insurance".to_string(), - policies: HashMap::new(), claims: HashMap::new(), - insurance_pool: 0, pending_events: Vec::new(), - created_at: Timestamp::now(), updated_at: Timestamp::now(), - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ACCInsuranceProtocol { + pub protocol_uid: String, + pub lens_protocol_vector: String, + pub policies: HashMap, + pub claims: HashMap, + pub insurance_pool: u128, + pub pending_events: Vec, + pub created_at: Timestamp, + pub updated_at: Timestamp, +} +impl ACCInsuranceProtocol { + pub fn new() -> Self { + Self { + protocol_uid: "nac.acc.ACCInsuranceProtocol.v1".to_string(), + lens_protocol_vector: "ACC-Insurance".to_string(), + policies: HashMap::new(), claims: HashMap::new(), + insurance_pool: 0, pending_events: Vec::new(), + created_at: Timestamp::now(), updated_at: Timestamp::now(), } - pub fn fund_pool(&mut self, amount: u128) { self.insurance_pool = self.insurance_pool.saturating_add(amount); } - pub fn issue_policy( - &mut self, asset_id: Hash, insured: Address, insurer: Address, - insurance_type: InsuranceType, coverage_amount: u128, premium_rate_bps: u16, - duration_secs: u64, constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result { - if constitutional_receipt.is_zero() { return Err(ACCInsuranceError::InvalidConstitutionalReceipt); } - let mut data = Vec::new(); - data.extend_from_slice(asset_id.as_bytes()); - data.extend_from_slice(insured.as_bytes()); - data.extend_from_slice(×tamp.as_secs().to_be_bytes()); - let policy_id = Hash::sha3_384(&data); - let policy = InsurancePolicy { - policy_id, asset_id, insured: insured.clone(), insurer, insurance_type, - coverage_amount, claimed_amount: 0, premium_rate_bps, - start_time: timestamp.clone(), - end_time: timestamp.add_secs(duration_secs), - is_active: true, constitutional_receipt, created_at: timestamp.clone(), - }; - self.policies.insert(policy_id, policy); - self.pending_events.push(InsuranceProtocolEvent::PolicyIssued { - policy_id, asset_id, insured, coverage: coverage_amount, timestamp, - }); - self.updated_at = Timestamp::now(); - Ok(policy_id) - } - pub fn submit_claim( - &mut self, policy_id: Hash, claimant: Address, claim_amount: u128, - claim_reason: String, evidence_hash: Hash, constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result { - let policy = self.policies.get(&policy_id).ok_or(ACCInsuranceError::PolicyNotFound(policy_id))?; - if policy.is_expired() { return Err(ACCInsuranceError::PolicyExpired(policy_id)); } - if claim_amount > policy.remaining_coverage() { - return Err(ACCInsuranceError::ClaimExceedsCoverage { coverage: policy.remaining_coverage(), claim: claim_amount }); - } - let mut data = Vec::new(); - data.extend_from_slice(policy_id.as_bytes()); - data.extend_from_slice(×tamp.as_secs().to_be_bytes()); - let claim_id = Hash::sha3_384(&data); - let claim = InsuranceClaim { - claim_id, policy_id, claimant, claim_amount, claim_reason, - evidence_hash, status: ClaimStatus::Pending, - submitted_at: timestamp.clone(), processed_at: None, constitutional_receipt, - }; - self.claims.insert(claim_id, claim); - self.pending_events.push(InsuranceProtocolEvent::ClaimSubmitted { claim_id, policy_id, amount: claim_amount, timestamp }); - Ok(claim_id) - } - pub fn pay_claim( - &mut self, claim_id: Hash, constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result { - if constitutional_receipt.is_zero() { return Err(ACCInsuranceError::InvalidConstitutionalReceipt); } - let claim = self.claims.get_mut(&claim_id).ok_or(ACCInsuranceError::PolicyNotFound(claim_id))?; - if claim.status != ClaimStatus::Pending && claim.status != ClaimStatus::UnderReview { - return Err(ACCInsuranceError::ClaimAlreadyProcessed(claim_id)); - } - let amount = claim.claim_amount; - let policy_id = claim.policy_id; - claim.status = ClaimStatus::Paid; - claim.processed_at = Some(timestamp.clone()); - if let Some(policy) = self.policies.get_mut(&policy_id) { - policy.claimed_amount = policy.claimed_amount.saturating_add(amount); - } - self.insurance_pool = self.insurance_pool.saturating_sub(amount); - self.pending_events.push(InsuranceProtocolEvent::ClaimPaid { claim_id, amount, timestamp, constitutional_receipt }); - Ok(amount) - } - pub fn get_policy(&self, id: &Hash) -> Option<&InsurancePolicy> { self.policies.get(id) } - pub fn get_claim(&self, id: &Hash) -> Option<&InsuranceClaim> { self.claims.get(id) } - pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } } + pub fn fund_pool(&mut self, amount: u128) { self.insurance_pool = self.insurance_pool.saturating_add(amount); } + pub fn issue_policy( + &mut self, asset_id: Hash, insured: Address, insurer: Address, + insurance_type: InsuranceType, coverage_amount: u128, premium_rate_bps: u16, + duration_secs: u64, constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result { + if constitutional_receipt.is_zero() { return Err(ACCInsuranceError::InvalidConstitutionalReceipt); } + let mut data = Vec::new(); + data.extend_from_slice(asset_id.as_bytes()); + data.extend_from_slice(insured.as_bytes()); + data.extend_from_slice(×tamp.as_secs().to_be_bytes()); + let policy_id = Hash::sha3_384(&data); + let policy = InsurancePolicy { + policy_id, asset_id, insured: insured.clone(), insurer, insurance_type, + coverage_amount, claimed_amount: 0, premium_rate_bps, + start_time: timestamp.clone(), + end_time: timestamp.add_secs(duration_secs), + is_active: true, constitutional_receipt, created_at: timestamp.clone(), + }; + self.policies.insert(policy_id, policy); + self.pending_events.push(InsuranceProtocolEvent::PolicyIssued { + policy_id, asset_id, insured, coverage: coverage_amount, timestamp, + }); + self.updated_at = Timestamp::now(); + Ok(policy_id) + } + pub fn submit_claim( + &mut self, policy_id: Hash, claimant: Address, claim_amount: u128, + claim_reason: String, evidence_hash: Hash, constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result { + let policy = self.policies.get(&policy_id).ok_or(ACCInsuranceError::PolicyNotFound(policy_id))?; + if policy.is_expired() { return Err(ACCInsuranceError::PolicyExpired(policy_id)); } + if claim_amount > policy.remaining_coverage() { + return Err(ACCInsuranceError::ClaimExceedsCoverage { coverage: policy.remaining_coverage(), claim: claim_amount }); + } + let mut data = Vec::new(); + data.extend_from_slice(policy_id.as_bytes()); + data.extend_from_slice(×tamp.as_secs().to_be_bytes()); + let claim_id = Hash::sha3_384(&data); + let claim = InsuranceClaim { + claim_id, policy_id, claimant, claim_amount, claim_reason, + evidence_hash, status: ClaimStatus::Pending, + submitted_at: timestamp.clone(), processed_at: None, constitutional_receipt, + }; + self.claims.insert(claim_id, claim); + self.pending_events.push(InsuranceProtocolEvent::ClaimSubmitted { claim_id, policy_id, amount: claim_amount, timestamp }); + Ok(claim_id) + } + pub fn pay_claim( + &mut self, claim_id: Hash, constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result { + if constitutional_receipt.is_zero() { return Err(ACCInsuranceError::InvalidConstitutionalReceipt); } + let claim = self.claims.get_mut(&claim_id).ok_or(ACCInsuranceError::PolicyNotFound(claim_id))?; + if claim.status != ClaimStatus::Pending && claim.status != ClaimStatus::UnderReview { + return Err(ACCInsuranceError::ClaimAlreadyProcessed(claim_id)); + } + let amount = claim.claim_amount; + let policy_id = claim.policy_id; + claim.status = ClaimStatus::Paid; + claim.processed_at = Some(timestamp.clone()); + if let Some(policy) = self.policies.get_mut(&policy_id) { + policy.claimed_amount = policy.claimed_amount.saturating_add(amount); + } + self.insurance_pool = self.insurance_pool.saturating_sub(amount); + self.pending_events.push(InsuranceProtocolEvent::ClaimPaid { claim_id, amount, timestamp, constitutional_receipt }); + Ok(amount) + } + pub fn get_policy(&self, id: &Hash) -> Option<&InsurancePolicy> { self.policies.get(id) } + pub fn get_claim(&self, id: &Hash) -> Option<&InsuranceClaim> { self.claims.get(id) } + pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } +} diff --git a/nac-udm/src/l1_protocol/acc/acc_redemption.rs b/nac-udm/src/l1_protocol/acc/acc_redemption.rs index b317052..e8a9ca1 100644 --- a/nac-udm/src/l1_protocol/acc/acc_redemption.rs +++ b/nac-udm/src/l1_protocol/acc/acc_redemption.rs @@ -1,119 +1,119 @@ //! acc_redemption - NAC 原生协议实现 //! 从 acc_remaining_protocols.rs 提取 use crate::primitives::{Address, Hash, Timestamp}; - use serde::{Deserialize, Serialize}; - use std::collections::HashMap; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub enum ACCRedemptionError { - RedemptionNotFound(Hash), - InsufficientRedemptionFund { available: u128, requested: u128 }, - RedemptionWindowClosed, - InvalidConstitutionalReceipt, - Unauthorized(Address), - RedemptionAlreadyProcessed(Hash), - } - impl std::fmt::Display for ACCRedemptionError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::RedemptionNotFound(h) => write!(f, "赎回请求不存在: {}", h.to_hex()), - Self::InsufficientRedemptionFund { available, requested } => write!(f, "赎回资金不足: 可用 {},请求 {}", available, requested), - Self::RedemptionWindowClosed => write!(f, "赎回窗口已关闭"), - Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), - Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), - Self::RedemptionAlreadyProcessed(h) => write!(f, "赎回请求已处理: {}", h.to_hex()), - } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum ACCRedemptionError { + RedemptionNotFound(Hash), + InsufficientRedemptionFund { available: u128, requested: u128 }, + RedemptionWindowClosed, + InvalidConstitutionalReceipt, + Unauthorized(Address), + RedemptionAlreadyProcessed(Hash), +} +impl std::fmt::Display for ACCRedemptionError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::RedemptionNotFound(h) => write!(f, "赎回请求不存在: {}", h.to_hex()), + Self::InsufficientRedemptionFund { available, requested } => write!(f, "赎回资金不足: 可用 {},请求 {}", available, requested), + Self::RedemptionWindowClosed => write!(f, "赎回窗口已关闭"), + Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), + Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), + Self::RedemptionAlreadyProcessed(h) => write!(f, "赎回请求已处理: {}", h.to_hex()), } } +} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] - pub enum RedemptionStatus { Pending, Processing, Completed, Rejected, Cancelled } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum RedemptionStatus { Pending, Processing, Completed, Rejected, Cancelled } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct RedemptionRequest { - pub redemption_id: Hash, - pub asset_id: Hash, - pub redeemer: Address, - pub amount: u128, - pub redemption_price_xtzh: u128, - pub total_redemption_xtzh: u128, - pub status: RedemptionStatus, - pub requested_at: Timestamp, - pub processed_at: Option, - pub constitutional_receipt: Hash, - pub rejection_reason: Option, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RedemptionRequest { + pub redemption_id: Hash, + pub asset_id: Hash, + pub redeemer: Address, + pub amount: u128, + pub redemption_price_xtzh: u128, + pub total_redemption_xtzh: u128, + pub status: RedemptionStatus, + pub requested_at: Timestamp, + pub processed_at: Option, + pub constitutional_receipt: Hash, + pub rejection_reason: Option, +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum RedemptionProtocolEvent { - RedemptionRequested { redemption_id: Hash, asset_id: Hash, redeemer: Address, amount: u128, timestamp: Timestamp }, - RedemptionCompleted { redemption_id: Hash, total_xtzh: u128, timestamp: Timestamp }, - RedemptionRejected { redemption_id: Hash, reason: String, timestamp: Timestamp }, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum RedemptionProtocolEvent { + RedemptionRequested { redemption_id: Hash, asset_id: Hash, redeemer: Address, amount: u128, timestamp: Timestamp }, + RedemptionCompleted { redemption_id: Hash, total_xtzh: u128, timestamp: Timestamp }, + RedemptionRejected { redemption_id: Hash, reason: String, timestamp: Timestamp }, +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ACCRedemptionProtocol { - pub protocol_uid: String, - pub lens_protocol_vector: String, - pub requests: HashMap, - pub redemption_fund: HashMap, - pub redemption_window_open: bool, - pub pending_events: Vec, - pub created_at: Timestamp, - pub updated_at: Timestamp, +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ACCRedemptionProtocol { + pub protocol_uid: String, + pub lens_protocol_vector: String, + pub requests: HashMap, + pub redemption_fund: HashMap, + pub redemption_window_open: bool, + pub pending_events: Vec, + pub created_at: Timestamp, + pub updated_at: Timestamp, +} +impl ACCRedemptionProtocol { + pub fn new() -> Self { + Self { + protocol_uid: "nac.acc.ACCRedemptionProtocol.v1".to_string(), + lens_protocol_vector: "ACC-Redemption".to_string(), + requests: HashMap::new(), redemption_fund: HashMap::new(), + redemption_window_open: true, pending_events: Vec::new(), + created_at: Timestamp::now(), updated_at: Timestamp::now(), + } } - impl ACCRedemptionProtocol { - pub fn new() -> Self { - Self { - protocol_uid: "nac.acc.ACCRedemptionProtocol.v1".to_string(), - lens_protocol_vector: "ACC-Redemption".to_string(), - requests: HashMap::new(), redemption_fund: HashMap::new(), - redemption_window_open: true, pending_events: Vec::new(), - created_at: Timestamp::now(), updated_at: Timestamp::now(), - } - } - pub fn fund_redemption_pool(&mut self, asset_id: Hash, amount_xtzh: u128, constitutional_receipt: Hash) -> Result<(), ACCRedemptionError> { - if constitutional_receipt.is_zero() { return Err(ACCRedemptionError::InvalidConstitutionalReceipt); } - *self.redemption_fund.entry(asset_id).or_insert(0) += amount_xtzh; - Ok(()) - } - pub fn request_redemption( - &mut self, asset_id: Hash, redeemer: Address, amount: u128, - redemption_price_xtzh: u128, constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result { - if !self.redemption_window_open { return Err(ACCRedemptionError::RedemptionWindowClosed); } - let total = amount.saturating_mul(redemption_price_xtzh); - let available = self.redemption_fund.get(&asset_id).copied().unwrap_or(0); - if available < total { return Err(ACCRedemptionError::InsufficientRedemptionFund { available, requested: total }); } - let mut data = Vec::new(); - data.extend_from_slice(asset_id.as_bytes()); - data.extend_from_slice(redeemer.as_bytes()); - data.extend_from_slice(×tamp.as_secs().to_be_bytes()); - let redemption_id = Hash::sha3_384(&data); - let request = RedemptionRequest { - redemption_id, asset_id, redeemer: redeemer.clone(), amount, - redemption_price_xtzh, total_redemption_xtzh: total, - status: RedemptionStatus::Pending, - requested_at: timestamp.clone(), processed_at: None, - constitutional_receipt, rejection_reason: None, - }; - self.requests.insert(redemption_id, request); - self.pending_events.push(RedemptionProtocolEvent::RedemptionRequested { redemption_id, asset_id, redeemer, amount, timestamp }); - self.updated_at = Timestamp::now(); - Ok(redemption_id) - } - pub fn complete_redemption(&mut self, redemption_id: Hash, constitutional_receipt: Hash, timestamp: Timestamp) -> Result { - if constitutional_receipt.is_zero() { return Err(ACCRedemptionError::InvalidConstitutionalReceipt); } - let request = self.requests.get_mut(&redemption_id).ok_or(ACCRedemptionError::RedemptionNotFound(redemption_id))?; - if request.status != RedemptionStatus::Pending { return Err(ACCRedemptionError::RedemptionAlreadyProcessed(redemption_id)); } - let total = request.total_redemption_xtzh; - let asset_id = request.asset_id; - if let Some(fund) = self.redemption_fund.get_mut(&asset_id) { *fund = fund.saturating_sub(total); } - request.status = RedemptionStatus::Completed; - request.processed_at = Some(timestamp.clone()); - self.pending_events.push(RedemptionProtocolEvent::RedemptionCompleted { redemption_id, total_xtzh: total, timestamp }); - Ok(total) - } - pub fn get_request(&self, id: &Hash) -> Option<&RedemptionRequest> { self.requests.get(id) } - pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } + pub fn fund_redemption_pool(&mut self, asset_id: Hash, amount_xtzh: u128, constitutional_receipt: Hash) -> Result<(), ACCRedemptionError> { + if constitutional_receipt.is_zero() { return Err(ACCRedemptionError::InvalidConstitutionalReceipt); } + *self.redemption_fund.entry(asset_id).or_insert(0) += amount_xtzh; + Ok(()) } + pub fn request_redemption( + &mut self, asset_id: Hash, redeemer: Address, amount: u128, + redemption_price_xtzh: u128, constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result { + if !self.redemption_window_open { return Err(ACCRedemptionError::RedemptionWindowClosed); } + let total = amount.saturating_mul(redemption_price_xtzh); + let available = self.redemption_fund.get(&asset_id).copied().unwrap_or(0); + if available < total { return Err(ACCRedemptionError::InsufficientRedemptionFund { available, requested: total }); } + let mut data = Vec::new(); + data.extend_from_slice(asset_id.as_bytes()); + data.extend_from_slice(redeemer.as_bytes()); + data.extend_from_slice(×tamp.as_secs().to_be_bytes()); + let redemption_id = Hash::sha3_384(&data); + let request = RedemptionRequest { + redemption_id, asset_id, redeemer: redeemer.clone(), amount, + redemption_price_xtzh, total_redemption_xtzh: total, + status: RedemptionStatus::Pending, + requested_at: timestamp.clone(), processed_at: None, + constitutional_receipt, rejection_reason: None, + }; + self.requests.insert(redemption_id, request); + self.pending_events.push(RedemptionProtocolEvent::RedemptionRequested { redemption_id, asset_id, redeemer, amount, timestamp }); + self.updated_at = Timestamp::now(); + Ok(redemption_id) + } + pub fn complete_redemption(&mut self, redemption_id: Hash, constitutional_receipt: Hash, timestamp: Timestamp) -> Result { + if constitutional_receipt.is_zero() { return Err(ACCRedemptionError::InvalidConstitutionalReceipt); } + let request = self.requests.get_mut(&redemption_id).ok_or(ACCRedemptionError::RedemptionNotFound(redemption_id))?; + if request.status != RedemptionStatus::Pending { return Err(ACCRedemptionError::RedemptionAlreadyProcessed(redemption_id)); } + let total = request.total_redemption_xtzh; + let asset_id = request.asset_id; + if let Some(fund) = self.redemption_fund.get_mut(&asset_id) { *fund = fund.saturating_sub(total); } + request.status = RedemptionStatus::Completed; + request.processed_at = Some(timestamp.clone()); + self.pending_events.push(RedemptionProtocolEvent::RedemptionCompleted { redemption_id, total_xtzh: total, timestamp }); + Ok(total) + } + pub fn get_request(&self, id: &Hash) -> Option<&RedemptionRequest> { self.requests.get(id) } + pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } +} diff --git a/nac-udm/src/l1_protocol/acc/acc_reserve.rs b/nac-udm/src/l1_protocol/acc/acc_reserve.rs index 94deaf2..a1710f1 100644 --- a/nac-udm/src/l1_protocol/acc/acc_reserve.rs +++ b/nac-udm/src/l1_protocol/acc/acc_reserve.rs @@ -1,112 +1,112 @@ //! acc_reserve - NAC 原生协议实现 //! 从 acc_remaining_protocols.rs 提取 use crate::primitives::{Address, Hash, Timestamp}; - use serde::{Deserialize, Serialize}; - use std::collections::HashMap; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub enum ACCReserveError { - ReserveNotFound(String), - InsufficientReserve { asset: String, available: u128, requested: u128 }, - InvalidConstitutionalReceipt, - Unauthorized(Address), - ReserveRatioViolation { required: u8, actual: u8 }, - } - impl std::fmt::Display for ACCReserveError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::ReserveNotFound(s) => write!(f, "储备资产不存在: {}", s), - Self::InsufficientReserve { asset, available, requested } => write!(f, "储备不足 {}: 可用 {},请求 {}", asset, available, requested), - Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), - Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), - Self::ReserveRatioViolation { required, actual } => write!(f, "储备率违规: 要求 {}%,实际 {}%", required, actual), - } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum ACCReserveError { + ReserveNotFound(String), + InsufficientReserve { asset: String, available: u128, requested: u128 }, + InvalidConstitutionalReceipt, + Unauthorized(Address), + ReserveRatioViolation { required: u8, actual: u8 }, +} +impl std::fmt::Display for ACCReserveError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::ReserveNotFound(s) => write!(f, "储备资产不存在: {}", s), + Self::InsufficientReserve { asset, available, requested } => write!(f, "储备不足 {}: 可用 {},请求 {}", asset, available, requested), + Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), + Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), + Self::ReserveRatioViolation { required, actual } => write!(f, "储备率违规: 要求 {}%,实际 {}%", required, actual), } } +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ReserveEntry { - pub asset_symbol: String, - pub amount: u128, - pub custodian: Address, - pub last_audited: Timestamp, - pub audit_hash: Hash, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ReserveEntry { + pub asset_symbol: String, + pub amount: u128, + pub custodian: Address, + pub last_audited: Timestamp, + pub audit_hash: Hash, +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum ReserveProtocolEvent { - ReserveDeposited { asset: String, amount: u128, custodian: Address, timestamp: Timestamp }, - ReserveWithdrawn { asset: String, amount: u128, recipient: Address, constitutional_receipt: Hash, timestamp: Timestamp }, - ReserveAudited { asset: String, audit_hash: Hash, timestamp: Timestamp }, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum ReserveProtocolEvent { + ReserveDeposited { asset: String, amount: u128, custodian: Address, timestamp: Timestamp }, + ReserveWithdrawn { asset: String, amount: u128, recipient: Address, constitutional_receipt: Hash, timestamp: Timestamp }, + ReserveAudited { asset: String, audit_hash: Hash, timestamp: Timestamp }, +} - /// ACC-Reserve 储备协议 - /// UID: nac.acc.ACCReserveProtocol.v1 - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ACCReserveProtocol { - pub protocol_uid: String, - pub lens_protocol_vector: String, - pub reserves: HashMap, - /// 最低储备率(百分比) - pub min_reserve_ratio: u8, - pub pending_events: Vec, - pub created_at: Timestamp, - pub updated_at: Timestamp, +/// ACC-Reserve 储备协议 +/// UID: nac.acc.ACCReserveProtocol.v1 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ACCReserveProtocol { + pub protocol_uid: String, + pub lens_protocol_vector: String, + pub reserves: HashMap, + /// 最低储备率(百分比) + pub min_reserve_ratio: u8, + pub pending_events: Vec, + pub created_at: Timestamp, + pub updated_at: Timestamp, +} +impl ACCReserveProtocol { + pub fn new(min_reserve_ratio: u8) -> Self { + Self { + protocol_uid: "nac.acc.ACCReserveProtocol.v1".to_string(), + lens_protocol_vector: "ACC-Reserve".to_string(), + reserves: HashMap::new(), + min_reserve_ratio, + pending_events: Vec::new(), + created_at: Timestamp::now(), + updated_at: Timestamp::now(), + } } - impl ACCReserveProtocol { - pub fn new(min_reserve_ratio: u8) -> Self { - Self { - protocol_uid: "nac.acc.ACCReserveProtocol.v1".to_string(), - lens_protocol_vector: "ACC-Reserve".to_string(), - reserves: HashMap::new(), - min_reserve_ratio, - pending_events: Vec::new(), - created_at: Timestamp::now(), - updated_at: Timestamp::now(), - } - } - pub fn deposit( - &mut self, asset_symbol: String, amount: u128, custodian: Address, - constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result<(), ACCReserveError> { - if constitutional_receipt.is_zero() { return Err(ACCReserveError::InvalidConstitutionalReceipt); } - let entry = self.reserves.entry(asset_symbol.clone()).or_insert(ReserveEntry { - asset_symbol: asset_symbol.clone(), amount: 0, - custodian: custodian.clone(), last_audited: timestamp.clone(), - audit_hash: Hash::zero(), - }); - entry.amount = entry.amount.saturating_add(amount); - entry.custodian = custodian.clone(); - self.pending_events.push(ReserveProtocolEvent::ReserveDeposited { asset: asset_symbol, amount, custodian, timestamp }); - self.updated_at = Timestamp::now(); - Ok(()) - } - pub fn withdraw( - &mut self, asset_symbol: String, amount: u128, recipient: Address, - constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result<(), ACCReserveError> { - if constitutional_receipt.is_zero() { return Err(ACCReserveError::InvalidConstitutionalReceipt); } - let entry = self.reserves.get_mut(&asset_symbol) - .ok_or_else(|| ACCReserveError::ReserveNotFound(asset_symbol.clone()))?; - if entry.amount < amount { - return Err(ACCReserveError::InsufficientReserve { asset: asset_symbol.clone(), available: entry.amount, requested: amount }); - } - entry.amount -= amount; - self.pending_events.push(ReserveProtocolEvent::ReserveWithdrawn { asset: asset_symbol, amount, recipient, constitutional_receipt, timestamp }); - self.updated_at = Timestamp::now(); - Ok(()) - } - pub fn audit( - &mut self, asset_symbol: String, audit_hash: Hash, timestamp: Timestamp, - ) -> Result<(), ACCReserveError> { - let entry = self.reserves.get_mut(&asset_symbol) - .ok_or_else(|| ACCReserveError::ReserveNotFound(asset_symbol.clone()))?; - entry.last_audited = timestamp.clone(); - entry.audit_hash = audit_hash; - self.pending_events.push(ReserveProtocolEvent::ReserveAudited { asset: asset_symbol, audit_hash, timestamp }); - Ok(()) - } - pub fn get_reserve(&self, asset: &str) -> Option<&ReserveEntry> { self.reserves.get(asset) } - pub fn total_reserve_count(&self) -> usize { self.reserves.len() } - pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } + pub fn deposit( + &mut self, asset_symbol: String, amount: u128, custodian: Address, + constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result<(), ACCReserveError> { + if constitutional_receipt.is_zero() { return Err(ACCReserveError::InvalidConstitutionalReceipt); } + let entry = self.reserves.entry(asset_symbol.clone()).or_insert(ReserveEntry { + asset_symbol: asset_symbol.clone(), amount: 0, + custodian: custodian.clone(), last_audited: timestamp.clone(), + audit_hash: Hash::zero(), + }); + entry.amount = entry.amount.saturating_add(amount); + entry.custodian = custodian.clone(); + self.pending_events.push(ReserveProtocolEvent::ReserveDeposited { asset: asset_symbol, amount, custodian, timestamp }); + self.updated_at = Timestamp::now(); + Ok(()) } + pub fn withdraw( + &mut self, asset_symbol: String, amount: u128, recipient: Address, + constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result<(), ACCReserveError> { + if constitutional_receipt.is_zero() { return Err(ACCReserveError::InvalidConstitutionalReceipt); } + let entry = self.reserves.get_mut(&asset_symbol) + .ok_or_else(|| ACCReserveError::ReserveNotFound(asset_symbol.clone()))?; + if entry.amount < amount { + return Err(ACCReserveError::InsufficientReserve { asset: asset_symbol.clone(), available: entry.amount, requested: amount }); + } + entry.amount -= amount; + self.pending_events.push(ReserveProtocolEvent::ReserveWithdrawn { asset: asset_symbol, amount, recipient, constitutional_receipt, timestamp }); + self.updated_at = Timestamp::now(); + Ok(()) + } + pub fn audit( + &mut self, asset_symbol: String, audit_hash: Hash, timestamp: Timestamp, + ) -> Result<(), ACCReserveError> { + let entry = self.reserves.get_mut(&asset_symbol) + .ok_or_else(|| ACCReserveError::ReserveNotFound(asset_symbol.clone()))?; + entry.last_audited = timestamp.clone(); + entry.audit_hash = audit_hash; + self.pending_events.push(ReserveProtocolEvent::ReserveAudited { asset: asset_symbol, audit_hash, timestamp }); + Ok(()) + } + pub fn get_reserve(&self, asset: &str) -> Option<&ReserveEntry> { self.reserves.get(asset) } + pub fn total_reserve_count(&self) -> usize { self.reserves.len() } + pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } +} diff --git a/nac-udm/src/l1_protocol/acc/acc_rwa.rs b/nac-udm/src/l1_protocol/acc/acc_rwa.rs index 553a978..cf0191a 100644 --- a/nac-udm/src/l1_protocol/acc/acc_rwa.rs +++ b/nac-udm/src/l1_protocol/acc/acc_rwa.rs @@ -1,177 +1,177 @@ //! acc_rwa - NAC 原生协议实现 //! 从 acc_remaining_protocols.rs 提取 use crate::primitives::{Address, Hash, Timestamp}; - use serde::{Deserialize, Serialize}; - use std::collections::HashMap; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub enum ACCRWAError { - AssetNotFound(Hash), - AssetAlreadyRegistered(Hash), - InvalidConstitutionalReceipt, - Unauthorized(Address), - ComplianceCheckFailed(String), - ValuationExpired(Hash), - AssetFrozen(Hash), - } - impl std::fmt::Display for ACCRWAError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::AssetNotFound(h) => write!(f, "RWA 资产不存在: {}", h.to_hex()), - Self::AssetAlreadyRegistered(h) => write!(f, "RWA 资产已注册: {}", h.to_hex()), - Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), - Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), - Self::ComplianceCheckFailed(msg) => write!(f, "合规检查失败: {}", msg), - Self::ValuationExpired(h) => write!(f, "估值已过期: {}", h.to_hex()), - Self::AssetFrozen(h) => write!(f, "资产已冻结: {}", h.to_hex()), - } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum ACCRWAError { + AssetNotFound(Hash), + AssetAlreadyRegistered(Hash), + InvalidConstitutionalReceipt, + Unauthorized(Address), + ComplianceCheckFailed(String), + ValuationExpired(Hash), + AssetFrozen(Hash), +} +impl std::fmt::Display for ACCRWAError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::AssetNotFound(h) => write!(f, "RWA 资产不存在: {}", h.to_hex()), + Self::AssetAlreadyRegistered(h) => write!(f, "RWA 资产已注册: {}", h.to_hex()), + Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), + Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), + Self::ComplianceCheckFailed(msg) => write!(f, "合规检查失败: {}", msg), + Self::ValuationExpired(h) => write!(f, "估值已过期: {}", h.to_hex()), + Self::AssetFrozen(h) => write!(f, "资产已冻结: {}", h.to_hex()), } } +} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] - pub enum RWAAssetType { - RealEstate, - CorporateBond, - GovernmentBond, - Commodity, - PrivateEquity, - Infrastructure, - IntellectualProperty, - NaturalResource, - Other, - } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum RWAAssetType { + RealEstate, + CorporateBond, + GovernmentBond, + Commodity, + PrivateEquity, + Infrastructure, + IntellectualProperty, + NaturalResource, + Other, +} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] - pub enum RWAAssetStatus { Pending, Active, Frozen, Redeemed, Delisted } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum RWAAssetStatus { Pending, Active, Frozen, Redeemed, Delisted } - /// RWA 资产记录 - /// UID: nac.acc.RWAAssetRecord.v1 - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct RWAAssetRecord { - pub asset_id: Hash, - pub gnacs_code: String, - pub asset_type: RWAAssetType, - pub owner: Address, - pub issuer: Address, - pub total_supply: u128, - pub current_valuation_xtzh: u128, - pub jurisdiction: String, - pub status: RWAAssetStatus, - /// 法律文件哈希(SHA3-384) - pub legal_document_hash: Hash, - /// AI 合规评分(0-100) - pub ai_compliance_score: u8, - pub constitutional_receipt: Hash, - pub registered_at: Timestamp, - pub updated_at: Timestamp, - } +/// RWA 资产记录 +/// UID: nac.acc.RWAAssetRecord.v1 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RWAAssetRecord { + pub asset_id: Hash, + pub gnacs_code: String, + pub asset_type: RWAAssetType, + pub owner: Address, + pub issuer: Address, + pub total_supply: u128, + pub current_valuation_xtzh: u128, + pub jurisdiction: String, + pub status: RWAAssetStatus, + /// 法律文件哈希(SHA3-384) + pub legal_document_hash: Hash, + /// AI 合规评分(0-100) + pub ai_compliance_score: u8, + pub constitutional_receipt: Hash, + pub registered_at: Timestamp, + pub updated_at: Timestamp, +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum RWAProtocolEvent { - AssetRegistered { asset_id: Hash, gnacs_code: String, owner: Address, valuation: u128, timestamp: Timestamp }, - AssetTransferred { asset_id: Hash, from: Address, to: Address, amount: u128, timestamp: Timestamp }, - AssetFrozen { asset_id: Hash, reason: String, timestamp: Timestamp, constitutional_receipt: Hash }, - AssetUnfrozen { asset_id: Hash, timestamp: Timestamp, constitutional_receipt: Hash }, - ValuationUpdated { asset_id: Hash, old_value: u128, new_value: u128, timestamp: Timestamp }, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum RWAProtocolEvent { + AssetRegistered { asset_id: Hash, gnacs_code: String, owner: Address, valuation: u128, timestamp: Timestamp }, + AssetTransferred { asset_id: Hash, from: Address, to: Address, amount: u128, timestamp: Timestamp }, + AssetFrozen { asset_id: Hash, reason: String, timestamp: Timestamp, constitutional_receipt: Hash }, + AssetUnfrozen { asset_id: Hash, timestamp: Timestamp, constitutional_receipt: Hash }, + ValuationUpdated { asset_id: Hash, old_value: u128, new_value: u128, timestamp: Timestamp }, +} - /// ACC-RWA 真实世界资产协议 - /// UID: nac.acc.ACCRWAProtocol.v1 - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ACCRWAProtocol { - pub protocol_uid: String, - pub lens_protocol_vector: String, - pub assets: HashMap, - /// 持仓(asset_id -> (address -> amount)) - pub holdings: HashMap>, - pub pending_events: Vec, - pub created_at: Timestamp, - pub updated_at: Timestamp, +/// ACC-RWA 真实世界资产协议 +/// UID: nac.acc.ACCRWAProtocol.v1 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ACCRWAProtocol { + pub protocol_uid: String, + pub lens_protocol_vector: String, + pub assets: HashMap, + /// 持仓(asset_id -> (address -> amount)) + pub holdings: HashMap>, + pub pending_events: Vec, + pub created_at: Timestamp, + pub updated_at: Timestamp, +} +impl ACCRWAProtocol { + pub fn new() -> Self { + Self { + protocol_uid: "nac.acc.ACCRWAProtocol.v1".to_string(), + lens_protocol_vector: "ACC-RWA".to_string(), + assets: HashMap::new(), + holdings: HashMap::new(), + pending_events: Vec::new(), + created_at: Timestamp::now(), + updated_at: Timestamp::now(), + } } - impl ACCRWAProtocol { - pub fn new() -> Self { - Self { - protocol_uid: "nac.acc.ACCRWAProtocol.v1".to_string(), - lens_protocol_vector: "ACC-RWA".to_string(), - assets: HashMap::new(), - holdings: HashMap::new(), - pending_events: Vec::new(), - created_at: Timestamp::now(), - updated_at: Timestamp::now(), - } + pub fn register_asset( + &mut self, gnacs_code: String, asset_type: RWAAssetType, owner: Address, issuer: Address, + total_supply: u128, initial_valuation_xtzh: u128, jurisdiction: String, + legal_document_hash: Hash, ai_compliance_score: u8, + constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result { + if constitutional_receipt.is_zero() { return Err(ACCRWAError::InvalidConstitutionalReceipt); } + if ai_compliance_score < 60 { + return Err(ACCRWAError::ComplianceCheckFailed(format!("AI 合规评分不足: {}/100", ai_compliance_score))); } - pub fn register_asset( - &mut self, gnacs_code: String, asset_type: RWAAssetType, owner: Address, issuer: Address, - total_supply: u128, initial_valuation_xtzh: u128, jurisdiction: String, - legal_document_hash: Hash, ai_compliance_score: u8, - constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result { - if constitutional_receipt.is_zero() { return Err(ACCRWAError::InvalidConstitutionalReceipt); } - if ai_compliance_score < 60 { - return Err(ACCRWAError::ComplianceCheckFailed(format!("AI 合规评分不足: {}/100", ai_compliance_score))); - } - let mut data = Vec::new(); - data.extend_from_slice(gnacs_code.as_bytes()); - data.extend_from_slice(owner.as_bytes()); - data.extend_from_slice(×tamp.as_secs().to_be_bytes()); - let asset_id = Hash::sha3_384(&data); - if self.assets.contains_key(&asset_id) { return Err(ACCRWAError::AssetAlreadyRegistered(asset_id)); } - let record = RWAAssetRecord { - asset_id, gnacs_code: gnacs_code.clone(), asset_type, owner: owner.clone(), issuer, - total_supply, current_valuation_xtzh: initial_valuation_xtzh, - jurisdiction, status: RWAAssetStatus::Active, - legal_document_hash, ai_compliance_score, constitutional_receipt, - registered_at: timestamp.clone(), updated_at: timestamp.clone(), - }; - let mut asset_holdings = HashMap::new(); - asset_holdings.insert(owner.clone(), total_supply); - self.holdings.insert(asset_id, asset_holdings); - self.assets.insert(asset_id, record); - self.pending_events.push(RWAProtocolEvent::AssetRegistered { - asset_id, gnacs_code, owner, valuation: initial_valuation_xtzh, timestamp, - }); - self.updated_at = Timestamp::now(); - Ok(asset_id) - } - pub fn transfer_asset( - &mut self, asset_id: Hash, from: Address, to: Address, amount: u128, timestamp: Timestamp, - ) -> Result<(), ACCRWAError> { - let asset = self.assets.get(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; - if asset.status == RWAAssetStatus::Frozen { return Err(ACCRWAError::AssetFrozen(asset_id)); } - let holdings = self.holdings.get_mut(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; - let from_balance = holdings.get(&from).copied().unwrap_or(0); - if from_balance < amount { - return Err(ACCRWAError::Unauthorized(from.clone())); - } - *holdings.get_mut(&from).unwrap() -= amount; - *holdings.entry(to.clone()).or_insert(0) += amount; - self.pending_events.push(RWAProtocolEvent::AssetTransferred { asset_id, from, to, amount, timestamp }); - Ok(()) - } - pub fn freeze_asset( - &mut self, asset_id: Hash, reason: String, constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result<(), ACCRWAError> { - if constitutional_receipt.is_zero() { return Err(ACCRWAError::InvalidConstitutionalReceipt); } - let asset = self.assets.get_mut(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; - asset.status = RWAAssetStatus::Frozen; - asset.updated_at = timestamp.clone(); - self.pending_events.push(RWAProtocolEvent::AssetFrozen { asset_id, reason, timestamp, constitutional_receipt }); - Ok(()) - } - pub fn update_valuation( - &mut self, asset_id: Hash, new_valuation: u128, constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result<(), ACCRWAError> { - if constitutional_receipt.is_zero() { return Err(ACCRWAError::InvalidConstitutionalReceipt); } - let asset = self.assets.get_mut(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; - let old_value = asset.current_valuation_xtzh; - asset.current_valuation_xtzh = new_valuation; - asset.updated_at = timestamp.clone(); - self.pending_events.push(RWAProtocolEvent::ValuationUpdated { asset_id, old_value, new_value: new_valuation, timestamp }); - Ok(()) - } - pub fn get_asset(&self, id: &Hash) -> Option<&RWAAssetRecord> { self.assets.get(id) } - pub fn balance_of(&self, asset_id: &Hash, holder: &Address) -> u128 { - self.holdings.get(asset_id).and_then(|h| h.get(holder)).copied().unwrap_or(0) - } - pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } + let mut data = Vec::new(); + data.extend_from_slice(gnacs_code.as_bytes()); + data.extend_from_slice(owner.as_bytes()); + data.extend_from_slice(×tamp.as_secs().to_be_bytes()); + let asset_id = Hash::sha3_384(&data); + if self.assets.contains_key(&asset_id) { return Err(ACCRWAError::AssetAlreadyRegistered(asset_id)); } + let record = RWAAssetRecord { + asset_id, gnacs_code: gnacs_code.clone(), asset_type, owner: owner.clone(), issuer, + total_supply, current_valuation_xtzh: initial_valuation_xtzh, + jurisdiction, status: RWAAssetStatus::Active, + legal_document_hash, ai_compliance_score, constitutional_receipt, + registered_at: timestamp.clone(), updated_at: timestamp.clone(), + }; + let mut asset_holdings = HashMap::new(); + asset_holdings.insert(owner.clone(), total_supply); + self.holdings.insert(asset_id, asset_holdings); + self.assets.insert(asset_id, record); + self.pending_events.push(RWAProtocolEvent::AssetRegistered { + asset_id, gnacs_code, owner, valuation: initial_valuation_xtzh, timestamp, + }); + self.updated_at = Timestamp::now(); + Ok(asset_id) } + pub fn transfer_asset( + &mut self, asset_id: Hash, from: Address, to: Address, amount: u128, timestamp: Timestamp, + ) -> Result<(), ACCRWAError> { + let asset = self.assets.get(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; + if asset.status == RWAAssetStatus::Frozen { return Err(ACCRWAError::AssetFrozen(asset_id)); } + let holdings = self.holdings.get_mut(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; + let from_balance = holdings.get(&from).copied().unwrap_or(0); + if from_balance < amount { + return Err(ACCRWAError::Unauthorized(from.clone())); + } + *holdings.get_mut(&from).unwrap() -= amount; + *holdings.entry(to.clone()).or_insert(0) += amount; + self.pending_events.push(RWAProtocolEvent::AssetTransferred { asset_id, from, to, amount, timestamp }); + Ok(()) + } + pub fn freeze_asset( + &mut self, asset_id: Hash, reason: String, constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result<(), ACCRWAError> { + if constitutional_receipt.is_zero() { return Err(ACCRWAError::InvalidConstitutionalReceipt); } + let asset = self.assets.get_mut(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; + asset.status = RWAAssetStatus::Frozen; + asset.updated_at = timestamp.clone(); + self.pending_events.push(RWAProtocolEvent::AssetFrozen { asset_id, reason, timestamp, constitutional_receipt }); + Ok(()) + } + pub fn update_valuation( + &mut self, asset_id: Hash, new_valuation: u128, constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result<(), ACCRWAError> { + if constitutional_receipt.is_zero() { return Err(ACCRWAError::InvalidConstitutionalReceipt); } + let asset = self.assets.get_mut(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; + let old_value = asset.current_valuation_xtzh; + asset.current_valuation_xtzh = new_valuation; + asset.updated_at = timestamp.clone(); + self.pending_events.push(RWAProtocolEvent::ValuationUpdated { asset_id, old_value, new_value: new_valuation, timestamp }); + Ok(()) + } + pub fn get_asset(&self, id: &Hash) -> Option<&RWAAssetRecord> { self.assets.get(id) } + pub fn balance_of(&self, asset_id: &Hash, holder: &Address) -> u128 { + self.holdings.get(asset_id).and_then(|h| h.get(holder)).copied().unwrap_or(0) + } + pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } +} diff --git a/nac-udm/src/l1_protocol/acc/acc_xtzh.rs b/nac-udm/src/l1_protocol/acc/acc_xtzh.rs index 1146cd9..28152ee 100644 --- a/nac-udm/src/l1_protocol/acc/acc_xtzh.rs +++ b/nac-udm/src/l1_protocol/acc/acc_xtzh.rs @@ -1,172 +1,172 @@ //! acc_xtzh - NAC 原生协议实现 //! 从 acc_remaining_protocols.rs 提取 use crate::primitives::{Address, Hash, Timestamp}; - use serde::{Deserialize, Serialize}; - use std::collections::HashMap; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub enum ACCXTZHError { - InsufficientBalance { holder: Address, available: u128, requested: u128 }, - InsufficientReserve { required: u128, available: u128 }, - InvalidConstitutionalReceipt, - Unauthorized(Address), - SDRPegViolation { current_rate: u128, min_rate: u128, max_rate: u128 }, - GoldReserveInsufficient { required_ratio: u8, actual_ratio: u8 }, - } - impl std::fmt::Display for ACCXTZHError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::InsufficientBalance { holder, available, requested } => write!(f, "余额不足 {}: 可用 {},请求 {}", holder.to_hex(), available, requested), - Self::InsufficientReserve { required, available } => write!(f, "储备不足: 需要 {},可用 {}", required, available), - Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), - Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), - Self::SDRPegViolation { current_rate, min_rate, max_rate } => write!(f, "SDR 锚定偏离: 当前 {},允许范围 [{}, {}]", current_rate, min_rate, max_rate), - Self::GoldReserveInsufficient { required_ratio, actual_ratio } => write!(f, "黄金储备不足: 要求 {}%,实际 {}%", required_ratio, actual_ratio), - } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum ACCXTZHError { + InsufficientBalance { holder: Address, available: u128, requested: u128 }, + InsufficientReserve { required: u128, available: u128 }, + InvalidConstitutionalReceipt, + Unauthorized(Address), + SDRPegViolation { current_rate: u128, min_rate: u128, max_rate: u128 }, + GoldReserveInsufficient { required_ratio: u8, actual_ratio: u8 }, +} +impl std::fmt::Display for ACCXTZHError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::InsufficientBalance { holder, available, requested } => write!(f, "余额不足 {}: 可用 {},请求 {}", holder.to_hex(), available, requested), + Self::InsufficientReserve { required, available } => write!(f, "储备不足: 需要 {},可用 {}", required, available), + Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), + Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), + Self::SDRPegViolation { current_rate, min_rate, max_rate } => write!(f, "SDR 锚定偏离: 当前 {},允许范围 [{}, {}]", current_rate, min_rate, max_rate), + Self::GoldReserveInsufficient { required_ratio, actual_ratio } => write!(f, "黄金储备不足: 要求 {}%,实际 {}%", required_ratio, actual_ratio), } } +} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] - pub enum ReserveAssetType { Gold, USD, EUR, GBP, JPY, CNY, NACNative } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum ReserveAssetType { Gold, USD, EUR, GBP, JPY, CNY, NACNative } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ReserveAsset { - pub asset_type: ReserveAssetType, - pub amount: u128, - /// 权重(基点,10000=100%) - pub weight_bps: u16, - pub last_updated: Timestamp, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ReserveAsset { + pub asset_type: ReserveAssetType, + pub amount: u128, + /// 权重(基点,10000=100%) + pub weight_bps: u16, + pub last_updated: Timestamp, +} - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum XTZHProtocolEvent { - Minted { recipient: Address, amount: u128, constitutional_receipt: Hash, timestamp: Timestamp }, - Burned { holder: Address, amount: u128, constitutional_receipt: Hash, timestamp: Timestamp }, - Transferred { from: Address, to: Address, amount: u128, timestamp: Timestamp }, - ReserveRebalanced { old_gold_ratio: u8, new_gold_ratio: u8, timestamp: Timestamp }, - SDRRateUpdated { old_rate: u128, new_rate: u128, timestamp: Timestamp }, - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum XTZHProtocolEvent { + Minted { recipient: Address, amount: u128, constitutional_receipt: Hash, timestamp: Timestamp }, + Burned { holder: Address, amount: u128, constitutional_receipt: Hash, timestamp: Timestamp }, + Transferred { from: Address, to: Address, amount: u128, timestamp: Timestamp }, + ReserveRebalanced { old_gold_ratio: u8, new_gold_ratio: u8, timestamp: Timestamp }, + SDRRateUpdated { old_rate: u128, new_rate: u128, timestamp: Timestamp }, +} - /// XTZH 稳定币协议 - /// UID: nac.acc.XTZHStablecoinProtocol.v1 - /// SDR 锚定 + 黄金储备保障 - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct XTZHStablecoinProtocol { - pub protocol_uid: String, - pub lens_protocol_vector: String, - pub total_supply: u128, - /// 持仓(address -> 余额,精度18位) - pub holdings: HashMap, - /// 储备资产 - pub reserve_assets: Vec, - /// SDR 锚定汇率(XTZH/SDR,精度18位,1 XTZH = 1 SDR) - pub sdr_peg_rate: u128, - /// SDR 汇率允许偏差(基点,默认200=2%) - pub sdr_tolerance_bps: u16, - /// 黄金储备最低比例(百分比,默认40) - pub min_gold_reserve_ratio: u8, - /// 当前黄金储备比例 - pub current_gold_reserve_ratio: u8, - pub pending_events: Vec, - pub created_at: Timestamp, - pub updated_at: Timestamp, +/// XTZH 稳定币协议 +/// UID: nac.acc.XTZHStablecoinProtocol.v1 +/// SDR 锚定 + 黄金储备保障 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct XTZHStablecoinProtocol { + pub protocol_uid: String, + pub lens_protocol_vector: String, + pub total_supply: u128, + /// 持仓(address -> 余额,精度18位) + pub holdings: HashMap, + /// 储备资产 + pub reserve_assets: Vec, + /// SDR 锚定汇率(XTZH/SDR,精度18位,1 XTZH = 1 SDR) + pub sdr_peg_rate: u128, + /// SDR 汇率允许偏差(基点,默认200=2%) + pub sdr_tolerance_bps: u16, + /// 黄金储备最低比例(百分比,默认40) + pub min_gold_reserve_ratio: u8, + /// 当前黄金储备比例 + pub current_gold_reserve_ratio: u8, + pub pending_events: Vec, + pub created_at: Timestamp, + pub updated_at: Timestamp, +} +impl XTZHStablecoinProtocol { + pub fn new(sdr_peg_rate: u128, min_gold_reserve_ratio: u8) -> Self { + Self { + protocol_uid: "nac.acc.XTZHStablecoinProtocol.v1".to_string(), + lens_protocol_vector: "ACC-XTZH".to_string(), + total_supply: 0, + holdings: HashMap::new(), + reserve_assets: Vec::new(), + sdr_peg_rate, + sdr_tolerance_bps: 200, + min_gold_reserve_ratio, + current_gold_reserve_ratio: 0, + pending_events: Vec::new(), + created_at: Timestamp::now(), + updated_at: Timestamp::now(), + } } - impl XTZHStablecoinProtocol { - pub fn new(sdr_peg_rate: u128, min_gold_reserve_ratio: u8) -> Self { - Self { - protocol_uid: "nac.acc.XTZHStablecoinProtocol.v1".to_string(), - lens_protocol_vector: "ACC-XTZH".to_string(), - total_supply: 0, - holdings: HashMap::new(), - reserve_assets: Vec::new(), - sdr_peg_rate, - sdr_tolerance_bps: 200, - min_gold_reserve_ratio, - current_gold_reserve_ratio: 0, - pending_events: Vec::new(), - created_at: Timestamp::now(), - updated_at: Timestamp::now(), - } + pub fn mint( + &mut self, recipient: Address, amount: u128, + constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result<(), ACCXTZHError> { + if constitutional_receipt.is_zero() { return Err(ACCXTZHError::InvalidConstitutionalReceipt); } + if self.current_gold_reserve_ratio < self.min_gold_reserve_ratio { + return Err(ACCXTZHError::GoldReserveInsufficient { + required_ratio: self.min_gold_reserve_ratio, + actual_ratio: self.current_gold_reserve_ratio, + }); } - pub fn mint( - &mut self, recipient: Address, amount: u128, - constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result<(), ACCXTZHError> { - if constitutional_receipt.is_zero() { return Err(ACCXTZHError::InvalidConstitutionalReceipt); } - if self.current_gold_reserve_ratio < self.min_gold_reserve_ratio { - return Err(ACCXTZHError::GoldReserveInsufficient { - required_ratio: self.min_gold_reserve_ratio, - actual_ratio: self.current_gold_reserve_ratio, - }); - } - *self.holdings.entry(recipient.clone()).or_insert(0) += amount; - self.total_supply = self.total_supply.saturating_add(amount); - self.pending_events.push(XTZHProtocolEvent::Minted { recipient, amount, constitutional_receipt, timestamp }); - self.updated_at = Timestamp::now(); - Ok(()) - } - pub fn burn( - &mut self, holder: Address, amount: u128, - constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result<(), ACCXTZHError> { - if constitutional_receipt.is_zero() { return Err(ACCXTZHError::InvalidConstitutionalReceipt); } - let balance = self.holdings.get(&holder).copied().unwrap_or(0); - if balance < amount { - return Err(ACCXTZHError::InsufficientBalance { holder: holder.clone(), available: balance, requested: amount }); - } - *self.holdings.get_mut(&holder).unwrap() -= amount; - self.total_supply = self.total_supply.saturating_sub(amount); - self.pending_events.push(XTZHProtocolEvent::Burned { holder, amount, constitutional_receipt, timestamp }); - self.updated_at = Timestamp::now(); - Ok(()) - } - pub fn transfer( - &mut self, from: Address, to: Address, amount: u128, timestamp: Timestamp, - ) -> Result<(), ACCXTZHError> { - let balance = self.holdings.get(&from).copied().unwrap_or(0); - if balance < amount { - return Err(ACCXTZHError::InsufficientBalance { holder: from.clone(), available: balance, requested: amount }); - } - *self.holdings.get_mut(&from).unwrap() -= amount; - *self.holdings.entry(to.clone()).or_insert(0) += amount; - self.pending_events.push(XTZHProtocolEvent::Transferred { from, to, amount, timestamp }); - Ok(()) - } - pub fn update_sdr_rate( - &mut self, new_rate: u128, constitutional_receipt: Hash, timestamp: Timestamp, - ) -> Result<(), ACCXTZHError> { - if constitutional_receipt.is_zero() { return Err(ACCXTZHError::InvalidConstitutionalReceipt); } - let tolerance = self.sdr_peg_rate * self.sdr_tolerance_bps as u128 / 10000; - let min_rate = self.sdr_peg_rate.saturating_sub(tolerance); - let max_rate = self.sdr_peg_rate.saturating_add(tolerance); - if new_rate < min_rate || new_rate > max_rate { - return Err(ACCXTZHError::SDRPegViolation { current_rate: new_rate, min_rate, max_rate }); - } - let old_rate = self.sdr_peg_rate; - self.sdr_peg_rate = new_rate; - self.pending_events.push(XTZHProtocolEvent::SDRRateUpdated { old_rate, new_rate, timestamp }); - Ok(()) - } - pub fn update_reserve( - &mut self, asset_type: ReserveAssetType, amount: u128, weight_bps: u16, timestamp: Timestamp, - ) { - if let Some(r) = self.reserve_assets.iter_mut().find(|r| r.asset_type == asset_type) { - r.amount = amount; - r.weight_bps = weight_bps; - r.last_updated = timestamp; - } else { - self.reserve_assets.push(ReserveAsset { asset_type, amount, weight_bps, last_updated: timestamp }); - } - self.recalculate_gold_ratio(); - } - fn recalculate_gold_ratio(&mut self) { - let total_weight: u16 = self.reserve_assets.iter().map(|r| r.weight_bps).sum(); - if total_weight == 0 { self.current_gold_reserve_ratio = 0; return; } - let gold_weight: u16 = self.reserve_assets.iter() - .filter(|r| r.asset_type == ReserveAssetType::Gold) - .map(|r| r.weight_bps).sum(); - self.current_gold_reserve_ratio = (gold_weight as u32 * 100 / total_weight as u32) as u8; - } - pub fn balance_of(&self, address: &Address) -> u128 { self.holdings.get(address).copied().unwrap_or(0) } - pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } + *self.holdings.entry(recipient.clone()).or_insert(0) += amount; + self.total_supply = self.total_supply.saturating_add(amount); + self.pending_events.push(XTZHProtocolEvent::Minted { recipient, amount, constitutional_receipt, timestamp }); + self.updated_at = Timestamp::now(); + Ok(()) } + pub fn burn( + &mut self, holder: Address, amount: u128, + constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result<(), ACCXTZHError> { + if constitutional_receipt.is_zero() { return Err(ACCXTZHError::InvalidConstitutionalReceipt); } + let balance = self.holdings.get(&holder).copied().unwrap_or(0); + if balance < amount { + return Err(ACCXTZHError::InsufficientBalance { holder: holder.clone(), available: balance, requested: amount }); + } + *self.holdings.get_mut(&holder).unwrap() -= amount; + self.total_supply = self.total_supply.saturating_sub(amount); + self.pending_events.push(XTZHProtocolEvent::Burned { holder, amount, constitutional_receipt, timestamp }); + self.updated_at = Timestamp::now(); + Ok(()) + } + pub fn transfer( + &mut self, from: Address, to: Address, amount: u128, timestamp: Timestamp, + ) -> Result<(), ACCXTZHError> { + let balance = self.holdings.get(&from).copied().unwrap_or(0); + if balance < amount { + return Err(ACCXTZHError::InsufficientBalance { holder: from.clone(), available: balance, requested: amount }); + } + *self.holdings.get_mut(&from).unwrap() -= amount; + *self.holdings.entry(to.clone()).or_insert(0) += amount; + self.pending_events.push(XTZHProtocolEvent::Transferred { from, to, amount, timestamp }); + Ok(()) + } + pub fn update_sdr_rate( + &mut self, new_rate: u128, constitutional_receipt: Hash, timestamp: Timestamp, + ) -> Result<(), ACCXTZHError> { + if constitutional_receipt.is_zero() { return Err(ACCXTZHError::InvalidConstitutionalReceipt); } + let tolerance = self.sdr_peg_rate * self.sdr_tolerance_bps as u128 / 10000; + let min_rate = self.sdr_peg_rate.saturating_sub(tolerance); + let max_rate = self.sdr_peg_rate.saturating_add(tolerance); + if new_rate < min_rate || new_rate > max_rate { + return Err(ACCXTZHError::SDRPegViolation { current_rate: new_rate, min_rate, max_rate }); + } + let old_rate = self.sdr_peg_rate; + self.sdr_peg_rate = new_rate; + self.pending_events.push(XTZHProtocolEvent::SDRRateUpdated { old_rate, new_rate, timestamp }); + Ok(()) + } + pub fn update_reserve( + &mut self, asset_type: ReserveAssetType, amount: u128, weight_bps: u16, timestamp: Timestamp, + ) { + if let Some(r) = self.reserve_assets.iter_mut().find(|r| r.asset_type == asset_type) { + r.amount = amount; + r.weight_bps = weight_bps; + r.last_updated = timestamp; + } else { + self.reserve_assets.push(ReserveAsset { asset_type, amount, weight_bps, last_updated: timestamp }); + } + self.recalculate_gold_ratio(); + } + fn recalculate_gold_ratio(&mut self) { + let total_weight: u16 = self.reserve_assets.iter().map(|r| r.weight_bps).sum(); + if total_weight == 0 { self.current_gold_reserve_ratio = 0; return; } + let gold_weight: u16 = self.reserve_assets.iter() + .filter(|r| r.asset_type == ReserveAssetType::Gold) + .map(|r| r.weight_bps).sum(); + self.current_gold_reserve_ratio = (gold_weight as u32 * 100 / total_weight as u32) as u8; + } + pub fn balance_of(&self, address: &Address) -> u128 { self.holdings.get(address).copied().unwrap_or(0) } + pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } +}