Transaction.build()

Summary

Calling Transaction.build() on a programmable transaction block is generally required before executing a transaction. The method makes additional requests to a Sui Full Node in order to gather the information it needs to build the programmable transaction block. This is why the method takes a SuiClient as an argument. You can also pass a Transaction into the Shinami or Mysten SDK's devInspectTransactionBlock method, in which case it calls Transaction.build() on the Transaction before sending the sui_devInspectTransactionBlock request to the Sui network (covered below). Finally, our SDK helper method buildGaslessTransaction, used to prepare a Transaction for sponsorship with our Gas Station, also calls Transaction.build() (covered below).

We made this guide so you can better:

  1. understand the Transaction.build() process
  2. estimate your Shinami usage and billing (these requests, like all requests you make to our Node Service, count towards your Node access key's QPS limit and your daily request total).

Note: the examples below show 4-5 Node Service requests generated from calling Transaction.build(). However, the count of requests can increase above 5 for larger and different transaction blocks. You can run a test with your transactions and observe your own results.

Transaction.build()

In order to build the transaction, the TransactionBlock build method uses the Full Node client you pass it to make a variety of JSON-RPC requests to get the information it needs to build the transaction. This can include, but is not necessarily limited to, fetching the current reference gas price, retrieving the structured representation of any Move calls, fetching information about any objects involved in the transaction, and checking the available gas coins of the address paying for the gas (sender or otherwise).

The exact type and count of requests your Transaction.build() calls produce will vary based on the contents of your transaction blocks.

When you build the transaction block, you pass in a Sui Full Node client (here a Shinami Node Service client):

let txb = new Transaction();
// populate the Transaction
const txBytes = await txb.build({ client: shinamiNodeClient, onlyTransactionKind: false});

One of my recent calls totxb.build() produced the following requests to the client I provided it (a Shinami Node Service client):

"sui_getNormalizedMoveFunction": 1,
"sui_getProtocolConfig": 1,
"sui_multiGetObjects": 1,
"suix_getCoins": 1,
"suix_getReferenceGasPrice": 1

I could see this in my Node Service Metrics in my Shinami Dashboard. The hover state of the stack bar graph shows me I had 5 total requests, and the individual section I was hovering over shows me that 1 of those requests was a suix_getCoins request.

The exact type and count of requests your Transaction.build() calls produce will vary based on the contents of your transaction blocks.

devInspectTransactionBlock

devInspectTransactionBlock can be sent a Transaction. If you do this, it will call Transaction.build() with the input block , which will lead to additional Node Service requests made from the build process.

let txb = new Transaction();
// populate the Transaction

await shinamiNodeClient.devInspectTransactionBlock({
    transactionBlock: txb,
    sender: SENDER_ADDRESS
});

One of my recent calls to sui_devInspectTransactionBlock with an Transaction produced four requests to Shinami's Node service:

"sui_getNormalizedMoveFunction": 1,
"sui_getProtocolConfig": 1,
"sui_multiGetObjects": 1,
"sui_devInspectTransactionBlock": 1

I could see them in the Node Service Metrics in my Shinami Dashboard by hovering over the parts of the stack bar on the Requests graph.

The exact type and count of requests your Transaction.build() calls produce will vary based on the contents of your transaction blocks.

buildGaslessTransaction (Shinami TypeScript SDK)

Our SDK has a helper function called buildGaslessTransaction to prepare a Transaction for sponsorship. Here is an example of calling it with a function to populate a transaction:

import { buildGaslessTransaction } from "@shinami/clients/sui";
...
await buildGaslessTransaction(
  (txb) => {
    txb.moveCall({
      target: "0xfa0e78030bd16672174c2d6cc4cd5d1d1423d03c28a74909b2a148eda8bcca16::clock::access",
      arguments: [txb.object('0x6')],
    });
  },
  {
    sui: nodeClient
  }
);

This function calls Transaction.build(). As a result, it will produce the same set of requests that would get produced if you called Transaction.build() directly on a similarly populated Transaction.