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.
- package/.claude/settings.local.json +7 -0
- package/README.md +222 -131
- package/index.js +0 -2
- package/lib/SuiCliCommands.js +18 -25
- package/lib/SuiCoin.js +79 -137
- package/lib/SuiCoins.js +41 -29
- package/lib/SuiCommonMethods.js +40 -3
- package/lib/SuiEvent.js +54 -6
- package/lib/SuiInBrowser.js +161 -16
- package/lib/SuiInBrowserAdapter.js +192 -40
- package/lib/SuiLocalTestValidator.js +76 -14
- package/lib/SuiMaster.js +335 -139
- package/lib/SuiMemoryObjectStorage.js +66 -73
- package/lib/SuiObject.js +128 -153
- package/lib/SuiPackage.js +292 -187
- package/lib/SuiPackageModule.js +176 -221
- package/lib/SuiPaginatedResponse.js +288 -25
- package/lib/SuiPseudoRandomAddress.js +29 -2
- package/lib/SuiTransaction.js +115 -70
- package/lib/SuiUtils.js +179 -127
- package/package.json +29 -13
- package/test/build_modules.test.js +41 -0
- package/test/coins.test.js +17 -16
- package/test/custom_transaction.test.js +167 -0
- package/test/event_listeners.test.js +171 -0
- package/test/failed_transaction.test.js +184 -0
- package/test/name_service.test.js +28 -0
- package/test/owned_objects.test.js +148 -0
- package/test/rpc.test.js +3 -6
- package/test/sui_in_browser.test.js +2 -2
- package/test/sui_master_basic.test.js +4 -5
- package/test/sui_master_onlocal.test.js +84 -22
- package/test/sui_object_properties.test.js +85 -0
- package/test/test_move_contracts/different_types/Move.lock +18 -0
- package/test/test_move_contracts/suidouble_chat/Move.lock +18 -0
- package/tsconfig.json +15 -0
- package/types/index.d.ts +15 -0
- package/types/lib/SuiCliCommands.d.ts +6 -0
- package/types/lib/SuiCoin.d.ts +183 -0
- package/types/lib/SuiCoins.d.ts +93 -0
- package/types/lib/SuiCommonMethods.d.ts +37 -0
- package/types/lib/SuiEvent.d.ts +95 -0
- package/types/lib/SuiInBrowser.d.ts +195 -0
- package/types/lib/SuiInBrowserAdapter.d.ts +173 -0
- package/types/lib/SuiLocalTestValidator.d.ts +92 -0
- package/types/lib/SuiMaster.d.ts +333 -0
- package/types/lib/SuiMemoryObjectStorage.d.ts +96 -0
- package/types/lib/SuiObject.d.ts +135 -0
- package/types/lib/SuiPackage.d.ts +233 -0
- package/types/lib/SuiPackageModule.d.ts +139 -0
- package/types/lib/SuiPaginatedResponse.d.ts +148 -0
- package/types/lib/SuiPseudoRandomAddress.d.ts +33 -0
- package/types/lib/SuiTransaction.d.ts +92 -0
- package/types/lib/SuiUtils.d.ts +152 -0
- package/types/lib/data/icons.d.ts +12 -0
- package/lib/SuiTestScenario.js +0 -169
- package/test/sui_test_scenario.test.js +0 -61
package/README.md
CHANGED
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
# suidouble
|
|
2
2
|
|
|
3
|
-
Set of provider, package and object classes for
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
20
|
-
- [Connecting web3
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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', // '
|
|
76
|
-
client: '
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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(
|
|
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
|
-
//
|
|
183
|
-
const res = await contract.moveCall('
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
|
|
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
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
223
|
+
##### move method argument types
|
|
216
224
|
|
|
217
|
-
|
|
225
|
+
`SuiPackage` and `SuiPackageModule` both expose an `arg(type, value)` helper that builds a BCS-serialised Pure input:
|
|
218
226
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
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
|
|
229
|
-
|
|
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
|
-
|
|
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
|
-
|
|
240
|
-
{type: '
|
|
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
|
|
271
|
+
const moveCallResult = await contract.moveCall('suidouble_chat', 'post_pay', [
|
|
252
272
|
chatShopObjectId,
|
|
253
|
-
{type: '
|
|
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
|
-
|
|
278
|
+
Coin selection, merging, and splitting are handled by the SDK's `tx.coin({ balance })` intent at build time.
|
|
260
279
|
|
|
261
|
-
|
|
280
|
+
For contracts that require `vector<Coin<T>>`, wrap the magic object in a single-element array:
|
|
262
281
|
|
|
263
282
|
```javascript
|
|
264
|
-
|
|
283
|
+
await contract.moveCall('suidouble_chat', 'post_pay_with_coin_vector', [
|
|
265
284
|
chatShopObjectId,
|
|
266
|
-
[{type: '
|
|
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
|
-
|
|
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:
|
|
301
|
+
target: `${contract.address}::suidouble_chat::post`,
|
|
284
302
|
arguments: [
|
|
285
|
-
|
|
286
|
-
txInput(tx, '
|
|
287
|
-
tx
|
|
303
|
+
tx.object(chatShopObjectId),
|
|
304
|
+
txInput(tx, 'string', 'hello'),
|
|
305
|
+
txInput(tx, 'string', 'metadata'),
|
|
288
306
|
],
|
|
289
307
|
});
|
|
290
|
-
|
|
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
|
-
|
|
328
|
+
`SuiMemoryObjectStorage` is attached to every `SuiMaster` instance. Every `moveCall` automatically pushes created and mutated objects into it.
|
|
297
329
|
|
|
298
330
|
```javascript
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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
|
-
|
|
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
|
|
308
|
-
const
|
|
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
|
|
312
|
-
|
|
313
|
-
|
|
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
|
|
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
|
|
428
|
+
const contract = suiMaster.addPackage({
|
|
335
429
|
path: '../path_to_move_project_root/',
|
|
336
430
|
});
|
|
337
431
|
|
|
338
|
-
await
|
|
339
|
-
console.log('published as',
|
|
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
|
|
439
|
+
const contract = suiMaster.addPackage({
|
|
346
440
|
path: '../path_to_move_project_root/',
|
|
347
441
|
});
|
|
348
|
-
await
|
|
349
|
-
await
|
|
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
|
|
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
|
|
459
|
+
const contract = suiMaster.addPackage({
|
|
367
460
|
path: '../path_to_move_project_root/',
|
|
368
461
|
});
|
|
369
462
|
|
|
370
|
-
if (!(await
|
|
371
|
-
await
|
|
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
|
|
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
|
|
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(
|
|
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>',
|
|
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);
|
|
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,
|