Rust智能合约开发库near-abi的使用,NEAR协议ABI编码与解码工具
Rust智能合约开发库near-abi的使用,NEAR协议ABI编码与解码工具
概述
❗ 警告:ABI仍处于早期开发阶段,在达到1.0版本前可能会有重大变更
near-abi-rs
是一个为Rust提供NEAR ABI模型的库,可作为NEAR ABI的参考实现。
安装
在项目目录中运行以下Cargo命令:
cargo add near-abi
或在Cargo.toml中添加以下行:
near-abi = "0.4.3"
ABI元模式
该库还包含ABI的元JSON Schemas,这些模式可用于验证JSON文件是否为有效的NEAR ABI。
使用示例
下面是一个使用near-abi
进行编码和解码的完整示例:
use near_abi::{AbiFunction, AbiParameter, AbiType};
// 创建ABI函数定义
let function = AbiFunction {
name: "transfer".to_string(),
doc: Some("Transfer tokens".to_string()),
modifiers: vec![],
params: vec![
AbiParameter {
name: "receiver_id".to_string(),
ty: AbiType::String,
doc: None,
},
AbiParameter {
name: "amount".to_string(),
ty: AbiType::U128,
doc: None,
},
],
result: Some(AbiType::Unit),
is_view: false,
is_payable: false,
is_mutable: true,
};
// 序列化为JSON
let json = serde_json::to_string_pretty(&function).unwrap();
println!("{}", json);
// 从JSON反序列化
let deserialized: AbiFunction = serde_json::from_str(&json).unwrap();
assert_eq!(function, deserialized);
完整示例demo
以下是基于near-abi的完整使用示例,展示了如何定义、序列化和反序列化ABI:
use near_abi::{AbiFunction, AbiParameter, AbiType};
fn main() {
// 定义一个转账函数ABI
let transfer_function = AbiFunction {
name: "transfer".to_string(),
doc: Some("Transfer tokens between accounts".to_string()),
modifiers: vec![],
params: vec![
AbiParameter {
name: "receiver_id".to_string(),
ty: AbiType::String,
doc: Some("Account ID of the receiver".to_string()),
},
AbiParameter {
name: "amount".to_string(),
ty: AbiType::U128,
doc: Some("Amount of tokens to transfer".to_string()),
},
],
result: Some(AbiType::Unit),
is_view: false,
is_payable: false,
is_mutable: true,
};
// 序列化为JSON字符串
let json_str = serde_json::to_string_pretty(&transfer_function).unwrap();
println!("序列化后的ABI JSON:");
println!("{}", json_str);
// 从JSON字符串反序列化
let deserialized: AbiFunction = serde_json::from_str(&json_str).unwrap();
println!("\n反序列化后的ABI:");
println!("函数名: {}", deserialized.name);
println!("参数:");
for param in deserialized.params {
println!(" - {}: {:?}", param.name, param.ty);
}
// 验证原始对象和反序列化对象是否相等
assert_eq!(transfer_function, deserialized);
println!("\n验证通过: 原始ABI与反序列化ABI一致");
}
贡献
如果您有兴趣贡献,请查看贡献指南。
许可证
根据以下任一许可证授权:
- Apache License, Version 2.0
- MIT license
1 回复
Rust智能合约开发库near-abi的使用:NEAR协议ABI编码与解码工具
介绍
near-abi
是 NEAR 协议生态中的一个 Rust 库,用于处理智能合约的 ABI(Application Binary Interface)编码与解码。它提供了在 NEAR 区块链上开发智能合约时所需的类型系统和序列化工具,使得合约与外部调用者之间的数据交互更加安全和方便。
主要功能包括:
- 类型定义(如
Function
、Parameter
、Type
等) - ABI 编码与解码
- JSON ABI 格式支持
- 与 NEAR SDK 的无缝集成
安装方法
在 Cargo.toml 中添加依赖:
[dependencies]
near-abi = "0.4.0"
基本使用方法
1. 定义 ABI
use near_abi::{AbiFunction, AbiParameters, AbiType};
// 定义一个函数的ABI
let function_abi = AbiFunction {
name: "transfer".to_string(),
doc: Some("Transfer tokens to another account".to_string()),
params: AbiParameters {
args: vec![
("receiver_id".to_string(), AbiType::String),
("amount".to_string(), AbiType::U64),
],
},
result: Some(AbiType::Bool),
};
2. 序列化 ABI 到 JSON
use near_abi::AbiRoot;
let abi_root = AbiRoot {
functions: vec![function_abi],
..Default::default()
};
let json_str = serde_json::to_string_pretty(&abi_root).unwrap();
println!("{}", json_str);
3. 从 JSON 反序列化 ABI
let json_str = r#"
{
"functions": [
{
"name": "transfer",
"doc": "Transfer tokens to another account",
"params": {
"args": [
["receiver_id", "string"],
["amount", "u64"]
]
},
"result": "bool"
}
]
}"#;
let abi_root: AbiRoot = serde_json::from_str(json_str).unwrap();
4. 编码函数调用参数
use near_abi::AbiSerializer;
let serializer = AbiSerializer::new(&abi_root);
let args = serializer.serialize("transfer", &["alice.near", "100"]).unwrap();
// args 现在可以用于合约调用
5. 解码函数调用结果
let result_bytes: Vec<u8> = // 从合约调用获取的结果
let result: bool = serializer.deserialize_result("transfer", &result_bytes).unwrap();
完整示例:NEAR 智能合约 ABI 定义
use near_abi::{AbiRoot, AbiFunction, AbiParameters, AbiType};
fn create_token_abi() → AbiRoot {
let transfer = AbiFunction {
name: "transfer".to_string(),
doc: Some("Transfer tokens to another account".to_string()),
params: AbiParameters {
args: vec![
("receiver_id".to_string(), AbiType::String),
("amount".to_string(), AbiType::U64),
],
},
result: Some(AbiType::Bool),
};
let balance_of = AbiFunction {
name: "balance_of".to_string(),
doc: Some("Get account balance".to_string()),
params: AbiParameters {
args: vec![
("account_id".to_string(), AbiType::String),
],
},
result: Some(AbiType::U64),
};
AbiRoot {
functions: vec![transfer, balance_of],
..Default::default()
}
}
fn main() {
let token_abi = create_token_abi();
// 序列化为JSON
let json = serde_json::to_string_pretty(&token_abi).unwrap();
println!("Token ABI:\n{}", json);
// 创建序列化器
let serializer = near_abi::AbiSerializer::new(&token_abi);
// 编码transfer调用参数
let args = serializer.serialize("transfer", &["bob.near", "50"]).unwrap();
println!("Encoded args: {:?}", args);
// 解码balance_of结果
let result_bytes = vec![0, 0, 0, 0, 0, 0, 1, 100]; // 假设返回300
let balance: u64 = serializer.deserialize_result("balance_of", &result_bytes).unwrap();
println!("Decoded balance: {}", balance);
}
高级用法
自定义类型支持
use near_abi::{AbiType, AbiRoot};
let mut abi_root = AbiRoot::default();
abi_root.types.push((
"MyStruct".to_string(),
AbiType::Struct(vec![
("field1".to_string(), AbiType::String),
("field2".to_string(), AbiType::U32),
]),
));
事件定义
use near_abi::{AbiEvent, AbiRoot};
let mut abi_root = AbiRoot::default();
abi_root.events.push(AbiEvent {
name: "Transfer".to_string(),
doc: Some("Token transfer event".to_string()),
params: vec![
("from".to_string(), AbiType::String),
("to".to_string(), AbiType::String),
("amount".to_string(), AbiType::U64),
],
});
完整示例demo
以下是一个完整的 NEAR 智能合约 ABI 定义和使用示例:
use near_abi::{AbiRoot, AbiFunction, AbiParameters, AbiType, AbiSerializer};
// 定义一个NFT合约的ABI
fn create_nft_abi() -> AbiRoot {
// 定义mint函数
let mint = AbiFunction {
name: "mint".to_string(),
doc: Some("Mint a new NFT".to_string()),
params: AbiParameters {
args: vec![
("token_id".to_string(), AbiType::String),
("owner_id".to_string(), AbiType::String),
("metadata".to_string(), AbiType::String),
],
},
result: Some(AbiType::Bool),
};
// 定义get_owner函数
let get_owner = AbiFunction {
name: "get_owner".to_string(),
doc: Some("Get NFT owner".to_string()),
params: AbiParameters {
args: vec![
("token_id".to_string(), AbiType::String),
],
},
result: Some(AbiType::String),
};
// 定义NFT转移事件
let transfer_event = AbiEvent {
name: "NftTransferred".to_string(),
doc: Some("NFT transfer event".to_string()),
params: vec![
("from".to_string(), AbiType::String),
("to".to_string(), AbiType::String),
("token_id".to_string(), AbiType::String),
],
};
// 创建ABI根对象
AbiRoot {
functions: vec![mint, get_owner],
events: vec![transfer_event],
..Default::default()
}
}
fn main() {
// 创建NFT合约ABI
let nft_abi = create_nft_abi();
// 序列化为JSON
let json = serde_json::to_string_pretty(&nft_abi).unwrap();
println!("NFT Contract ABI:\n{}", json);
// 创建ABI序列化器
let serializer = AbiSerializer::new(&nft_abi);
// 编码mint函数调用参数
let mint_args = serializer.serialize(
"mint",
&["nft-001", "alice.near", "{\"title\":\"My NFT\"}"]
).unwrap();
println!("Encoded mint args: {:?}", mint_args);
// 解码get_owner函数结果
let owner_bytes = b"bob.near".to_vec(); // 假设返回"bob.near"
let owner: String = serializer.deserialize_result("get_owner", &owner_bytes).unwrap();
println!("Decoded owner: {}", owner);
// 编码事件数据
let event_data = serializer.serialize_event(
"NftTransferred",
&["alice.near", "bob.near", "nft-001"]
).unwrap();
println!("Encoded event data: {:?}", event_data);
}
注意事项
near-abi
主要设计用于 NEAR 协议的智能合约开发- ABI 定义应与合约实际的函数签名严格匹配
- 编码/解码时确保使用正确的函数名和参数类型
- 对于生产环境,建议将 ABI JSON 存储在单独的文件中
通过 near-abi
,开发者可以更方便地在 NEAR 生态系统中构建类型安全的智能合约接口,并确保合约与前端应用之间的数据交互正确无误。