@mysten/sui 2.24.0 → 2.26.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 (77) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/dist/bcs/bcs.d.mts +6 -6
  3. package/dist/client/core.d.mts.map +1 -1
  4. package/dist/client/core.mjs +4 -1
  5. package/dist/client/core.mjs.map +1 -1
  6. package/dist/client/errors.d.mts +31 -2
  7. package/dist/client/errors.d.mts.map +1 -1
  8. package/dist/client/errors.mjs +15 -13
  9. package/dist/client/errors.mjs.map +1 -1
  10. package/dist/client/index.d.mts +2 -2
  11. package/dist/client/index.mjs +2 -2
  12. package/dist/client/mvr.d.mts.map +1 -1
  13. package/dist/client/mvr.mjs +1 -0
  14. package/dist/client/mvr.mjs.map +1 -1
  15. package/dist/cryptography/signature.d.mts +6 -6
  16. package/dist/graphql/client.d.mts +5 -1
  17. package/dist/graphql/client.d.mts.map +1 -1
  18. package/dist/graphql/client.mjs +15 -2
  19. package/dist/graphql/client.mjs.map +1 -1
  20. package/dist/graphql/core.d.mts +4 -4
  21. package/dist/graphql/core.d.mts.map +1 -1
  22. package/dist/graphql/core.mjs +61 -18
  23. package/dist/graphql/core.mjs.map +1 -1
  24. package/dist/graphql/generated/tada-env.d.mts +16 -0
  25. package/dist/grpc/client.d.mts +5 -1
  26. package/dist/grpc/client.d.mts.map +1 -1
  27. package/dist/grpc/client.mjs +14 -2
  28. package/dist/grpc/client.mjs.map +1 -1
  29. package/dist/grpc/core.d.mts.map +1 -1
  30. package/dist/grpc/core.mjs +29 -12
  31. package/dist/grpc/core.mjs.map +1 -1
  32. package/dist/grpc/proto/sui/rpc/v2/ledger_service.client.d.mts +4 -4
  33. package/dist/grpc/proto/sui/rpc/v2/name_service.client.d.mts +4 -4
  34. package/dist/grpc/proto/sui/rpc/v2/signature_verification_service.client.d.mts +4 -4
  35. package/dist/grpc/proto/sui/rpc/v2/state_service.client.d.mts +4 -4
  36. package/dist/grpc/proto/sui/rpc/v2/subscription_service.client.d.mts +4 -4
  37. package/dist/grpc/proto/sui/rpc/v2/transaction_execution_service.client.d.mts +4 -4
  38. package/dist/jsonRpc/client.d.mts.map +1 -1
  39. package/dist/jsonRpc/client.mjs +60 -15
  40. package/dist/jsonRpc/client.mjs.map +1 -1
  41. package/dist/jsonRpc/core.d.mts +1 -1
  42. package/dist/jsonRpc/core.d.mts.map +1 -1
  43. package/dist/jsonRpc/core.mjs +73 -22
  44. package/dist/jsonRpc/core.mjs.map +1 -1
  45. package/dist/transactions/Transaction.d.mts +6 -6
  46. package/dist/transactions/data/v1.d.mts +220 -220
  47. package/dist/transactions/data/v1.d.mts.map +1 -1
  48. package/dist/transactions/data/v2.d.mts +16 -16
  49. package/dist/transactions/data/v2.d.mts.map +1 -1
  50. package/dist/version.mjs +1 -1
  51. package/dist/version.mjs.map +1 -1
  52. package/dist/zklogin/bcs.d.mts +14 -14
  53. package/docs/bcs.md +2 -2
  54. package/docs/clients/core.md +150 -710
  55. package/docs/clients/executing.md +113 -0
  56. package/docs/clients/graphql.md +80 -70
  57. package/docs/clients/grpc.md +223 -208
  58. package/docs/clients/index.md +56 -67
  59. package/docs/clients/querying.md +539 -0
  60. package/docs/llms-index.md +6 -5
  61. package/docs/migrations/sui-2.0/json-rpc-migration.md +3 -1
  62. package/docs/transactions/signing-and-execution.md +8 -28
  63. package/package.json +1 -1
  64. package/src/client/core.ts +1 -0
  65. package/src/client/errors.ts +39 -23
  66. package/src/client/index.ts +9 -1
  67. package/src/client/mvr.ts +6 -0
  68. package/src/graphql/client.ts +29 -2
  69. package/src/graphql/core.ts +53 -16
  70. package/src/graphql/generated/schema.graphql +11 -1
  71. package/src/graphql/generated/tada-env.ts +20 -0
  72. package/src/grpc/client.ts +28 -2
  73. package/src/grpc/core.ts +90 -65
  74. package/src/jsonRpc/client.ts +15 -0
  75. package/src/jsonRpc/core.ts +102 -24
  76. package/src/version.ts +1 -1
  77. package/docs/clients/json-rpc.md +0 -243
@@ -1,758 +1,198 @@
1
1
  # Core API
2
2
 
3
- > Transport-agnostic Core API shared by Sui clients
3
+ > The transport-agnostic client contract that SDKs and libraries build against
4
4
 
