Rust智能合约开发工具fuels-code-gen的使用:Fuel区块链SDK代码生成与类型安全交互

以下是关于Rust智能合约开发工具fuels-code-gen的使用介绍,包含Fuel区块链SDK代码生成与类型安全交互的完整示例:

// 在Cargo.toml中添加依赖
[dependencies]
fuels-code-gen = "0.74.0"

fuels-code-gen是Fuel区块链生态系统的Rust SDK的一部分,用于生成类型安全的智能合约交互代码。

完整使用示例:

use fuels_code_gen::{generate_bindings, AbiPath};

// 生成类型安全的合约绑定
fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 指定合约ABI文件路径
    let abi_path = AbiPath::new("./path/to/your/contract-abi.json")?;
    
    // 生成绑定代码
    generate_bindings(
        &abi_path,
        "your_contract_name",
        "./output/mod.rs",  // 输出文件路径
    )?;
    
    Ok(())
}

// 生成的代码将提供类型安全的方法来与合约交互
/*
mod generated_bindings {
    pub struct YourContract {
        contract_id: ContractId,
        wallet: Wallet,
    }
    
    impl YourContract {
        pub fn new(contract_id: ContractId, wallet: Wallet) -> Self {
            Self { contract_id, wallet }
        }
        
        // 自动生成的合约方法
        pub async fn your_contract_method(&self, param: u64) -> Result<u64> {
            // 类型安全的调用逻辑
        }
    }
}
*/

主要功能:

  1. 从合约ABI自动生成Rust绑定代码
  2. 提供类型安全的合约方法调用
  3. 简化与Fuel区块链上智能合约的交互

安装方式:

  1. 直接运行 cargo add fuels-code-gen
  2. 或在Cargo.toml中手动添加 fuels-code-gen = "0.74.0"

该项目由Fuel Labs维护,采用Apache-2.0许可证。

以下是一个完整的示例demo:

// 1. 首先在Cargo.toml中添加依赖
// [dependencies]
// fuels-code-gen = "0.74.0"
// fuels = { version = "0.74.0", features = ["std"] }

use fuels::{
    contract::Contract,
    prelude::*,
    types::ContractId,
};
use fuels_code_gen::{generate_bindings, AbiPath};
use std::path::PathBuf;

// 2. 生成合约绑定代码
fn generate_contract_bindings() -> Result<(), Box<dyn std::error::Error>> {
    let abi_path = PathBuf::from("./contracts/my_contract/out/debug/my_contract-abi.json");
    
    generate_bindings(
        &AbiPath::new(abi_path)?,
        "MyContract",
        "./src/contract_bindings.rs",
    )?;
    
    Ok(())
}

// 3. 使用生成的绑定代码与合约交互
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 生成绑定代码
    generate_contract_bindings()?;
    
    // 引入生成的模块
    mod contract_bindings {
        include!("./src/contract_bindings.rs");
    }
    use contract_bindings::MyContract;
    
    // 设置钱包和provider
    let wallet = Wallet::new_uncategorized();
    let provider = Provider::connect("node-url").await?;
    
    // 部署合约
    let contract_id = Contract::deploy(
        "./contracts/my_contract/out/debug/my_contract.bin",
        &wallet,
        TxParameters::default(),
    )
    .await?;
    
    // 创建合约实例
    let contract = MyContract::new(contract_id, wallet);
    
    // 调用合约方法
    let result = contract.your_contract_method(42).await?;
    println!("Result: {}", result);
    
    Ok(())
}

这个完整示例演示了:

  1. 添加必要的依赖
  2. 从合约ABI生成绑定代码
  3. 部署合约
  4. 使用类型安全的方法与合约交互

注意:实际使用时需要替换以下内容:

  • 合约ABI和二进制文件的路径
  • 合约名称"MyContract"
  • 节点URL"node-url"
  • 具体的合约方法名和参数

1 回复

Rust智能合约开发工具fuels-code-gen使用指南

介绍

fuels-code-gen是Fuel区块链SDK的一部分,用于生成与Fuel智能合约交互的类型安全Rust代码。它通过解析合约ABI(应用程序二进制接口)自动生成Rust绑定,使开发者能够以类型安全的方式与智能合约交互。

主要特点:

  • 自动生成类型安全的Rust绑定
  • 简化合约调用过程
  • 提供编译时类型检查
  • 减少手动编码错误

安装

首先将fuelsfuels-code-gen添加到你的Cargo.toml

[dependencies]
fuels = { version = "0.40", features = ["codegen"] }

基本使用方法

1. 生成合约绑定

假设你有一个已编译的Fuel智能合约ABI文件(my_contract-abi.json),可以这样生成Rust绑定:

use fuels::code_gen::ProgramType;
use fuels_code_gen::generate_program_bindings;

