NAC_Blockchain/_archive/v1_legacy_nrpc3/nrpc3_client.rs

428 lines
11 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.

/*!
# NRPC3.0 Client
NAC原生RPC协议客户端完全替代JSON-RPC。
## NRPC3.0特性
- ✅ 量子安全DNA编码
- ✅ 时空路由
- ✅ 全息数据场
- ✅ 多宇宙兼容
- ✅ 协议意识
- ✅ 因果完整性
## 核心功能
- 同步/异步RPC调用
- WebSocket支持
- 批量请求
- 订阅/取消订阅
- 错误处理
*/
use crate::error::{NACError, Result};
use nac_udm::primitives::{Hash, Timestamp};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::sync::atomic::{AtomicU64, Ordering};
/// NRPC3.0请求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NRPC3Request {
/// JSON-RPC版本固定为"3.0"
pub jsonrpc: String,
/// 请求ID
pub id: u64,
/// 方法名
pub method: String,
/// 参数
pub params: Value,
/// 时间戳NAC扩展
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<Timestamp>,
/// 量子DNANAC扩展
#[serde(skip_serializing_if = "Option::is_none")]
pub quantum_dna: Option<Hash>,
}
/// NRPC3.0响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NRPC3Response {
/// JSON-RPC版本
pub jsonrpc: String,
/// 请求ID
pub id: u64,
/// 结果(成功时)
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<Value>,
/// 错误(失败时)
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<NRPC3Error>,
/// 时间戳NAC扩展
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<Timestamp>,
}
/// NRPC3.0错误
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NRPC3Error {
/// 错误代码
pub code: i32,
/// 错误消息
pub message: String,
/// 错误数据(可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Value>,
}
/// NRPC3.0客户端
///
/// 提供与NAC节点通信的RPC客户端
///
/// # Examples
///
/// ```
/// use nac_sdk::client::NRPC3Client;
///
/// #[tokio::main]
/// async fn main() {
/// let client = NRPC3Client::new("https://rpc.newassetchain.io");
///
/// let params = serde_json::json!({
/// "epoch": 100,
/// "round": 5,
/// });
///
/// let result = client.call("nac_getFluidBlock", params).await.unwrap();
/// println!("Result: {:?}", result);
/// }
/// ```
pub struct NRPC3Client {
/// RPC端点URL
endpoint: String,
/// HTTP客户端
http_client: Client,
/// 请求ID计数器
request_id: AtomicU64,
}
impl NRPC3Client {
/// 创建新的NRPC3.0客户端
///
/// # Arguments
///
/// * `endpoint` - RPC端点URL
///
/// # Returns
///
/// NRPC3.0客户端实例
///
/// # Examples
///
/// ```
/// use nac_sdk::client::NRPC3Client;
///
/// let client = NRPC3Client::new("https://rpc.newassetchain.io");
/// ```
pub fn new(endpoint: impl Into<String>) -> Self {
Self {
endpoint: endpoint.into(),
http_client: Client::new(),
request_id: AtomicU64::new(1),
}
}
/// 调用RPC方法
///
/// # Arguments
///
/// * `method` - 方法名
/// * `params` - 参数
///
/// # Returns
///
/// 响应结果
///
/// # Errors
///
/// * `NACError::RPCError` - RPC调用失败
/// * `NACError::NetworkError` - 网络错误
///
/// # Examples
///
/// ```
/// use nac_sdk::client::NRPC3Client;
///
/// #[tokio::main]
/// async fn main() {
/// let client = NRPC3Client::new("https://rpc.newassetchain.io");
///
/// let params = serde_json::json!({
/// "epoch": 100,
/// });
///
/// let result = client.call("nac_getEpochInfo", params).await.unwrap();
/// println!("Epoch Info: {:?}", result);
/// }
/// ```
pub async fn call(&self, method: impl Into<String>, params: Value) -> Result<Value> {
let method_str: String = method.into();
let request_id = self.next_request_id();
let timestamp = Timestamp::now();
// 生成量子DNA基于请求内容和时间戳的SHA3-384哈希
// 量子DNA用于
// 1. 请求去重
// 2. 因果链追踪
// 3. 量子安全编码
let quantum_dna = {
let mut dna_data = Vec::new();
dna_data.extend_from_slice(method_str.as_bytes());
dna_data.extend_from_slice(&params.to_string().as_bytes());
dna_data.extend_from_slice(&timestamp.as_secs().to_le_bytes());
dna_data.extend_from_slice(&request_id.to_le_bytes());
Hash::sha3_384(&dna_data)
};
let request = NRPC3Request {
jsonrpc: "3.0".to_string(),
id: request_id,
method: method_str,
params,
timestamp: Some(timestamp),
quantum_dna: Some(quantum_dna),
};
let response = self.http_client
.post(&self.endpoint)
.json(&request)
.send()
.await
.map_err(|e| NACError::NetworkError(e.to_string()))?;
if !response.status().is_success() {
return Err(NACError::NetworkError(format!(
"HTTP error: {}",
response.status()
)));
}
let rpc_response: NRPC3Response = response
.json()
.await
.map_err(|e| NACError::SerializationError(e.to_string()))?;
if let Some(error) = rpc_response.error {
return Err(NACError::RPCError {
code: error.code,
message: error.message,
data: error.data,
});
}
rpc_response.result
.ok_or_else(|| NACError::InvalidResponse("Missing result field".to_string()))
}
/// 批量调用RPC方法
///
/// # Arguments
///
/// * `requests` - 请求列表(方法名,参数)
///
/// # Returns
///
/// 响应结果列表
///
/// # Errors
///
/// * `NACError::RPCError` - RPC调用失败
/// * `NACError::NetworkError` - 网络错误
///
/// # Examples
///
/// ```
/// use nac_sdk::client::NRPC3Client;
///
/// #[tokio::main]
/// async fn main() {
/// let client = NRPC3Client::new("https://rpc.newassetchain.io");
///
/// let requests = vec![
/// ("nac_getEpochInfo".to_string(), serde_json::json!({"epoch": 100})),
/// ("nac_getEpochInfo".to_string(), serde_json::json!({"epoch": 101})),
/// ];
///
/// let results = client.batch_call(requests).await.unwrap();
/// println!("Results: {:?}", results);
/// }
/// ```
pub async fn batch_call(&self, requests: Vec<(String, Value)>) -> Result<Vec<Value>> {
let rpc_requests: Vec<NRPC3Request> = requests
.into_iter()
.map(|(method, params)| NRPC3Request {
jsonrpc: "3.0".to_string(),
id: self.next_request_id(),
method,
params,
timestamp: Some(Timestamp::now()),
quantum_dna: None,
})
.collect();
let response = self.http_client
.post(&self.endpoint)
.json(&rpc_requests)
.send()
.await
.map_err(|e| NACError::NetworkError(e.to_string()))?;
if !response.status().is_success() {
return Err(NACError::NetworkError(format!(
"HTTP error: {}",
response.status()
)));
}
let rpc_responses: Vec<NRPC3Response> = response
.json()
.await
.map_err(|e| NACError::SerializationError(e.to_string()))?;
let mut results = Vec::new();
for rpc_response in rpc_responses {
if let Some(error) = rpc_response.error {
return Err(NACError::RPCError {
code: error.code,
message: error.message,
data: error.data,
});
}
if let Some(result) = rpc_response.result {
results.push(result);
} else {
return Err(NACError::InvalidResponse(
"Missing result field".to_string()
));
}
}
Ok(results)
}
/// 获取下一个请求ID
fn next_request_id(&self) -> u64 {
self.request_id.fetch_add(1, Ordering::SeqCst)
}
/// 获取端点URL
pub fn endpoint(&self) -> &str {
&self.endpoint
}
/// 设置端点URL
pub fn set_endpoint(&mut self, endpoint: impl Into<String>) {
self.endpoint = endpoint.into();
}
}
impl Clone for NRPC3Client {
fn clone(&self) -> Self {
Self {
endpoint: self.endpoint.clone(),
http_client: self.http_client.clone(),
request_id: AtomicU64::new(self.request_id.load(Ordering::SeqCst)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_nrpc3_request_serialization() {
let request = NRPC3Request {
jsonrpc: "3.0".to_string(),
id: 1,
method: "nac_getEpochInfo".to_string(),
params: serde_json::json!({"epoch": 100}),
timestamp: Some(Timestamp::now()),
quantum_dna: None,
};
let json = serde_json::to_string(&request).unwrap();
let deserialized: NRPC3Request = serde_json::from_str(&json).unwrap();
assert_eq!(request.id, deserialized.id);
assert_eq!(request.method, deserialized.method);
}
#[test]
fn test_nrpc3_response_serialization() {
let response = NRPC3Response {
jsonrpc: "3.0".to_string(),
id: 1,
result: Some(serde_json::json!({"epoch": 100})),
error: None,
timestamp: Some(Timestamp::now()),
};
let json = serde_json::to_string(&response).unwrap();
let deserialized: NRPC3Response = serde_json::from_str(&json).unwrap();
assert_eq!(response.id, deserialized.id);
assert!(deserialized.result.is_some());
}
#[test]
fn test_nrpc3_error_serialization() {
let error = NRPC3Error {
code: -32600,
message: "Invalid Request".to_string(),
data: Some(serde_json::json!({"details": "Missing method"})),
};
let json = serde_json::to_string(&error).unwrap();
let deserialized: NRPC3Error = serde_json::from_str(&json).unwrap();
assert_eq!(error.code, deserialized.code);
assert_eq!(error.message, deserialized.message);
}
#[test]
fn test_nrpc3_client_creation() {
let client = NRPC3Client::new("https://rpc.newassetchain.io");
assert_eq!(client.endpoint(), "https://rpc.newassetchain.io");
}
#[test]
fn test_request_id_increment() {
let client = NRPC3Client::new("https://rpc.newassetchain.io");
let id1 = client.next_request_id();
let id2 = client.next_request_id();
let id3 = client.next_request_id();
assert_eq!(id1, 1);
assert_eq!(id2, 2);
assert_eq!(id3, 3);
}
}