Rust NEAR RPC错误处理宏库near-rpc-error-macro的使用,简化区块链RPC调用错误处理流程

Rust NEAR RPC错误处理宏库near-rpc-error-macro的使用,简化区块链RPC调用错误处理流程

安装

在项目目录中运行以下Cargo命令:

cargo add near-rpc-error-macro

或者在Cargo.toml中添加以下行:

near-rpc-error-macro = "0.26.0"

使用示例

near-rpc-error-macro是一个用于简化NEAR区块链RPC调用错误处理的宏库。它提供了一些宏来简化错误处理和RPC响应处理。

以下是一个完整的使用示例:

use near_jsonrpc_primitives::errors::RpcError;
use near_rpc_error_macro::rpc_error;

// 使用宏定义RPC错误类型
#[rpc_error]
pub enum MyRpcError {
    /// 当请求参数无效时返回
    InvalidParams,
    /// 当内部服务器错误发生时返回
    InternalError,
    /// 当请求超时时返回
    RequestTimeout,
}

fn handle_rpc_response(result: Result<String, RpcError>) -> Result<String, MyRpcError> {
    match result {
        Ok(response) => Ok(response),
        Err(e) => {
            // 使用宏生成的转换方法
            MyRpcError::from_rpc_error(e)
                .map_err(|e| {
                    // 处理无法转换的RPC错误
                    log::error!("Unhandled RPC error: {:?}", e);
                    MyRpcError::InternalError
                })
        }
    }
}

#[tokio::main]
async fn main() {
    let rpc_client = near_jsonrpc_client::JsonRpcClient::connect("https://rpc.testnet.near.org");
    
    let request = near_jsonrpc_client::methods::block::RpcBlockRequest {
        block_id: near_primitives::types::BlockId::latest(),
    };
    
    let result = rpc_client.call(request).await;
    
    match handle_rpc_response(result) {
        Ok(block) => println!("Got block: {:?}", block),
        Err(MyRpcError::InvalidParams) => println!("Invalid parameters provided"),
        Err(MyRpcError::RequestTimeout) => println!("Request timed out"),
        Err(MyRpcError::InternalError) => println!("Internal server error occurred"),
    }
}

主要特性

  1. #[rpc_error]宏自动为枚举生成RPC错误转换实现
  2. 简化了NEAR RPC错误处理流程
  3. 提供了清晰的错误分类和匹配
  4. 自动生成错误文档

错误处理

使用该宏库时,可以轻松地将原始RPC错误转换为自定义的错误类型,从而在应用程序中提供更清晰的错误处理路径。

许可证

该库采用MIT或Apache-2.0许可证。

完整示例代码

use near_jsonrpc_primitives::errors::RpcError;
use near_rpc_error_macro::rpc_error;
use serde_json::Value;

// 自定义RPC错误枚举
#[rpc_error]
pub enum CustomRpcError {
    /// 无效参数错误
    InvalidParams,
    /// 内部服务器错误
    InternalError,
    /// 请求超时错误
    RequestTimeout,
    /// 找不到区块错误
    BlockNotFound,
}

// 处理RPC响应函数
async fn fetch_block_data(
    client: &near_jsonrpc_client::JsonRpcClient,
    block_id: near_primitives::types::BlockId,
) -> Result<Value, CustomRpcError> {
    let request = near_jsonrpc_client::methods::block::RpcBlockRequest {
        block_id,
    };
    
    // 调用RPC并处理响应
    let result = client.call(request).await;
    
    match result {
        Ok(response) => Ok(response),
        Err(e) => {
            // 将RPC错误转换为自定义错误类型
            CustomRpcError::from_rpc_error(e)
                .map_err(|e| {
                    log::warn!("Unmapped RPC error: {:?}", e);
                    CustomRpcError::InternalError
                })
        }
    }
}

#[tokio::main]
async fn main() {
    // 初始化RPC客户端
    let rpc_client = near_jsonrpc_client::JsonRpcClient::connect("https://rpc.testnet.near.org");
    
    // 获取最新区块数据
    match fetch_block_data(&rpc_client, near_primitives::types::BlockId::latest()).await {
        Ok(block_data) => {
            println!("Successfully fetched block data: {:#?}", block_data);
        }
        Err(CustomRpcError::InvalidParams) => {
            eprintln!("Error: Invalid parameters provided");
        }
        Err(CustomRpcError::RequestTimeout) => {
            eprintln!("Error: Request timed out");
        }
        Err(CustomRpcError::BlockNotFound) => {
            eprintln!("Error: Requested block not found");
        }
        Err(CustomRpcError::InternalError) => {
            eprintln!("Error: Internal server error occurred");
        }
    }
}

这个完整示例展示了如何:

  1. 定义自定义RPC错误类型
  2. 创建RPC客户端
  3. 发起区块数据请求
  4. 处理RPC响应和错误
  5. 使用宏生成的错误转换功能

代码中包含了详细的注释,帮助理解每个步骤的作用。


