Rust智能合约开发库fuel-abi-types的使用,Fuel区块链ABI类型定义与序列化工具

Rust智能合约开发库fuel-abi-types的使用,Fuel区块链ABI类型定义与序列化工具

安装

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

cargo add fuel-abi-types

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

fuel-abi-types = "0.15.0"

示例使用

以下是一个完整的示例代码,展示如何使用fuel-abi-types库进行ABI类型定义和序列化:

use fuel_abi_types::{
    abi::{
        full_program::FullProgramABI,
        program::{ProgramABI, TypeApplication},
    },
    utils::{extract_custom_type_name, extract_generic_parameters},
};
use serde_json;

fn main() {
    // 定义一个简单的ABI类型
    let abi_type = TypeApplication {
        name: "MyType".to_string(),
        type_id: 1,
        type_arguments: vec![],
    };

    // 创建程序ABI
    let program_abi = ProgramABI {
        types: vec![abi_type],
        functions: vec![],
        logged_types: vec![],
        messages_types: vec![],
    };

    // 创建完整的程序ABI
    let full_program_abi = FullProgramABI {
        program_abi,
        storage_slots: vec![],
    };

    // 序列化为JSON
    let json = serde_json::to_string_pretty(&full_program_abi).unwrap();
    println!("Serialized ABI:\n{}", json);

    // 从JSON反序列化
    let deserialized: FullProgramABI = serde_json::from_str(&json).unwrap();
    println!("\nDeserialized type name: {}", deserialized.program_abi.types[0].name);

    // 使用实用工具函数
    let custom_type_name = extract_custom_type_name("struct MyGenericType<T, U>");
    println!("\nExtracted custom type name: {}", custom_type_name);

    let generic_params = extract_generic_parameters("struct MyGenericType<T, U>");
    println!("Extracted generic parameters: {:?}", generic_params);
}

完整示例demo

以下是基于上述内容的完整示例扩展,展示更多fuel-abi-types库的功能:

use fuel_abi_types::{
    abi::{
        full_program::FullProgramABI,
        program::{ProgramABI, TypeApplication, Function},
        parameter::Parameter,
    },
    utils::{extract_custom_type_name, extract_generic_parameters},
};
use serde_json;

fn main() {
    // 示例1: 基础类型定义
    let simple_type = TypeApplication {
        name: "u64".to_string(),
        type_id: 1,
        type_arguments: vec![],
    };

    // 示例2: 泛型类型定义
    let generic_type = TypeApplication {
        name: "Option".to_string(),
        type_id: 2,
        type_arguments: vec![
            TypeApplication {
                name: "T".to_string(),
                type_id: 3,
                type_arguments: vec![],
            }
        ],
    };

    // 示例3: 定义函数参数
    let param = Parameter {
        name: "amount".to_string(),
        type_application: TypeApplication {
            name: "u64".to_string(),
            type_id: 1,
            type_arguments: vec![],
        },
    };

    // 示例4: 定义函数ABI
    let function = Function {
        name: "transfer".to_string(),
        inputs: vec![param],
        output: TypeApplication {
            name: "bool".to_string(),
            type_id: 4,
            type_arguments: vec![],
        },
    };

    // 创建完整程序ABI
    let program_abi = ProgramABI {
        types: vec![simple_type, generic_type],
        functions: vec![function],
        logged_types: vec![],
        messages_types: vec![],
    };

    let full_program_abi = FullProgramABI {
        program_abi,
        storage_slots: vec![],
    };

    // 序列化并打印
    let json = serde_json::to_string_pretty(&full_program_abi).unwrap();
    println!("完整程序ABI:\n{}", json);

    // 使用工具函数示例
    let complex_type_str = "enum Result<T, E> { Ok(T), Err(E) }";
    println!("\n提取类型名称: {}", extract_custom_type_name(complex_type_str));
    println!("提取泛型参数: {:?}", extract_generic_parameters(complex_type_str));
}

