Rust NEAR协议JSON-RPC基础库near-jsonrpc-primitives的使用,实现区块链节点交互与数据查询
Rust NEAR协议JSON-RPC基础库near-jsonrpc-primitives的使用,实现区块链节点交互与数据查询
安装
在项目目录中运行以下Cargo命令:
cargo add near-jsonrpc-primitives
或者在Cargo.toml中添加以下行:
near-jsonrpc-primitives = "0.30.3"
基本使用示例
以下是一个使用near-jsonrpc-primitives库与NEAR区块链节点交互的完整示例:
use near_jsonrpc_primitives::types::query::RpcQueryRequest;
use near_jsonrpc_client::{methods, JsonRpcClient};
use near_primitives::types::{AccountId, BlockReference};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建JSON-RPC客户端连接NEAR主网节点
let client = JsonRpcClient::connect("https://rpc.mainnet.near.org");
// 示例1: 查询区块状态
let block_request = methods::block::RpcBlockRequest {
block_reference: BlockReference::latest(),
};
let block_response = client.call(block_request).await?;
println!("Latest block height: {}", block_response.header.height);
// 示例2: 查询账户信息
let account_id: AccountId = "example.near".parse()?;
let account_request = methods::query::RpcQueryRequest {
block_reference: BlockReference::latest(),
request: RpcQueryRequest::ViewAccount {
account_id: account_id.clone(),
},
};
let account_response = client.call(account_request).await?;
if let methods::query::RpcQueryResponse::ViewAccount(result) = account_response {
println!("Account {} balance: {} yoctoNEAR", account_id, result.amount);
}
// 示例3: 查询合约状态
let contract_id: AccountId = "guest-book.near".parse()?;
let contract_request = methods::query::RpcQueryRequest {
block_reference: BlockReference::latest(),
request: RpcQueryRequest::ViewState {
account_id: contract_id.clone(),
prefix: near_primitives::types::StoreKey::from(vec![]),
},
};
let contract_response = client.call(contract_request).await?;
if let methods::query::RpcQueryResponse::ViewState(result) = contract_response {
println!("Contract {} state size: {}", contract_id, result.values.len());
}
Ok(())
}
完整示例扩展
以下是一个更完整的示例,展示了更多功能:
use near_jsonrpc_primitives::types::query::RpcQueryRequest;
use near_jsonrpc_client::{methods, JsonRpcClient};
use near_primitives::types::{AccountId, BlockReference, Finality};
use near_primitives::views::QueryRequest;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 连接到测试网节点
let client = JsonRpcClient::connect("https://rpc.testnet.near.org");
// 1. 查询最新区块
let block_request = methods::block::RpcBlockRequest {
block_reference: BlockReference::Finality(Finality::Final),
};
let block = client.call(block_request).await?;
println!("Final block height: {}", block.header.height);
// 2. 查询账户详情
let account_id: AccountId = "test.near".parse()?;
let account_query = methods::query::RpcQueryRequest {
block_reference: BlockReference::latest(),
request: RpcQueryRequest::ViewAccount {
account_id: account_id.clone(),
},
};
let account = client.call(account_query).await?;
// 3. 查询合约方法
let contract_id: AccountId = "demo.testnet".parse()?;
let method_query = methods::query::RpcQueryRequest {
block_reference: BlockReference::latest(),
request: RpcQueryRequest::CallFunction {
account_id: contract_id.clone(),
method_name: "get_value".to_string(),
args: near_primitives::types::FunctionArgs::from(vec![]),
},
};
let method_response = client.call(method_query).await?;
// 4. 查询交易状态
let tx_hash = "9FtHUFBQs9...".to_string(); // 替换为实际交易哈希
let tx_status = methods::tx::RpcTransactionStatusRequest {
transaction_info: near_jsonrpc_primitives::types::transactions::TransactionInfo::TransactionId {
hash: tx_hash.parse()?,
account_id: "sender.testnet".parse()?,
},
};
let tx_result = client.call(tx_status).await?;
Ok(())
}
功能说明
-
区块查询:通过
methods::block::RpcBlockRequest
可以查询区块链的最新区块或指定区块的信息。 -
账户查询:使用
RpcQueryRequest::ViewAccount
可以查询NEAR账户的余额、合约代码等信息。 -
合约状态查询:通过
RpcQueryRequest::ViewState
可以查询合约的存储状态。 -
合约方法调用:使用
RpcQueryRequest::CallFunction
可以调用合约的只读方法。 -
交易查询:通过
methods::tx::RpcTransactionStatusRequest
可以查询交易状态。
注意事项
- 需要异步运行时(如tokio)来执行RPC调用
- 所有RPC方法都返回
Result
类型,需要处理可能的错误 - 对于主网查询,建议使用公共RPC节点或自己运行的节点
- 查询响应需要匹配相应的枚举变体来获取具体数据
许可证
该库采用MIT或Apache-2.0双重许可。
1 回复
Rust NEAR协议JSON-RPC基础库near-jsonrpc-primitives使用指南
near-jsonrpc-primitives
是一个用于与NEAR区块链节点交互的Rust库,它提供了JSON-RPC客户端功能,可以查询区块链数据、发送交易等操作。
安装方法
在Cargo.toml中添加依赖:
[dependencies]
near-jsonrpc-primitives = "0.1.0"
serde_json = "1.0"
tokio = { version = "1.0", features = ["full"] }
基本使用方法
1. 创建客户端连接
use near_jsonrpc_primitives::client::Client;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("https://rpc.mainnet.near.org");
// 使用客户端进行各种查询...
Ok(())
}
2. 查询区块信息
use near_jsonrpc_primitives::types::blocks::RpcBlockRequest;
async fn get_block(client: &Client, block_id: u64) {
let request = RpcBlockRequest {
block_id: block_id.into(),
};
match client.block(request).await {
Ok(response) => println!("Block info: {:?}", response),
Err(e) => eprintln!("Error getting block: {}", e),
}
}
3. 查询账户信息
use near_jsonrpc_primitives::types::account::RpcAccountViewRequest;
async fn get_account_info(client: &Client, account_id: &str) {
let request = RpcAccountViewRequest {
account_id: account_id.parse().unwrap(),
};
match client.account_view(request).await {
Ok(response) => println!("Account info: {:?}", response),
Err(e) => eprintln!("Error getting account info: {}", e),
}
}
4. 查询交易状态
use near_jsonrpc_primitives::types::transactions::RpcTransactionStatusRequest;
use near_primitives::transaction::Transaction;
async fn get_transaction_status(client: &Client, transaction: Transaction) {
let request = RpcTransactionStatusRequest {
transaction,
};
match client.transaction_status(request).await {
Ok(response) => println!("Transaction status: {:?}", response),
Err(e) => eprintln!("Error getting transaction status: {}", e),
}
}
高级用法
批量请求
use near_jsonrpc_primitives::client::BatchClient;
use near_jsonrpc_primitives::types::blocks::RpcBlockRequest;
async fn batch_request(client: &Client) {
let batch_client = BatchClient::new(client);
let requests = vec![
RpcBlockRequest { block_id: 极好的.into() }.into(),
RpcBlockRequest { block_id: 2.into() }.into(),
];
match batch_client.batch(requests).await {
Ok(responses) => {
for response in responses {
println!("Batch response: {:?}", response);
}
}
Err(e) => eprintln!("Batch request failed: {}", e),
}
}
自定义请求
use near_jsonrpc_primitives::client::Method;
use serde_json::json;
async fn custom_request(client: &Client) {
let method = Method::Query("query".to_string());
let params = json!({
"request_type": "call_function",
"account_id": "contract.near",
"method_name": "get_info",
"args_base64": "",
"finality": "optimistic"
});
match client.call(method, params).await {
Ok(response) => println!("Custom response: {:?}", response),
Err(e) => eprintln!("Custom request failed: {}", e),
}
}
错误处理
use near_jsonrpc_primitives::errors极好的::RpcError;
async fn handle_errors(client: &Client) {
match client.block(RpcBlockRequest { block_id: 9999999.into() }).await {
Ok(response) => println!("Got block: {:?}", response),
Err(RpcError::ServerError(code, message)) => {
eprintln!("Server error ({}): {}", code, message);
}
Err(RpcError::TransportError(e)) => {
eprintln!("Network error: {}", e);
}
Err(e) => {
eprintln!("Other error: {}", e);
}
}
}
完整示例代码
use near_jsonrpc_primitives::{
client::{Client, BatchClient},
types::{
blocks::RpcBlockRequest,
account::RpcAccountViewRequest,
transactions::RpcTransactionStatusRequest
},
errors::RpcError
};
use near_primitives::transaction::Transaction;
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 创建客户端连接
let client = Client::new("https://rpc.testnet.near.org");
// 2. 查询区块信息
get_block(&client, 1).await;
// 3. 查询账户信息
get_account_info(&client, "example.testnet").await;
// 4. 批量请求示例
batch_request(&client).await;
// 5. 错误处理示例
handle_errors(&client).await;
Ok(())
}
async fn get_block(client: &Client, block_id: u64) {
println!("\n--- 查询区块信息 ---");
let request = RpcBlockRequest {
block_id: block_id.into(),
};
match client.block(request).await {
Ok(response) => println!("区块信息: {:#?}", response),
Err(e) => eprintln!("查询区块错误: {}", e),
}
}
async fn get_account_info(client: &Client, account_id: &str) {
println!("\n--- 查询账户信息 ---");
let request = RpcAccountViewRequest {
account_id: account_id.parse().unwrap(),
};
match client.account_view(request).await {
Ok(response) => println!("账户信息: {:#?}", response),
Err(e) => eprintln!("查询账户错误: {}", e),
}
}
async fn batch_request(client: &Client) {
println!("\n--- 批量请求示例 ---");
let batch_client = BatchClient::new(client);
let requests = vec![
RpcBlockRequest { block_id: 1.into() }.into(),
RpcBlockRequest { block_id: 2.into() }.into(),
];
match batch_client.batch(requests).await {
Ok(responses) => {
for (i, response) in responses.iter().enumerate() {
println!("批量响应 {}: {:#?}", i+1, response);
}
}
Err(e) => eprintln!("批量请求失败: {}", e),
}
}
async fn handle_errors(client: &Client) {
println!("\n--- 错误处理示例 ---");
match client.block(RpcBlockRequest { block_id: 9999999.into() }).await {
Ok(response) => println!("获取区块成功: {:?}", response),
Err(RpcError::ServerError(code, message)) => {
eprintln!("服务器错误 ({}): {}", code, message);
}
Err(RpcError::TransportError(e)) => {
eprintln!("网络错误: {}", e);
}
Err(e) => {
eprintln!("其他错误: {}", e);
}
}
}
注意事项
- 所有API调用都是异步的,需要使用async/await
- 生产环境中应该添加适当的重试逻辑和错误处理
- 对于频繁查询,考虑使用NEAR Indexer框架获取更高效的数据访问
- 主网和测试网的RPC端点不同:
- 主网:
https://rpc.mainnet.near.org
- 测试网:
https://rpc.testnet.near.org
- 主网:
这个库提供了与NEAR区块链交互的基础功能,适合需要直接与NEAR节点通信的应用场景。