suidouble 2.5.0 → 2.17.0-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 (57) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/README.md +222 -131
  3. package/index.js +0 -2
  4. package/lib/SuiCliCommands.js +18 -25
  5. package/lib/SuiCoin.js +79 -137
  6. package/lib/SuiCoins.js +41 -29
  7. package/lib/SuiCommonMethods.js +40 -3
  8. package/lib/SuiEvent.js +54 -6
  9. package/lib/SuiInBrowser.js +161 -16
  10. package/lib/SuiInBrowserAdapter.js +192 -40
  11. package/lib/SuiLocalTestValidator.js +76 -14
  12. package/lib/SuiMaster.js +335 -139
  13. package/lib/SuiMemoryObjectStorage.js +66 -73
  14. package/lib/SuiObject.js +128 -153
  15. package/lib/SuiPackage.js +292 -187
  16. package/lib/SuiPackageModule.js +176 -221
  17. package/lib/SuiPaginatedResponse.js +288 -25
  18. package/lib/SuiPseudoRandomAddress.js +29 -2
  19. package/lib/SuiTransaction.js +115 -70
  20. package/lib/SuiUtils.js +179 -127
  21. package/package.json +29 -13
  22. package/test/build_modules.test.js +41 -0
  23. package/test/coins.test.js +17 -16
  24. package/test/custom_transaction.test.js +167 -0
  25. package/test/event_listeners.test.js +171 -0
  26. package/test/failed_transaction.test.js +184 -0
  27. package/test/name_service.test.js +28 -0
  28. package/test/owned_objects.test.js +148 -0
  29. package/test/rpc.test.js +3 -6
  30. package/test/sui_in_browser.test.js +2 -2
  31. package/test/sui_master_basic.test.js +4 -5
  32. package/test/sui_master_onlocal.test.js +84 -22
  33. package/test/sui_object_properties.test.js +85 -0
  34. package/test/test_move_contracts/different_types/Move.lock +18 -0
  35. package/test/test_move_contracts/suidouble_chat/Move.lock +18 -0
  36. package/tsconfig.json +15 -0
  37. package/types/index.d.ts +15 -0
  38. package/types/lib/SuiCliCommands.d.ts +6 -0
  39. package/types/lib/SuiCoin.d.ts +183 -0
  40. package/types/lib/SuiCoins.d.ts +93 -0
  41. package/types/lib/SuiCommonMethods.d.ts +37 -0
  42. package/types/lib/SuiEvent.d.ts +95 -0
  43. package/types/lib/SuiInBrowser.d.ts +195 -0
  44. package/types/lib/SuiInBrowserAdapter.d.ts +173 -0
  45. package/types/lib/SuiLocalTestValidator.d.ts +92 -0
  46. package/types/lib/SuiMaster.d.ts +333 -0
  47. package/types/lib/SuiMemoryObjectStorage.d.ts +96 -0
  48. package/types/lib/SuiObject.d.ts +135 -0
  49. package/types/lib/SuiPackage.d.ts +233 -0
  50. package/types/lib/SuiPackageModule.d.ts +139 -0
  51. package/types/lib/SuiPaginatedResponse.d.ts +148 -0
  52. package/types/lib/SuiPseudoRandomAddress.d.ts +33 -0
  53. package/types/lib/SuiTransaction.d.ts +92 -0
  54. package/types/lib/SuiUtils.d.ts +152 -0
  55. package/types/lib/data/icons.d.ts +12 -0
  56. package/lib/SuiTestScenario.js +0 -169
  57. package/test/sui_test_scenario.test.js +0 -61
@@ -0,0 +1,7 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(npx tsc *)"
5
+ ]
6
+ }
7
+ }
package/README.md CHANGED
@@ -1,23 +1,30 @@
1
1
  # suidouble
2
2
 
3
- Set of provider, package and object classes for javascript representation of Sui's smart contracts. Use same code for publishing, upgrading, integration testing, interaction with smart contracts and integration in browser dapps. Very alpha for now.
3
+ Set of provider, package and object classes for JavaScript representation of Sui Move smart contracts. Use the same code for publishing, upgrading, integration testing, interacting with contracts, and building browser dApps.
4
4
 
