Rust调用sui合约

照着move-book教程 Hello, Sui! - The Move Book 很快写完 move 合约部署到测试网

创建一个 todo_list Object 并将 ownership 转移给我自己的合约调用如下(ptb=ProgrammableTransactionBuilder)

sui client ptb \
  --assign sender @$(sui client active-address) \
  --move-call $PACKAGE_ID::todo_list::new \
  # 将new函数的返回值保存到list中
  --assign list \
  # transfer 之后用 sui client objects --json 就能看到我拥有个 TodoList Object
  --transfer-objects "[list]" sender

sui client ptb 一次可以传入多个 --move-call 但字符串的入参要单双引号两个参数转义 否则就报错如下

sui client ptb --move-call 0x702815e66354365ec77e0ea708912725be4e8e0407b041e11f3b3f733c2a4a53::todo_list::add @0x6d08e394bcc4dec6a8349f1ffb4e5630c0cd55df1ba9882cfe66dfa5b1f7d130 'item 3'
   ╭────
 1 │ --move-call 0x702815e66354365ec77e0ea708912725be4e8e0407b041e11f3b3f733c2a4a53::todo_list::add @0x6d08e394bcc4dec6a8349f1ffb4e5630c0cd55df1ba9882cfe66dfa5b1f7d130 item 3 
   ·                                                                                                ─────────────────────────────────────┬────────────────────────────────────
   ·                                                                                                                                     ╰── Expected 2 arguments, but got 3

sui client ptb 或者 call 都能调用合约,但 ptb 的功能更多点不仅限于调用合约

sui client ptb --move-call 0x702815e66354365ec77e0ea708912725be4e8e0407b041e11f3b3f733c2a4a53::todo_list::add @0x6d08e394bcc4dec6a8349f1ffb4e5630c0cd55df1ba9882cfe66dfa5b1f7d130 ''\''item 2'\'''

sui client call --package 0x702815e66354365ec77e0ea708912725be4e8e0407b041e11f3b3f733c2a4a53 --module todo_list --function add --args 0x6d08e394bcc4dec6a8349f1ffb4e5630c0cd55df1ba9882cfe66dfa5b1f7d130 'item 2'

最后区块浏览器查看 https://suiscan.xyz/testnet/object/0x6d08e394bcc4dec6a8349f1ffb4e5630c0cd55df1ba9882cfe66dfa5b1f7d130

sui/sol/apt一样,数据存储需要支付押金 Storage Rebate Sui Gas Pricing | Sui Documentation

可以类似sol销户那样退存储押金

背景知识

struct SuiObjectData

Object Model | Sui Documentation, Object 类似于 aptos 的 Resource 和 solana 的 Account

核心字段(组成 ObjectRef ):

  • object_id: u256
  • version: SequenceNumber
  • digest: hash of the object's contents and metadata

发送交易的是必须要传入 GasCoin 的 ObjectRef, 如果要修改 Object 函数入参第一个一般都是 ObjectRef

悲剧的是区块浏览器不能获取到 digest (我一开始还以为是nonce作用类似的previous_transaction digest)

例如我 todo_list object 修改了三次之后 digest 是 o#B1t1pVwpn8vQ9LDEeKT5HY6wA859rPHwuJwUGW1NcXyt

理论上修改第四次的时候 digest 会变,果然变了 o#n9pBGbgV3fF2R2KDDWicVitys7PGvStQgYSizo4R5N9

tx commands

  • SplitCoins: 例如支付GAS
  • MoveCall: 调用智能合约函数
  • TransferObjects

Transaction effects are the changes that a transaction makes to the blockchain state

sign tx

Signing and Sending Transactions | Sui Documentation

tx_data 通过 bcs::to_bytes 序列化成 Vec 后面再用 blake2 哈希出摘要,摘要+签名算法flag+公钥 一起签名得到 Signature

整个过程跟 bluefin 交易所下单/撤单的交易签名类似

ptb

Building Programmable Transaction Blocks | Sui Documentation

SuiClientCommands::Call