1 回复

Rust NEAR RPC错误处理宏库near-rpc-error-macro使用指南

介绍

near-rpc-error-macro是一个用于简化NEAR区块链RPC调用错误处理的Rust宏库。它通过提供声明式宏来自动化常见的错误处理模式,减少样板代码,使开发者能更专注于业务逻辑而非错误处理。

主要特性

  • 自动将NEAR RPC错误转换为自定义错误类型
  • 简化错误传播和转换
  • 提供统一的错误处理接口
  • 减少重复的错误匹配代码

安装

在Cargo.toml中添加依赖:

[dependencies]
near-rpc-error-macro = "0.1"  # 请使用最新版本
thiserror = "1.0"  # 必须添加
near-jsonrpc-client = "0.6"  # 需要同时添加

完整示例代码

use near_jsonrpc_client::JsonRpcClient;
use near_primitives::types::AccountId;
use near_rpc_error_macro::rpc_error;
use thiserror::Error;

// 1. 定义自定义错误类型
#[rpc_error]
#[derive(Debug, Error)]
pub enum MyAppError {
    #[error("Network error: {0}")]
    Network(String),
    
    #[error("Account {0} not found")]
    AccountNotFound(String),
    
    #[error("Transaction failed")]
    TransactionFailed,
    
    #[map_error(code = -32000, message = "Server error")]
    ServerError,
    
    #[map_error(code = -32602, message = "Invalid params")]
    InvalidParams,
}

// 2. 实现转账功能
async fn transfer_tokens(
    client: &JsonRpcClient,
    sender: &AccountId,
    receiver: &AccountId,
    amount: u128,
) -> Result<(), MyAppError> {
    // 创建转账交易
    let tx = create_transfer_tx(sender, receiver, amount)
        .map_err(|e| MyAppError::Network(e.to_string()))?;
    
    // 发送交易
    let tx_result = rpc_try!(
        client
            .call(near_jsonrpc_client::methods::broadcast_tx_async::RpcBroadcastTxAsyncRequest {
                signed_transaction: tx,
            })
            .await
    );
    
    // 检查交易状态
    let receipt = rpc_try!(
        client
            .call(near_jsonrpc_client::methods::tx::RpcTransactionStatusRequest {
                transaction_info: near_jsonrpc_client::methods::tx::TransactionInfo::TransactionId {
                    hash: tx_result.transaction.hash,
                    sender_account_id: sender.clone(),
                },
            })
            .await
    );
    
    if !receipt.status.is_success() {
        return Err(MyAppError::TransactionFailed);
    }
    
    Ok(())
}

// 3. 查询账户余额
async fn get_balance(
    client: &JsonRpcClient,
    account_id: &AccountId,
) -> Result<u128, MyAppError> {
    let response = rpc_try!(
        client
            .call(near_jsonrpc_client::methods::query::RpcQueryRequest {
                block_reference: near_primitives::types::Finality::Final.into(),
                request: near_primitives::views::QueryRequest::ViewAccount {
                    account_id: account_id.clone(),
                },
            })
            .await
    );
    
    Ok(response.amount)
}

// 辅助函数 - 创建转账交易
fn create_transfer_tx(
    sender: &AccountId,
    receiver: &AccountId,
    amount: u128,
) -> Result<near_primitives::transaction::SignedTransaction, Box<dyn std::error::Error>> {
    // 这里实现创建交易的逻辑
    // 返回SignedTransaction或错误
    unimplemented!()
}

#[tokio::main]
async fn main() {
    let client = JsonRpcClient::connect("https://rpc.testnet.near.org");
    let sender: AccountId = "sender.testnet".parse().unwrap();
    let receiver: AccountId = "receiver.testnet".parse().unwrap();
    
    match get_balance(&client, &sender).await {
        Ok(balance) => println!("Sender balance: {}", balance),
        Err(e) => eprintln!("Error getting balance: {}", e),
    }
    
    match transfer_tokens(&client, &sender, &receiver, 1_000_000).await {
        Ok(_) => println!("Transfer succeeded"),
        Err(e) => eprintln!("Transfer failed: {}", e),
    }
}

代码说明

  1. 错误定义

    • 使用#[rpc_error]宏自动实现RPC错误转换
    • 使用#[map_error]属性映射特定错误码
    • 结合thiserror提供友好的错误信息
  2. RPC调用

    • rpc_try!宏自动处理RPC错误并转换为自定义错误类型
    • 简化错误传播,减少样板代码
  3. 完整流程

    • 包含账户余额查询
    • 转账交易发送
    • 交易状态检查
    • 统一的错误处理

注意事项

  1. 确保添加所有必要的依赖项
  2. 对于生产环境,需要实现完整的交易创建逻辑
  3. 根据实际需求调整错误类型和映射关系

这个完整示例展示了如何使用near-rpc-error-macro处理NEAR区块链RPC调用的完整流程,包括错误定义、RPC调用和错误处理。

回到顶部