Sui Client PTB CLI
The client ptb command allows you to specify the transactions for execution in a programmable transaction block (PTB) directly from your CLI or through bash scripts.
The examples in this document were tested using a bash shell environment. Your experience might vary depending on how your shell interprets the input values (for example, zsh requires quotes around passed values in brackets: "[]"; whereas bash accepts them without quotes). On Windows, you might need to add even more quotes around arguments passed (for example, --assign "forge @<FORGE-ID>").
Commands
The following list itemizes all the available args for the sui client ptb command. Use the --help for a long help version that includes some examples on how to use this command.
$ sui client ptb --help
console-output/sui-client-ptb-help.mdxDesign philosophy and concepts
The main philosophy behind the CLI PTB support is to enable a user to build and execute a PTB from the command line. Bash scripts can be used to construct and execute the PTB just as you would do from the command line, providing great flexibility when it comes to automating different tasks.
Besides using existing traditional PTB related concepts, we introduce a few new and important concepts for this command.
All the following examples were tested using a bash shell environment and your experience may vary depending on how your shell interprets the input values (e.g., zsh requires to pass values in brackets by adding quotes around it: "[]"; bash accepts them without quotes).
Types
Sometimes, CLI PTBs require that you specify the type of a value or variable. For instance, in the following example you must provide the <u64> type when calling the 0x1::option::is_none function.
$ sui client ptb \
--assign my_variable none \
--move-call 0x1::option::is_none "<u64>" my_variable \
--gas-budget 50000000
To pass in multiple types, delimit them with a comma:
...
--move-call package::module::function "<u64,u8,u256>" \
...
Strings
CLI PTBs support string literals as inputs, which will be encoded as pure values that can be used as inputs to vector<u8>, std::ascii::String and std::string::String parameters. The following example previews a transaction block that passes the string "Hello, world" to a function m::f in a package $PKG (its ID is held in an environment variable).
$ sui client ptb --move-call "$PKG::m::f" '"Hello, world"' --gas-budget 10000000 --preview
Double-quoted string literals tend to also be valid syntax for shells (like bash), so when inputting PTBs on the command-line, remember to wrap the entire string in single-quotes so that its double-quotes are interpreted literally, as in the previous example.
Addresses and Object IDs
You can pass literal addresses and objects IDs by prefixing them with '@'. This is needed to distinguish a hexadecimal value from an address in some situations.
For addresses that are in your local wallet, you can use their alias instead (passing them without '@', for example, --transfer-objects my_alias).
Here are some examples for transfer-objects and gas-coin:
$ sui client ptb --transfer-objects "[ARRAY_OF_OBJECTS]" @0x02a212de6a9dfa3a69e22387acfbafbb1a9e591bd9d636e7895dcfc8de05f331 --gas-coin @0x00002819ee07a66e53800495ccf5eeade8a02054a2e0827546c70e4b226f0495
Vectors
CLI PTBs support vectors of serializable types as input (which includes all the primitive types, IDs, and Options). Vectors are represented as a comma-separated list of values in square brackets prefixed with vector.
$ sui client ptb --move-call "$PKG::m::f" vector[1, 2, 3]
Example above illustrates a vector of integer values. Depending on the type of the vector, you can pass any supported type:
--move-call package::module::function vector[@0x1, @0x2, @0x3] # vector<address>
--move-call package::module::function vector[none, none] # vector<Option<T>>
--move-call package::module::function vector["1", "2", "3"] # vector<String>
Option
Options are represented as none or some(value). The value can be any supported primitive type, ID, or Option.
$ sui client ptb --move-call "0x1::option::destroy_some" some(2)
For none, you can use the none keyword. For some, you can use the some keyword followed by the value.
$ sui client ptb --move-call "0x1::option::destroy_none" none
Addresses
Assign
Use the --assign argument to bind values to variables. There are two ways you can use it:
- assign a value to a variable
- assign a variable to the result of the previous command
Let's look at the first case where you assign a value to a variable. You want to check if some variable's value is none. Call the 0x1::option::is_none function from the Move standard library, and pass in the variable name:
$ sui client ptb \
--assign my_variable none \
--move-call 0x1::option::is_none "<u64>" my_variable \
--gas-budget 50000000
CLI PTB uses name resolution for common packages like sui, std, deepbook, so you can use them directly instead of their addresses: 0x2, 0x1, or 0xdee9.
In the second case, if a previous command outputs some result, you can bound it to a variable for later access. Let's see an example where you want a new coin with 1000 MIST, which you can achieve by using the split-coins command. After you do that, you want to transfer the new coin to another address. Without the --assign argument, you couldn't instruct the CLI to transfer that new coin object as you would not have a way to refer to it.
$ sui client ptb \
--split-coins gas "[1000]" \
--assign coin \
--transfer-objects "[coin]" @recipient_address \
--gas-budget 50000000
If you build a complex PTB, use the --preview flag to display the PTB transaction list instead of executing it.
Examples
The following examples demonstrate how to use the client ptb command.
When a PTB is executed, the output contains all the relevant information (transaction data, gas cost, effects, object changes, and so on). Use --summary to get a short summary when you do not need all the data. For complex PTBs, you can use --preview to display the PTB transaction list instead of executing it.
Move call
When needing to execute a Move call, use the --move-call transaction to call a specific function from a package. The CLI PTB supports name resolution for common packages like sui, std, deepbook, so you can use both 0x1::option::is_none as well as std::option::is_none for passing the function name.
--assign A none
--move-call std::option::is_none "<u64>" A
To call a specific function from a specific package, you can use the following call:
--move-call PACKAGE_ADDR::MODULE::FUNCTION "<TYPE>" FUNC_ARG1 FUNC_ARG2 ...
Publish
Publishing a package is one of the most important commands you need when working with Sui. While the CLI has a standalone publish command, PTBs also support publishing and upgrading packages. One main difference is that with sui client ptb, you must explicitly transfer the UpgradeCap object that is returned when creating a package, or destroy it with a call to make_immutable. Here is an example on how to publish a Move project on chain using the sui client ptb command. It makes a call to the sui::tx_context::sender to acquire the sender and assigns the result of that call to the sender variable, and then calls the publish command. The result of publish is bounded to upgrade_cap variable, and then this object is transferred to the sender.
$ sui client ptb \
--move-call sui::tx_context::sender \
--assign sender \
--publish "." \
--assign upgrade_cap \
--transfer-objects "[upgrade_cap]" sender \
--gas-budget 100000000
Split, destroy, and merge coins
The following example showcases how to split a gas coin into multiple coins, make a move call to destroy one or more of the new coins, and finally merge the coins that were not destroyed back into the gas coin. It also showcases how to use framework name resolution (for example, sui::coin instead of 0x2::coin) and how to refer to different values in an array using the . syntax.
# Split off from gas
--split-coins gas "[0,1,2,3]"
--assign coins
--move-call sui::coin::destroy_zero<sui::sui::SUI> coins.0
# Can further split a split coin (and through variable bindings/result accesses)
--split-coins coins.1 "[0,0]"
--assign zcoins
# Destroy both new coins
--move-call sui::coin::destroy_zero<sui::sui::SUI> zcoins.0
--move-call sui::coin::destroy_zero<sui::sui::SUI> zcoins.1
# Can merge the split coins back
--merge-coins gas "[coins.1, coins.2, coins.3]"
--gas-budget 10000000
Transfer objects
This example creates three new coins from gas and transfers them to a different address.
--assign to_address @0x02a212de6a9dfa3a69e22387acfbafbb1a9e591bd9d636e7895dcfc8de05f331 \
--split-coins gas "[1,2,3]" \
--assign s \
--transfer-objects "[s.0, s.1, s.2]" to_address \
--gas-budget 10000000
You can also pass an alias (without the '@') instead of an address.
Reserved words
You cannot use the following words for variable names:
addressboolvectorsomenonegasu8u16u32u64u128u256
JSON output
Append the --json flag to commands to format responses in JSON instead of the more human-friendly default Sui CLI output. This can be useful for extremely large datasets, for example, as those results can have a troublesome display on smaller screens. In these cases, the --json flag is useful.