Programmable Transaction Blocks
On Sui, transactions are made up of a series of commands that operate on inputs to produce a result. These grouped commands are called programmable transaction blocks (PTBs), and they form the basis of all user transactions on the network.
The SDK provides two ways for building transactions depending on the users' needs or preference. The DSL Style and the Builder Style.
DSL Style
With this approach, the SDK provides a top level ptb {...}
that provides the scope for composing a PTB. Use this block to define a full transaction inline. This style is best when your logic is self-contained and readable as a single unit.
Here is an example of sending multiple coins to a single address:
You can attach multiple commands of the same type to a transaction, as well. For example, to get a list of transfers and iterate over them to transfer coins to each of them:
Builder Style
Use this when you need to build a PTB gradually — for example, across different parts of your app or conditionally based on user input.
To finalize the assembling of the PTB with the builder style, call the build
method as shown below:
Inputs and Results
Some Move functions need arguments. The SDK provides a powerful arg()
function that intelligently creates the correct argument type for you based on the value and its Move type.
For simple values (Primitives):
For Objects:
To use an on-chain object as an input, simply pass its ID string. The builder will automatically fetch its details during the final build step.
For Lists (Vectors):
The arg()
function is smart enough to handle lists correctly. It automatically determines whether to serialize the list directly (for pure types like address
) or to create a makeMoveVec
command (for a list of objects).
Chaining Commands and Using Results
The real power of PTBs comes from using the result of one command as an input to the next. The APIs make this as intuitive as possible.
Here’s how to perform the common task of creating an on-chain object and sending the new object to a recipient:
Operator Overloads
The SDK provides helper overloads when working with the DSL style for passing inputs to commands. These are the unaryPlus
operator and plus
operator.
unaryPlus operator
Use this when you're passing a single input into a command as shown below:
plus operator
Use this when passing a list of inputs into a command as shown below:
Signing and Executing
To execute a transaction on-chain, we need to first sign than execute the transaction.
The SDK provides a method that collapses these two steps into a single method, signAndExecuteTransactionBlock
.
Observing the results of a transaction
When you call sui.signAndExecuteTransaction
, the transaction is finalized on the blockchain before the function returns. However, the effects of that transaction might not be visible right away.
There are two ways to observe the outcome of a transaction. The first is by using the options parameter available in methods like sui.signAndExecuteTransaction
. You can specify options such as showObjectChanges
and showBalanceChanges
, which include additional details about the transaction’s effects in the response. These can be used immediately in your application to update the UI or trigger further actions.
The second approach is to query the blockchain directly using RPC methods like sui.getBalances
, which return the current state of objects or balances for a specific address. These methods rely on the RPC node indexing the transaction effects, which may not happen right after execution.
To ensure that subsequent RPC calls reflect the transaction’s outcome, you can call waitForTransaction
on the client. This method waits until the transaction has been fully processed and its effects are available to the indexer.
Response Handling
You can find more info on response handling here
Performing Dry Runs
Simulate running a transaction to inspect its effects without committing to them on-chain.
Once a transaction has been assembled, its serialized bytes can be retrieved as a Base64-encoded string, as shown below:
This can then be passed to the dryRunTransactionBlock
method on the Sui
instance as:
In the next section of Transactions, we're going to see how to visually compose PTBs using PTB Studio.