@mysten/docs 0.1.1

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 (108) hide show
  1. package/README.md +24 -0
  2. package/dist/bcs/index.md +358 -0
  3. package/dist/bcs/llms-index.md +4 -0
  4. package/dist/codegen/index.md +441 -0
  5. package/dist/codegen/llms-index.md +4 -0
  6. package/dist/dapp-kit/actions/connect-wallet.md +69 -0
  7. package/dist/dapp-kit/actions/disconnect-wallet.md +38 -0
  8. package/dist/dapp-kit/actions/sign-and-execute-transaction.md +96 -0
  9. package/dist/dapp-kit/actions/sign-personal-message.md +58 -0
  10. package/dist/dapp-kit/actions/sign-transaction.md +65 -0
  11. package/dist/dapp-kit/actions/switch-account.md +37 -0
  12. package/dist/dapp-kit/actions/switch-network.md +37 -0
  13. package/dist/dapp-kit/dapp-kit-instance.md +162 -0
  14. package/dist/dapp-kit/getting-started/create-dapp.md +151 -0
  15. package/dist/dapp-kit/getting-started/next-js.md +162 -0
  16. package/dist/dapp-kit/getting-started/react.md +172 -0
  17. package/dist/dapp-kit/getting-started/vue.md +193 -0
  18. package/dist/dapp-kit/index.md +70 -0
  19. package/dist/dapp-kit/llms-index.md +26 -0
  20. package/dist/dapp-kit/react/components/connect-button.md +42 -0
  21. package/dist/dapp-kit/react/components/connect-modal.md +51 -0
  22. package/dist/dapp-kit/react/components/index.md +13 -0
  23. package/dist/dapp-kit/react/dapp-kit-provider.md +86 -0
  24. package/dist/dapp-kit/react/hooks/index.md +25 -0
  25. package/dist/dapp-kit/react/hooks/use-current-account.md +33 -0
  26. package/dist/dapp-kit/react/hooks/use-current-client.md +36 -0
  27. package/dist/dapp-kit/react/hooks/use-current-network.md +28 -0
  28. package/dist/dapp-kit/react/hooks/use-current-wallet.md +36 -0
  29. package/dist/dapp-kit/react/hooks/use-dapp-kit.md +100 -0
  30. package/dist/dapp-kit/react/hooks/use-wallet-connection.md +48 -0
  31. package/dist/dapp-kit/react/hooks/use-wallets.md +33 -0
  32. package/dist/dapp-kit/state.md +169 -0
  33. package/dist/dapp-kit/theming.md +196 -0
  34. package/dist/dapp-kit/web-components/connect-button.md +89 -0
  35. package/dist/dapp-kit/web-components/connect-modal.md +177 -0
  36. package/dist/kiosk/advanced-examples.md +101 -0
  37. package/dist/kiosk/from-v1.md +320 -0
  38. package/dist/kiosk/index.md +22 -0
  39. package/dist/kiosk/kiosk-client/introduction.md +52 -0
  40. package/dist/kiosk/kiosk-client/kiosk-transaction/examples.md +119 -0
  41. package/dist/kiosk/kiosk-client/kiosk-transaction/kiosk-transaction.md +103 -0
  42. package/dist/kiosk/kiosk-client/kiosk-transaction/managing.md +235 -0
  43. package/dist/kiosk/kiosk-client/kiosk-transaction/purchasing.md +110 -0
  44. package/dist/kiosk/kiosk-client/querying.md +237 -0
  45. package/dist/kiosk/kiosk-client/transfer-policy-transaction/introduction.md +79 -0
  46. package/dist/kiosk/kiosk-client/transfer-policy-transaction/using-the-manager.md +115 -0
  47. package/dist/kiosk/llms-index.md +8 -0
  48. package/dist/llms-index.md +125 -0
  49. package/dist/payment-kit/getting-started.md +256 -0
  50. package/dist/payment-kit/index.md +132 -0
  51. package/dist/payment-kit/llms-index.md +8 -0
  52. package/dist/payment-kit/payment-kit-sdk.md +747 -0
  53. package/dist/payment-kit/payment-processing.md +372 -0
  54. package/dist/payment-kit/registry-management.md +529 -0
  55. package/dist/seal/index.md +85 -0
  56. package/dist/seal/llms-index.md +4 -0
  57. package/dist/slush-wallet/dapp.md +95 -0
  58. package/dist/slush-wallet/deep-linking.md +465 -0
  59. package/dist/slush-wallet/index.md +7 -0
  60. package/dist/slush-wallet/llms-index.md +6 -0
  61. package/dist/sui/bcs.md +134 -0
  62. package/dist/sui/clients/core.md +606 -0
  63. package/dist/sui/clients/graphql.md +101 -0
  64. package/dist/sui/clients/grpc.md +155 -0
  65. package/dist/sui/clients/index.md +95 -0
  66. package/dist/sui/clients/json-rpc.md +239 -0
  67. package/dist/sui/cryptography/keypairs.md +267 -0
  68. package/dist/sui/cryptography/multisig.md +194 -0
  69. package/dist/sui/cryptography/passkey.md +111 -0
  70. package/dist/sui/cryptography/webcrypto-signer.md +81 -0
  71. package/dist/sui/executors.md +148 -0
  72. package/dist/sui/faucet.md +26 -0
  73. package/dist/sui/hello-sui.md +115 -0
  74. package/dist/sui/index.md +53 -0
  75. package/dist/sui/install.md +61 -0
  76. package/dist/sui/llm-docs.md +32 -0
  77. package/dist/sui/llms-index.md +44 -0
  78. package/dist/sui/migrations/0.38.md +58 -0
  79. package/dist/sui/migrations/sui-1.0.md +455 -0
  80. package/dist/sui/migrations/sui-2.0/agent-prompt.md +42 -0
  81. package/dist/sui/migrations/sui-2.0/dapp-kit.md +350 -0
  82. package/dist/sui/migrations/sui-2.0/deepbook-v3.md +33 -0
  83. package/dist/sui/migrations/sui-2.0/index.md +158 -0
  84. package/dist/sui/migrations/sui-2.0/json-rpc-migration.md +386 -0
  85. package/dist/sui/migrations/sui-2.0/kiosk.md +120 -0
  86. package/dist/sui/migrations/sui-2.0/sdk-maintainers.md +90 -0
  87. package/dist/sui/migrations/sui-2.0/seal.md +14 -0
  88. package/dist/sui/migrations/sui-2.0/sui.md +341 -0
  89. package/dist/sui/migrations/sui-2.0/suins.md +43 -0
  90. package/dist/sui/migrations/sui-2.0/wallet-builders.md +66 -0
  91. package/dist/sui/migrations/sui-2.0/walrus.md +41 -0
  92. package/dist/sui/migrations/sui-2.0/zksend.md +95 -0
  93. package/dist/sui/plugins.md +258 -0
  94. package/dist/sui/sdk-building.md +344 -0
  95. package/dist/sui/transaction-building/basics.md +299 -0
  96. package/dist/sui/transaction-building/gas.md +62 -0
  97. package/dist/sui/transaction-building/intents.md +62 -0
  98. package/dist/sui/transaction-building/offline.md +73 -0
  99. package/dist/sui/transaction-building/sponsored-transactions.md +22 -0
  100. package/dist/sui/utils/derived_objects.md +59 -0
  101. package/dist/sui/utils/index.md +52 -0
  102. package/dist/sui/zklogin.md +83 -0
  103. package/dist/walrus/index.md +527 -0
  104. package/dist/walrus/llms-index.md +4 -0
  105. package/dist/zksend/index.md +27 -0
  106. package/dist/zksend/link-builder.md +192 -0
  107. package/dist/zksend/llms-index.md +5 -0
  108. package/package.json +66 -0