功能说明

  1. ABI类型定义:提供了TypeApplication等核心类型来表示ABI中的类型定义
  2. 程序ABI结构:通过ProgramABIFullProgramABI结构体完整描述智能合约的ABI
  3. 序列化支持:支持通过serde将ABI结构序列化为JSON格式
  4. 实用工具:提供提取自定义类型名称和泛型参数等实用函数

许可证

Apache-2.0


1 回复

Rust智能合约开发库fuel-abi-types使用指南

简介

fuel-abi-types是Fuel区块链生态中的一个Rust库,专门用于处理Fuel智能合约的ABI(应用程序二进制接口)类型定义和序列化。它为Fuel区块链上的智能合约开发提供了类型安全的ABI处理能力。

主要功能

  1. 提供Fuel区块链ABI的核心类型定义
  2. 实现ABI类型的序列化与反序列化
  3. 支持Fuel合约调用参数编码
  4. 提供类型转换工具

安装方法

在Cargo.toml中添加依赖:

[dependencies]
fuel-abi-types = "0.1"

基本使用方法

1. 基本类型使用

use fuel_abi_types::abi::full_program::FullTypeDeclaration;
use fuel_abi_types::utils::extract_custom_type_name;

let type_decl = FullTypeDeclaration {
    type_field: "struct MyStruct".to_string(),
    components: None,
    type_parameters: None,
};

let custom_name = extract_custom_type_name(&type_decl.type_field);
assert_eq!(custom_name, Some("MyStruct"));

2. ABI参数编码

use fuel_abi_types::abi::program::ProgramABI;
use fuel_abi_types::traits::{Parameterize, Tokenizable};
use serde_json;

// 从JSON加载ABI定义
let abi_json = r#"
{
    "types": [],
    "functions": [
        {
            "inputs": [
                {
                    "name": "amount",
                    "type": "u64",
                    "components": null,
                    "typeParameters": null
                }
            ],
            "name": "transfer",
            "output": {
                "name": "",
                "type": "bool",
                "components": null,
                "typeParameters": null
            }
        }
    ]
}"#;

let abi: ProgramABI = serde_json::from_str(abi_json).unwrap();
println!("Loaded ABI with {} functions", abi.functions.len());

3. 类型转换

use fuel_abi_types::abi::full_program::FullTypeDeclaration;
use fuel_abi_types::program_bindings::utils::to_token;

let value = 42u64;
let token = to_token(&value).unwrap();
println!("Token representation: {:?}", token);

高级用法

自定义类型处理

use fuel_abi_types::abi::full_program::{FullTypeDeclaration, FullTypeApplication};
use fuel_abi_types::program_bindings::utils::transform_json_type_to_token;

let custom_type = FullTypeDeclaration {
    type_field: "struct MyCustomType".to_string(),
    components: Some(vec![
        FullTypeApplication {
            name: "field1".to_string(),
            type_decl: FullTypeDeclaration {
                type_field: "u32".to_string(),
                components: None,
                type_parameters: None,
            },
        },
        FullTypeApplication {
            name: "field2".to_string(),
            type_decl: FullTypeDeclaration {
                type_field: "bool".to_string(),
                components: None,
                type_parameters: None,
            },
        },
    ]),
    type_parameters: None,
};

let json_value = serde_json::json!({
    "field1": 100,
    "field2": true
});

let token = transform_json_type_to_token(&json_value, &custom_type).unwrap();
println!("Custom type token: {:?}", token);

实际应用场景

  1. 合约调用参数编码
use fuel_abi_types::program_bindings::ParamType;
use fuel_abi_types::traits::Tokenizable;

fn encode_transfer_call(recipient: [u8; 32], amount: u64) -> Vec<u8> {
    let recipient_param = ParamType::B256;
    let amount_param = ParamType::U64;
    
    let tokens = vec![
        recipient_param.encode_token(recipient).unwrap(),
        amount_param.encode_token(amount).unwrap()
    ];
    
    // 这里通常会使用fuel-vm或其他库进行实际编码
    tokens.iter().flat_map(|t| t.to_bytes()).collect()
}
  1. ABI验证
