Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

交易(Transaction)

交易(Transaction)是改变 Sui 区块链状态的唯一方式。无论是转移对象、调用智能合约函数,还是发布新的 Move 包,都必须通过交易来完成。理解交易的结构和生命周期,是掌握 Sui 开发的关键。

交易的结构

一笔 Sui 交易由以下几个核心部分组成:

Transaction {
    sender:    发送者地址(签名者)
    commands:  操作命令列表
    inputs:    输入参数(纯值参数 + 对象参数)
    gas:       Gas 支付信息(Gas 对象、价格、预算)
}

发送者(Sender)

每笔交易都有一个发送者,即签署并提交交易的账户地址。发送者必须用对应的私钥对交易进行签名。

命令(Commands)

交易可以包含一个或多个命令,按顺序执行。Sui 支持的命令类型:

命令说明
MoveCall调用已发布包中的 Move 函数
TransferObjects将一个或多个对象转移给指定地址
SplitCoins从一个 Coin 中拆分出指定金额
MergeCoins将多个同类型 Coin 合并为一个
Publish发布一个新的 Move 包
Upgrade升级一个已发布的 Move 包
MakeMoveVec创建一个 Move 向量

输入(Inputs)

交易的输入分为两类:

纯值参数(Pure Arguments)

可以直接传入交易的基础值类型:

类型示例
booltrue, false
整数类型u8, u16, u32, u64, u128, u256
address0xa11ce...
String"hello"
vector<T>vector[1, 2, 3]
Option<T>some(42), none
ID对象标识符

对象参数(Object Arguments)

链上对象需要根据其所有权类型以不同方式传入:

对象类型传入方式说明
拥有的对象(Owned)按引用或按值只有所有者可以使用
共享对象(Shared)按可变引用任何人都可以使用
冻结对象(Frozen/Immutable)按不可变引用任何人都可以读取

交易命令详解

MoveCall — 调用 Move 函数

最常用的命令,用于调用链上已发布包中的函数:

module marketplace::shop;

use sui::coin::Coin;
use sui::sui::SUI;

public struct Item has key, store {
    id: UID,
    name: vector<u8>,
}

public fun purchase(
    payment: Coin<SUI>,
    ctx: &mut TxContext,
): Item {
    // 验证支付金额、处理业务逻辑...
    let item = Item {
        id: object::new(ctx),
        name: b"Rare Sword",
    };
    transfer::public_transfer(payment, @0xSHOP_OWNER);
    item
}

SplitCoins — 拆分代币

从一个 Coin 对象中拆分出指定金额。Gas 是一个特殊的关键字,表示交易的 Gas 支付 Coin:

SplitCoins(Gas, [1000])
// 从 Gas Coin 中拆分出 1000 MIST

MergeCoins — 合并代币

将多个同类型 Coin 合并为一个:

MergeCoins(dest_coin, [coin_a, coin_b])
// 将 coin_a 和 coin_b 合并到 dest_coin 中

TransferObjects — 转移对象

将对象转移给指定地址:

TransferObjects([object_a, object_b], recipient)
// 将 object_a 和 object_b 转移给 recipient

交易示例

以下是一个在市场中购买物品的完整交易伪代码:

Inputs:
  - sender = 0xa11ce

Commands:
  - payment = SplitCoins(Gas, [1000])
  - item = MoveCall(0xAAA::market::purchase, [payment])
  - TransferObjects([item], sender)

这笔交易执行了三步操作:

  1. 从 Gas Coin 中拆分出 1000 MIST 作为支付
  2. 调用市场合约的 purchase 函数,传入支付 Coin,获取物品
  3. 将获得的物品转移给自己(发送者)

使用 Sui TypeScript SDK 构建同样的交易:

const tx = new Transaction();

const [payment] = tx.splitCoins(tx.gas, [1000]);
const [item] = tx.moveCall({
    target: '0xAAA::market::purchase',
    arguments: [payment],
});
tx.transferObjects([item], tx.pure.address('0xa11ce'));