5
- The Core API is the transport-agnostic interface shared by Sui clients. It provides a consistent set
6
- of methods for interacting with the Sui blockchain across `SuiGrpcClient`, `SuiGraphQLClient`, and
7
- the deprecated `SuiJsonRpcClient`.
5
+ The Core API is the contract every Sui client implements. It exists so that libraries do not have to
6
+ care which transport their caller chose: an SDK written against the Core API works with
7
+ `SuiGrpcClient`, `SuiGraphQLClient`, and the deprecated `SuiJsonRpcClient` alike.
8
8
 
9
- For application code, prefer the top-level methods on the concrete client you instantiate, such as
10
- `grpcClient.getObject()` or `graphqlClient.listTransactions()`. Those methods match the Core API for
11
- common operations and may expose transport-specific additions. Use `client.core` when writing SDKs,
12
- libraries, or helpers that accept any `ClientWithCoreApi`.
9
+ > **Note:** This page is for SDK and library authors. If you are writing application code, create a client and
10
+ > call its [top-level methods](/sui/clients/querying) directly. You do not need `client.core`.
11
+
12
+ For packaging, extension, and code-generation patterns that go with this contract, see
13
+ [Building SDKs](/sui/sdk-building).
13
14
 
14
15
  ## `ClientWithCoreApi`
15
16
 
16
- The `ClientWithCoreApi` type represents any client that implements the Core API. Use this type when
17
- building SDKs or libraries that should work with any transport:
17
+ `ClientWithCoreApi` is the type to accept in library code. It says "any Sui client", and gives you
18
+ `client.core` to work through:
18
19
 