use fuel_abi_types::abi::program::ProgramABI;
use fuel_abi_types::abi::errors::AbiError;

fn validate_abi(abi: &ProgramABI) -> Result<(), AbiError> {
    // 检查是否有函数定义
    if abi.functions.is_empty() {
        return Err(AbiError::new("ABI must contain at least one function"));
    }
    
    // 检查每个函数的输入输出类型是否有效
    for func in &abi.functions {
        // 验证逻辑...
    }
    
    Ok(())
}

完整示例Demo

下面是一个完整的合约调用示例,展示了如何使用fuel-abi-types库进行参数编码和ABI处理:

use fuel_abi_types::{
    abi::{
        full_program::{FullTypeApplication, FullTypeDeclaration},
        program::ProgramABI,
    },
    program_bindings::{utils::transform_json_type_to_token, ParamType},
    traits::{Parameterize, Tokenizable},
};
use serde_json::json;

fn main() {
    // 1. 定义合约ABI
    let abi_json = r#"
    {
        "types": [
            {
                "typeField": "struct TransferParams",
                "components": [
                    {
                        "name": "recipient",
                        "type": "b256",
                        "components": null,
                        "typeParameters": null
                    },
                    {
                        "name": "amount",
                        "type": "u64",
                        "components": null,
                        "typeParameters": null
                    }
                ],
                "typeParameters": null
            }
        ],
        "functions": [
            {
                "inputs": [
                    {
                        "name": "params",
                        "type": "TransferParams",
                        "components": null,
                        "typeParameters": null
                    }
                ],
                "name": "transfer",
                "output": {
                    "name": "",
                    "type": "bool",
                    "components": null,
                    "typeParameters": null
                }
            }
        ]
    }"#;

    // 2. 解析ABI
    let abi: ProgramABI = serde_json::from_str(abi_json).unwrap();
    
    // 3. 准备调用参数
    let transfer_params = json!({
        "recipient": "0x7d9d9e7e7d9d9e7e7d9d9e7e7d9d9e7e7d9d9e7e7d9d9e7e7d9d9e7e7d9d9e7e",
        "amount": 1000
    });

    // 4. 查找类型定义
    let transfer_type = abi.types.iter().find(|t| t.type_field == "struct TransferParams").unwrap();

    // 5. 将JSON参数转换为Token
    let token = transform_json_type_to_token(&transfer_params, transfer_type).unwrap();
    println!("Generated token: {:?}", token);

    // 6. 编码为字节
    let encoded: Vec<u8> = token.to_bytes();
    println!("Encoded bytes: {:?}", encoded);
    
    // 7. 验证ABI
    if let Err(e) = validate_abi(&abi) {
        eprintln!("ABI validation failed: {}", e);
    }
}

// ABI验证函数
fn validate_abi(abi: &ProgramABI) -> Result<(), String> {
    if abi.functions.is_empty() {
        return Err("ABI must contain at least one function".to_string());
    }
    
    for func in &abi.functions {
        if func.name.is_empty() {
            return Err("Function name cannot be empty".to_string());
        }
    }
    
    Ok(())
}

注意事项

  1. Fuel区块链使用特定的ABI格式,与其他区块链(如Ethereum)不兼容
  2. 类型序列化遵循Fuel区块链的规范
  3. 复杂类型(如结构体、枚举)需要正确定义components字段
  4. 处理大整数时要注意类型范围和精度

总结

fuel-abi-types库为Fuel区块链智能合约开发提供了强大的ABI处理能力,通过类型安全的方式简化了合约调用参数编码、返回值解码等常见任务。结合Fuel生态的其他工具如fuels-rs,可以构建完整的区块链应用开发工作流。

回到顶部