@@ -0,0 +1,258 @@
1
+ # Transaction Plugins
2
+
3
+ > Extend transaction building with reusable plugins
4
+
5
+ > **Warning:** The `Transaction` plugin API is experimental and may change rapidly as it is being developed.
6
+
7
+ This document describes the plugin API for the `Transaction` builder. It covers internal details
8
+ intended for developers interested in extending the `Transaction` builder. Developers using the
9
+ `Transaction` builder to build transactions do not need this level of detail. The `Transaction`
10
+ builder includes a plugin system designed to extend how transactions are built. The two primary
11
+ goals are:
12
+
13
+ 1. Allow developers to customize how data is resolved when building transactions.
14
+ 2. Provide a way for developers to extend the core commands that can be added to transactions.
15
+
16
+ The Plugin API consists of three main components: serialization plugins, build plugins, and
17
+ Transaction Intents. Serialization and build plugins act like middleware, allowing developers to
18
+ modify the data and commands added to a transaction before it is serialized to JSON or built into
19
+ BCS bytes. Transaction Intents are custom representations of user intents for a transaction,
20
+ eventually resolved to one or more commands in the transaction.
21
+
22
+ ## Contents of a Transaction
23
+
24
+ When a `Transaction` is created (e.g., `new Transaction()`), it is initialized with an empty
25
+ [TransactionDataBuilder](/typedoc/classes/_mysten_sui.transactions.TransactionDataBuilder.html)
26
+ instance which stores the state of the partially built transaction. The full API of the
27
+ `TransactionDataBuilder` won't be covered here, but you can find the available methods and
28
+ properties in the
29
+ [typedoc definition](/typedoc/classes/_mysten_sui.transactions.TransactionDataBuilder.html).
30
+
31
+ As commands are added to the `Transaction`, they are stored in the `TransactionDataBuilder`. The
32
+ `TransactionData` contains a list of commands and their arguments. The exact arguments a command
33
+ takes depend on the command, but they will be one of a few different types:
34
+
35
+ - `GasCoin`: A reference to the coin used to pay for gas.
36
+ - `Input`: An input to the transaction (described below).
37
+ - `Result`: The result of a previous command.
38
+ - `NestedResult`: If a previous command returns a tuple (e.g., `SplitCoin`), a `NestedResult` is
39
+ used to refer to a specific value in that tuple.
40
+
41
+ Transactions also store a list of Inputs, which refer to user-provided values. Inputs can either be
42
+ objects or Pure values and can be represented in several different ways:
43
+
44
+ - `Pure`: An input value serialized to BCS. Pure values are generally scalar values or simple
45
+ wrappers like options or vectors and cannot represent object types.
46
+ - `Object`: A fully resolved object reference, which will be one of the following types:
47
+ - `ImmOrOwnedObject`: A reference to an object, including the object's `id`, `version`, and
48
+ `digest`.
49
+ - `SharedObject`: A reference to a shared object, including the object's `id`,
50
+ `initialSharedVersion`, and whether the shared object is used mutably.
51
+ - `Receiving`: A reference to a receiving object, including the object's `id`, `version`, and
52
+ `digest`.
53
+ - `UnresolvedPure`: A placeholder for a pure value that has not been serialized to BCS.
54
+ - `UnresolvedObject`: A partial reference to an object, often containing just the object's `id`, but
55
+ may also include a version, digest, or initialSharedVersion.
56
+
57
+ ## Lifecycle of a Transaction
58
+
59
+ Because transactions can contain `UnresolvedPure` and `UnresolvedObject` inputs, these values need
60
+ to be resolved before the transaction can be serialized to BCS. However, these unresolved inputs can
61
+ be represented in JSON. What may not be able to be represented in JSON are Transaction Intents.
62
+ Transaction Intents represent custom concepts added by plugins or third-party SDKs. To account for
63
+ this, the build process of a transaction is split into two phases: serialization and building.
64
+ Serialization prepares the transaction to be serialized to JSON by running serialization plugins,
65
+ and resolving any unsupported intents. The Build phase then runs, which runs build plugins and
66
+ resolves any UnresolvedPure and UnresolvedObject inputs, before the transaction is serialized to
67
+ BCS.
68
+
69
+ ## Serialization Plugins
70
+
71
+ Serialization plugins can be added to a `Transaction` by calling the `addSerializationPlugin` method
72
+ on a `Transaction` instance. Serialization plugins are called in the order they are added and are
73
+ passed the `TransactionDataBuilder` instance of the transaction.
74
+
75
+ ```typescript
76
+ const transaction = new Transaction();
77
+
78
+ transaction.addSerializationPlugin(async (transactionData, buildOptions, next) => {
79
+ // Modify the data before running other serialization steps
80
+ await next();
81
+ // Modify the data after running other serialization steps
82
+ });
83
+ ```
84
+
85
+ ## Build Plugins
86
+
87
+ The build phase is responsible for taking unresolved objects and unresolved pure values and
88
+ converting them to their resolved versions by querying the RPC API to fetch the missing data. Build
89
+ plugins can hook into this phase to resolve some of this data from a cache instead, avoiding extra
90
+ API calls.
91
+
92
+ Build plugins work just like serialization plugins and can be added to a `Transaction` by calling
93
+ the `addBuildPlugin` method on a `Transaction` instance. Build plugins are called in the order they
94
+ are added and are passed the `TransactionDataBuilder` instance of the transaction.
95
+
96
+ The following example demonstrates a simplified version of the caching plugin used by the
97
+ `SerialTransactionExecutor` and `ParallelTransactionExecutor` classes. This example works by adding
98
+ missing object versions and digest from a cache. Updating the cache (which could be done by looking
99
+ at transaction effects of previous transactions) is not covered in this example.
100
+
101
+ ```typescript
102
+
103
+ BuildTransactionOptions,
104
+ Transaction,
105
+ TransactionDataBuilder,
106
+ } from '@mysten/sui/transactions';
107
+
108
+ const objectCache = new Map<string, { objectId: string; version: string; digest: string }>();
109
+
110
+ function simpleObjectCachePlugin(
111
+ transactionData: TransactionDataBuilder,
112
+ _options: BuildTransactionOptions,
113
+ next: () => Promise<void>,
114
+ ) {
115
+ for (const input of transactionData.inputs) {
116
+ if (!input.UnresolvedObject) continue;
117
+
118
+ const cached = objectCache.get(input.UnresolvedObject.objectId);
119
+
120
+ if (!cached) continue;
121
+
122
+ if (cached.version && !input.UnresolvedObject.version) {
123
+ input.UnresolvedObject.version = cached.version;
124
+ }
125
+
126
+ if (cached.digest && !input.UnresolvedObject.digest) {
127
+ input.UnresolvedObject.digest = cached.digest;
128
+ }
129
+ }
130
+
131
+ return next();
132
+ }
133
+
134
+ // Example usage of the build plugin
135
+ const transaction = new Transaction();
136
+ transaction.addBuildPlugin(simpleObjectCachePlugin);
137
+ ```
138
+
139
+ ## Transaction Intents
140
+
141
+ Transaction Intents consist of two parts: adding the intent to the transaction and resolving the
142
+ intent to standard commands.
143
+
144
+ Adding an intent is similar to adding any other command to a transaction:
145
+
146
+ ```typescript
147
+
148
+ const transaction = new Transaction();
149
+
150
+ transaction.add(
151
+ Commands.Intent({
152
+ name: 'TransferToSender',
153
+ inputs: {
154
+ objects: [transaction.object(someId)],
155
+ },
156
+ }),
157
+ );
158
+ ```
159
+
160
+ To make our custom `TransferToSender` intent easier to use, we can write a helper function that
161
+ wraps things up a bit. The `add` method on transactions accepts a function that will be passed the
162
+ current transaction instance. This allows us to create a helper that automatically adds the intent:
163
+
164
+ ```typescript
165
+
166
+ function transferToSender(objects: TransactionObjectInput[]) {
167
+ return (tx: Transaction) => {
168
+ tx.add(
169
+ Commands.Intent({
170
+ name: 'TransferToSender',
171
+ inputs: {
172
+ objects: objects.map((obj) => tx.object(obj)),
173
+ },
174
+ }),
175
+ );
176
+ };
177
+ }
178
+
179
+ const transaction = new Transaction();
180
+
181
+ transaction.add(transferToSender(['0x1234']));
182
+ ```
183
+
184
+ Now that we've added the intent to the transaction, we need to resolve the intent to standard
185
+ commands. To do this, we'll use the `addIntentResolver` method on the `Transaction` instance. The
186
+ `addIntentResolver` method works like serialization and build plugins but will only be called if the
187
+ intent is present in the transaction.
188
+
189
+ ```typescript
190
+
191
+ const transaction = new Transaction();
192
+
193
+ transaction.addIntentResolver('TransferToSender', resolveTransferToSender);
194
+
195
+ async function resolveTransferToSender(
196
+ transactionData: TransactionDataBuilder,
197
+ buildOptions: BuildTransactionOptions,
198
+ next: () => Promise<void>,
199
+ ) {
200
+ if (!transactionData.sender) {
201
+ throw new Error('Sender must be set to resolve TransferToSender');
202
+ }
203
+
204
+ // Add an input that references the sender's address
205
+ const addressInput = Inputs.Pure(bcs.Address.serialize(transactionData.sender));
206
+ transactionData.inputs.push(addressInput);
207
+ // Get the index of the input to use when adding the TransferObjects command
208
+ const addressIndex = transactionData.inputs.length - 1;
209
+
210
+ for (const [index, transaction] of transactionData.commands.entries()) {
211
+ if (transaction.$kind !== '$Intent' || transaction.$Intent.name !== 'TransferToSender') {
212
+ continue;
213
+ }
214
+
215
+ // This will replace the intent command with the correct TransferObjects command
216
+ transactionData.replaceCommand(index, [
217
+ Commands.TransferObjects(
218
+ // The inputs for intents are not currently typed, so we need to cast to the correct type here
219
+ transaction.$Intent.inputs.objects as Extract<
220
+ TransactionObjectArgument,
221
+ { $kind: 'Input' }
222
+ >,
223
+ // This is a CallArg referencing the addressInput we added above
224
+ {
225
+ Input: addressIndex,
226
+ },
227
+ ),
228
+ ]);
229
+ }
230
+
231
+ // Plugins always need to call next() to continue the build process
232
+ return next();
233
+ }
234
+ ```
235
+
236
+ Manually adding intent resolvers to a transaction can be cumbersome, so we can add the resolver
237
+ automatically when our `transferToSender` helper is called:
238
+
239
+ ```typescript
240
+
241
+ function transferToSender(objects: TransactionObjectInput[]) {
242
+ return (tx: Transaction) => {
243
+ // As long as we are adding the same function reference, it will only be added once
244
+ tx.addIntentResolver('TransferToSender', resolveTransferToSender);
245
+ tx.add(
246
+ Commands.Intent({
247
+ name: 'TransferToSender',
248
+ inputs: {
249
+ objects: objects.map((obj) => tx.object(obj)),
250
+ },
251
+ }),
252
+ );
253
+ };
254
+ }
255
+
256
+ const transaction = new Transaction();
257
+ transaction.add(transferToSender(['0x1234']));
258
+ ```
@@ -0,0 +1,344 @@
1
+ # Building SDKs
2
+
3
+ > Build custom SDKs on top of the Sui TypeScript SDK
4
+
5
+ This guide covers recommended patterns for building TypeScript SDKs that integrate with the Sui SDK.
6
+ Following these patterns ensures your SDK integrates seamlessly with the ecosystem, works across
7
+ different transports (JSON-RPC, GraphQL, gRPC), and composes well with other SDKs.
8
+
9
+ **Key requirement:** All SDKs should depend on [`ClientWithCoreApi`](./clients/core), which is the
10
+ transport-agnostic interface implemented by all Sui clients. This ensures your SDK works with any
11
+ client the user chooses.
12
+
13
+ ## Package Setup
14
+
15
+ ### Use Mysten Packages as Peer Dependencies
16
+
17
+ SDKs should declare all `@mysten/*` packages as **peer dependencies** rather than direct
18
+ dependencies. This ensures users get a single shared instance of each package, avoiding version
19
+ conflicts and duplicate code.
20
+
21
+ ```json title="package.json"
22
+ {
23
+ "name": "@your-org/your-sdk",
24
+ "peerDependencies": {
25
+ "@mysten/sui": "^2.0.0",
26
+ "@mysten/bcs": "^2.0.0"
27
+ },
28
+ "devDependencies": {
29
+ "@mysten/sui": "^2.0.0",
30
+ "@mysten/bcs": "^2.0.0"
31
+ }
32
+ }
33
+ ```
34
+
35
+ This approach:
36
+
37
+ - Prevents multiple versions of Mysten packages from being bundled
38
+ - Ensures compatibility with user's chosen package versions
39
+ - Reduces bundle size for end users
40
+ - Avoids subtle bugs from mismatched package instances
41
+ - Allows the SDK to work with any compatible client
42
+
43
+ ## Client Extensions
44
+
45
+ The recommended way to build SDKs is using the **client extension pattern**. This allows your SDK to
46
+ extend the Sui client with custom functionality. This makes it easier to use custom SDKs across the
47
+ ecosystem without having to build custom bindings (like react context providers) for each individual
48
+ SDK and client.
49
+
50
+ ### Extension Pattern
51
+
52
+ Client extensions use the `$extend` method to add functionality to any Sui client. Create a factory
53
+ function that returns a `name` and `register` function:
54
+
55
+ ```typescript
56
+
57
+ name?: Name;
58
+ // Add SDK-specific configuration here
59
+ apiKey?: string;
60
+ }
61
+
62
+ name = 'mySDK' as Name,
63
+ ...options
64
+ }: MySDKOptions<Name> = {}) {
65
+ return {
66
+ name,
67
+ register: (client: ClientWithCoreApi) => {
68
+ return new MySDKClient({ client, ...options });
69
+ },
70
+ };
71
+ }
72
+
73
+ #client: ClientWithCoreApi;
74
+ #apiKey?: string;
75
+
76
+ constructor({ client, apiKey }: { client: ClientWithCoreApi; apiKey?: string }) {
77
+ this.#client = client;
78
+ this.#apiKey = apiKey;
79
+ }
80
+
81
+ async getResource(id: string) {
82
+ const result = await this.#client.core.getObject({ objectId: id });
83
+ // Process and return result
84
+ return result;
85
+ }
86
+ }
87
+ ```
88
+
89
+ Users can then extend their client:
90
+
91
+ ```typescript
92
+
93
+ const client = new SuiGrpcClient({
94
+ network: 'testnet',
95
+ baseUrl: 'https://fullnode.testnet.sui.io:443',
96
+ }).$extend(mySDK());
97
+
98
+ // Access your extension
99
+ await client.mySDK.getResource('0x...');
100
+ ```
101
+
102
+ ### Real-World Examples
103
+
104
+ Several official SDKs use this pattern:
105
+
106
+ - **[@mysten/walrus](https://www.npmjs.com/package/@mysten/walrus)** - Decentralized storage
107
+ - **[@mysten/seal](https://www.npmjs.com/package/@mysten/seal)** - Encryption and key management
108
+
109
+ ## SDK Organization
110
+
111
+ Most Mysten SDKs do not strictly follow these patterns yet, but we recommend scoping methods on your
112
+ client extension into the following categories for clarity and consistency:
113
+
114
+ | Property | Purpose | Example |
115
+ | -------- | --------------------------------------------------------- | ----------------------------------- |
116
+ | Methods | Top-level operations (execute actions or read/parse data) | `sdk.readBlob()`, `sdk.getConfig()` |
117
+ | `tx` | Methods that create transactions without executing | `sdk.tx.registerBlob()` |
118
+ | `bcs` | BCS type definitions for encoding/decoding | `sdk.bcs.MyStruct` |
119
+ | `call` | Methods returning Move calls that can be used with tx.add | `sdk.call.myFunction()` |
120
+ | `view` | Methods that use simulate API to read onchain state | `sdk.view.getState()` |
121
+
122
+ ```typescript
123
+
124
+ #client: ClientWithCoreApi;
125
+
126
+ constructor({ client }: { client: ClientWithCoreApi }) {
127
+ this.#client = client;
128
+ }
129
+
130
+ // Top-level methods - execute actions or read/parse data
131
+ async executeAction(options: ActionOptions) {
132
+ const transaction = this.tx.createAction(options);
133
+ // Execute and return result
134
+ }
135
+
136
+ async getResource(objectId: string) {
137
+ const { object } = await this.#client.core.getObject({
138
+ objectId,
139
+ include: { content: true },
140
+ });
141
+ return myModule.MyStruct.parse(object.content);
142
+ }
143
+
144
+ // Transaction builders
145
+ tx = {
146
+ createAction: (options: ActionOptions) => {
147
+ const transaction = new Transaction();
148
+ transaction.add(this.call.action(options));
149
+ return transaction;
150
+ },
151
+ };
152
+
153
+ // Move call helpers - use generated functions with typed options
154
+ call = {
155
+ action: (options: ActionOptions) => {
156
+ return myModule.action({
157
+ arguments: {
158
+ obj: options.objectId,
159
+ amount: options.amount,
160
+ },
161
+ });
162
+ },
163
+ };
164
+
165
+ // View methods - use simulate API to read onchain state
166
+ view = {
167
+ getBalance: async (managerId: string) => {
168
+ const tx = new Transaction();
169
+ tx.add(myModule.getBalance({ arguments: { manager: managerId } }));
170
+
171
+ const res = await this.#client.core.simulateTransaction({
172
+ transaction: tx,
173
+ include: { commandResults: true },
174
+ });
175
+
176
+ return bcs.U64.parse(res.commandResults![0].returnValues[0].bcs);
177
+ },
178
+ };
179
+ }
180
+ ```
181
+
182
+ ## Transaction Building Patterns
183
+
184
+ ### Transaction Thunks
185
+
186
+ Transaction thunks are functions that accept a `Transaction` and mutate it. This pattern enables
187
+ composition across multiple SDKs in a single transaction.
188
+
189
+ ```typescript
190
+
191
+ // Synchronous thunk for operations that don't need async work
192
+ function createResource(options: { name: string }) {
193
+ return (tx: Transaction): TransactionObjectArgument => {
194
+ const [resource] = tx.moveCall({
195
+ target: `${PACKAGE_ID}::module::create`,
196
+ arguments: [tx.pure.string(options.name)],
197
+ });
198
+ return resource;
199
+ };
200
+ }
201
+
202
+ // Usage
203
+ const tx = new Transaction();
204
+ const resource = tx.add(createResource({ name: 'my-resource' }));
205
+ tx.transferObjects([resource], recipient);
206
+ ```
207
+
208
+ ### Async Thunks
209
+
210
+ For operations requiring async work (like fetching package IDs or configuration), return async
211
+ thunks. These are used with `tx.add()` exactly like synchronous thunks - the async resolution
212
+ happens automatically before signing:
213
+
214
+ ```typescript
215
+ function createResourceAsync(options: { name: string }) {
216
+ return async (tx: Transaction): Promise<TransactionObjectArgument> => {
217
+ // Async work happens here, before the transaction is signed
218
+ const packageId = await getLatestPackageId();
219
+
220
+ const [resource] = tx.moveCall({
221
+ target: `${packageId}::module::create`,
222
+ arguments: [tx.pure.string(options.name)],
223
+ });
224
+ return resource;
225
+ };
226
+ }
227
+
228
+ // Usage is identical to synchronous thunks
229
+ const tx = new Transaction();
230
+ const resource = tx.add(createResourceAsync({ name: 'my-resource' }));
231
+ tx.transferObjects([resource], recipient);
232
+
233
+ // Async work resolves automatically when the transaction is built/signed
234
+ await signer.signAndExecuteTransaction({ transaction: tx, client });
235
+ ```
236
+
237
+ This pattern is critical for web wallet compatibility - async work that happens during transaction
238
+ construction won't block the popup triggered by user interaction.
239
+
240
+ ## Transaction Execution
241
+
242
+ ### Accept a Signer Parameter
243
+
244
+ For methods that execute transactions, accept a `Signer` parameter and always use the signer to
245
+ execute the transaction. This enables:
246
+
247
+ - Wallet integration through dApp Kit
248
+ - Transaction sponsorship
249
+ - Custom signing flows
250
+
251
+ ```typescript
252
+
253
+ #client: ClientWithCoreApi;
254
+
255
+ async createAndExecute({ signer, ...options }: CreateOptions & { signer: Signer }) {
256
+ const transaction = this.tx.create(options);
257
+
258
+ // Use signAndExecuteTransaction for maximum flexibility
259
+ const result = await signer.signAndExecuteTransaction({
260
+ transaction,
261
+ client: this.#client,
262
+ });
263
+
264
+ return result;
265
+ }
266
+ }
267
+ ```
268
+
269
+ Using `signAndExecuteTransaction` allows wallets and sponsors to customize execution behavior.
270
+
271
+ ## Code Generation
272
+
273
+ For SDKs that interact with Move contracts, use **[@mysten/codegen](/codegen)** to generate
274
+ type-safe TypeScript bindings from your Move packages.
275
+
276
+ Benefits include type safety, BCS parsing, IDE support, and MoveRegistry support for human-readable
277
+ package names. See the [codegen documentation](/codegen) for setup instructions.
278
+
279
+ ### Using Generated Code
280
+
281
+ The generated code provides both Move call functions and BCS struct definitions:
282
+
283
+ ```typescript
284
+
285
+ // Generated Move call functions return thunks with typed options
286
+ const tx = new Transaction();
287
+ tx.add(
288
+ myContract.doSomething({
289
+ arguments: {
290
+ obj: '0x123...',
291
+ amount: 100n,
292
+ },
293
+ }),
294
+ );
295
+
296
+ // Generated BCS types parse on-chain data
297
+ const { object } = await client.core.getObject({
298
+ objectId: '0x123...',
299
+ include: { content: true },
300
+ });
301
+ const parsed = myContract.MyStruct.parse(object.content);
302
+ ```
303
+
304
+ See the [codegen documentation](/codegen) for complete setup and configuration options.
305
+
306
+ ## Reading Object Contents
307
+
308
+ SDKs often need to fetch objects and parse their BCS-encoded content. Use `getObject` with
309
+ `include: { content: true }` and generated BCS types:
310
+
311
+ ```typescript
312
+
313
+ async function getResource(objectId: string) {
314
+ const { object } = await this.#client.core.getObject({
315
+ objectId,
316
+ include: { content: true },
317
+ });
318
+
319
+ if (!object) {
320
+ throw new Error(`Object ${objectId} not found`);
321
+ }
322
+
323
+ // Parse BCS content using generated type
324
+ return MyStruct.parse(object.content);
325
+ }
326
+ ```
327
+
328
+ For batching multiple object fetches, use `getObjects`:
329
+
330
+ ```typescript
331
+ async function getResources(objectIds: string[]) {
332
+ const { objects } = await this.#client.core.getObjects({
333
+ objectIds,
334
+ include: { content: true },
335
+ });
336
+
337
+ return objects.map((obj) => {
338
+ if (obj instanceof Error) {
339
+ throw obj;
340
+ }
341
+ return MyStruct.parse(obj.content);
342
+ });
343
+ }
344
+ ```