NAC_Blockchain/nac-wallet-core/src/nac_lens_wrapper.rs

330 lines
9.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// NAC Lens方法包装层
// 提供高级API封装nac-sdk的NacLensClient
use nac_sdk::client::NacLensClient;
use nac_sdk::error::Result as NACResult;
use serde_json::{json, Value};
/// NAC Lens包装客户端
///
/// 提供钱包常用的RPC方法包装
pub struct NacLensWrapper {
client: NacLensClient,
}
impl NacLensWrapper {
/// 创建新的NAC Lens包装客户端
pub fn new(endpoint: impl Into<String>) -> Self {
Self {
client: NacLensClient::new(endpoint),
}
}
/// 查询余额
///
/// # Arguments
///
/// * `address` - 账户地址32字节
/// * `asset_id` - 资产ID可选默认为XTZH
///
/// # Returns
///
/// 余额u128
pub async fn get_balance(&self, address: &[u8; 32], asset_id: Option<&str>) -> NACResult<u128> {
let address_hex = hex::encode(address);
let asset = asset_id.unwrap_or("xtzh");
let params = json!({
"address": address_hex,
"asset_id": asset,
});
let result = self.client.call("nac_getBalance", params).await?;
// 解析余额
let balance_str = result.as_str()
.ok_or_else(|| nac_sdk::error::NACError::InvalidResponse("Invalid balance format".to_string()))?;
let balance = u128::from_str_radix(balance_str.trim_start_matches("0x"), 16)
.map_err(|e| nac_sdk::error::NACError::InvalidResponse(format!("Failed to parse balance: {}", e)))?;
Ok(balance)
}
/// 查询Nonce
///
/// # Arguments
///
/// * `address` - 账户地址32字节
///
/// # Returns
///
/// Nonce值u64
pub async fn get_nonce(&self, address: &[u8; 32]) -> NACResult<u64> {
let address_hex = hex::encode(address);
let params = json!({
"address": address_hex,
});
let result = self.client.call("nac_getTransactionCount", params).await?;
let nonce_str = result.as_str()
.ok_or_else(|| nac_sdk::error::NACError::InvalidResponse("Invalid nonce format".to_string()))?;
let nonce = u64::from_str_radix(nonce_str.trim_start_matches("0x"), 16)
.map_err(|e| nac_sdk::error::NACError::InvalidResponse(format!("Failed to parse nonce: {}", e)))?;
Ok(nonce)
}
/// 发送原始交易
///
/// # Arguments
///
/// * `raw_tx` - 原始交易数据(十六进制字符串)
///
/// # Returns
///
/// 交易哈希
pub async fn send_raw_transaction(&self, raw_tx: &str) -> NACResult<String> {
let params = json!({
"data": raw_tx,
});
let result = self.client.call("nac_sendRawTransaction", params).await?;
let tx_hash = result.as_str()
.ok_or_else(|| nac_sdk::error::NACError::InvalidResponse("Invalid tx hash format".to_string()))?
.to_string();
Ok(tx_hash)
}
/// 查询交易
///
/// # Arguments
///
/// * `tx_hash` - 交易哈希
///
/// # Returns
///
/// 交易详情JSON
pub async fn get_transaction(&self, tx_hash: &str) -> NACResult<Value> {
let params = json!({
"hash": tx_hash,
});
self.client.call("nac_getTransactionByHash", params).await
}
/// 查询交易收据
///
/// # Arguments
///
/// * `tx_hash` - 交易哈希
///
/// # Returns
///
/// 交易收据JSON
pub async fn get_transaction_receipt(&self, tx_hash: &str) -> NACResult<Value> {
let params = json!({
"hash": tx_hash,
});
self.client.call("nac_getTransactionReceipt", params).await
}
/// 查询当前区块号
///
/// # Returns
///
/// 区块号u64
pub async fn get_block_number(&self) -> NACResult<u64> {
let params = json!({});
let result = self.client.call("nac_blockNumber", params).await?;
let block_str = result.as_str()
.ok_or_else(|| nac_sdk::error::NACError::InvalidResponse("Invalid block number format".to_string()))?;
let block_number = u64::from_str_radix(block_str.trim_start_matches("0x"), 16)
.map_err(|e| nac_sdk::error::NACError::InvalidResponse(format!("Failed to parse block number: {}", e)))?;
Ok(block_number)
}
/// 查询区块
///
/// # Arguments
///
/// * `block_number` - 区块号
/// * `full_transactions` - 是否包含完整交易
///
/// # Returns
///
/// 区块详情JSON
pub async fn get_block(&self, block_number: u64, full_transactions: bool) -> NACResult<Value> {
let block_hex = format!("0x{:x}", block_number);
let params = json!({
"block": block_hex,
"full": full_transactions,
});
self.client.call("nac_getBlockByNumber", params).await
}
/// 估算Gas
///
/// # Arguments
///
/// * `from` - 发送方地址
/// * `to` - 接收方地址(可选)
/// * `value` - 转账金额
/// * `data` - 交易数据(可选)
///
/// # Returns
///
/// Gas估算值u64
pub async fn estimate_gas(
&self,
from: &[u8; 32],
to: Option<&[u8; 32]>,
value: u128,
data: Option<&str>,
) -> NACResult<u64> {
let from_hex = hex::encode(from);
let to_hex = to.map(|addr| hex::encode(addr));
let value_hex = format!("0x{:x}", value);
let mut params_obj = json!({
"from": from_hex,
"value": value_hex,
});
if let Some(to_addr) = to_hex {
params_obj["to"] = json!(to_addr);
}
if let Some(tx_data) = data {
params_obj["data"] = json!(tx_data);
}
let params = json!([params_obj]);
let result = self.client.call("nac_estimateGas", params).await?;
let gas_str = result.as_str()
.ok_or_else(|| nac_sdk::error::NACError::InvalidResponse("Invalid gas format".to_string()))?;
let gas = u64::from_str_radix(gas_str.trim_start_matches("0x"), 16)
.map_err(|e| nac_sdk::error::NACError::InvalidResponse(format!("Failed to parse gas: {}", e)))?;
Ok(gas)
}
/// 查询Gas价格
///
/// # Returns
///
/// Gas价格u64
pub async fn get_gas_price(&self) -> NACResult<u64> {
let params = json!({});
let result = self.client.call("nac_gasPrice", params).await?;
let price_str = result.as_str()
.ok_or_else(|| nac_sdk::error::NACError::InvalidResponse("Invalid gas price format".to_string()))?;
let price = u64::from_str_radix(price_str.trim_start_matches("0x"), 16)
.map_err(|e| nac_sdk::error::NACError::InvalidResponse(format!("Failed to parse gas price: {}", e)))?;
Ok(price)
}
/// 查询链ID
///
/// # Returns
///
/// 链IDu64
pub async fn get_chain_id(&self) -> NACResult<u64> {
let params = json!({});
let result = self.client.call("nac_chainId", params).await?;
let chain_id_str = result.as_str()
.ok_or_else(|| nac_sdk::error::NACError::InvalidResponse("Invalid chain ID format".to_string()))?;
let chain_id = u64::from_str_radix(chain_id_str.trim_start_matches("0x"), 16)
.map_err(|e| nac_sdk::error::NACError::InvalidResponse(format!("Failed to parse chain ID: {}", e)))?;
Ok(chain_id)
}
/// 等待交易确认
///
/// # Arguments
///
/// * `tx_hash` - 交易哈希
/// * `confirmations` - 需要的确认数
/// * `timeout_secs` - 超时时间(秒)
///
/// # Returns
///
/// 交易收据JSON
pub async fn wait_for_confirmation(
&self,
tx_hash: &str,
confirmations: u64,
timeout_secs: u64,
) -> NACResult<Value> {
use tokio::time::{sleep, Duration};
let start = std::time::Instant::now();
let timeout = Duration::from_secs(timeout_secs);
loop {
if start.elapsed() > timeout {
return Err(nac_sdk::error::NACError::Timeout(format!(
"Transaction {} not confirmed after {} seconds",
tx_hash, timeout_secs
)));
}
// 查询交易收据
match self.get_transaction_receipt(tx_hash).await {
Ok(receipt) => {
// 检查确认数
if let Some(block_number) = receipt.get("blockNumber").and_then(|v| v.as_str()) {
let tx_block = u64::from_str_radix(block_number.trim_start_matches("0x"), 16)
.unwrap_or(0);
let current_block = self.get_block_number().await?;
if current_block >= tx_block + confirmations {
return Ok(receipt);
}
}
}
Err(_) => {
// 交易还未被打包,继续等待
}
}
sleep(Duration::from_secs(2)).await;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_nac_lens_wrapper_creation() {
let wrapper = NacLensWrapper::new("https://rpc.newassetchain.io");
assert!(true); // 创建成功
}
}