照着 sui 源码 Call sub command 的处理流程读一遍,就加深对 sui 调用合约函数过程的理解

Rust 代码实现

参考 crates/sui-sdk/examples/function_move_call.rs

Cargo.toml

sui_sdk = { git = "https://github.com/mystenlabs/sui", package = "sui-sdk"}
sui_keys = { git = "https://github.com/mystenlabs/sui", package = "sui-keys"}
shared_crypto = { git = "https://github.com/mystenlabs/sui", package = "shared-crypto"}
bcs = "0.1.6"

初始化查询下 sui 的 ObjectRef 信息和我自己 Object 信息,后续可以优化成只查询一次缓存下来

let sui_client = sui_sdk::SuiClientBuilder::default().build_testnet().await.unwrap();
let sender: SuiAddress = my_addr.parse().unwrap();
let coins = sui_client.coin_read_api().get_coins(sender, None, None, None).await.unwrap();
let gas_coin = coins.data.into_iter().next().unwrap();

let object_id: ObjectID = object_id.parse().unwrap();
let obj = sui_client.read_api().get_object_with_options(object_id, SuiObjectDataOptions::bcs_lossless()).await.unwrap().data.unwrap();
dbg!(&obj.digest);

请求的入参封装如下

let mut ptb = ProgrammableTransactionBuilder::new();
let arg0 = CallArg::Object(ObjectArg::ImmOrOwnedObject((obj.object_id, obj.version, obj.digest)));
// Add this input to the builder
ptb.input(arg0).unwrap();
let arg1 = "item 4";
ptb.input(CallArg::Pure(bcs::to_bytes(&arg1).unwrap())).unwrap();
let pkg_id = "0x702815e66354365ec77e0ea708912725be4e8e0407b041e11f3b3f733c2a4a53";
let package = ObjectID::from_hex_literal(pkg_id).unwrap();
let module = Identifier::new("todo_list").unwrap();
let function = Identifier::new("add").unwrap();
ptb.command(Command::MoveCall(Box::new(ProgrammableMoveCall {
    package,
    module,
    function,
    type_arguments: vec![],
    arguments: vec![Argument::Input(0), Argument::Input(1)],
})));
let builder = ptb.finish();

这个函数对应的 move 源码 以及 ABI

module todo_list::todo_list {
// 因为sui有次升级为了方便前端tx调用合约函数,没有entry修饰的函数也可以rpc调用了
public fun add(list: &mut TodoList, item: String) {
    list.items.push_back(item);
}
}

原帖地址: Rust调用sui合约 - 苏慕白的博客

相关推荐
计算机毕设孵化场17 分钟前
计算机毕设-基于springboot的多彩吉安红色旅游网站的设计与实现(附源码+lw+ppt+开题报告)
vue.js·spring boot·后端·计算机外设·课程设计·计算机毕设论文·多彩吉安红色旅游网站
爪哇学长18 分钟前
解锁API的无限潜力:RESTful、SOAP、GraphQL和Webhooks的应用前景
java·开发语言·后端·restful·graphql
战神刘玉栋42 分钟前
《SpringBoot、Vue 组装exe与套壳保姆级教学》
vue.js·spring boot·后端
码到成功>_<2 小时前
Spring Boot实现License生成和校验
数据库·spring boot·后端
Ztiddler3 小时前
【npm设置代理-解决npm网络连接error network失败问题】
前端·后端·npm·node.js·vue
货拉拉技术3 小时前
多元消息融合分发平台
javascript·后端·架构
醒过来摸鱼3 小时前
【Golang】协程
开发语言·后端·golang
谷大羽3 小时前
Kafka Stream实战教程
spring boot·后端·中间件·kafka·stream
2401_857636393 小时前
实验室管理平台:Spring Boot技术构建
java·spring boot·后端
Hotchip华芯邦科技4 小时前
MEMS硅麦克风应用电子烟雾化产业稳步爬升,耐高温、 防油、防酸、防腐蚀等性能优势和可实现自动化贴片及极高的一致性等特性使其必将成为主流
科技·单片机·金融·生活·社交电子·健康医疗·制造