544 lines
14 KiB
Rust
544 lines
14 KiB
Rust
//! L1协议层适配器
|
||
//!
|
||
//! 提供NAC公链L1层的核心功能:
|
||
//! - NVM虚拟机:部署和调用Charter智能合约
|
||
//! - CBPP共识:交易提交和区块查询
|
||
//! - GNACS编码:资产分类编码系统
|
||
//! - ACC协议族:ACC-20、ACC-1400、XTZH稳定币
|
||
//!
|
||
//! # 示例
|
||
//!
|
||
//! ```rust
|
||
//! use nac_sdk::adapters::{L1ProtocolAdapter, config::L1Config};
|
||
//!
|
||
//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
|
||
//! // 创建L1适配器
|
||
//! let config = L1Config {
|
||
//! nrpc4_url: "http://localhost:8545".to_string(),
|
||
//! chain_id: 1,
|
||
//! timeout: std::time::Duration::from_secs(30),
|
||
//! };
|
||
//! let l1 = L1ProtocolAdapter::new(&config).await?;
|
||
//!
|
||
//! // 获取最新区块
|
||
//! let block_number = l1.get_latest_block_number().await?;
|
||
//! println!("Latest block: {}", block_number);
|
||
//!
|
||
//! # Ok(())
|
||
//! # }
|
||
//! ```
|
||
|
||
use crate::error::{NACError, Result};
|
||
use super::config::L1Config;
|
||
use nac_udm::primitives::{Address, Hash, Decimal};
|
||
use nac_udm::types::{
|
||
Block, Transaction, SignedTransaction, TransactionReceipt,
|
||
GNACSCode, GNACSMetadata, ACC20Metadata, ACC1400Metadata,
|
||
CollateralProof, CrossShardStatus,
|
||
};
|
||
use nac_lens::client::NRPC4Client;
|
||
use std::time::Duration;
|
||
|
||
/// L1协议层适配器
|
||
///
|
||
/// 统一封装NVM、CBPP、GNACS、ACC四大子系统
|
||
#[derive(Debug, Clone)]
|
||
pub struct L1ProtocolAdapter {
|
||
/// NRPC4客户端
|
||
client: NRPC4Client,
|
||
/// 链ID
|
||
chain_id: u32,
|
||
/// 超时时间
|
||
timeout: Duration,
|
||
}
|
||
|
||
impl L1ProtocolAdapter {
|
||
/// 创建新的L1适配器
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `config` - L1层配置
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回初始化完成的L1适配器实例
|
||
pub async fn new(config: &L1Config) -> Result<Self> {
|
||
let client = NRPC4Client::new(&config.nrpc4_url, config.timeout)
|
||
.map_err(|e| NACError::NetworkError(format!("Failed to create NRPC4 client: {}", e)))?;
|
||
|
||
Ok(Self {
|
||
client,
|
||
chain_id: config.chain_id,
|
||
timeout: config.timeout,
|
||
})
|
||
}
|
||
|
||
// ===== NVM虚拟机 =====
|
||
|
||
/// 部署Charter智能合约
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `bytecode` - Charter合约字节码
|
||
/// * `constructor_args` - 构造函数参数
|
||
/// * `deployer` - 部署者地址
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回部署的合约地址
|
||
pub async fn deploy_contract(
|
||
&self,
|
||
bytecode: &[u8],
|
||
constructor_args: &[u8],
|
||
deployer: &Address,
|
||
) -> Result<Address> {
|
||
self.client
|
||
.deploy_contract(bytecode, constructor_args, deployer, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::ContractError(format!("Failed to deploy contract: {}", e)))
|
||
}
|
||
|
||
/// 调用合约方法
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `contract_addr` - 合约地址
|
||
/// * `method` - 方法名
|
||
/// * `args` - 方法参数
|
||
/// * `caller` - 调用者地址
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回方法调用结果
|
||
pub async fn call_contract(
|
||
&self,
|
||
contract_addr: &Address,
|
||
method: &str,
|
||
args: &[u8],
|
||
caller: &Address,
|
||
) -> Result<Vec<u8>> {
|
||
self.client
|
||
.call_contract(contract_addr, method, args, caller, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::ContractError(format!("Failed to call contract: {}", e)))
|
||
}
|
||
|
||
/// 查询合约状态
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `contract_addr` - 合约地址
|
||
/// * `key` - 状态键
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回状态值
|
||
pub async fn query_contract_state(
|
||
&self,
|
||
contract_addr: &Address,
|
||
key: &[u8],
|
||
) -> Result<Vec<u8>> {
|
||
self.client
|
||
.query_state(contract_addr, key, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::ContractError(format!("Failed to query contract state: {}", e)))
|
||
}
|
||
|
||
/// 估算Gas消耗
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `tx` - 交易对象
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回预估的Gas消耗量
|
||
pub async fn estimate_gas(
|
||
&self,
|
||
tx: &Transaction,
|
||
) -> Result<u64> {
|
||
self.client
|
||
.estimate_gas(tx, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::NetworkError(format!("Failed to estimate gas: {}", e)))
|
||
}
|
||
|
||
// ===== CBPP共识 =====
|
||
|
||
/// 提交交易到交易池
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `tx` - 已签名的交易
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回交易哈希
|
||
pub async fn submit_transaction(
|
||
&self,
|
||
tx: &SignedTransaction,
|
||
) -> Result<Hash> {
|
||
self.client
|
||
.submit_transaction(tx, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::NetworkError(format!("Failed to submit transaction: {}", e)))
|
||
}
|
||
|
||
/// 获取区块(按高度)
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `block_number` - 区块高度
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回区块对象
|
||
pub async fn get_block(
|
||
&self,
|
||
block_number: u64,
|
||
) -> Result<Block> {
|
||
self.client
|
||
.get_block_by_number(block_number, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::NetworkError(format!("Failed to get block: {}", e)))
|
||
}
|
||
|
||
/// 获取区块(按哈希)
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `block_hash` - 区块哈希
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回区块对象
|
||
pub async fn get_block_by_hash(
|
||
&self,
|
||
block_hash: &Hash,
|
||
) -> Result<Block> {
|
||
self.client
|
||
.get_block_by_hash(block_hash, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::NetworkError(format!("Failed to get block by hash: {}", e)))
|
||
}
|
||
|
||
/// 获取最新区块高度
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回当前最新的区块高度
|
||
pub async fn get_latest_block_number(&self) -> Result<u64> {
|
||
self.client
|
||
.get_latest_block_number(self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::NetworkError(format!("Failed to get latest block number: {}", e)))
|
||
}
|
||
|
||
/// 获取交易收据
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `tx_hash` - 交易哈希
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回交易收据
|
||
pub async fn get_transaction_receipt(
|
||
&self,
|
||
tx_hash: &Hash,
|
||
) -> Result<TransactionReceipt> {
|
||
self.client
|
||
.get_transaction_receipt(tx_hash, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::NetworkError(format!("Failed to get transaction receipt: {}", e)))
|
||
}
|
||
|
||
/// 等待交易确认
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `tx_hash` - 交易哈希
|
||
/// * `confirmations` - 需要的确认数
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回交易收据
|
||
pub async fn wait_for_confirmation(
|
||
&self,
|
||
tx_hash: &Hash,
|
||
confirmations: u32,
|
||
) -> Result<TransactionReceipt> {
|
||
self.client
|
||
.wait_for_confirmation(tx_hash, confirmations, self.chain_id, self.timeout)
|
||
.await
|
||
.map_err(|e| NACError::NetworkError(format!("Failed to wait for confirmation: {}", e)))
|
||
}
|
||
|
||
// ===== GNACS编码系统 =====
|
||
|
||
/// 生成GNACS编码
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `asset_type` - 资产类型
|
||
/// * `jurisdiction` - 司法辖区
|
||
/// * `sub_category` - 子类别(可选)
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回GNACS编码
|
||
pub fn generate_gnacs_code(
|
||
&self,
|
||
asset_type: &str,
|
||
jurisdiction: &str,
|
||
sub_category: Option<&str>,
|
||
) -> Result<GNACSCode> {
|
||
GNACSCode::generate(asset_type, jurisdiction, sub_category)
|
||
.map_err(|e| NACError::ValidationError(format!("Failed to generate GNACS code: {}", e)))
|
||
}
|
||
|
||
/// 解析GNACS编码
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `code` - GNACS编码
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回解析后的元数据
|
||
pub fn parse_gnacs_code(
|
||
&self,
|
||
code: &GNACSCode,
|
||
) -> Result<GNACSMetadata> {
|
||
code.parse()
|
||
.map_err(|e| NACError::ValidationError(format!("Failed to parse GNACS code: {}", e)))
|
||
}
|
||
|
||
/// 验证GNACS编码
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `code` - GNACS编码
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 如果编码有效返回true,否则返回false
|
||
pub fn validate_gnacs_code(
|
||
&self,
|
||
code: &GNACSCode,
|
||
) -> bool {
|
||
code.validate()
|
||
}
|
||
|
||
// ===== ACC协议族 =====
|
||
|
||
/// 部署ACC-20代币
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `metadata` - 代币元数据
|
||
/// * `deployer` - 部署者地址
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回代币合约地址
|
||
pub async fn deploy_acc20_token(
|
||
&self,
|
||
metadata: &ACC20Metadata,
|
||
deployer: &Address,
|
||
) -> Result<Address> {
|
||
self.client
|
||
.deploy_acc20(metadata, deployer, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::ContractError(format!("Failed to deploy ACC-20 token: {}", e)))
|
||
}
|
||
|
||
/// 铸造ACC-20代币
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `token_addr` - 代币合约地址
|
||
/// * `to` - 接收者地址
|
||
/// * `amount` - 铸造数量
|
||
/// * `minter` - 铸造者地址
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回交易哈希
|
||
pub async fn mint_acc20(
|
||
&self,
|
||
token_addr: &Address,
|
||
to: &Address,
|
||
amount: Decimal,
|
||
minter: &Address,
|
||
) -> Result<Hash> {
|
||
self.client
|
||
.mint_acc20(token_addr, to, amount, minter, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::ContractError(format!("Failed to mint ACC-20: {}", e)))
|
||
}
|
||
|
||
/// 转账ACC-20代币
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `token_addr` - 代币合约地址
|
||
/// * `from` - 发送者地址
|
||
/// * `to` - 接收者地址
|
||
/// * `amount` - 转账数量
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回交易哈希
|
||
pub async fn transfer_acc20(
|
||
&self,
|
||
token_addr: &Address,
|
||
from: &Address,
|
||
to: &Address,
|
||
amount: Decimal,
|
||
) -> Result<Hash> {
|
||
self.client
|
||
.transfer_acc20(token_addr, from, to, amount, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::ContractError(format!("Failed to transfer ACC-20: {}", e)))
|
||
}
|
||
|
||
/// 查询ACC-20余额
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `token_addr` - 代币合约地址
|
||
/// * `owner` - 持有者地址
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回余额
|
||
pub async fn balance_of_acc20(
|
||
&self,
|
||
token_addr: &Address,
|
||
owner: &Address,
|
||
) -> Result<Decimal> {
|
||
self.client
|
||
.balance_of_acc20(token_addr, owner, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::ContractError(format!("Failed to query ACC-20 balance: {}", e)))
|
||
}
|
||
|
||
/// 部署ACC-1400证券型代币
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `metadata` - 证券型代币元数据
|
||
/// * `deployer` - 部署者地址
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回代币合约地址
|
||
pub async fn deploy_acc1400_token(
|
||
&self,
|
||
metadata: &ACC1400Metadata,
|
||
deployer: &Address,
|
||
) -> Result<Address> {
|
||
self.client
|
||
.deploy_acc1400(metadata, deployer, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::ContractError(format!("Failed to deploy ACC-1400 token: {}", e)))
|
||
}
|
||
|
||
/// 铸造XTZH稳定币
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `amount` - 铸造数量
|
||
/// * `collateral_proof` - 抵押证明
|
||
/// * `minter` - 铸造者地址
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回交易哈希
|
||
pub async fn mint_xtzh(
|
||
&self,
|
||
amount: Decimal,
|
||
collateral_proof: &CollateralProof,
|
||
minter: &Address,
|
||
) -> Result<Hash> {
|
||
self.client
|
||
.mint_xtzh(amount, collateral_proof, minter, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::ContractError(format!("Failed to mint XTZH: {}", e)))
|
||
}
|
||
|
||
/// 查询XTZH余额
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `owner` - 持有者地址
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回XTZH余额
|
||
pub async fn balance_of_xtzh(
|
||
&self,
|
||
owner: &Address,
|
||
) -> Result<Decimal> {
|
||
self.client
|
||
.balance_of_xtzh(owner, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::ContractError(format!("Failed to query XTZH balance: {}", e)))
|
||
}
|
||
|
||
/// 查询SDR汇率
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回当前SDR汇率
|
||
pub async fn get_sdr_rate(&self) -> Result<Decimal> {
|
||
self.client
|
||
.get_sdr_rate(self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::NetworkError(format!("Failed to get SDR rate: {}", e)))
|
||
}
|
||
|
||
// ===== 跨分片交易 =====
|
||
|
||
/// 提交跨分片交易
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `tx` - 已签名的交易
|
||
/// * `target_shard` - 目标分片ID
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回交易哈希
|
||
pub async fn submit_cross_shard_transaction(
|
||
&self,
|
||
tx: &SignedTransaction,
|
||
target_shard: u32,
|
||
) -> Result<Hash> {
|
||
self.client
|
||
.submit_cross_shard_tx(tx, target_shard, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::NetworkError(format!("Failed to submit cross-shard transaction: {}", e)))
|
||
}
|
||
|
||
/// 查询跨分片交易状态
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `tx_hash` - 交易哈希
|
||
///
|
||
/// # 返回
|
||
///
|
||
/// 返回跨分片交易状态
|
||
pub async fn get_cross_shard_status(
|
||
&self,
|
||
tx_hash: &Hash,
|
||
) -> Result<CrossShardStatus> {
|
||
self.client
|
||
.get_cross_shard_status(tx_hash, self.chain_id)
|
||
.await
|
||
.map_err(|e| NACError::NetworkError(format!("Failed to get cross-shard status: {}", e)))
|
||
}
|
||
}
|