Code in Move [5] — Programmable Transaction Blocks on Sui

Thouny
Building on Sui
Published in
5 min readMar 21, 2024
https://blog.sui.io/programmable-transaction-blocks-explained/

After exploring the basics of Sui Move and the CLI, let’s keep moving with one of the best building primitive existing in Web3: Programmable Transaction Blocks (PTBs). Believe me, when you experienced Sui Move and PTBs there is no going back.

Concept

Traditional blockchains execute each transaction individually. While this model makes sense in systems that focus on p2p exchanges, it seems simplistic for more advanced use cases. With its object-centric, model Sui is probably the best platform to build composable dApps. PTBs leverage this model to allow many transactions (up to 1024) to be chained together and executed atomically, lowering fees and latency. Read this post from the CTO of a top protocol on Sui to understand how powerful it is.

Each command within a PTB takes inputs that can be objects or pure types (number, boolean, address, string, ID, vector, option). The commands available are TransferObjects, Splitcoins, MergeCoins, MakeMoveVec, MoveCall, Publish, Upgrade and return a heterogenous array of any type.

The best way to understand this new programming paradigm is to dive into some code, let’s look at an example.

Move Package

You can clone this repository to get started. In here, there is a package (written by Jose) defining a simple DeFi protocol. Users create an account, they can then deposit some SUI into the bank and finally use them as collateral to borrow DOLLAR. You will notice that it is a good practice to dedicate an entire module to a Coin.

Let’s start by writing our publishing PTB. We start by instantiating a new TransactionBlock, then we call the publish command that returns the UpgradeCap. This cap will be useful if we later want to upgrade the package. We call the transferObjects command to send the cap to the deployer’s address and we end by signing and executing the PTB.

We can see in this example an options field, this is used to display various data after execution. You can show effects (everything happening in the transaction), events, balance changes, input, raw input, object changes.

The requestType field can be set to “WaitForLocalExecution” meaning that the request wait for the transaction to be executed at the validator level, or “WaitForEffectsCert” that is faster but returns less data.

Here is what the PTB response looks like:

Using the effects, we can retrieve all created objects and the package id. In the example, I write them in a json file to be able to retrieve them easily (see ./utils/getId).

Now let’s see how we can interact with the protocol. As explained previously, a new user needs to create an account. The newAccount PTB does just that. We create an Account object that we transfer to the caller. It’s convenient to display object changes and status in the terminal.

The last file does three things. First, it tries to get an Account for the caller. It’s done using getOwnedObjects that retrieve all objects owned for the address and then filtering the right type.

Here how we compose the PTB. The first thing to do is to get a SUI Coin with the right balance. tx.gas smash (=merge) all SUI Coins, giving us a single Coin. From this one, we split a new Coin with the wanted amount. Then we get an Account for the user, if he doesn’t have one (undefined), we create one with a new moveCall. The next step is to deposit our SUI Coin to the bank and updating our Account. After that we can borrow some DOLLAR that we transfer with another command. You’ll notice that we don’t transfer it within the move code which enhance greatly composability. Finally if we created a new Account for the user, it means he doesn’t own it yet, so we must transfer it. If he already had one we only borrowed it mutably.

To finish we just print the new DOLLAR balance for the user.

A few more words

Now you begin to grasp the power of PTBs. On traditional blockchains, you would typically need multiple transactions to create an account, then deposit your collateral and finally borrow some coins. On Sui, all this can be done in a single execution.

This new programming paradigm also enhance composability greatly. We could imagine here that other protocols may want to use the Bank and Account as collateral for their own money market. Or someone may want to build a yield optimizer between several protocol. A project might want to provide a different front-end and include loyalty nfts in the middle of the PTB. Possibilities are endless.

The most important things to keep in mind is: don’t build the ethereum way!

  • users should own their own state (decentralization is key)
  • functions take and return objects, but can also borrow them
  • build by thinking about the best way for devs to “plug” to your package

Programmable Transaction Blocks with Sui Move really changed my perspective about smart contract programming and I hope it will for you too! If you have any questions, feel free to drop a dm on Twitter.

--

--

Thouny
Building on Sui

Blockchain developer crafting educational and technical content on Web3 techs and philosophies. Digressions on life trying to make sense of it.