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);
            }
        }
    }
}

最佳实践

  1. 合理设置重试策略以避免网络拥堵
  2. 使用类型安全的接口减少运行时错误
  3. 适当配置超时时间以适应不同的网络条件
  4. 实现适当的错误处理和日志记录

注意事项

  • 确保正确管理Canister调用的认证和授权
  • 注意IC网络的速率限制和资源消耗
  • 定期更新工具包版本以获得最新功能和性能优化

通过ic-cdk-executor,开发者可以更专注于业务逻辑的实现,而不必过多关注底层交互细节,显著提高开发效率和代码质量。

回到顶部