ptbs

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Sui Programmable Transaction Blocks (PTBs)

Sui Programmable Transaction Blocks (PTBs)

MCP tool: When available in your environment, also query the Sui documentation MCP server (
https://sui.mcp.kapa.ai
) for up-to-date answers. Use it for verification and for details not covered by these reference files.
A PTB is one Sui transaction that batches up to 1,024 commands — Move calls, coin splits/merges, object transfers, vector construction, package publish/upgrade — executed in order, atomically (one command fails ⇒ whole block fails), sharing inputs and chaining results. PTBs are the only way to execute transactions on Sui; there is no "single call" mode.
This skill routes to focused reference files. Load only the ones relevant to the current task.
All patterns in this skill are derived from:
If unsure about any API, method signature, or error message, fetch the relevant page before answering. Do not guess or extrapolate from Ethereum, Solana, or other chains — PTBs have no direct analog.

MCP工具提示: 当你的环境支持时,也可查询Sui文档MCP服务器(
https://sui.mcp.kapa.ai
)获取最新答案。可用于验证信息以及获取本参考文件未涵盖的细节。
PTB是一种Sui交易,可批量处理最多1024条命令——包括Move调用、代币拆分/合并、对象转移、向量构建、包发布/升级——按顺序执行且具有原子性(任一命令失败则整个交易块失败),支持输入共享和结果链式调用。PTBs是在Sui上执行交易的唯一方式;不存在“单次调用”模式。
本技能会引导至针对性的参考文件。仅加载与当前任务相关的文件即可。
本技能中的所有模式均源自:
若对任何API、方法签名或错误信息不确定,请先获取相关页面内容再作答。请勿基于Ethereum、Solana或其他链的经验猜测或推断——PTBs没有直接的类似概念。

Reference files

参考文件

fundamentals — PTB data model

fundamentals — PTB数据模型

Path:
fundamentals.md
Load when: explaining what a PTB is, talking about
Input
,
Argument
,
NestedResult
,
GasCoin
, owned vs shared vs immutable vs receiving object references, pure-input BCS rules, command chaining semantics, or execution ordering / atomicity. Covers: PTB structure,
Input
(CallArg) and
ObjectArg
variants, pure input types,
Argument
enum, result chaining, execution semantics (borrow rules, move/copy, hot potato cliques, end-of-tx constraints), protocol limits.
路径:
fundamentals.md
加载场景: 解释PTB是什么、讨论
Input
Argument
NestedResult
GasCoin
、自有对象/共享对象/不可变对象/接收对象引用的区别、纯输入BCS规则、命令链式调用语义,或执行顺序/原子性相关内容。 涵盖内容: PTB结构、
Input
(CallArg)和
ObjectArg
变体、纯输入类型、
Argument
枚举、结果链式调用、执行语义(借用规则、移动/复制、热土豆 clique、交易结束约束)、协议限制。

commands — Command reference

commands — 命令参考

Path:
commands.md
Load when: writing or reviewing any specific command —
MoveCall
,
SplitCoins
,
MergeCoins
,
TransferObjects
,
MakeMoveVec
,
Publish
,
Upgrade
— or debugging argument-type mismatches and return-value shape. Covers: signature, argument rules, return shape, and common pitfalls for each of the seven commands.
路径:
commands.md
加载场景: 编写或评审任何特定命令——
MoveCall
SplitCoins
MergeCoins
TransferObjects
MakeMoveVec
Publish
Upgrade
——或调试参数类型不匹配和返回值格式问题。 涵盖内容: 七个命令各自的签名、参数规则、返回格式及常见陷阱。

building — TypeScript SDK
Transaction
class

building — TypeScript SDK
Transaction

Path:
building.md
Load when: writing TS/JS code that constructs a PTB with
@mysten/sui/transactions
, configuring gas, building for wallets, serializing across services, or sending PTBs between app ↔ wallet ↔ sponsor. Covers:
Transaction
API (
tx.moveCall
,
tx.splitCoins
,
tx.mergeCoins
,
tx.transferObjects
,
tx.makeMoveVec
,
tx.publish
,
tx.upgrade
,
tx.object
,
tx.pure
,
tx.gas
,
tx.setSender/setGasPrice/setGasBudget/setGasPayment/setGasOwner
),
Inputs.*Ref
helpers, result destructuring,
build({ onlyTransactionKind: true })
,
Transaction.from
/
fromKind
, sponsored transaction flow, signing & executing.
路径:
building.md
加载场景: 使用
@mysten/sui/transactions
编写TS/JS代码构建PTB、配置Gas、为钱包构建交易、跨服务序列化,或在应用↔钱包↔赞助方之间传递PTBs。 涵盖内容:
Transaction
API(
tx.moveCall
tx.splitCoins
tx.mergeCoins
tx.transferObjects
tx.makeMoveVec
tx.publish
tx.upgrade
tx.object
tx.pure
tx.gas
tx.setSender/setGasPrice/setGasBudget/setGasPayment/setGasOwner
)、
Inputs.*Ref
辅助工具、结果解构、
build({ onlyTransactionKind: true })
Transaction.from
/
fromKind
、赞助交易流程、签名与执行。

