Rust IC开发工具包ic-cdk-executor的使用:简化DFINITY Canister智能合约执行与交互
ic-cdk-executor = “1.0.2”
use ic_cdk::api::call::CallResult;
use ic_cdk_executor::canister_call;
// 定义Canister ID和要调用的方法
const TARGET_CANISTER_ID: &str = "ryjl3-tyaaa-aaaaa-aaaba-cai"; // 示例Canister ID
#[ic_cdk::update]
async fn execute_canister_call() -> CallResult<()> {
// 使用ic-cdk-executor执行Canister调用
let result: CallResult<(String,)> = canister_call(
TARGET_CANISTER_ID,
"greet",
("World",),
).await;
match result {
Ok((response,)) => {
ic_cdk::println!("Received response: {}", response);
Ok(())
}
Err(error) => {
ic_cdk::println!("Error calling canister: {:?}", error);
Err(error)
}
}
}
完整示例demo:
// Cargo.toml依赖
// [dependencies]
// ic-cdk = "0.12.0"
// ic-cdk-executor = "1.0.2"
use ic_cdk::api::call::CallResult;
use ic_cdk_executor::canister_call;
use serde::{Deserialize, Serialize};
// 目标Canister ID
const LEDGER_CANISTER_ID: &str = "ryjl3-tyaaa-aaaaa-aaaba-cai";
// 账户余额查询数据结构
#[derive(Serialize, Deserialize)]
struct AccountBalanceArgs {
account: Vec<u8>,
}
#[ic_cdk::update]
async fn get_account_balance(account: Vec<u8>) -> CallResult<u64> {
// 准备调用参数
let args = AccountBalanceArgs { account };
// 使用ic-cdk-executor执行Canister调用
let result: CallResult<(u64,)> = canister_call(
LEDGER_CANISTER_ID,
"account_balance",
(args,),
).await;
match result {
Ok((balance,)) => {
ic_cdk::println!("Account balance: {}", balance);
Ok(balance)
}
Err(error) => {
ic_cdk::println!("Error getting account balance: {:?}", error);
Err(error)
}
}
}
#[ic_cdk::update]
async fn transfer_tokens(to_account: Vec<u8>, amount: u64) -> CallResult<()> {
// 转账调用示例
let result: CallResult<()> = canister_call(
LEDGER_CANISTER_ID,
"transfer",
(to_account, amount),
).await;
match result {
Ok(_) => {
ic_cdk::println!("Transfer successful");
Ok(())
}
Err(error) => {
ic_cdk::println!("Transfer failed: {:?}", error);
Err(error)
}
}
}
// Canister初始化
#[ic_cdk::init]
fn init() {
ic_cdk::println!("Canister initialized with ic-cdk-executor");
}
// 查询方法示例
#[ic_cdk::query]
fn get_version() -> String {
"1.0.0".to_string()
}
1 回复
Rust IC开发工具包ic-cdk-executor的使用指南
简介
ic-cdk-executor是专为DFINITY互联网计算机(IC)生态系统设计的Rust工具包,旨在简化Canister智能合约的执行与交互过程。该工具包提供了高级抽象接口,帮助开发者更高效地构建和管理去中心化应用。
主要功能
- 简化Canister智能合约的调用和执行
- 提供类型安全的接口封装
- 支持异步操作和错误处理
- 优化与IC网络的交互性能
安装方法
在Cargo.toml中添加依赖:
[dependencies]
ic-cdk-executor = "0.8"
基本使用方法
1. 初始化执行器
use ic_cdk_executor::Executor;
let executor = Executor::new();
2. 调用Canister方法
use candid::{Encode, Decode};
use ic_cdk::api::call::CallResult;
async fn call_canister_method() -> CallResult<()> {
let canister_id = Principal::from_text("rrkah-fqaaa-aaaaa-aaaaq-cai").unwrap();
let result: CallResult<(String,)> = executor
.execute_call(
canister_id,
"greet",
Encode!(&"World").unwrap()
)
.await;
match result {
Ok((response,)) => {
println!("Received: {}", response);
Ok(())
}
Err(err) => {
eprintln!("Call failed: {:?}", err);
Err(err)
}
}
}
3. 批量执行调用
async fn batch_calls() {
let calls = vec![
// 多个canister调用任务
];
let results = executor.execute_batch(calls).await;
for result in results {
// 处理每个调用的结果
}
}
高级功能示例
错误处理和重试机制
use ic_cdk_executor::RetryPolicy;
let executor = Executor::new()
.with_retry_policy(RetryPolicy::exponential_backoff(3, 1000));
自定义超时设置
use std::time::Duration;
let executor = Executor::new()
.with_timeout(Duration::from_secs(30));
完整示例demo
use candid::{Encode, Decode, Principal};
use ic_cdk::api::call::CallResult;
use ic_cdk_executor::{Executor, RetryPolicy};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 初始化执行器,配置重试策略和超时
let executor = Executor::new()
.with_retry_policy(RetryPolicy::exponential_backoff(3, 1000))
.with_timeout(Duration::from_secs(30));
// 示例Canister ID(请替换为实际ID)
let canister_id = Principal::from_text("rrkah-fqaaa-aaaaa-aaaaq-cai").unwrap();
// 单个Canister方法调用示例
match call_greet_method(&executor, canister_id).await {
Ok(_) => println!("Greet call successful"),
Err(e) => eprintln!("Greet call failed: {:?}", e),
}
// 批量调用示例
batch_calls_example(&executor).await;
Ok(())
}
// 调用greet方法示例
async fn call_greet_method(executor: &Executor, canister_id: Principal) -> CallResult<()> {
let result: CallResult<(String,)> = executor
.execute_call(
canister_id,
"greet",
Encode!(&"World").unwrap()
)
.await;
match result {
Ok((response,)) => {
println!("Received: {}", response);
Ok(())
}
Err(err) => {
eprintln!("Call failed: {:?}", err);
Err(err)
}
}
}
// 批量调用示例
async fn batch_calls_example(executor: &Executor) {
// 创建多个调用任务(示例)
let calls = vec![
// 这里可以添加多个execute_call调用
// 实际使用时需要具体的canister_id、方法名和参数
];
// 执行批量调用
let results = executor.execute_batch(calls).await;
// 处理每个调用的结果
for (index, result) in results.iter().enumerate() {
match result {
Ok(response) => {
println!("Call {} succeeded: {:?}", index, response);
}
Err(error) => {
eprintln!("Call {} failed: {:?}", index, error);
}
}
}
}
最佳实践
- 合理设置重试策略以避免网络拥堵
- 使用类型安全的接口减少运行时错误
- 适当配置超时时间以适应不同的网络条件
- 实现适当的错误处理和日志记录
注意事项
- 确保正确管理Canister调用的认证和授权
- 注意IC网络的速率限制和资源消耗
- 定期更新工具包版本以获得最新功能和性能优化
通过ic-cdk-executor,开发者可以更专注于业务逻辑的实现,而不必过多关注底层交互细节,显著提高开发效率和代码质量。