交易的生命周期

一笔交易从构建到最终确认,经历以下阶段:

构建(Construct)
    ↓
签名(Sign)
    ↓
提交(Submit)
    ↓
执行(Execute)
    ↓
产生效果(Effects)

1. 构建

开发者使用 SDK 或 CLI 构建交易,指定命令、输入和 Gas 参数。

2. 签名

发送者使用私钥对交易进行数字签名。

3. 提交

将签名后的交易提交给 Sui 验证者节点。

4. 执行

验证者验证签名和交易合法性后,执行交易中的命令序列。

5. 产生效果

交易执行完成后产生 交易效果(Transaction Effects),记录交易的所有结果。

交易效果(Transaction Effects)

每笔交易执行后都会产生一组效果,详细记录了交易的执行结果:

字段说明
Transaction Digest交易的唯一哈希标识符
Status执行状态:成功(success)或失败(failure)
Created Objects本次交易新创建的对象列表
Mutated Objects本次交易修改的对象列表
Deleted Objects本次交易删除的对象列表
Gas Cost SummaryGas 费用明细
Events交易中发出的事件列表
Balance Changes各账户的余额变动

使用 CLI 查看交易效果:

sui client tx-block <TRANSACTION_DIGEST>

Gas 机制

Gas 是执行交易所需的费用,以 Sui 的最小单位 MIST 计价:

1 SUI = 1,000,000,000 MIST(10^9 MIST)

Gas 的组成

每笔交易需要指定三个 Gas 相关参数:

参数说明
Gas 对象用于支付 Gas 费的 Coin 对象
Gas 预算(Gas Budget)交易愿意支付的最大 Gas 量(MIST)
Gas 价格(Gas Price)每单位计算的价格,不低于网络参考价格

Gas 费用明细

交易执行后的 Gas 费用包含以下几部分:

费用类型说明
计算费用(Computation Cost)执行交易中命令所消耗的计算资源
存储费用(Storage Cost)新创建或扩大的对象所需的链上存储费用
存储退款(Storage Rebate)删除或缩小对象时返还的存储费用

实际扣除的 Gas 费用计算公式:

实际费用 = 计算费用 + 存储费用 - 存储退款

Gas 预算

如果交易执行的实际费用超过了设定的 Gas 预算,交易将失败并回滚所有操作,但 Gas 费用仍会被扣除。因此建议设置合理的 Gas 预算:

# CLI 会自动估算 Gas,一般无需写 --gas-budget
sui client call --package 0xPKG --module shop --function purchase \
    --args 0xCOIN_ID

可编程交易块(PTB)

Sui 的一大特色是可编程交易块(Programmable Transaction Block, PTB)。一笔交易可以包含多个命令,这些命令按顺序执行,前一个命令的输出可以作为后一个命令的输入:

Commands:
  1. coin = SplitCoins(Gas, [5000])
  2. nft = MoveCall(0xBBB::nft::mint, ["My NFT"])
  3. MoveCall(0xCCC::auction::bid, [nft, coin])

PTB 的优势:

  • 原子性:所有命令要么全部成功,要么全部失败
  • 组合性:可以在一笔交易中调用多个不同包的函数
  • 高效性:减少了多次交易的网络往返开销
  • 数据流转:前一个命令的返回值可以直接传给后续命令

小结

交易是 Sui 区块链上改变状态的唯一方式。一笔交易包含发送者、命令列表、输入参数和 Gas 支付信息。Sui 提供了 MoveCallTransferObjectsSplitCoins 等多种命令类型,并通过可编程交易块(PTB)实现了多命令的原子组合。交易执行后会产生包含状态变更、Gas 费用、事件等信息的交易效果。Gas 以 MIST 为单位计价(1 SUI = 10^9 MIST),由计算费用、存储费用和存储退款三部分组成。