cli — Building PTBs from the CLI

cli — 通过CLI构建PTBs

Path:
cli.md
Load when: constructing PTBs from the command line using
sui client ptb
, scripting transactions without TypeScript, merging coins from the CLI, or teaching CLI-based workflows. Covers:
sui client ptb
syntax, chaining commands, common CLI PTB patterns (transfers, coin merges, Move calls), gas budget, previewing before execution.
路径:
cli.md
加载场景: 使用
sui client ptb
从命令行构建PTBs、无需TypeScript编写交易脚本、通过CLI合并代币,或教授基于CLI的工作流。 涵盖内容:
sui client ptb
语法、命令链式调用、常见CLI PTB模式(转移、代币合并、Move调用)、Gas预算、执行前预览。

troubleshooting — Common errors

troubleshooting — 常见错误

Path:
troubleshooting.md
Load when: diagnosing a failing PTB — any
ServerError
,
UnusedValueWithoutDrop
,
VMVerificationOrDeserializationError
,
No valid gas coins
,
InsufficientGas
, shared-object congestion, or cryptic "transaction failed" output. Covers: each error category with the Move/PTB-level cause and concrete fix.
路径:
troubleshooting.md
加载场景: 诊断执行失败的PTB——包括任何
ServerError
UnusedValueWithoutDrop
VMVerificationOrDeserializationError
No valid gas coins
InsufficientGas
、共享对象拥堵,或模糊的“交易失败”输出。 涵盖内容: 每个错误类别对应的Move/PTB层面原因及具体修复方案。

Routing guide

路由指南

TaskLoad
"What is a PTB?" / conceptual explanationfundamentals
Writing a new PTB in TypeScriptbuilding + commands
Writing a new PTB from the CLIcli + commands
Reviewing a PTB for correctnessfundamentals + commands + building
A specific command fails type checkingcommands
Sponsored / gasless transactionsbuilding
Debugging a failing PTBtroubleshooting + (fundamentals if execution-semantics related)
Publishing or upgrading a package in a PTBcommands
Building PTB bytes across services (app/wallet/sponsor)building
Merging coins or simple operations from the CLIcli
Full code reviewall reference files
任务加载文件
“什么是PTB?” / 概念性解释fundamentals
使用TypeScript编写新的PTBbuilding + commands
通过CLI编写新的PTBcli + commands
评审PTB的正确性fundamentals + commands + building
特定命令类型检查失败commands
赞助/无Gas交易building
调试执行失败的PTBtroubleshooting +(若涉及执行语义则加fundamentals)
在PTB中发布或升级包commands
跨服务(应用/钱包/赞助方)构建PTB字节building
通过CLI合并代币或执行简单操作cli
完整代码评审所有参考文件

Skill Content

技能内容

Key concepts

核心概念

  • A PTB is the transaction. Every Sui transaction is a PTB — even a single
    moveCall
    is a one-command PTB. There is no non-PTB execution path.
  • Inputs vs commands.
    inputs
    are values fed in from outside (objects and BCS-encoded "pure" bytes).
    commands
    operate on those inputs and on each other's results. Commands reference values via the
    Argument
    enum:
    Input(i)
    ,
    GasCoin
    ,
    Result(i)
    ,
    NestedResult(cmd, result)
    .
  • Chaining. Each command produces an array of results. The next command can consume any result (by
    NestedResult(cmd, idx)
    or, when a command has exactly one return,
    Result(cmd)
    ). The TS SDK surfaces this as destructurable values:
    const [coin] = tx.splitCoins(tx.gas, [tx.pure.u64(100)]);
    .
  • Atomicity. Commands execute in order. Any failure reverts the entire block; no partial effects.
  • End-of-tx constraints. Every non-
    drop
    value produced during execution must be consumed (transferred, destroyed, or fed into another command). Shared objects have exactly two legal endings: re-share or delete — they cannot be transferred or frozen. Gas coin is returned to its owner with unused gas refunded.
  • PTB即为交易:每一笔Sui交易都是一个PTB——即使是单次
    moveCall
    也是一个单命令PTB。不存在非PTB的执行路径。
  • 输入 vs 命令
    inputs
    是从外部传入的值(对象和BCS编码的“纯”字节)。
    commands
    基于这些输入和彼此的结果进行操作。命令通过
    Argument
    枚举引用值:
    Input(i)
    GasCoin
    Result(i)
    NestedResult(cmd, result)
  • 链式调用:每个命令会生成一个结果数组。下一个命令可以消费任意结果(通过
    NestedResult(cmd, idx)
    ,或当命令仅有一个返回值时使用
    Result(cmd)
    )。TypeScript SDK将其体现为可解构的值:
    const [coin] = tx.splitCoins(tx.gas, [tx.pure.u64(100)]);
  • 原子性:命令按顺序执行。任何失败都会回滚整个交易块;不会产生部分效果。
  • 交易结束约束:执行过程中产生的所有非
    drop
    值必须被消费(转移、销毁或传入另一个命令)。共享对象仅有两种合法结局:重新共享或删除——无法被转移或冻结。Gas币会返还给所有者,未使用的Gas将被退还。