5
5
  - [Installation](#installation)
6
6
  - [Usage](#usage)
7
7
  - [Connecting](#connecting)
8
8
  - [Attaching a package](#attaching-a-package)
9
9
  - [Interacting with smart contract](#interacting-with-smart-contract)
10
- - [SuiObject](#suiobject)
11
- - [Fetching objects](#fetching-objects)
12
- - [Fetching Events](#fetching-events)
13
- - [Subscribe to Events](#subscribing-to-events)
14
- - [Executing smart contract method](#executing-smart-contract-method)
15
- - [Sending sui / coins with smart contract methods](#sending-sui--coins-with-smart-contract-methods)
16
- - [Composing transaction block yourself](#composing-transaction-block-yourself)
10
+ - [SuiObject](#suiobject)
11
+ - [Fetching events](#fetching-events)
12
+ - [Executing smart contract method](#executing-smart-contract-method)
13
+ - [Move method argument types](#move-method-argument-types)
14
+ - [Move methods with type parameters](#move-methods-with-type-parameters)
15
+ - [Sending SUI / coins](#sending-sui--coins-with-smart-contract-methods)
16
+ - [Composing a transaction yourself](#composing-a-transaction-yourself)
17
+ - [Fetching objects](#fetching-objects)
18
+ - [Fetching object fields](#fetching-object-fields)
19
+ - [Fetching objects by id](#fetching-objects-by-id)
20
+ - [Querying owned objects](#querying-owned-objects)
21
+ - [Fetching transaction history for an object](#fetching-transaction-history-for-an-object)
22
+ - [Resolving a Sui Name Service name](#resolving-a-sui-name-service-suins-name)
17
23
  - [Publishing the package](#publishing-the-package)
18
24
  - [Upgrading the package](#upgrading-the-package)
19
- - [Writing Sue Move intergration tests](#sui-move-integration-testing)
20
- - [Connecting web3 dapps to Sui](#sui-move-connect-in-browser)
25
+ - [Writing Sui Move integration tests](#sui-move-integration-testing)
26
+ - [Connecting web3 dApps to Sui](#sui-move-connect-in-browser)
27
+ - [Unit tests](#unit-tests)
21
28
  - [Todo](#todo)
22
29
 
23
30
  ### Sample applications
@@ -51,29 +58,29 @@ You can initialize it directly, if you have keypair, secret phrase, or privateKe
51
58
  const suiMaster = new SuiMaster({
52
59
  keypair: Ed25519Keypair || Secp256r1Keypair || Secp256k1Keypair,
53
60
  debug: true, // echo testing messages to console
54
- client: 'test', // 'test', 'dev', 'local', 'main' or instance of this lib's SuiLocalTestValidator
61
+ client: 'testnet', // 'testnet', 'devnet', 'localnet', 'mainnet' or instance of this lib's SuiLocalTestValidator
55
62
  });
56
63
  const suiMaster = new SuiMaster({
57
64
  debug: false,
58
65
  privateKey: 'suiprivkey1qpwly9xrfsv50mqug706s40l58klez5q6mpchq4f5ldzktjyr4x7yhj9lf2',
59
- client: 'dev',
66
+ client: 'devnet',
60
67
  });
61
68
  const suiMaster = new SuiMaster({
62
69
  debug: false,
63
70
  phrase: 'thrive mean two thrive mean two thrive mean two thrive mean two', // secret phrase to generate keypair
64
- client: 'dev',
71
+ client: 'devnet',
65
72
  });
66
73
  const suiMaster = new SuiMaster({
67
74
  debug: false,
68
75
  phrase: 'thrive mean two thrive mean two thrive mean two thrive mean two', // secret phrase to generate keypair
69
76
  accountIndex: 1, // derive path index (you can generate few addresses with same seed phrase)
70
- client: 'dev',
77
+ client: 'devnet',
71
78
  });
72
79
  const suiMaster = new SuiMaster({
73
80
  debug: false,
74
81
  phrase: 'thrive mean two thrive mean two thrive mean two thrive mean two', // secret phrase to generate keypair
75
- keypairAlgo: 'secp256k1', // 'secp256r1' or 'secp256r1' or 'ed25519' default is ed25519
76
- client: 'dev',
82
+ keypairAlgo: 'secp256k1', // 'secp256k1' or 'secp256r1' or 'ed25519' default is ed25519
83
+ client: 'devnet',
77
84
  });
78
85
  ```
79
86
 
@@ -119,7 +126,7 @@ const contract = suiMaster.addPackage({
119
126
  await contract.isOnChain();
120
127
  ```
121
128
 
122
- Yes, it can find it's address on chain, by comparing Move's module names with package you own on chain. Works ok if you want to test upgrading or something. Also, you can attach the package only by modules names. This will work in browser too (note: you have to own this package, its UpgradeCap):
129
+ Yes, it can find its address on chain, by comparing Move's module names with package you own on chain. Works ok if you want to test upgrading or something. Also, you can attach the package only by modules names. This will work in browser too (note: you have to own this package, its UpgradeCap):
123
130
 
124
131
  ```javascript
125
132
  const contract = suiMaster.addPackage({
@@ -132,7 +139,7 @@ await contract.isOnChain();
132
139
 
133
140
  ##### SuiObject
134
141
 
135
- Everyhing in Sui is an object. So is in suidouble. SuiObject's instance class follows:
142
+ Everything in Sui is an object. So is in suidouble. SuiObject's instance class follows:
136
143
 
137
144
  ```javascript
138
145
  suiObject.id; // '0x10cded4f9df05e37b44e3be2ffa9004dec77786950719fad6083694fdca45bf2' or something
@@ -146,19 +153,15 @@ suiObject.fields; // {}, object. Fields stored on blockchain
146
153
  suiObject.display; // display object stored on blockchain
147
154
  suiObject.localProperties; // {} object. Any local properties you want to attach to object. No interaction with blockchain. May be helpful to store some temp data
148
155
  suiObject.isOwnedBy('0x10cded4f9df05e37b44e3be2ffa9004dec77786950719fad6083694fdca45bf2'); // is object owned by somebody or some object
149
- /// past versions:
150
- await suiObject.getPastObject(version); // get instance of object from the past
151
- await suiObject.getPastObject(); // try to get previous
152
156
  /// object-related transactions:
153
- await suiObject.queryTransactionBlocks(); // returns instance of SuiPaginatedResponse
157
+ await suiObject.fetchTransactions(); // returns instance of SuiPaginatedResponse
154
158
  ```
155
159
 
156
- @todo: better SuiObject documentation
157
-
158
160
  ##### fetching events
159
161
 
160
162
  ```javascript
161
- const events = await contract.fetchEvents('modulename', {eventTypeName: 'ChatResponseCreated', order: 'descending'});
163
+ // fetch events for a specific module (all events or filtered by type):
164
+ const events = await contract.modules.modulename.fetchEvents({eventTypeName: 'ChatResponseCreated', order: 'descending'});
162
165
  // events is instance of SuiPaginatedResponse. Data is stored in .data, has method to fetch next page - .nextPage();
163
166
  while (events.hasNextPage) {
164
167
  for (const event of events.data) {
@@ -168,153 +171,245 @@ while (events.hasNextPage) {
168
171
  }
169
172
  await events.nextPage();
170
173
  }
171
- // const events = await contract.fetchEvents('modulename', {order: 'descending'}); // or all module events
174
+ // const events = await contract.modules.modulename.fetchEvents({order: 'descending'}); // all module events
175
+ // const events = await contract.fetchEvents({order: 'descending'}); // all events across all modules in the package
172
176
  ```
173
177
 
174
- ##### subscribing to events
175
-
176
- *** Subscribe to Events is deprecated in Sui SDK *** You should plan to use different architecture in your application.
177
-
178
178
 
179
179
  ##### executing smart contract method
180
180
 
181
+ Both `SuiPackage` and `SuiPackageModule` expose a `moveCall` method. After execution the result is a `SuiTransaction` with `created`, `mutated`, and `deleted` arrays of `SuiObject` instances. Created and mutated objects are also pushed into `suiMaster.objectStorage` automatically.
182
+
181
183
  ```javascript
182
- // executing method with parameters of (chat_shop: &ChatShop, metadata: vector<u8>, text: vector<u8>)
183
- const res = await contract.moveCall('chat', 'post', ['0x10cded4f9df05e37b44e3be2ffa9004dec77786950719fad6083694fdca45bf2', contract.arg('vector<u8>', [3,24,55]), contract.arg('string', 'anotherparam') ]);
184
- // or await contract.modules.chat.moveCall('methodname', ['somedata', [3,24,55], 'anotherparam']);
185
- console.log(res);
186
- for (const object of res.created) {
187
- console.log('created', object.address, 'with type of', object.typeName); // instances of SuiObject (@todo: write documentation for it)
188
- }
189
- for (const object of res.mutated) {
190
- console.log('mutated', object.address, 'with type of', object.typeName);
191
- }
192
- for (const object of res.deleted) {
193
- console.log('deleted', object.address, 'with type of', object.typeName, object.isDeleted);
194
- }
184
+ // via SuiPackage (module name is the first argument):
185
+ const res = await contract.moveCall('suidouble_chat', 'post', [
186
+ '0x10cded4f9df05e37b44e3be2ffa9004dec77786950719fad6083694fdca45bf2', // object id string
187
+ contract.arg('string', 'hello'),
188
+ contract.arg('string', 'metadata'),
189
+ ]);
190
+
191
+ // or directly via SuiPackageModule:
192
+ const res = await contract.modules.suidouble_chat.moveCall('post', [
193
+ '0x10cded4f9df05e37b44e3be2ffa9004dec77786950719fad6083694fdca45bf2',
194
+ contract.arg('string', 'hello'),
195
+ contract.arg('string', 'metadata'),
196
+ ]);
197
+
198
+ // inspect results — all SuiObject instances
199
+ for (const object of res.created) {
200
+ // Note: fields are NOT populated from effects. Call fetchFields() first if you need them.
201
+ await object.fetchFields();
202
+ console.log('created', object.address, object.typeName, object.fields);
203
+ }
204
+ for (const object of res.mutated) {
205
+ console.log('mutated', object.address, object.typeName);
206
+ }
207
+ for (const object of res.deleted) {
208
+ console.log('deleted', object.address, object.isDeleted); // true
209
+ }
195
210
  ```
196
211
 
197
- ##### move methods argumets types
198
-
199
- Sui forces you to specify argument type in SDK v1.0, so we are going to follow this paradigm. With few little helpers. Both `SuiPackage` and `SuiPackageModule` have methods to make Inputs.Pure with bcs for you based on the desired type, you can use for executing `suiPackage.moveCall` or `suiPackageModule.moveCall`:
212
+ The returned `SuiTransaction` also exposes transaction-level metadata:
200
213
 
201
214
  ```javascript
202
- const arguments = [];
203
- arguments.push(contract.arg('bool', true));
204
- arguments.push(contract.arg('u8', 222));
205
- arguments.push(contract.arg('u16', 2222));
206
- arguments.push(contract.arg('u32', 3333));
207
- arguments.push(contract.arg('u64', 4444));
208
- arguments.push(contract.arg('u128', 5555));
209
- arguments.push(contract.arg('u256', 6666));
210
- arguments.push(contract.arg('address', '0xd9a95d7cc137f71dd7766f02791536453062a7509e9f461620cc4f583b09134c'));
211
- arguments.push(contract.arg('string', 'some utf-8 💧string'));
212
- arguments.push(contract.arg('vector<u8>', [222,111,211])); // works for other vectors with primitive contents, e.g. u128, bool etc
215
+ res.digest; // Base58-encoded transaction digest
216
+ res.isSuccessful(); // boolean — true if the transaction executed without errors
217
+ res.gasUsed; // bigint — net gas cost in MIST (computationCost + storageCost − storageRebate)
218
+ res.executedEpoch; // number — epoch the transaction was finalised in
219
+ res.timestampMs; // number | null — checkpoint timestamp in ms (only for GraphQL-fetched transactions)
220
+ res.events; // SuiEvent[] — events emitted (requires include: { events: true })
213
221
  ```
214
222
 
215
- Take a look at unit test covering all types arguments [here](test/different_types_args.test.js)
223
+ ##### move method argument types
216
224
 
217
- ##### move methods typed arguments
225
+ `SuiPackage` and `SuiPackageModule` both expose an `arg(type, value)` helper that builds a BCS-serialised Pure input:
218
226
 
219
- To specify types for move methods declared as:
220
-
221
- ```rust
222
- public entry fun method<T>(...)
227
+ ```javascript
228
+ contract.arg('bool', true)
229
+ contract.arg('u8', 222)
230
+ contract.arg('u16', 2222)
231
+ contract.arg('u32', 3333)
232
+ contract.arg('u64', 4444n)
233
+ contract.arg('u128', 5555n)
234
+ contract.arg('u256', 6666n)
235
+ contract.arg('address', '0xd9a95d7cc137f71dd7766f02791536453062a7509e9f461620cc4f583b09134c')
236
+ contract.arg('string', 'some utf-8 💧string')
237
+ contract.arg('vector<u8>', [222, 111, 211]) // also works for other primitive vectors
223
238
  ```
224
239
 
225
- you can specify `typeArguments` as a 3rd parameter to `suiPackageModule.moveCall` or 4th to `suiPackage.moveCall`:
240
+ Take a look at the unit test covering all argument types [here](test/different_types_args.test.js).
241
+
242
+ ##### move methods with type parameters
243
+
244
+ For Move methods declared as `public entry fun method<T>(...)`, pass type arguments as a third parameter to `module.moveCall` or fourth to `contract.moveCall`:
226
245
 
227
246
  ```javascript
228
- await mod.moveCall('test_method', [ store.id ], [ '0xca90beae66f23df1a830357c92e0a4348b6164d142c96b06936c5f28fdeaa99f::different_types::Store' ]);
229
- await contract.moveCall('module_name', 'test_method', [ store.id ], [ '0xca90beae66f23df1a83036936c5f28fdeaa99f::different_types::Store' ]);
247
+ await contract.modules.module_name.moveCall(
248
+ 'test_method',
249
+ [ store.id ],
250
+ [ '0xca90beae66f23df1a830357c92e0a4348b6164d142c96b06936c5f28fdeaa99f::different_types::Store' ],
251
+ );
252
+ await contract.moveCall(
253
+ 'module_name',
254
+ 'test_method',
255
+ [ store.id ],
256
+ [ '0xca90beae66f23df1a830357c92e0a4348b6164d142c96b06936c5f28fdeaa99f::different_types::Store' ],
257
+ );
230
258
  ```
231
259
 
260
+ ##### sending SUI / coins with smart contract methods
232
261
 
233
- ##### sending sui / coins with smart contract methods
234
-
235
- If you need to transfer some SUI/coins as part of executing contract method, you can use a magic parameter in form of:
262
+ Pass a coin magic object in place of the coin argument. The amount can be a `BigInt` (raw MIST) or a decimal string (e.g. `'0.2'`):
236
263
 
237
264
  ```javascript
238
- {type: 'SUI', amount: 400000000000n}
239
- // 400000000000 MISTs, if amount is BigInt, it's used in decimal items
240
- {type: 'SUI', amount: '0.2'}
241
- // 0.2 SUI , if amount is String, it's translated to decimals, using coin metadata in a lazy way
242
- {type: '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN', amount: '1.0'}
243
- // 1 USDC, note it should have a dot even if it's '0' after. You may want to use `Number(var).toFixed(decimals)` as a conversion
244
- {type: '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN', amount: '99.99'}
245
- // 99.99 USDT
265
+ { type: 'SUI', amount: 400000000000n } // 400 SUI in MIST
266
+ { type: 'SUI', amount: '0.2' } // 0.2 SUI converted via coin metadata
267
+ { type: '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN', amount: '1.0' } // 1 USDC
246
268
  ```
247
269
 
248
- So executing
249
-
250
270
  ```javascript
251
- const params = [
271
+ const moveCallResult = await contract.moveCall('suidouble_chat', 'post_pay', [
252
272
  chatShopObjectId,
253
- {type: '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN', amount: '9.99'},
273
+ { type: 'SUI', amount: 400000000000n },
254
274
  contract.arg('string', messageText),
255
- ];
256
- const moveCallResult = await contract.moveCall('suidouble_chat', 'post_pay', params);
275
+ ]);
257
276
  ```
258
277
 
259
- will send 9.99 USDT as the second parameter of the package method. Suidouble will convert needed coins using Sui's SplitCoins and MergeCoins internally to match amount you expect to send.
278
+ Coin selection, merging, and splitting are handled by the SDK's `tx.coin({ balance })` intent at build time.
260
279
 
261
- Some smart contracts requires clients to send coins in form of vectors. This is covered too, just pass magic parameter if the form of an array with one element:
280
+ For contracts that require `vector<Coin<T>>`, wrap the magic object in a single-element array:
262
281
 
263
282
  ```javascript
264
- const params = [
283
+ await contract.moveCall('suidouble_chat', 'post_pay_with_coin_vector', [
265
284
  chatShopObjectId,
266
- [{type: '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN', amount: '9.99'}],
285
+ [{ type: 'SUI', amount: 400000000000n }], // vector<Coin<SUI>>
267
286
  contract.arg('string', messageText),
268
- ];
287
+ ]);
269
288
  ```
270
289
 
271
290
  Don't forget to test transactions sending real money on devnet/testnet first!
272
291
 
292
+ ##### composing a transaction yourself
273
293
 
274
- ##### composing transaction block yourself
275
-
276
- If you need more flexebility, there's always an option to construct the transaction yourself:
294
+ For full control, build a `Transaction` manually and execute it via `module.executeTransaction(tx)`. This method signs, submits, and then syncs `objectStorage` and fires module events — just like `moveCall` does internally.
277
295
 
278
296
  ```javascript
279
- import { Transaction, txInput } from 'suidouble';
297
+ import { Transaction, txInput } from 'suidouble';
280
298
 
281
299
  const tx = new Transaction();
282
300
  tx.moveCall({
283
- target: `package_id::module_id::method_name`,
301
+ target: `${contract.address}::suidouble_chat::post`,
284
302
  arguments: [
285
- txInput(tx, 'u256', some_value),
286
- txInput(tx, 'vector<bool>', some_array),
287
- tx.object('0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c'), // object ids are ok t
303
+ tx.object(chatShopObjectId),
304
+ txInput(tx, 'string', 'hello'),
305
+ txInput(tx, 'string', 'metadata'),
288
306
  ],
289
307
  });
290
- const moveCallResult = await contract.moveCall('suidouble_chat', 'post_pay', {tx: tx});
308
+
309
+ // high-level: signs + submits + syncs objectStorage + emits events
310
+ const res = await contract.modules.suidouble_chat.executeTransaction(tx);
311
+ console.log('created', res.created.length, 'objects');
312
+ ```
313
+
314
+ If you want only signing and submission without the storage/event sync (e.g. you're building a multi-step PTB and managing state yourself), call the lower-level method directly:
315
+
316
+ ```javascript
317
+ const suiTransaction = await suiMaster.signAndExecuteTransaction({
318
+ transaction: tx,
319
+ include: { effects: true, objectTypes: true },
320
+ });
321
+ // objectStorage is NOT updated; module events are NOT emitted
322
+ console.log(suiTransaction.digest);
291
323
  ```
292
324
 
293
325
 
294
326
  ##### fetching objects
295
327
 
296
- There's instance of SuiMemoryObjectStorage attached to every SuiMaster instance. Every smart contract method call adds created and mutated objects to it. You can also attach any object with it's address (id).
328
+ `SuiMemoryObjectStorage` is attached to every `SuiMaster` instance. Every `moveCall` automatically pushes created and mutated objects into it.
297
329
 
298
330
  ```javascript
299
- contract.modules.modulename.pushObject('0x10cded4f9df05e37b44e3be2ffa9004dec77786950719fad6083694fdca45bf2');
300
- await contract.modules.modulename.fetchObjects(); // fetch objects fields etc
301
- const object = contract.modules.modulename.objectStorage.byAddress('0x10cded4f9df05e37b44e3be2ffa9004dec77786950719fad6083694fdca45bf2');
331
+ // find the most recently created ChatTopMessage in local storage:
332
+ const chatTopMessage = suiMaster.objectStorage.findMostRecentByTypeName('ChatTopMessage');
333
+
334
+ // look up by address:
335
+ const object = suiMaster.objectStorage.byAddress('0x10cded4f9df05e37b44e3be2ffa9004dec77786950719fad6083694fdca45bf2');
302
336
  ```
303
337
 
304
- Another option (if you don't know the object id) is to query current wallet owned module's objects from blockchain:
338
+ ##### fetching object fields
339
+
340
+ Objects returned from `moveCall` have their `id`, `version`, and `type` populated but `fields` is empty until you call `fetchFields()`. This fetches content from chain and populates `fields`, `display`, `owner`, etc.
305
341
 
306
342
  ```javascript
307
- const module = await contract.getModule('suidouble_chat');
308
- const paginatedResponse = await module.getOwnedObjects(); // all module objects owned by you
309
- const paginatedResponse2 = await module.getOwnedObjects({ typeName: 'ChatResponse' }); // specific type objects owned by you
343
+ const result = await contract.moveCall('suidouble_chat', 'post', [...]);
344
+ const chatResponse = result.created.find(o => o.typeName === 'ChatResponse');
310
345
 
311
- await paginatedResponse.forEach(async(suiObject)=>{
312
- console.log(suiObject.id, suiObject.typeName, suiObject.fields);
313
- }, maxLimit); // optional maxLimit, if (!maxLimit) - it will fetch and call callback for all available objects
346
+ await chatResponse.fetchFields();
347
+ console.log(chatResponse.fields.text); // now populated
348
+ ```
349
+
350
+ ##### fetching objects by id
351
+
352
+ Use `suiMaster.getObject(id)` for a single object or `suiMaster.getObjects(ids)` for a batch. Both return fully-populated `SuiObject` instances. `getObjects` also accepts existing `SuiObject` instances and updates them in-place.
353
+
354
+ ```javascript
355
+ // single fetch:
356
+ const obj = await suiMaster.getObject('0x10cded4f9df05e37b44e3be2ffa9004dec77786950719fad6083694fdca45bf2');
357
+ console.log(obj.typeName, obj.fields);
358
+
359
+ // batch fetch — accepts ids, SuiObject instances, or a mix:
360
+ const objects = await suiMaster.getObjects([id1, id2, existingSuiObject]);
361
+ for (const o of objects) {
362
+ console.log(o.id, o.typeName, o.fields);
363
+ }
364
+ ```
365
+
366
+ ##### querying owned objects
367
+
368
+ Use `getOwnedObjects` to query owned objects from the chain, scoped to the whole address, a package, a module, or a specific struct type:
369
+
370
+ ```javascript
371
+ // all objects owned by the connected address:
372
+ const all = await suiMaster.getOwnedObjects({ owner: suiMaster.address, limit: 50 });
373
+
374
+ // all objects from this package owned by you (uses GraphQL — supports package/module prefixes):
375
+ const pkgObjects = await contract.getOwnedObjects();
376
+
377
+ // all objects of a specific module owned by you:
378
+ const modObjects = await contract.modules.suidouble_chat.getOwnedObjects();
379
+
380
+ // objects of a specific struct type (uses gRPC — full struct type required):
381
+ const responses = await contract.modules.suidouble_chat.getOwnedObjects({ typeName: 'ChatResponse' });
382
+
383
+ // iterate across all pages with forEach:
384
+ await responses.forEach(async (suiObject) => {
385
+ await suiObject.fetchFields();
386
+ console.log(suiObject.id, suiObject.fields);
387
+ });
388
+ ```
389
+
390
+ ##### fetching transaction history for an object
391
+
392
+ ```javascript
393
+ const txs = await chatTopMessage.fetchTransactions({ limit: 20, order: 'desc' });
394
+ for (const tx of txs.data) {
395
+ console.log(tx.digest, tx.timestampMs);
396
+ }
397
+ ```
398
+
399
+ ##### resolving a Sui Name Service (SuiNS) name
400
+
401
+ Returns the primary `.sui` name registered for the connected wallet address, or `null` if none. Uses the v2 gRPC client — works on mainnet and testnet.
402
+
403
+ Each call hits the network, so **cache the result yourself** if you plan to display it repeatedly (e.g. in a UI that re-renders often).
404
+
405
+ ```javascript
406
+ const name = await suiMaster.defaultNameServiceName();
407
+ // e.g. 'adeniyi.sui', or null if no name is registered
408
+ if (name) {
409
+ console.log('connected as', name);
410
+ }
314
411
  ```
315
412
 
316
- @todo: move pushing/fetching to SuiMemoryObjectStorage directly, as there's nothing package or module related?
317
- @todo: invalidation? No need to re-fetch all objects each time
318
413
 
319
414
 
320
415
  ### publishing the package
@@ -325,28 +420,27 @@ Builds a package and publish it to blockchain. CLI thing, as it needs `execSync`
325
420
  import { SuiMaster } from 'suidouble';
326
421
 
327
422
 
328
- const client = 'dev';
329
- const suiMaster = new SuiMaster({ debug: true, as: 'admin', client: client, });
423
+ const suiMaster = new SuiMaster({ debug: true, as: 'admin', client: 'devnet', });
330
424
 
331
425
  await suiMaster.requestSuiFromFaucet();
332
426
  await suiMaster.getBalance();
333
427
 
334
- const package = suiMaster.addPackage({
428
+ const contract = suiMaster.addPackage({
335
429
  path: '../path_to_move_project_root/',
336
430
  });
337
431
 
338
- await package.publish();
339
- console.log('published as', package.address);
432
+ await contract.publish();
433
+ console.log('published as', contract.address);
340
434
  ```
341
435
 
342
436
  Optionally, you can switch sui's env of `sui client switch` for the build (useful for Automated Address Management of dependencies via their Move.lock)
343
437
 
344
438
  ```javascript
345
- const package = suiMaster.addPackage({
439
+ const contract = suiMaster.addPackage({
346
440
  path: '../path_to_move_project_root/',
347
441
  });
348
- await package.build({ env: 'testnet', });
349
- await package.publish();
442
+ await contract.build({ env: 'testnet', });
443
+ await contract.publish();
350
444
 
351
445
  ```
352
446
 
@@ -357,20 +451,19 @@ Same, it's for CLI as it re-builds the package.
357
451
  ```javascript
358
452
  import { SuiMaster } from 'suidouble';
359
453
 
360
- const client = 'local';// or await SuiLocalTestValidator.launch({debug: true, epochDuration: 30000});
361
-
362
- const suiMaster = new SuiMaster({ debug: true, as: 'admin', client: client, });
454
+ const suiMaster = new SuiMaster({ debug: true, as: 'admin', client: 'localnet', });
455
+ // or: client: await SuiLocalTestValidator.launch({debug: true, epochDuration: 30000})
363
456
  await suiMaster.requestSuiFromFaucet();
364
457
  await suiMaster.getBalance();
365
458
 
366
- const package = suiMaster.addPackage({
459
+ const contract = suiMaster.addPackage({
367
460
  path: '../path_to_move_project_root/',
368
461
  });
369
462
 
370
- if (!(await package.isOnChain())) { // suidouble tries to find package with needed modules in UpgradeCaps owned by you
371
- await package.publish();
463
+ if (!(await contract.isOnChain())) { // suidouble tries to find package with needed modules in UpgradeCaps owned by you
464
+ await contract.publish();
372
465
  } else {
373
- await package.upgrade();
466
+ await contract.upgrade();
374
467
  }
375
468
  ```
376
469
 
@@ -415,7 +508,7 @@ await testScenario.end();
415
508
 
416
509
  Check out [suidouble Vue component](https://www.npmjs.com/package/vue-sui) to connect your dapp to the Sui blockchain.
417
510
 
418
- Or write the one manually, code is framework independed:
511
+ Or write it manually — the code is framework-independent:
419
512
 
420
513
  ```javascript
421
514
  import { SuiInBrowser } from 'suidouble';
@@ -444,16 +537,14 @@ suiInBrowser.addEventListener('connected', async()=>{
444
537
 
445
538
  await contract.isOnChain();
446
539
 
447
- const events = await contract.fetchEvents('chat', {eventTypeName: 'ChatResponseCreated', order: 'descending'});
540
+ const events = await contract.modules.chat.fetchEvents({eventTypeName: 'ChatResponseCreated', order: 'descending'});
448
541
  for (const event of events.data) {
449
- // instances of SuiEvent (@todo: write documentation for it)
450
542
  console.log('event', event.parsedJson);
451
543
  }
452
544
 
453
- const res = await contract.moveCall('chat', 'post', [contract.arg('string', 'somedata'), contract.arg('vector<u8>', 'somedata') ]);
454
- console.log(res);
545
+ const res = await contract.moveCall('chat', 'post', [contract.arg('string', 'somedata'), contract.arg('vector<u8>', [1, 2, 3]) ]);
455
546
  for (const object of res.created) {
456
- console.log('created', object.address, 'with type of', object.typeName); // instances of SuiObject (@todo: write documentation for it)
547
+ console.log('created', object.address, 'with type of', object.typeName);
457
548
  }
458
549
  });
459
550
 
package/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import SuiMaster from './lib/SuiMaster.js';
2
2
  import SuiInBrowser from './lib/SuiInBrowser.js';
3
- import SuiTestScenario from './lib/SuiTestScenario.js';
4
3
  import SuiObject from './lib/SuiObject.js';
5
4
  import SuiUtils from './lib/SuiUtils.js';
6
5
  import SuiLocalTestValidator from './lib/SuiLocalTestValidator.js';
@@ -18,7 +17,6 @@ export {
18
17
  SuiMaster,
19
18
  SuiObject,
20
19
  SuiInBrowser,
21
- SuiTestScenario,
22
20
  SuiLocalTestValidator,
23
21
  MIST_PER_SUI,
24
22
  Transaction,