fn main() {
    let abi_path = "my_contract-abi.json";
    let generated_code = generate_program_bindings(abi_path, ProgramType::Contract)
        .expect("Failed to generate bindings");
    
    // 将生成的代码写入文件
    std::fs::write("bindings.rs", generated_code.to_string())
        .expect("Failed to write bindings");
}

2. 使用生成的绑定

mod bindings;
use bindings::my_contract_mod::MyContract;

#[tokio::main]
async fn main() {
    // 连接到本地Fuel节点
    let provider = Provider::connect("localhost:4000").await.unwrap();
    
    // 合约ID
    let contract_id = "0x123...".parse().unwrap();
    
    // 创建合约实例
    let contract = MyContract::new(contract_id, provider);
    
    // 调用合约方法
    let result = contract.my_function().call().await.unwrap();
    println!("Result: {:?}", result.value);
}

高级用法

自定义类型绑定

如果你的合约使用自定义类型,可以这样处理:

use fuels::types::Identity;

#[derive(fuels::macros::Parameterize, fuels::macros::Tokenize)]
struct MyCustomType {
    field1: u64,
    field2: String,
    field3: Identity,
}

// 然后在生成绑定时包含这个类型

事件处理

// 监听合约事件
let event_handler = contract.event_handler();

while let Some(event) = event_handler.next().await {
    match event {
        Ok(MyContractEvents::MyEvent { value, .. }) => {
            println!("Received event with value: {}", value);
        }
        Err(e) => eprintln!("Error processing event: {}", e),
    }
}

示例项目结构

典型的使用fuels-code-gen的项目结构:

my_project/
├── Cargo.toml
├── contracts/
│   └── my_contract/      # Fuel智能合约项目
│       └── out/
│           └── debug/
│               └── my_contract-abi.json  # 合约ABI
├── src/
│   ├── main.rs           # 主程序
│   └── bindings.rs       # 生成的绑定代码(可选)
├── build.rs              # 构建脚本,用于自动生成绑定

完整示例demo

下面是一个完整的示例项目,展示如何使用fuels-code-gen

  1. 首先创建项目结构:
fuel_contract_client/
├── Cargo.toml
├── contracts/
│   └── counter_contract/
│       └── out/
│           └── debug/
│               └── counter_contract-abi.json
├── src/
│   ├── main.rs
│   └── bindings.rs
└── build.rs
  1. Cargo.toml内容:
[package]
name = "fuel_contract_client"
version = "0.1.0"
edition = "2021"

[dependencies]
fuels = { version = "0.40", features = ["codegen"] }
tokio = { version = "1.0", features = ["full"] }
  1. build.rs构建脚本:
use fuels::code_gen::ProgramType;
use fuels_code_gen::generate_program_bindings;

fn main() {
    // 生成合约绑定代码
    let abi_path = "contracts/counter_contract/out/debug/counter_contract-abi.json";
    let generated_code = generate_program_bindings(abi_path, ProgramType::Contract)
        .expect("Failed to generate bindings");
    
    // 将生成的代码写入src/bindings.rs
    std::fs::write("src/bindings.rs", generated_code.to_string())
        .expect("Failed to write bindings");
}
  1. src/main.rs主程序:
mod bindings;
use bindings::counter_contract_mod::CounterContract;

use fuels::prelude::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 连接到本地Fuel节点
    let provider = Provider::connect("localhost:4000").await?;
    
    // 合约ID (替换为你的实际合约ID)
    let contract_id = "0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef"
        .parse()?;
    
    // 创建合约实例
    let contract = CounterContract::new(contract_id, provider.clone());
    
    // 调用get_count方法
    let count = contract.get_count().call().await?.value;
    println!("Current count: {}", count);
    
    // 调用increment_count方法
    let _ = contract.increment_count().call().await?;
    println!("Count incremented");
    
    // 再次获取count
    let new_count = contract.get_count().call().await?.value;
    println!("New count: {}", new_count);
    
    Ok(())
}
  1. 假设的counter_contract-abi.json示例内容:
{
  "types": [],
  "functions": [
    {
      "inputs": [],
      "name": "get_count",
      "output": {
        "name": "",
        "type": "u64",
        "components": null
      }
    },
    {
      "inputs": [],
      "name": "increment_count",
      "output": {
        "name": "",
        "type": "()",
        "components": null
      }
    }
  ],
  "loggedTypes": []
}

注意事项

  1. 确保你的Rust版本是最新的稳定版
  2. 生成绑定后,建议检查生成的代码以确保符合预期
  3. 当合约ABI发生变化时,需要重新生成绑定
  4. 对于大型项目,考虑将绑定生成作为构建过程的一部分(在build.rs中)

通过使用fuels-code-gen,你可以显著提高Fuel智能合约开发的效率和安全性,减少手动编码错误,并享受Rust强大的类型系统带来的好处。

回到顶部