Programmable Transaction Blocks
A Programmable Transaction Block (PTB) is a single Sui transaction built as an ordered sequence of commands that execute atomically: either every command succeeds and the whole block commits, or any failure reverts the entire block. The defining feature is that the output of one command can be fed as the input to a later one. Results behave like registers — typed, transient values that live only for the duration of the transaction — so you can wire heterogeneous operations together: Move calls, object transfers, coin splits and merges, package publishing, and building Move vectors, all in one shot.
No Glue Contract Required#
The closest analogue on Ethereum is the “multicall” or router pattern: to batch N actions atomically, you must deploy a smart contract that performs them in its own function body, because the EVM gives the client no way to chain arbitrary calls within one transaction. That deployed contract is on-chain glue you have to write, audit, and maintain.
Sui inverts this. The PTB is the composition layer, assembled client-side and submitted as data. You can compose calls across protocols you do not control and have never deployed code against, with no intermediary contract. This is why PTBs are central to how dApps and DeFi aggregators are built on Sui — the composability lives in the transaction, not in a bespoke contract.
Anatomy#
A PTB carries a list of inputs (objects and pure values) and a list of commands that consume those inputs and each other’s results. A block can hold up to roughly 1024 commands, which is enough to encode substantial multi-step flows in one atomic unit. The common command types:
splitCoins— split one or more new coins off an existing coin (often the gas coin).mergeCoins— fold several coins into one.transferObjects— send a list of objects to a recipient.moveCall— invoke a function in a published Move package.makeMoveVec— assemble individual values into a Movevectorto pass to amoveCall.publish— publish a new Move package.
The Classic Example#
The canonical pattern is: split an exact amount off the gas coin, hand it to a DeFi method, then transfer whatever comes back — all in one atomic block. The example below uses the current TypeScript SDK, the @mysten/sui package and its Transaction builder.
|
|
Note that tx.gas references the gas coin directly — splitCoins peels a new coin off it without a separate funding object. The [coin] and result values are command outputs, not concrete objects; they only resolve when the network executes the block.
An earlier SDK,
@mysten/sui.js, exposed this through aTransactionBlockclass. That package is deprecated; current code uses@mysten/suiwithTransaction. The on-chain concept is identical — only the client class was renamed.
Why It Matters#
- Composability without on-chain glue. Chain actions across unrelated protocols with no router contract to deploy or trust.
- Atomicity. Partial execution is impossible, so multi-step DeFi flows (split → swap → stake → transfer) cannot leave funds stranded mid-sequence.
- Fewer round-trips and lower cost. One signature, one transaction, one gas payment for what would otherwise be several transactions or a custom contract deployment.
- Aggregator-friendly. Routers and DEX aggregators compose pool calls dynamically per request instead of shipping a new contract for each strategy.
External Links#
- Programmable Transaction Blocks — Sui concept documentation
- Sui TypeScript SDK —
@mysten/suireference and theTransactionbuilder