Rules

规则

  1. tx.gas
    must be used by reference, except in
    transferObjects
    .
    To get an owned
    Coin<SUI>
    from the gas coin, use
    SplitCoins(tx.gas, [amount])
    first.
  2. Leave gas config to the wallet when possible. Do not hardcode
    setGasBudget
    /
    setGasPrice
    /
    setGasPayment
    in app code that will be signed by a user wallet — the wallet dry-runs and selects coins correctly. Only set them for backend-signed flows.
  3. In app code that hands a PTB to a wallet, use
    tx.serialize()
    (not
    tx.build()
    ).
    The wallet must perform gas logic and coin selection itself; building bytes in app code preempts that.
  4. Use
    Transaction.fromKind(kindBytes)
    for sponsored flows.
    Build in app with
    tx.build({ client, onlyTransactionKind: true })
    , send the kind-only bytes to the sponsor service, rehydrate there with
    fromKind
    , then
    setSender
    ,
    setGasOwner
    ,
    setGasPayment
    . The user (or either party) should submit the fully-signed transaction directly to a full node — not back through the sponsor service — to avoid censorship.
  5. Every non-
    drop
    value must be consumed.
    If
    moveCall
    returns a value you don't need, pass it to
    transferObjects
    (if it has
    key + store
    ), to
    public_transfer
    , or to a destructor.
    UnusedValueWithoutDrop
    is the PTB-level error.
  6. Shared objects cannot be transferred, frozen, or consumed by value if passed as read-only (
    mutable: false
    ). If you need mutable access, mark them mutable when building the input.
  7. Types coming from Move calls cannot be references.
    MoveCall
    results are values; if a Move function returns
    &T
    , it cannot be called from a PTB.
  8. For multi-return Move calls, use destructuring or array indexing.
    const [a, b] = tx.moveCall(...)
    or
    const r = tx.moveCall(...); r[0]; r[1];
    . Do not assume single-return shape.
  9. Cite the docs when unsure. Canonical sources above. Legacy
    /develop/transactions/ptbs/*
    URLs still render but prefer
    /concepts/transactions/prog-txn-blocks
    and
    /guides/developer/sui-101/building-ptb
    .
  1. tx.gas
    必须通过引用使用,
    transferObjects
    除外
    。要从Gas币中获取自有
    Coin<SUI>
    ,需先使用
    SplitCoins(tx.gas, [amount])
  2. 尽可能将Gas配置交给钱包处理。在将由用户钱包签名的应用代码中,不要硬编码
    setGasBudget
    /
    setGasPrice
    /
    setGasPayment
    ——钱包会进行试运行并正确选择代币。仅在后端签名流程中设置这些参数。
  3. 在将PTB交给钱包的应用代码中,使用
    tx.serialize()
    (而非
    tx.build()
    。钱包必须自行执行Gas逻辑和代币选择;在应用代码中构建字节会抢占这一流程。
  4. 赞助流程使用
    Transaction.fromKind(kindBytes)
    。在应用中使用
    tx.build({ client, onlyTransactionKind: true })
    构建,将仅包含交易类型的字节发送给赞助服务,在服务端使用
    fromKind
    重新构建,然后设置
    setSender
    setGasOwner
    setGasPayment
    。用户(或任意一方)应直接将完全签名的交易提交给全节点——而非通过赞助服务返回——以避免审查。
  5. 所有非
    drop
    值必须被消费
    。如果
    moveCall
    返回了你不需要的值,可将其传入
    transferObjects
    (若该值具有
    key + store
    )、
    public_transfer
    ,或销毁函数。
    UnusedValueWithoutDrop
    是PTB层面的错误。
  6. 共享对象若以只读方式传入(
    mutable: false
    ),则无法被转移、冻结或按值消费
    。如果需要可变访问权限,在构建输入时标记其为可变。
  7. 来自Move调用的类型不能是引用
    MoveCall
    的结果是值;如果Move函数返回
    &T
    ,则无法从PTB中调用该函数。
  8. 对于多返回值的Move调用,使用解构或数组索引
    const [a, b] = tx.moveCall(...)
    const r = tx.moveCall(...); r[0]; r[1];
    。不要假设返回值为单一值。
  9. 不确定时参考官方文档:上述权威来源。旧版
    /develop/transactions/ptbs/*
    URL仍可访问,但优先使用
    /concepts/transactions/prog-txn-blocks
    /guides/developer/sui-101/building-ptb

Common mistakes

常见错误

  • Calling
    tx.pure(value)
    without a type.
    Untyped pure values fail at input resolution. Use typed helpers:
    tx.pure.u64(n)
    ,
    tx.pure.address(addr)
    ,
    tx.pure.string(s)
    , or the generic
    tx.pure('u64', n)
    .
  • Passing a string object ID to
    moveCall
    arguments without
    tx.object(...)
    .
    Mixed-type arguments require explicit
    tx.object(id)
    wrapping; otherwise the SDK can't distinguish pure from object.
  • Transferring or freezing a shared object. Shared objects cannot be transferred or frozen — but they can be deleted. The two legal endings for a shared object in a PTB are re-share or delete. Do not include shared objects in
    transferObjects
    . Note that consuming a shared object by value permanently marks its hot-potato clique as "hot", which blocks subsequent non-public
    entry
    calls on any entangled value in that clique.
  • Forgetting to
    setSender
    on offline builds.
    When calling
    tx.build()
    without signing through a signer that sets the sender, the sender field stays empty and the build fails.
  • Treating multi-return
    moveCall
    results as single values.
    The return is a vector; index or destructure.
  • Using
    transfer::transfer
    /
    transfer::share_object
    on generic types from a PTB.
    Those entries require a module-private type param. From a PTB, use
    transfer::public_transfer
    /
    transfer::public_share_object
    , which require the type to have
    store
    .
  • Setting a gas budget that's too tight. A tx that exceeds budget aborts but still charges the gas coin. Prefer the SDK's dry-run-based auto-budget.
  • Not checking execution status. A transaction can be accepted by validators but fail at the Move level (assertion, out of gas, etc.). Always check
    result.effects.status.status === 'success'
    before treating an operation as successful. The tx digest alone does not mean the effects were applied.
  • Looping in app code to submit N individual transactions. Batch into one PTB (up to 1,024 ops). One PTB is cheaper and atomic.
  • 调用
    tx.pure(value)
    时未指定类型
    :无类型的纯值会在输入解析阶段失败。请使用类型化辅助函数:
    tx.pure.u64(n)
    tx.pure.address(addr)
    tx.pure.string(s)
    ,或泛型
    tx.pure('u64', n)
  • 将字符串对象ID直接传入
    moveCall
    参数而未使用
    tx.object(...)
    包装
    :混合类型参数需要显式使用
    tx.object(id)
    包装;否则SDK无法区分纯值和对象。
  • 转移或冻结共享对象:共享对象无法被转移或冻结——但可以被删除。PTB中共享对象的两种合法结局是重新共享或删除。请勿将共享对象包含在
    transferObjects
    中。注意,按值消费共享对象会永久标记其热土豆clique为“热”,这会阻止后续对该clique中任何关联值的非公开
    entry
    调用。
  • 离线构建时忘记
    setSender
    :当调用
    tx.build()
    但未通过签名者设置发送方时,发送方字段会保持为空,导致构建失败。
  • 将多返回值的
    moveCall
    结果视为单一值
    :返回值是一个向量;需使用索引或解构。
  • 在PTB中对泛型类型使用
    transfer::transfer
    /
    transfer::share_object
    :这些入口函数需要模块私有类型参数。在PTB中,请使用
    transfer::public_transfer
    /
    transfer::public_share_object
    ,它们要求类型具有
    store
    属性。
  • 设置的Gas预算过低:超过预算的交易会中止,但仍会扣除Gas币。优先使用SDK基于试运行的自动预算功能。
  • 未检查执行状态:交易可能被验证节点接受,但在Move层面失败(断言错误、Gas不足等)。在确认操作成功前,务必检查
    result.effects.status.status === 'success'
    。仅交易摘要并不意味着效果已生效。
  • 在应用代码中循环提交N笔独立交易:应批量合并为一个PTB(最多1024个操作)。单个PTB成本更低且具有原子性。