19
20
  ```typescript
20
21
 
21
- // Your SDK works with any client
22
- class MySDK {
23
- constructor(private client: ClientWithCoreApi) {}
22
+ #client: ClientWithCoreApi;
24
23
 
25
- async doSomething() {
26
- // Use client.core for all operations
27
- return this.client.core.getObject({ objectId: '0x...' });
24
+ constructor(client: ClientWithCoreApi) {
25
+ this.#client = client;
28
26
  }
29
- }
30
- ```
31
-
32
- ## Object methods
33
-
34
- Object methods accept an optional `include` parameter to control what data is returned. By default,
35
- every object comes with `objectId`, `version`, `digest`, `owner`, and `type`. The following fields
36
- are only populated when requested:
37
-
38
- | Option | Type | Description |
39
- | --------------------- | --------- | ------------------------------------------------------------------------- |
40
- | `content` | `boolean` | BCS-encoded Move struct content (pass this to generated BCS type parsers) |
41
- | `previousTransaction` | `boolean` | Digest of the transaction that last mutated this object |
42
- | `json` | `boolean` | JSON representation of the object's Move struct content |
43
- | `objectBcs` | `boolean` | Full BCS-encoded object envelope (rarely needed; see [below](#objectbcs)) |
44
- | `display` | `boolean` | [Sui Display Standard](https://docs.sui.io/standards/display) metadata |
45
-
46
- ### `getObject`
47
27
 
48
- Fetch a single object by ID.
28
+ async getResource(objectId: string) {
29
+ const { object } = await this.#client.core.getObject({
30
+ objectId,
31
+ include: { content: true },
32
+ });
49
33
 
50
- ```typescript
51
- const { object } = await client.core.getObject({
52
- objectId: '0x123...',
53
- include: {
54
- content: true, // Include BCS-encoded content
55
- previousTransaction: true, // Include creating transaction digest
56
- },
57
- });
58
-
59
- console.log(object.objectId);
60
- console.log(object.version);
61
- console.log(object.digest);
62
- console.log(object.type); // e.g., "0x2::coin::Coin<0x2::sui::SUI>"
63
- ```
64
-
65
- ### `getObjects`
66
-
67
- Fetch multiple objects in a single request.
68
-
69
- ```typescript
70
- const { objects } = await client.core.getObjects({
71
- objectIds: ['0x123...', '0x456...'],
72
- include: { content: true },
73
- });
74
-
75
- for (const obj of objects) {
76
- if (obj instanceof Error) {
77
- console.log('Object not found:', obj.message);
78
- } else {
79
- console.log(obj.objectId, obj.type);
34
+ return object;
80
35
  }
81
36
  }
82
37
  ```
83
38
 
84
- ### `listOwnedObjects`
85
-
86
- List objects owned by an address.
87
-
88
- ```typescript
89
- const result = await client.core.listOwnedObjects({
90
- owner: '0xabc...',
91
- type: '0x2::coin::Coin<0x2::sui::SUI>',
92
- limit: 10,
93
- });
94
-
95
- for (const obj of result.objects) {
96
- console.log(obj.objectId, obj.type);
97
- }
98
-
99
- // Paginate
100
- if (result.cursor) {
101
- const nextPage = await client.core.listOwnedObjects({
102
- owner: '0xabc...',
103
- cursor: result.cursor,
104
- });
105
- }
106
- ```
107
-
108
- ### Parsing object content
109
-
110
- Use `include: { content: true }` to get the BCS-encoded Move struct bytes, then parse them with
111
- generated types (from `@mysten/codegen`) or manual BCS definitions:
112
-
113
- ```typescript
114
-
115
- const { object } = await client.core.getObject({
116
- objectId: '0x123...',
117
- include: { content: true },
118
- });
119
-
120
- const parsed = MyStruct.parse(object.content);
121
- ```
122
-
123
- ### `json` include option
124
-
125
- You can also fetch a JSON representation of the object's content with `include: { json: true }`.
126
-
127
- > **Warning:** The `json` field structure might vary between API implementations. For example, JSON-RPC returns
128
- > UID fields as nested objects (`{ "id": { "id": "0x..." } }`), while gRPC and GraphQL flatten
129
- > them (`{ "id": "0x..." }`). For consistent data across all clients, use `content` and parse BCS
130
- > directly.
131
-
132
- ### `objectBcs`
133
-
134
- The `objectBcs` option returns the full BCS-encoded object envelope, which is the struct content
135
- wrapped in metadata (type, `hasPublicTransfer`, version, owner, previous transaction, and storage
136
- rebate). Most of this metadata is already available as fields on the object response, so you
137
- typically only need `content`. If you do need `objectBcs`, parse it with `bcs.Object` from
138
- `@mysten/sui/bcs`:
139
-
140
- ```typescript
141
-
142
- const envelope = bcs.Object.parse(object.objectBcs);
143
- ```
144
-
145
- > **Error:** Do not pass `objectBcs` to a Move struct parser. It contains wrapping metadata that will cause
146
- > parsing to fail or produce incorrect results. Use `content` for parsing Move struct fields.
147
-
148
- ### `display` include option
149
-
150
- The `display` option fetches [Sui Display Standard](https://docs.sui.io/standards/display) metadata
151
- for an object. Display templates define how an object should be presented in wallets and explorers,
152
- including fields like `name`, `description`, and `image_url`.
153
-
154
- ```typescript
155
- const { object } = await client.core.getObject({
156
- objectId: '0x123...',
157
- include: { display: true },
158
- });
159
-
160
- if (object.display) {
161
- // display is null if the object's type has no Display template
162
- console.log(object.display.output?.name);
163
- console.log(object.display.output?.image_url);
164
- }
165
- ```
166
-
167
- The `display` field is `null` when the object's type has no registered Display template, and
168
- `undefined` when `display` was not requested. The `Display` type has two fields:
169
-
170
- | Field | Type | Description |
171
- | -------- | -------------------------------- | --------------------------------------------------------------- |
172
- | `output` | `Record<string, string> \| null` | Interpolated display fields (template variables resolved) |
173
- | `errors` | `Record<string, string> \| null` | Per-field errors if any template variable failed to interpolate |
174
-
175
- `display` works with `getObject`, `getObjects`, and `listOwnedObjects`.
176
-
177
- ## Coin and balance methods
178
-
179
- ### `getBalance`
180
-
181
- Get the balance of a specific coin type for an owner.
182
-
183
- ```typescript
184
- const { balance } = await client.core.getBalance({
185
- owner: '0xabc...',
186
- coinType: '0x2::sui::SUI', // Optional, defaults to SUI
187
- });
188
-
189
- console.log(balance.balance); // Total balance (coin objects + address balance)
190
- console.log(balance.coinBalance); // Balance from coin objects only
191
- console.log(balance.addressBalance); // Balance from address balance only
192
- ```
193
-
194
- ### `listBalances`
195
-
196
- List all coin balances for an owner.
197
-
198
- ```typescript
199
- const { balances } = await client.core.listBalances({
200
- owner: '0xabc...',
201
- });
202
-
203
- for (const balance of balances) {
204
- console.log(balance.coinType, balance.balance);
205
- }
206
- ```
207
-
208
- ### `listCoins`
209
-
210
- List coin objects of a specific type owned by an address.
211
-
212
- ```typescript
213
- const result = await client.core.listCoins({
214
- owner: '0xabc...',
215
- coinType: '0x2::sui::SUI',
216
- limit: 10,
217
- });
218
-
219
- for (const coin of result.objects) {
220
- console.log(coin.objectId, coin.balance);
221
- }
222
- ```
223
-
224
- ### `getCoinMetadata`
225
-
226
- Get metadata for a coin type, including its name, symbol, decimals, and description.
227
-
228
- ```typescript
229
- const { coinMetadata } = await client.core.getCoinMetadata({
230
- coinType: '0x2::sui::SUI',
231
- });
232
-
233
- if (coinMetadata) {
234
- console.log(coinMetadata.name, coinMetadata.symbol, coinMetadata.decimals);
235
- // "Sui" "SUI" 9
236
- }
237
- ```
238
-
239
- ## Dynamic field methods
240
-
241
- ### `listDynamicFields`
242
-
243
- List dynamic fields on an object.
244
-
245
- ```typescript
246
- const result = await client.core.listDynamicFields({
247
- parentId: '0x123...',
248
- limit: 10,
249
- });
250
-
251
- for (const field of result.dynamicFields) {
252
- console.log(field.name, field.type);
253
- }
254
- ```
255
-
256
- ### `getDynamicField`
257
-
258
- Get a specific dynamic field by name.
259
-
260
- ```typescript
261
-
262
- const { dynamicField } = await client.core.getDynamicField({
263
- parentId: '0x123...',
264
- name: {
265
- type: 'u64',
266
- bcs: bcs.u64().serialize(42).toBytes(),
267
- },
268
- });
269
-
270
- console.log(dynamicField.name);
271
- console.log(dynamicField.value.type);
272
- console.log(dynamicField.value.bcs); // BCS-encoded value
273
- ```
274
-
275
- ### `getDynamicObjectField`
276
-
277
- Get a dynamic object field, returning the referenced object. Supports the same
278
- [object include options](#object-methods) as `getObject`.
279
-
280
- ```typescript
281
- const { object } = await client.core.getDynamicObjectField({
282
- parentId: '0x123...',
283
- name: {
284
- type: '0x2::object::ID',
285
- bcs: bcs.Address.serialize('0x456...').toBytes(),
286
- },
287
- include: { content: true },
288
- });
289
- ```
290
-
291
- ## Transaction methods
292
-
293
- Transaction methods accept an optional `include` parameter to control what data is returned. By
294
- default, every transaction result includes `digest`, `signatures`, `epoch`, and `status`. The
295
- following fields are only populated when requested:
296
-
297
- | Option | Type | Description |
298
- | ---------------- | --------- | ------------------------------------------------------------------ |
299
- | `effects` | `boolean` | Parsed transaction effects (gas used, changed objects, and status) |
300
- | `events` | `boolean` | Events emitted during execution |
301
- | `transaction` | `boolean` | Parsed transaction data (sender, gas config, inputs, commands) |
302
- | `balanceChanges` | `boolean` | Balance changes caused by the transaction |
303
- | `objectTypes` | `boolean` | Map of object IDs to their types for all changed objects |
304
- | `bcs` | `boolean` | Raw BCS-encoded transaction bytes |
305
-
306
- `simulateTransaction` also supports:
307
-
308
- | Option | Type | Description |
309
- | ---------------- | --------- | ------------------------------------------------------ |
310
- | `commandResults` | `boolean` | Return values and mutated references from each command |
311
-
312
- ### `executeTransaction`
39
+ Take the client as a parameter rather than constructing one: the caller has already configured a
40
+ network, endpoint, and transport, and a second client would bypass all of it along with the request
41
+ cache the caller's client holds.
313
42
 
314
- Execute a signed transaction.
43
+ ### Why go through `client.core`
315
44
 
316
- ```typescript
317
- const result = await client.core.executeTransaction({
318
- transaction: transactionBytes,
319
- signatures: [signature],
320
- include: {
321
- effects: true,
322
- events: true,
323
- },
324
- });
325
-
326
- if (result.Transaction) {
327
- console.log('Success:', result.Transaction.digest);
328
- console.log('Effects:', result.Transaction.effects);
329
- } else {
330
- console.log('Failed:', result.FailedTransaction?.status.error);
331
- }
332
- ```
333
-
334
- ### `simulateTransaction`
45
+ Top-level methods on `SuiGrpcClient` and `SuiGraphQLClient` are a superset of the Core API: each
46
+ transport can add fields where it has extra native data, such as `include: { protoJson: true }` on
47
+ gRPC. Those additions are not portable. `client.core` is the subset that every transport guarantees,
48
+ so library code that stays inside it keeps working whichever client the caller supplies.
335
49
 
336
- Simulate a transaction without executing it.
337
-
338
- ```typescript
339
- const result = await client.core.simulateTransaction({
340
- transaction: transactionBytes,
341
- include: {
342
- effects: true,
343
- balanceChanges: true,
344
- commandResults: true, // simulation-only option
345
- },
346
- });
347
-
348
- const simulatedTransaction =
349
- result.$kind === 'Transaction' ? result.Transaction : result.FailedTransaction;
350
-
351
- // Check simulated effects before signing
352
- console.log(simulatedTransaction.effects);
353
- console.log(simulatedTransaction.balanceChanges);
354
- ```
50
+ ## The contract
355
51
 
356
- #### Disabling checks
52
+ Every client implements these methods on `client.core`. [Querying data](/sui/clients/querying)
53
+ documents them in full, with options, include flags, and response shapes.
357
54
 
358
- By default, `simulateTransaction` runs with full transaction validation. For example when inspecting
359
- non-public or non-entry Move functions set `checksEnabled: false`:
55
+ | Category | Methods |
56
+ | -------------- | ------------------------------------------------------------------------------------------ |
57
+ | Objects | `getObject`, `getObjects`, `listOwnedObjects` |
58
+ | Coins | `getBalance`, `listBalances`, `listCoins`, `getCoinMetadata` |
59
+ | Dynamic fields | `listDynamicFields`, `getDynamicField`, `getDynamicObjectField` |
60
+ | Transactions | `getTransaction`, `executeTransaction`, `signAndExecuteTransaction`, `waitForTransaction` |
61
+ | Simulation | `simulateTransaction` |
62
+ | History | `listTransactions`, `listEvents` |
63
+ | Move | `getMoveFunction` |
64
+ | Names | `resolveNameServiceAddress`, `defaultNameServiceName`, `mvr` |
65
+ | Network | `getReferenceGasPrice`, `getCurrentSystemState`, `getProtocolConfig`, `getChainIdentifier` |
66
+ | Verification | `verifyZkLoginSignature` |
67
+ | Building | `resolveTransactionPlugin` |
360
68
 
361
- ```typescript
362
- const result = await client.core.simulateTransaction({
363
- transaction: transactionBytes,
364
- checksEnabled: false,
365
- include: {
366
- commandResults: true,
367
- },
368
- });
369
- ```
69
+ `SuiGrpcClient` and `SuiGraphQLClient` also expose every one of these as a top-level method, so the
70
+ choice between `client.core.getObject()` and `client.getObject()` is about portability rather than
71
+ reach. The deprecated `SuiJsonRpcClient` is the exception: it implements the contract on
72
+ `client.core`, but its own top-level methods keep their legacy JSON-RPC names and shapes.
370
73
 
371
- ### `signAndExecuteTransaction`
74
+ ## Typing library code
372
75
 
373
- Sign and execute a transaction in one step.
76
+ `SuiClientTypes` holds every option and response type in the contract. Import it to type your own
77
+ signatures rather than re-deriving shapes:
374
78
 
375
79
  ```typescript
376
80
 
377
- const tx = new Transaction();
378
- tx.transferObjects([tx.object('0x123...')], '0xrecipient...');
379
-
380
- const result = await client.core.signAndExecuteTransaction({
381
- transaction: tx,
382
- signer: keypair,
383
- include: { effects: true },
384
- });
385
-
386
- // Always check the result
387
- if (result.FailedTransaction) {
388
- throw new Error(`Failed: ${result.FailedTransaction.status.error}`);
81
+ // Include generics flow through, so `object.content` is typed as present here
82
+ function parseResource(object: SuiClientTypes.Object<{ content: true }>) {
83
+ return MyStruct.parse(object.content);
389
84
  }
390
85
 
391
- console.log('Digest:', result.Transaction.digest);
392
- ```
393
-
394
- ### `getTransaction`
395
-
396
- Fetch a transaction by digest.
397
-
398
- ```typescript
399
- const result = await client.core.getTransaction({
400
- digest: 'ABC123...',
401
- include: {
402
- effects: true,
403
- events: true,
404
- transaction: true,
405
- },
406
- });
407
-
408
- console.log(result.Transaction?.digest);
409
- console.log(result.Transaction?.effects);
410
- console.log(result.Transaction?.transaction?.sender);
411
- ```
412
-
413
- You can also fetch raw BCS-encoded transaction bytes:
414
-
415
- ```typescript
416
- const result = await client.core.getTransaction({
417
- digest: 'ABC123...',
418
- include: { bcs: true },
419
- });
420
-
421
- // Raw BCS bytes for the transaction
422
- console.log(result.Transaction?.bcs); // Uint8Array
423
- ```
424
-
425
- ### `waitForTransaction`
426
-
427
- Wait for a transaction to be available.
428
-
429
- ```typescript
430
- const result = await client.core.waitForTransaction({
431
- digest: 'ABC123...',
432
- timeout: 60_000, // 60 seconds
433
- include: { effects: true },
434
- });
435
- ```
436
-
437
- You can also pass the result directly from `executeTransaction`:
438
-
439
- ```typescript
440
- const executeResult = await client.core.executeTransaction({ ... });
441
-
442
- const finalResult = await client.core.waitForTransaction({
443
- result: executeResult,
444
- include: { effects: true },
445
- });
446
- ```
447
-
448
- ## Query methods
449
-
450
- Query methods return pages of transactions or events. They expose the same filters, pagination, and
451
- results on every transport, and share a common set of options. A few transport-specific caveats
452
- (page-size caps, gRPC scan-limited pages, generic event types and missing event checkpoints on the
453
- deprecated JSON-RPC transport, and GraphQL's per-transaction event limit) are documented on the
454
- corresponding option and response types in `SuiClientTypes`.
455
-
456
- | Option | Type | Description |
457
- | -------- | ---------------------------------- | ----------------------------------------------------- |
458
- | `filter` | `TransactionFilter \| EventFilter` | Filter to apply (transactions and events) |
459
- | `limit` | `number` | Maximum number of items to return (defaults to 50) |
460
- | `after` | `string \| null` | Return items strictly after this cursor (ascending) |
461
- | `before` | `string \| null` | Return items strictly before this cursor (descending) |
462
- | `order` | `'ascending' \| 'descending'` | Order of results (defaults to `ascending`) |
463
-
464
- A filter specifies exactly one predicate. MVR names in `function` and `eventType` predicates are
465
- resolved automatically.
466
-
467
- `after` and `before` are exclusive ledger-position bounds, and each page reports the positions of
468
- its first and last items as `startCursor` and `endCursor`. You can provide at most one bound per
469
- query, and the bound implies the traversal direction (`after` reads ascending, `before` reads
470
- descending), so a feed of recent activity can page in both directions from any point:
471
-
472
- ```typescript
473
- // Fetch the most recent transactions
474
- const latest = await client.core.listTransactions({
475
- filter: { sender: '0xabc...' },
476
- order: 'descending',
477
- limit: 10,
478
- });
479
-
480
- // Load older transactions
481
- const older = await client.core.listTransactions({
482
- filter: { sender: '0xabc...' },
483
- before: latest.endCursor,
484
- limit: 10,
485
- });
486
-
487
- // Poll for transactions executed since
488
- const newer = await client.core.listTransactions({
489
- filter: { sender: '0xabc...' },
490
- after: latest.startCursor,
491
- });
492
- ```
493
-
494
- > **Note:** Richer filtering (combined predicates, additional predicates like affected addresses and objects,
495
- > and checkpoint ranges on transaction and event queries) is available through the [raw gRPC ledger
496
- > service](/sui/clients/grpc#ledger-service) and [raw GraphQL queries](/sui/clients/graphql).
497
-
498
- ### `listTransactions`
499
-
500
- Query transactions matching a filter. Results support the same `include` options as
501
- [`getTransaction`](#gettransaction).
502
-
503
- ```typescript
504
- const result = await client.core.listTransactions({
505
- filter: { function: '0x2::coin::transfer' },
506
- limit: 10,
507
- include: { effects: true },
508
- });
509
-
510
- for (const tx of result.transactions) {
511
- const transaction = tx.Transaction ?? tx.FailedTransaction;
512
- console.log(transaction.digest, tx.$kind);
513
- }
514
-
515
- // Paginate
516
- if (result.hasNextPage) {
517
- const nextPage = await client.core.listTransactions({
518
- filter: { function: '0x2::coin::transfer' },
519
- after: result.endCursor,
520
- });
521
- }
522
- ```
523
-
524
- Transaction filters support one of the following predicates:
525
-
526
- | Predicate | Description |
527
- | ---------- | --------------------------------------------------------------------------- |
528
- | `sender` | Transactions sent by an address |
529
- | `function` | Transactions calling a Move function (`pkg`, `pkg::mod`, or `pkg::mod::fn`) |
530
-
531
- ### `listEvents`
532
-
533
- Query events matching a filter. Each event includes its position in the ledger (`transactionDigest`
534
- and `eventIndex`, plus `checkpoint` on transports that can provide it; `checkpoint` is `null` on
535
- JSON-RPC).
536
-
537
- ```typescript
538
- const result = await client.core.listEvents({
539
- filter: { eventType: '0x2::coin::CoinCreated' },
540
- order: 'descending',
541
- limit: 10,
542
- });
543
-
544
- for (const event of result.events) {
545
- console.log(event.eventType, event.transactionDigest, event.json);
86
+ async function fetchBalance(
87
+ client: ClientWithCoreApi,
88
+ owner: string,
89
+ ): Promise<SuiClientTypes.Balance> {
90
+ const { balance } = await client.core.getBalance({ owner });
91
+ return balance;
546
92
  }
547
93
  ```
548
94
 
549
- Event filters support one of the following predicates:
550
-
551
- | Predicate | Description |
552
- | ------------ | --------------------------------------------------------------------------------- |
553
- | `sender` | Events from transactions sent by an address |
554
- | `emitModule` | Events emitted by a module (`pkg::mod`) |
555
- | `eventType` | Events with types defined in a module (`pkg::mod`) or a fully qualified type name |
95
+ The `Include` generic is what makes optional data type-safe: a field that was not requested is typed
96
+ `undefined`, so forgetting to ask for `content` is a compile error rather than a runtime one.
556
97
 
557
- ## System methods
98
+ ### Discriminated unions
558
99
 
559
- ### `getReferenceGasPrice`
560
-
561
- Get the current reference gas price.
100
+ Polymorphic types in the contract use a `$kind` discriminant rather than optional fields. Narrow on
101
+ `$kind` and the matching property is typed for you:
562
102
 
563
103
  ```typescript
564
- const { referenceGasPrice } = await client.core.getReferenceGasPrice();
565
- console.log(referenceGasPrice); // bigint
566
- ```
567
-
568
- ### `getCurrentSystemState`
569
-
570
- Get the current system state including epoch information.
571
-
572
- ```typescript
573
- const { systemState } = await client.core.getCurrentSystemState();
574
- console.log(systemState.epoch);
575
- console.log(systemState.systemStateVersion);
576
- ```
577
-
578
- ### `getChainIdentifier`
579
-
580
- Get the chain identifier for the network.
581
-
582
- ```typescript
583
- const { chainIdentifier } = await client.core.getChainIdentifier();
584
- console.log(chainIdentifier); // e.g., "4c78adac"
585
- ```
586
-
587
- ## Move methods
588
-
589
- ### `getMoveFunction`
590
-
591
- Get information about a Move function.
592
-
593
- ```typescript
594
- const { function: fn } = await client.core.getMoveFunction({
595
- packageId: '0x2',
596
- moduleName: 'coin',
597
- name: 'value',
598
- });
599
-
600
- console.log(fn.name);
601
- console.log(fn.parameters);
602
- console.log(fn.typeParameters);
603
- ```
604
-
605
- ## Name service methods
606
-
607
- ### `resolveNameServiceAddress`
608
-
609
- Resolve a SuiNS name to its target address. The address is `null` when the name does not exist, has
610
- expired, or does not have a target address.
611
-
612
- ```typescript
613
- const { address } = await client.core.resolveNameServiceAddress({
614
- name: 'example.sui',
615
- });
616
-
617
- console.log(address); // e.g., "0x..." or null
618
- ```
619
-
620
- ### `defaultNameServiceName`
621
-
622
- Resolve an address to its default SuiNS name.
623
-
624
- ```typescript
625
- const {
626
- data: { name },
627
- } = await client.core.defaultNameServiceName({
628
- address: '0xabc...',
629
- });
630
-
631
- console.log(name); // e.g., "example.sui"
632
- ```
633
-
634
- ## MVR methods
635
-
636
- The client also exposes MVR (Move Registry) methods through `client.core.mvr`:
637
-
638
- ### `resolveType`
639
-
640
- Resolve a type name (including `.move` names) to a fully qualified type.
641
-
642
- ```typescript
643
- const { type } = await client.core.mvr.resolveType({
644
- type: '@mysten/sui::coin::Coin<@mysten/sui::sui::SUI>',
645
- });
646
-
647
- console.log(type); // "0x2::coin::Coin<0x2::sui::SUI>"
648
- ```
649
-
650
- ## Error handling
651
-
652
- Methods that fetch objects might return errors in the result:
653
-
654
- ```typescript
655
- const { objects } = await client.core.getObjects({
656
- objectIds: ['0x123...', '0x456...'],
657
- });
658
-
659
- for (const obj of objects) {
660
- if (obj instanceof Error) {
661
- // Object not found or other error
662
- console.error('Error:', obj.message);
663
- } else {
664
- // Successfully fetched
665
- console.log(obj.objectId);
104
+ function describeOwner(owner: SuiClientTypes.ObjectOwner) {
105
+ switch (owner.$kind) {
106
+ case 'AddressOwner':
107
+ return `owned by ${owner.AddressOwner}`;
108
+ case 'ObjectOwner':
109
+ return `owned by object ${owner.ObjectOwner}`;
110
+ case 'Shared':
111
+ return `shared since ${owner.Shared.initialSharedVersion}`;
112
+ case 'ConsensusAddressOwner':
113
+ return `consensus-owned by ${owner.ConsensusAddressOwner.owner}`;
114
+ case 'Immutable':
115
+ return 'immutable';
116
+ default:
117
+ return 'unknown';
666
118
  }
667
119
  }
668
120
  ```
669
121
 
670
- For transaction execution, always check the result type:
671
-
672
- ```typescript
673
- const result = await client.core.executeTransaction({ ... });
674
-
675
- if (result.Transaction) {
676
- // Success
677
- console.log(result.Transaction.digest);
678
- } else if (result.FailedTransaction) {
679
- // Transaction was executed but failed
680
- throw new Error(result.FailedTransaction.status.error);
681
- }
682
- ```
683
-
684
- ## `SuiClientTypes` Namespace
685
-
686
- The `SuiClientTypes` namespace contains all type definitions for the Core API. Import it when you
687
- need to type function parameters, return values, or variables:
122
+ `TransactionResult`, `SimulateTransactionResult`, `DatatypeResponse`, `ExecutionError`, and
123
+ `OpenSignatureBody` follow the same pattern.
688
124
 
689
- ```typescript
690
-
691
- // Type function parameters
692
- function processObject(obj: SuiClientTypes.Object<{ content: true }>) {
693
- console.log(obj.objectId, obj.content);
694
- }
125
+ ### Common types
695
126
 
696
- // Type return values
697
- async function fetchBalance(
127
+ | Type | Description |
128
+ | ---------------------- | ---------------------------------------------------------------------------------------- |
129
+ | `Object<Include>` | The unified object shape; `Include` controls which optional fields are present and typed |
130
+ | `Coin` | Coin object with balance |
131
+ | `Balance` | Balance summary for a coin type |
132
+ | `CoinMetadata` | Metadata for a coin type |
133
+ | `Transaction<Include>` | An executed transaction; `Include` controls which optional fields are present |
134
+ | `TransactionResult` | Success or failure result from execution |
135
+ | `TransactionEffects` | Detailed effects from transaction execution |
136
+ | `Event` | Emitted event from a transaction |
137
+ | `EventEntry` | Queried event with its ledger position |
138
+ | `TransactionFilter` | Filter for transaction queries |
139
+ | `EventFilter` | Filter for event queries |
140
+ | `ObjectOwner` | Union of all owner types |
141
+ | `ExecutionStatus` | Success/failure status with error details |
142
+ | `DynamicFieldName` | Name identifier for dynamic fields |
143
+ | `FunctionResponse` | Move function metadata |
144
+ | `Network` | Network identifier type |
145
+
146
+ Option types follow a predictable naming scheme (`GetObjectOptions`, `ListCoinsOptions`,
147
+ `SimulateTransactionOptions`, and so on), along with the include shapes `ObjectInclude`,
148
+ `TransactionInclude`, and `SimulateTransactionInclude`.
149
+
150
+ ## Cross-transport differences
151
+
152
+ All transports produce the same shapes, but they read from different backends, and a few differences
153
+ are visible to callers. Library code that runs against any client should account for them.
154
+
155
+ | Behavior | What differs |
156
+ | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
157
+ | `include: { json: true }` | Field shapes vary between implementations. Use `content` and parse BCS when the result must be stable |
158
+ | `include: { events: true }` | GraphQL returns at most the first 50 events of a transaction; gRPC and JSON-RPC return all of them |
159
+ | JSON-RPC query gaps | `EventEntry.checkpoint` is `null`, and a bare generic `eventType` filter matches nothing where gRPC and GraphQL match any instantiation |
160
+ | Page-size caps | Over-large `limit` values are silently truncated on gRPC and rejected with an error on GraphQL and JSON-RPC |
161
+ | Short pages | gRPC bounds how much ledger a filtered query scans, so a page can be short or empty with `hasNextPage: true` |
162
+ | Read-after-write | GraphQL reads an index that trails execution. Use `waitForTransaction` before reading your own writes |
163
+
164
+ Two constraints are enforced by the client itself, so they fail the same way everywhere: a query
165
+ takes at most one of `after` or `before`, and paginating transactions filtered by `function`
166
+ requires a fully qualified `package::module::function`.
167
+
168
+ ## Client services
169
+
170
+ Beyond the methods, `ClientWithCoreApi` carries a few properties worth knowing about when writing
171
+ library code:
172
+
173
+ | Property | Purpose |
174
+ | ----------------- | ---------------------------------------------------------------------------- |
175
+ | `client.network` | The network the client was created for (`'mainnet'`, `'testnet'`, and so on) |
176
+ | `client.cache` | A shared cache; call `cache.scope('my-sdk')` for a namespace of your own |
177
+ | `client.core.mvr` | Move Registry resolution, with its own cache |
178
+
179
+ Every Core API method also accepts a `signal`, so a library method can pass its caller's
180
+ `AbortSignal` straight through:
181
+
182
+ ```typescript
183
+ async function getResource(
698
184
  client: ClientWithCoreApi,
699
- owner: string,
700
- ): Promise<SuiClientTypes.Balance> {
701
- const { balance } = await client.core.getBalance({ owner });
702
- return balance;
185
+ objectId: string,
186
+ options?: { signal?: AbortSignal },
187
+ ) {
188
+ return client.core.getObject({
189
+ objectId,
190
+ include: { content: true },
191
+ signal: options?.signal,
192
+ });
703
193
  }
704
-
705
- // Type options
706
- const options: SuiClientTypes.GetObjectOptions<{ content: true }> = {
707
- objectId: '0x123...',
708
- include: { content: true },
709
- };
710
194
  ```
711
195
 
712
- ### Common types
713
-
714
- | Type | Description |
715
- | ---------------------- | ------------------------------------------- |
716
- | `Object<Include>` | Fetched object with optional included data |
717
- | `Coin` | Coin object with balance |
718
- | `Balance` | Balance summary for a coin type |
719
- | `CoinMetadata` | Metadata for a coin type |
720
- | `Transaction<Include>` | Executed transaction with optional data |
721
- | `TransactionResult` | Success or failure result from execution |
722
- | `TransactionEffects` | Detailed effects from transaction execution |
723
- | `Event` | Emitted event from a transaction |
724
- | `EventEntry` | Queried event with its ledger position |
725
- | `TransactionFilter` | Filter for transaction queries |
726
- | `EventFilter` | Filter for event queries |
727
- | `ObjectOwner` | Union of all owner types |
728
- | `ExecutionStatus` | Success/failure status with error details |
729
- | `DynamicFieldName` | Name identifier for dynamic fields |
730
- | `FunctionResponse` | Move function metadata |
731
- | `Network` | Network identifier type |
732
-
733
- ### Include options types
734
-
735
- | Type | Description |
736
- | ---------------------------- | --------------------------------------- |
737
- | `ObjectInclude` | Options for object data inclusion |
738
- | `TransactionInclude` | Options for transaction data inclusion |
739
- | `SimulateTransactionInclude` | Extended options for simulation results |
740
-
741
- ### Method options types
742
-
743
- | Type | Description |
744
- | ---------------------------------- | --------------------------------------- |
745
- | `GetObjectOptions` | Options for `getObject` |
746
- | `GetObjectsOptions` | Options for `getObjects` |
747
- | `ListOwnedObjectsOptions` | Options for `listOwnedObjects` |
748
- | `ListCoinsOptions` | Options for `listCoins` |
749
- | `GetBalanceOptions` | Options for `getBalance` |
750
- | `ListBalancesOptions` | Options for `listBalances` |
751
- | `GetCoinMetadataOptions` | Options for `getCoinMetadata` |
752
- | `ExecuteTransactionOptions` | Options for `executeTransaction` |
753
- | `SimulateTransactionOptions` | Options for `simulateTransaction` |
754
- | `SignAndExecuteTransactionOptions` | Options for `signAndExecuteTransaction` |
755
- | `GetTransactionOptions` | Options for `getTransaction` |
756
- | `WaitForTransactionOptions` | Options for `waitForTransaction` |
757
- | `ListTransactionsOptions` | Options for `listTransactions` |
758
- | `ListEventsOptions` | Options for `listEvents` |
196
+ SDKs attach themselves to a client with `$extend`, so several SDKs can compose on one client
197
+ instance. See [Building SDKs](/sui/sdk-building) for how to author an extension, choose peer
198
+ dependencies, and structure your SDK's methods.