@mysten/sui 2.16.3 → 2.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/bcs/bcs.d.mts +6 -6
  3. package/dist/bcs/index.d.mts +20 -20
  4. package/dist/graphql/generated/queries.d.mts.map +1 -1
  5. package/dist/graphql/generated/queries.mjs.map +1 -1
  6. package/dist/graphql/generated/tada-env.d.mts +82 -1
  7. package/dist/grpc/client.d.mts +2 -0
  8. package/dist/grpc/client.d.mts.map +1 -1
  9. package/dist/grpc/client.mjs +2 -0
  10. package/dist/grpc/client.mjs.map +1 -1
  11. package/dist/grpc/proto/google/protobuf/struct.mjs +1 -1
  12. package/dist/grpc/proto/google/protobuf/struct.mjs.map +1 -1
  13. package/dist/grpc/proto/google/rpc/status.mjs +1 -1
  14. package/dist/grpc/proto/google/rpc/status.mjs.map +1 -1
  15. package/dist/grpc/proto/sui/forking/v1alpha/forking_service.client.d.mts +66 -0
  16. package/dist/grpc/proto/sui/forking/v1alpha/forking_service.client.d.mts.map +1 -0
  17. package/dist/grpc/proto/sui/forking/v1alpha/forking_service.client.mjs +48 -0
  18. package/dist/grpc/proto/sui/forking/v1alpha/forking_service.client.mjs.map +1 -0
  19. package/dist/grpc/proto/sui/forking/v1alpha/forking_service.d.mts +135 -0
  20. package/dist/grpc/proto/sui/forking/v1alpha/forking_service.d.mts.map +1 -0
  21. package/dist/grpc/proto/sui/forking/v1alpha/forking_service.mjs +144 -0
  22. package/dist/grpc/proto/sui/forking/v1alpha/forking_service.mjs.map +1 -0
  23. package/dist/grpc/proto/sui/rpc/v2/checkpoint.mjs +1 -1
  24. package/dist/grpc/proto/sui/rpc/v2/checkpoint.mjs.map +1 -1
  25. package/dist/grpc/proto/sui/rpc/v2/checkpoint_contents.mjs +3 -3
  26. package/dist/grpc/proto/sui/rpc/v2/checkpoint_contents.mjs.map +1 -1
  27. package/dist/grpc/proto/sui/rpc/v2/checkpoint_summary.mjs +3 -3
  28. package/dist/grpc/proto/sui/rpc/v2/checkpoint_summary.mjs.map +1 -1
  29. package/dist/grpc/proto/sui/rpc/v2/effects.d.mts +71 -3
  30. package/dist/grpc/proto/sui/rpc/v2/effects.d.mts.map +1 -1
  31. package/dist/grpc/proto/sui/rpc/v2/effects.mjs +71 -5
  32. package/dist/grpc/proto/sui/rpc/v2/effects.mjs.map +1 -1
  33. package/dist/grpc/proto/sui/rpc/v2/event.mjs +1 -1
  34. package/dist/grpc/proto/sui/rpc/v2/event.mjs.map +1 -1
  35. package/dist/grpc/proto/sui/rpc/v2/executed_transaction.mjs +2 -2
  36. package/dist/grpc/proto/sui/rpc/v2/executed_transaction.mjs.map +1 -1
  37. package/dist/grpc/proto/sui/rpc/v2/ledger_service.client.d.mts +4 -4
  38. package/dist/grpc/proto/sui/rpc/v2/ledger_service.mjs +3 -3
  39. package/dist/grpc/proto/sui/rpc/v2/ledger_service.mjs.map +1 -1
  40. package/dist/grpc/proto/sui/rpc/v2/move_package.d.mts.map +1 -1
  41. package/dist/grpc/proto/sui/rpc/v2/move_package.mjs +13 -13
  42. package/dist/grpc/proto/sui/rpc/v2/move_package.mjs.map +1 -1
  43. package/dist/grpc/proto/sui/rpc/v2/move_package_service.client.d.mts +4 -4
  44. package/dist/grpc/proto/sui/rpc/v2/move_package_service.mjs +1 -1
  45. package/dist/grpc/proto/sui/rpc/v2/move_package_service.mjs.map +1 -1
  46. package/dist/grpc/proto/sui/rpc/v2/name_service.client.d.mts +4 -4
  47. package/dist/grpc/proto/sui/rpc/v2/object.d.mts.map +1 -1
  48. package/dist/grpc/proto/sui/rpc/v2/object.mjs +1 -1
  49. package/dist/grpc/proto/sui/rpc/v2/object.mjs.map +1 -1
  50. package/dist/grpc/proto/sui/rpc/v2/signature.mjs +3 -3
  51. package/dist/grpc/proto/sui/rpc/v2/signature.mjs.map +1 -1
  52. package/dist/grpc/proto/sui/rpc/v2/signature_verification_service.client.d.mts +4 -4
  53. package/dist/grpc/proto/sui/rpc/v2/signature_verification_service.d.mts.map +1 -1
  54. package/dist/grpc/proto/sui/rpc/v2/signature_verification_service.mjs +1 -1
  55. package/dist/grpc/proto/sui/rpc/v2/signature_verification_service.mjs.map +1 -1
  56. package/dist/grpc/proto/sui/rpc/v2/state_service.client.d.mts +4 -4
  57. package/dist/grpc/proto/sui/rpc/v2/state_service.d.mts.map +1 -1
  58. package/dist/grpc/proto/sui/rpc/v2/state_service.mjs +3 -3
  59. package/dist/grpc/proto/sui/rpc/v2/state_service.mjs.map +1 -1
  60. package/dist/grpc/proto/sui/rpc/v2/subscription_service.client.d.mts +4 -4
  61. package/dist/grpc/proto/sui/rpc/v2/system_state.mjs +2 -2
  62. package/dist/grpc/proto/sui/rpc/v2/system_state.mjs.map +1 -1
  63. package/dist/grpc/proto/sui/rpc/v2/transaction.d.mts.map +1 -1
  64. package/dist/grpc/proto/sui/rpc/v2/transaction.mjs +16 -16
  65. package/dist/grpc/proto/sui/rpc/v2/transaction.mjs.map +1 -1
  66. package/dist/grpc/proto/sui/rpc/v2/transaction_execution_service.mjs +4 -4
  67. package/dist/grpc/proto/sui/rpc/v2/transaction_execution_service.mjs.map +1 -1
  68. package/dist/grpc/proto/types.d.mts +3 -2
  69. package/dist/grpc/proto/types.mjs +11 -1
  70. package/dist/grpc/proto/types.mjs.map +1 -1
  71. package/dist/jsonRpc/types/params.d.mts +5 -5
  72. package/dist/transactions/Transaction.d.mts +25 -11
  73. package/dist/transactions/Transaction.d.mts.map +1 -1
  74. package/dist/transactions/Transaction.mjs +8 -3
  75. package/dist/transactions/Transaction.mjs.map +1 -1
  76. package/dist/transactions/index.d.mts +2 -2
  77. package/dist/version.mjs +1 -1
  78. package/dist/version.mjs.map +1 -1
  79. package/dist/zklogin/jwt-utils.d.mts.map +1 -1
  80. package/dist/zklogin/jwt-utils.mjs.map +1 -1
  81. package/dist/zklogin/utils.d.mts.map +1 -1
  82. package/dist/zklogin/utils.mjs +9 -0
  83. package/dist/zklogin/utils.mjs.map +1 -1
  84. package/docs/bcs.md +11 -6
  85. package/docs/clients/core.md +10 -9
  86. package/docs/clients/grpc.md +1 -1
  87. package/docs/index.md +176 -22
  88. package/docs/llms-index.md +6 -9
  89. package/docs/migrations/0.38.md +2 -2
  90. package/docs/migrations/sui-1.0.md +2 -2
  91. package/docs/migrations/sui-2.0/json-rpc-migration.md +76 -33
  92. package/docs/plugins.md +29 -5
  93. package/docs/transactions/basics.md +279 -0
  94. package/docs/transactions/coins-and-balances.md +293 -0
  95. package/docs/transactions/offline.md +192 -0
  96. package/docs/transactions/reference.md +380 -0
  97. package/docs/transactions/signing-and-execution.md +401 -0
  98. package/package.json +27 -27
  99. package/src/graphql/generated/queries.ts +46 -1
  100. package/src/graphql/generated/schema.graphql +49 -3
  101. package/src/graphql/generated/tada-env.ts +97 -1
  102. package/src/grpc/client.ts +3 -0
  103. package/src/grpc/proto/google/protobuf/struct.ts +1 -1
  104. package/src/grpc/proto/google/rpc/error_details.ts +4 -4
  105. package/src/grpc/proto/google/rpc/status.ts +1 -1
  106. package/src/grpc/proto/sui/forking/v1alpha/forking_service.client.ts +125 -0
  107. package/src/grpc/proto/sui/forking/v1alpha/forking_service.ts +230 -0
  108. package/src/grpc/proto/sui/rpc/v2/checkpoint.ts +1 -1
  109. package/src/grpc/proto/sui/rpc/v2/checkpoint_contents.ts +3 -3
  110. package/src/grpc/proto/sui/rpc/v2/checkpoint_summary.ts +3 -3
  111. package/src/grpc/proto/sui/rpc/v2/effects.ts +112 -6
  112. package/src/grpc/proto/sui/rpc/v2/event.ts +1 -1
  113. package/src/grpc/proto/sui/rpc/v2/executed_transaction.ts +2 -2
  114. package/src/grpc/proto/sui/rpc/v2/ledger_service.ts +3 -3
  115. package/src/grpc/proto/sui/rpc/v2/move_package.ts +19 -13
  116. package/src/grpc/proto/sui/rpc/v2/move_package_service.ts +1 -1
  117. package/src/grpc/proto/sui/rpc/v2/object.ts +7 -1
  118. package/src/grpc/proto/sui/rpc/v2/signature.ts +3 -3
  119. package/src/grpc/proto/sui/rpc/v2/signature_verification_service.ts +7 -1
  120. package/src/grpc/proto/sui/rpc/v2/state_service.ts +9 -3
  121. package/src/grpc/proto/sui/rpc/v2/system_state.ts +2 -2
  122. package/src/grpc/proto/sui/rpc/v2/transaction.ts +22 -16
  123. package/src/grpc/proto/sui/rpc/v2/transaction_execution_service.ts +4 -4
  124. package/src/grpc/proto/types.ts +1 -0
  125. package/src/jsonRpc/types/params.ts +5 -5
  126. package/src/transactions/Transaction.ts +36 -5
  127. package/src/transactions/index.ts +1 -0
  128. package/src/version.ts +1 -1
  129. package/src/zklogin/jwt-utils.ts +3 -0
  130. package/src/zklogin/utils.ts +17 -0
  131. package/docs/faucet.md +0 -26
  132. package/docs/hello-sui.md +0 -115
  133. package/docs/install.md +0 -61
  134. package/docs/transaction-building/basics.md +0 -299
  135. package/docs/transaction-building/gas.md +0 -61
  136. package/docs/transaction-building/intents.md +0 -62
  137. package/docs/transaction-building/offline.md +0 -73
  138. package/docs/transaction-building/sponsored-transactions.md +0 -22
@@ -92,22 +92,26 @@ These JSON-RPC methods have direct replacements in the core API:
92
92
 
93
93
  These JSON-RPC methods can be replaced by calling gRPC service clients directly:
94
94
 
95
- | JSON-RPC Method | gRPC Service Replacement |
96
- | ----------------------------------- | --------------------------------------------------------------- |
97
- | `getCheckpoint` | `ledgerService.getCheckpoint` |
98
- | `getCheckpoints` | `ledgerService.listCheckpoints` |
99
- | `getLatestCheckpointSequenceNumber` | `ledgerService.getCheckpoint` |
100
- | `getEpochs` | `ledgerService.listEpochs` |
101
- | `getCurrentEpoch` | `ledgerService.getEpoch` |
102
- | `getLatestSuiSystemState` | `ledgerService.getSystemState` |
103
- | `getCommitteeInfo` | `ledgerService.getCommittee` |
104
- | `getValidatorsApy` | `ledgerService.getValidators` |
105
- | `getProtocolConfig` | `ledgerService.getProtocolConfig` |
106
- | `getNormalizedMoveModule` | `movePackageService.getPackage` (response includes all modules) |
107
- | `getNormalizedMoveModulesByPackage` | `movePackageService.getPackage` |
108
- | `getNormalizedMoveStruct` | `movePackageService.getDatatype` |
109
- | `resolveNameServiceAddress` | `nameService.lookupName` |
110
- | `resolveNameServiceNames` | `nameService.reverseLookupName` |
95
+ | JSON-RPC Method | gRPC Service Replacement |
96
+ | ----------------------------------- | ---------------------------------------------------------------- |
97
+ | `getCheckpoint` | `ledgerService.getCheckpoint` |
98
+ | `getLatestCheckpointSequenceNumber` | `ledgerService.getServiceInfo` (read `checkpointHeight`) |
99
+ | `getCurrentEpoch` | `ledgerService.getEpoch` (omit `epoch` for the current) |
100
+ | `getLatestSuiSystemState` | `ledgerService.getEpoch` with `system_state` in the read mask |
101
+ | `getCommitteeInfo` | `ledgerService.getEpoch` with `committee` in the read mask |
102
+ | `getProtocolConfig` | `ledgerService.getEpoch` with `protocol_config` in the read mask |
103
+ | `getCoinMetadata` | `stateService.getCoinInfo` (response includes `metadata`) |
104
+ | `getTotalSupply` | `stateService.getCoinInfo` (response includes `treasury`) |
105
+ | `getNormalizedMoveModule` | `movePackageService.getPackage` (response includes all modules) |
106
+ | `getNormalizedMoveModulesByPackage` | `movePackageService.getPackage` |
107
+ | `getNormalizedMoveStruct` | `movePackageService.getDatatype` |
108
+ | `resolveNameServiceAddress` | `nameService.lookupName` |
109
+ | `resolveNameServiceNames` | `nameService.reverseLookupName` |
110
+
111
+ > **Warning:** `getCheckpoints` and `getEpochs` (paginated listings) have no gRPC equivalent — use the
112
+ > `checkpoints` / `epochs` GraphQL queries instead. `getValidatorsApy` also has no replacement:
113
+ > there is no canonical definition of validator APY, so it must be computed client-side from
114
+ > validator exchange rates (see [Validator APY](#validator-apy) below).
111
115
 
112
116
  ### Example: using gRPC service clients
113
117
 
@@ -118,13 +122,32 @@ const client = new SuiGrpcClient({
118
122
  network: 'mainnet',
119
123
  });
120
124
 
121
- // Get checkpoint information
125
+ // Get the latest checkpoint sequence number (replaces getLatestCheckpointSequenceNumber)
126
+ const { response: info } = await client.ledgerService.getServiceInfo({});
127
+ const latestCheckpoint = info.checkpointHeight;
128
+
129
+ // Get a specific checkpoint by sequence number. `checkpointId` is required (a oneof);
130
+ // the read mask defaults to `sequence_number,digest`, so request more fields as needed.
122
131
  const { response } = await client.ledgerService.getCheckpoint({
123
- sequenceNumber: 12345n,
132
+ checkpointId: { oneofKind: 'sequenceNumber', sequenceNumber: latestCheckpoint },
124
133
  });
125
134
 
126
- // Get current epoch
127
- const { response: epoch } = await client.ledgerService.getEpoch({});
135
+ // Get the current epoch (omit `epoch` for the current one). The system state,
136
+ // committee, and protocol config are NOT returned by default — you must request
137
+ // them via the read mask (the default mask is just `epoch`).
138
+ const { response: epoch } = await client.ledgerService.getEpoch({
139
+ readMask: { paths: ['epoch', 'system_state', 'committee', 'protocol_config'] },
140
+ });
141
+ const systemState = epoch.epoch?.systemState;
142
+ const committee = epoch.epoch?.committee;
143
+ const protocolConfig = epoch.epoch?.protocolConfig;
144
+
145
+ // Get coin metadata and total supply in one call
146
+ const { response: coinInfo } = await client.stateService.getCoinInfo({
147
+ coinType: '0x2::sui::SUI',
148
+ });
149
+ const metadata = coinInfo.metadata;
150
+ const totalSupply = coinInfo.treasury?.totalSupply;
128
151
 
129
152
  // Get Move package information (includes all modules)
130
153
  const { response: pkg } = await client.movePackageService.getPackage({
@@ -148,19 +171,21 @@ const { response: address } = await client.nameService.lookupName({
148
171
 
149
172
  Some JSON-RPC methods don't have gRPC equivalents and require using `SuiGraphQLClient` instead:
150
173
 
151
- | JSON-RPC Method | GraphQL Alternative |
152
- | --------------------------- | ---------------------------------- |
153
- | `queryTransactionBlocks` | `transactions` query |
154
- | `multiGetTransactionBlocks` | `multiGetTransactionEffects` query |
155
- | `queryEvents` | `events` query |
156
- | `getCoinMetadata` | `coinMetadata` query |
157
- | `getTotalSupply` | `coinMetadata` query |
158
- | `getStakes` | `address.stakedSuis` query |
159
- | `getStakesByIds` | `multiGetObjects` query |
160
- | `tryGetPastObject` | Historical object queries |
161
- | `getNetworkMetrics` | Use indexer |
162
- | `getAddressMetrics` | Use indexer |
163
- | `getMoveCallMetrics` | Use indexer |
174
+ | JSON-RPC Method | GraphQL Alternative |
175
+ | --------------------------- | --------------------------------------------------------- |
176
+ | `queryTransactionBlocks` | `transactions` query |
177
+ | `multiGetTransactionBlocks` | `multiGetTransactionEffects` query |
178
+ | `queryEvents` | `events` query |
179
+ | `getCheckpoints` | `checkpoints` query |
180
+ | `getEpochs` | `epochs` query |
181
+ | `getCoinMetadata` | `coinMetadata` query (or gRPC `stateService.getCoinInfo`) |
182
+ | `getTotalSupply` | `coinMetadata` query (or gRPC `stateService.getCoinInfo`) |
183
+ | `getStakes` | `address.stakedSuis` query |
184
+ | `getStakesByIds` | `multiGetObjects` query |
185
+ | `tryGetPastObject` | Historical object queries |
186
+ | `getNetworkMetrics` | Use indexer |
187
+ | `getAddressMetrics` | Use indexer |
188
+ | `getMoveCallMetrics` | Use indexer |
164
189
 
165
190
  ### Setting up GraphQL client
166
191
 
@@ -364,6 +389,24 @@ const result = await graphqlClient.query({
364
389
  });
365
390
  ```
366
391
 
392
+ ## Validator APY
393
+
394
+ There is **no replacement** for `getValidatorsApy`, and one will not be added. There is no canonical
395
+ definition of validator APY — no other chain's core/general-purpose RPCs offer this endpoint — so it
396
+ must be computed client-side from validator staking-pool exchange rates.
397
+
398
+ The general approach: read each validator's `exchangeRates` (a table of `pool_token_amount` /
399
+ `sui_amount` per epoch) and estimate the annualized rate from the change in exchange rate over the
400
+ trailing epochs. Two concrete reference implementations:
401
+
402
+ - The `jsonrpc-alt` implementation in
403
+ [`sui-indexer-alt-jsonrpc`](https://github.com/MystenLabs/sui/blob/31537d4d9235b9f61dc07a3a71b05ed61a2bda7b/crates/sui-indexer-alt-jsonrpc/src/api/governance.rs#L422-L440),
404
+ which is compact and readable.
405
+ - [This GraphQL approach](https://github.com/MystenLabs/sui/issues/23832#issuecomment-4437791087),
406
+ which fetches the precursor exchange-rate information in a single query.
407
+
408
+ Treat whichever formula you adopt as _a_ definition of validator APY, not _the_ definition.
409
+
367
410
  ## Response format differences
368
411
 
369
412
  The gRPC client uses the core API response format, which differs from JSON-RPC responses. See the
package/docs/plugins.md CHANGED
@@ -148,7 +148,7 @@ Adding an intent is similar to adding any other command to a transaction:
148
148
  const transaction = new Transaction();
149
149
 
150
150
  transaction.add(
151
- Commands.Intent({
151
+ TransactionCommands.Intent({
152
152
  name: 'TransferToSender',
153
153
  inputs: {
154
154
  objects: [transaction.object(someId)],
@@ -166,7 +166,7 @@ current transaction instance. This allows us to create a helper that automatical
166
166
  function transferToSender(objects: TransactionObjectInput[]) {
167
167
  return (tx: Transaction) => {
168
168
  tx.add(
169
- Commands.Intent({
169
+ TransactionCommands.Intent({
170
170
  name: 'TransferToSender',
171
171
  inputs: {
172
172
  objects: objects.map((obj) => tx.object(obj)),
@@ -214,7 +214,7 @@ async function resolveTransferToSender(
214
214
 
215
215
  // This will replace the intent command with the correct TransferObjects command
216
216
  transactionData.replaceCommand(index, [
217
- Commands.TransferObjects(
217
+ TransactionCommands.TransferObjects(
218
218
  // The inputs for intents are not currently typed, so we need to cast to the correct type here
219
219
  transaction.$Intent.inputs.objects as Extract<
220
220
  TransactionObjectArgument,
@@ -243,7 +243,7 @@ function transferToSender(objects: TransactionObjectInput[]) {
243
243
  // As long as we are adding the same function reference, it will only be added once
244
244
  tx.addIntentResolver('TransferToSender', resolveTransferToSender);
245
245
  tx.add(
246
- Commands.Intent({
246
+ TransactionCommands.Intent({
247
247
  name: 'TransferToSender',
248
248
  inputs: {
249
249
  objects: objects.map((obj) => tx.object(obj)),
@@ -255,4 +255,28 @@ function transferToSender(objects: TransactionObjectInput[]) {
255
255
 
256
256
  const transaction = new Transaction();
257
257
  transaction.add(transferToSender(['0x1234']));
258
- ```
258
+ ```
259
+
260
+ ## Copying transactions that use custom intents
261
+
262
+ `Transaction.from` creates a deep copy of a transaction. Copying is synchronous, so any unresolved
263
+ intents are carried over as-is and resolved later when the copy is built or serialized. To do that,
264
+ the copy needs the intent resolvers, but resolvers are functions and cannot be represented in the
265
+ serialized transaction data.
266
+
267
+ Built-in intents (such as the `CoinWithBalance` intent added by `tx.coin()`) are re-attached
268
+ automatically. For custom intents, pass the resolvers through the `intentResolvers` option so the
269
+ copy knows how to resolve them:
270
+
271
+ ```typescript
272
+
273
+ const copy = Transaction.from(transaction, {
274
+ intentResolvers: {
275
+ TransferToSender: resolveTransferToSender,
276
+ },
277
+ });
278
+ ```
279
+
280
+ Without this, `Transaction.from` throws if the transaction still contains unresolved custom intents.
281
+ Alternatively, you can `await transaction.prepareForSerialization()` first to resolve the intents
282
+ before copying, but that requires an async call and (for some intents) a client.
@@ -0,0 +1,279 @@
1
+ # Building Transactions
2
+
3
+ > Construct programmable transaction blocks with the Transaction API
4
+
5
+ Every interaction with the Sui network goes through a transaction. Sui transactions are a sequence
6
+ of commands called
7
+ [programmable transaction blocks (PTBs)](https://docs.sui.io/guides/developer/transactions/prog-txn-blocks)
8
+ that execute on inputs to produce a result. Commands within a transaction can call Move functions,
9
+ transfer objects, split and merge coins, and more. You can chain the result of one command into a
10
+ subsequent command, composing complex operations in a single transaction.
11
+
12
+ All commands in a transaction execute atomically. If any command fails, the entire transaction is
13
+ rolled back and none of its effects are applied.
14
+
15
+ For more information on transaction model, see the
16
+ [Sui documentation on PTBs](https://docs.sui.io/guides/developer/transactions/prog-txn-blocks) and
17
+ [inputs and results](https://docs.sui.io/concepts/transactions/inputs-and-results).
18
+
19
+ ## Creating a transaction
20
+
21
+ Import the `Transaction` class and create a new instance:
22
+
23
+ ```typescript
24
+
25
+ const tx = new Transaction();
26
+ ```
27
+
28
+ ## Sending SUI
29
+
30
+ Use `tx.balance()` and `balance::send_funds` to send SUI; this deposits directly into the
31
+ recipient's address balance:
32
+
33
+ ```typescript
34
+
35
+ const tx = new Transaction();
36
+
37
+ tx.moveCall({
38
+ target: '0x2::balance::send_funds',
39
+ typeArguments: ['0x2::sui::SUI'],
40
+ arguments: [tx.balance({ balance: 1n * MIST_PER_SUI }), tx.pure.address('0xRecipientAddress')],
41
+ });
42
+ ```
43
+
44
+ If the recipient needs a `Coin<T>` object, use `tx.coin()` with `transferObjects` instead:
45
+
46
+ ```typescript
47
+ tx.transferObjects([tx.coin({ balance: 1n * MIST_PER_SUI })], '0xRecipientAddress');
48
+ ```
49
+
50
+ Both `tx.balance()` and `tx.coin()` automatically draw from your coin objects and address balances.
51
+ You don't need to manage individual coins yourself. See [Coins and Balances](./coins-and-balances)
52
+ for full details.
53
+
54
+ ## Sending other tokens
55
+
56
+ For non-SUI tokens, use the same patterns for passing the coin type:
57
+
58
+ ```typescript
59
+ const tx = new Transaction();
60
+
61
+ // Send to address balance (preferred)
62
+ tx.moveCall({
63
+ target: '0x2::balance::send_funds',
64
+ typeArguments: ['0xPackageId::module::CoinType'],
65
+ arguments: [
66
+ tx.balance({ balance: 1_000_000, type: '0xPackageId::module::CoinType' }),
67
+ tx.pure.address('0xRecipientAddress'),
68
+ ],
69
+ });
70
+
71
+ // Or send as a coin object
72
+ tx.transferObjects(
73
+ [tx.coin({ balance: 1_000_000, type: '0xPackageId::module::CoinType' })],
74
+ '0xRecipientAddress',
75
+ );
76
+ ```
77
+
78
+ ## Calling Move functions
79
+
80
+ Use `moveCall` to call any function in a published Move package. The Sui framework at `0x2` provides
81
+ many built-in functions you can call directly. For example, to split a coin:
82
+
83
+ ```typescript
84
+ const tx = new Transaction();
85
+
86
+ const [newCoin] = tx.moveCall({
87
+ target: '0x2::coin::split',
88
+ typeArguments: ['0x2::sui::SUI'],
89
+ arguments: [tx.object('0xCoinId'), tx.pure.u64(1000)],
90
+ });
91
+
92
+ tx.transferObjects([newCoin], '0xRecipientAddress');
93
+ ```
94
+
95
+ The `target` format is `packageId::moduleName::functionName`.
96
+
97
+ To call functions in your own published packages, use the same pattern with your package ID:
98
+
99
+ ```typescript
100
+ tx.moveCall({
101
+ target: '0xYourPackageId::module::function_name',
102
+ arguments: [tx.pure.string('hello'), tx.object('0xSomeObjectId')],
103
+ });
104
+ ```
105
+
106
+ ### Using codegen for type-safe calls
107
+
108
+ The [`@mysten/codegen`](/codegen) package generates type-safe TypeScript functions from your Move
109
+ packages. Instead of writing `moveCall` with string targets and manual argument construction, use
110
+ `tx.add()` with generated functions:
111
+
112
+ ```typescript
113
+
114
+ const tx = new Transaction();
115
+ tx.add(
116
+ counter.increment({
117
+ arguments: {
118
+ counter: '0x123...', // Counter object ID
119
+ },
120
+ }),
121
+ );
122
+ ```
123
+
124
+ This gives you IDE autocompletion, compile-time type checking for arguments, and eliminates
125
+ incorrect target strings. See the [codegen documentation](/codegen) for setup instructions.
126
+
127
+ ### Return values
128
+
129
+ Commands return results that you can use as input to subsequent commands. For example, `splitCoins`
130
+ returns the new coins it creates:
131
+
132
+ ```typescript
133
+ const tx = new Transaction();
134
+
135
+ // splitCoins returns one result per amount
136
+ const [coin] = tx.splitCoins(tx.gas, [1_000_000]);
137
+
138
+ // Use that result as input to another command
139
+ tx.transferObjects([coin], '0xRecipientAddress');
140
+ ```
141
+
142
+ `moveCall` works the same way. When a Move function returns a value, you can capture it and pass it
143
+ to the next command:
144
+
145
+ ```typescript
146
+ const [nft] = tx.moveCall({
147
+ target: '0xPackageId::nft::mint',
148
+ arguments: [tx.pure.string('My NFT'), tx.pure.string('Description')],
149
+ });
150
+
151
+ tx.transferObjects([nft], '0xRecipientAddress');
152
+ ```
153
+
154
+ When a command returns multiple values, destructure or index into the result:
155
+
156
+ ```typescript
157
+ // Destructuring
158
+ const [nft1, nft2] = tx.moveCall({ target: '0xPackageId::nft::mint_pair' });
159
+
160
+ // Or indexing
161
+ const result = tx.moveCall({ target: '0xPackageId::nft::mint_pair' });
162
+ const firstNft = result[0];
163
+ const secondNft = result[1];
164
+ ```
165
+
166
+ > **Warning:** Always access elements by index or destructuring. Do not use the spread operator (`...result`) or
167
+ > pass results to `Array.from()`, which causes an infinite loop.
168
+
169
+ ### Type arguments
170
+
171
+ Some Move functions have generic type parameters. Pass them with `typeArguments`:
172
+
173
+ ```typescript
174
+ tx.moveCall({
175
+ target: '0x2::coin::split',
176
+ typeArguments: ['0x2::sui::SUI'],
177
+ arguments: [tx.object('0xCoinId'), tx.pure.u64(1000)],
178
+ });
179
+ ```
180
+
181
+ ## Chaining commands
182
+
183
+ The result of any command can be used as input to a subsequent command. This is what makes
184
+ transactions **programmable**. You can compose multiple operations into a single atomic transaction:
185
+
186
+ ```typescript
187
+ const tx = new Transaction();
188
+
189
+ // Mint an NFT
190
+ const [nft] = tx.moveCall({
191
+ target: '0xPackageId::nft::mint',
192
+ arguments: [tx.pure.string('My NFT')],
193
+ });
194
+
195
+ // Set a property on it
196
+ tx.moveCall({
197
+ target: '0xPackageId::nft::set_description',
198
+ arguments: [nft, tx.pure.string('A nice NFT')],
199
+ });
200
+
201
+ // Transfer it to someone
202
+ tx.transferObjects([nft], '0xRecipientAddress');
203
+ ```
204
+
205
+ ## Batch transfers
206
+
207
+ Send tokens to multiple recipients in a single transaction:
208
+
209
+ ```typescript
210
+
211
+ const transfers = [
212
+ { to: '0xAlice', amount: 1_000_000_000 },
213
+ { to: '0xBob', amount: 2_000_000_000 },
214
+ { to: '0xCarol', amount: 500_000_000 },
215
+ ];
216
+
217
+ const tx = new Transaction();
218
+
219
+ for (const transfer of transfers) {
220
+ // Send to address balances (preferred)
221
+ tx.moveCall({
222
+ target: '0x2::balance::send_funds',
223
+ typeArguments: ['0x2::sui::SUI'],
224
+ arguments: [tx.balance({ balance: transfer.amount }), tx.pure.address(transfer.to)],
225
+ });
226
+ }
227
+
228
+ // Or send as coin objects
229
+ for (const transfer of transfers) {
230
+ tx.transferObjects([tx.coin({ balance: transfer.amount })], transfer.to);
231
+ }
232
+ ```
233
+
234
+ ## Composable transaction building with thunks
235
+
236
+ The `tx.add()` method accepts thunks, which are functions that receive the transaction and add
237
+ commands to it. This enables building reusable, composable transaction pieces:
238
+
239
+ ```typescript
240
+ function mintNft(name: string) {
241
+ return (tx: Transaction) => {
242
+ return tx.moveCall({
243
+ target: '0xPackage::nft::mint',
244
+ arguments: [tx.pure.string(name)],
245
+ });
246
+ };
247
+ }
248
+
249
+ const tx = new Transaction();
250
+ const [nft] = tx.add(mintNft('My NFT'));
251
+ tx.transferObjects([nft], '0xRecipientAddress');
252
+ ```
253
+
254
+ See [SDK Building](/sui/sdk-building) for more information on building composable transaction
255
+ libraries.
256
+
257
+ ## Serializing transactions
258
+
259
+ Serialize a transaction to JSON for storage, transmission, or later reconstruction:
260
+
261
+ ```typescript
262
+ // Serialize to JSON — with a client, resolves any unresolved data first
263
+ const json = await tx.toJSON({ client: grpcClient });
264
+
265
+ // Serialize without a client — intents like tx.coin() are preserved as-is
266
+ const json = await tx.toJSON();
267
+
268
+ // Reconstruct from JSON
269
+ const tx = Transaction.from(json);
270
+ ```
271
+
272
+ This is useful for passing transactions between a frontend and backend, or for storing pre-built
273
+ transactions.
274
+
275
+ ## Executing transactions
276
+
277
+ Once you've built a transaction, see [Signing and Execution](./signing-and-execution) for all the
278
+ ways to sign and submit it, such as keypairs, [`dapp-kit`](/dapp-kit) hooks, sponsored transactions,
279
+ and more.