suidouble 2.5.0 → 2.16.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.
- 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 +143 -15
- package/lib/SuiInBrowserAdapter.js +164 -37
- 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/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 +189 -0
- package/types/lib/SuiInBrowserAdapter.d.ts +167 -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
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import SuiCommonMethods from './SuiCommonMethods.js';
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import("@mysten/sui/cryptography").SignatureWithBytes} SignatureWithBytes
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Wallet Standard feature identifiers — keys map to the string feature names used by the
|
|
10
|
+
* `@wallet-standard/core` registry.
|
|
11
|
+
* @enum {string}
|
|
12
|
+
*/
|
|
3
13
|
const Feature = {
|
|
4
14
|
DISCONNECT: 'standard:disconnect',
|
|
5
15
|
CONNECT: 'standard:connect',
|
|
@@ -12,25 +22,51 @@ const Feature = {
|
|
|
12
22
|
SUI_SIGN_PERSONAL_MESSAGE: 'sui:signPersonalMessage',
|
|
13
23
|
};
|
|
14
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Wrapper over a single Wallet Standard adapter (e.g. Sui Wallet, Martian, Suiet).
|
|
27
|
+
* Abstracts away legacy `signAndExecuteTransactionBlock` vs the current
|
|
28
|
+
* `signAndExecuteTransaction` API, and normalises connection state changes into
|
|
29
|
+
* `'connected'` / `'disconnected'` events on this instance.
|
|
30
|
+
*/
|
|
15
31
|
export default class SuiInBrowserAdapter extends SuiCommonMethods {
|
|
32
|
+
/**
|
|
33
|
+
* @param {Object} [params]
|
|
34
|
+
* @param {Object} [params.standardAdapter] - raw Wallet Standard adapter from `@wallet-standard/core`
|
|
35
|
+
* @param {?string} [params.name] - display name used when no adapter is attached (e.g. "not installed" placeholder)
|
|
36
|
+
* @param {?string} [params.icon] - data-URI icon used when no adapter is attached
|
|
37
|
+
* @param {Object} [params.downloadUrls] - map of browser name → extension store URL (e.g. `{ chrome: 'https://…' }`)
|
|
38
|
+
* @param {boolean} [params.debug]
|
|
39
|
+
*/
|
|
16
40
|
constructor(params = {}) {
|
|
17
41
|
super(params);
|
|
18
42
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (params.
|
|
22
|
-
this.setStandartAdapter(params.
|
|
43
|
+
/** @type {?Object} raw Wallet Standard adapter */
|
|
44
|
+
this._standardAdapter = null;
|
|
45
|
+
if (params.standardAdapter) {
|
|
46
|
+
this.setStandartAdapter(params.standardAdapter);
|
|
23
47
|
}
|
|
24
|
-
|
|
48
|
+
|
|
49
|
+
/** @type {?string} */
|
|
25
50
|
this._name = params.name || null;
|
|
51
|
+
/** @type {?string} */
|
|
26
52
|
this._icon = params.icon || null;
|
|
53
|
+
/** @type {Object.<string, string>} */
|
|
27
54
|
this._downloadUrls = params.downloadUrls || {};
|
|
28
55
|
|
|
56
|
+
/** @type {?string} */
|
|
29
57
|
this._connectedAddress = null;
|
|
58
|
+
/** @type {?string} */
|
|
30
59
|
this._connectedChain = null;
|
|
60
|
+
/** @type {boolean} */
|
|
31
61
|
this._isConnected = false;
|
|
32
62
|
}
|
|
33
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Sign and execute a transaction. Prefers the current `sui:signAndExecuteTransaction`
|
|
66
|
+
* feature; falls back to the legacy `sui:signAndExecuteTransactionBlock` for older wallets.
|
|
67
|
+
* @param {Object} params
|
|
68
|
+
* @returns {Promise<*>}
|
|
69
|
+
*/
|
|
34
70
|
async signAndExecuteTransaction(params) {
|
|
35
71
|
if (this.hasFeature(Feature.SUI_SIGN_AND_EXECUTE_TX)) {
|
|
36
72
|
return await this.getFeature(Feature.SUI_SIGN_AND_EXECUTE_TX).signAndExecuteTransaction(params);
|
|
@@ -41,10 +77,32 @@ export default class SuiInBrowserAdapter extends SuiCommonMethods {
|
|
|
41
77
|
}
|
|
42
78
|
}
|
|
43
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Sign and execute a transaction using the legacy `sui:signAndExecuteTransactionBlock` feature.
|
|
82
|
+
* @param {Object} params
|
|
83
|
+
* @returns {Promise<*>}
|
|
84
|
+
*/
|
|
44
85
|
async signAndExecuteTransactionBlock(params) {
|
|
45
86
|
return await this.getFeature(Feature.SUI_SIGN_AND_EXECUTE_TX_BLOCK).signAndExecuteTransactionBlock(params);
|
|
46
87
|
}
|
|
47
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Sign a transaction using the current `sui:signTransaction` feature.
|
|
91
|
+
* @param {Object} params
|
|
92
|
+
* @returns {Promise<SignatureWithBytes>}
|
|
93
|
+
*/
|
|
94
|
+
async signTransaction(params) {
|
|
95
|
+
/** @type {SignatureWithBytes} */
|
|
96
|
+
const resp = await this.getFeature(Feature.SUI_SIGN_TX).signTransaction(params);
|
|
97
|
+
return resp;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Sign a transaction. Prefers the current `sui:signTransaction` feature;
|
|
102
|
+
* falls back to the legacy `sui:signTransactionBlock` for older wallets.
|
|
103
|
+
* @param {Object} params
|
|
104
|
+
* @returns {Promise<*>}
|
|
105
|
+
*/
|
|
48
106
|
async signTransactionBlock(params) {
|
|
49
107
|
if (this.hasFeature(Feature.SUI_SIGN_TX)) {
|
|
50
108
|
return await this.getFeature(Feature.SUI_SIGN_TX).signTransaction(params);
|
|
@@ -55,10 +113,12 @@ export default class SuiInBrowserAdapter extends SuiCommonMethods {
|
|
|
55
113
|
}
|
|
56
114
|
}
|
|
57
115
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
116
|
+
/**
|
|
117
|
+
* Sign a personal/arbitrary message. Prefers `sui:signPersonalMessage`;
|
|
118
|
+
* falls back to `sui:signMessage` for older wallets.
|
|
119
|
+
* @param {Object} params
|
|
120
|
+
* @returns {Promise<*>}
|
|
121
|
+
*/
|
|
62
122
|
async signPersonalMessage(params) {
|
|
63
123
|
if (this.hasFeature(Feature.SUI_SIGN_PERSONAL_MESSAGE)) {
|
|
64
124
|
return await this.getFeature(Feature.SUI_SIGN_PERSONAL_MESSAGE).signPersonalMessage(params);
|
|
@@ -67,16 +127,30 @@ export default class SuiInBrowserAdapter extends SuiCommonMethods {
|
|
|
67
127
|
}
|
|
68
128
|
}
|
|
69
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Alias for `signPersonalMessage`.
|
|
132
|
+
* @param {Object} params
|
|
133
|
+
* @returns {Promise<*>}
|
|
134
|
+
*/
|
|
70
135
|
async signMessage(params) {
|
|
71
136
|
return await this.signPersonalMessage(params);
|
|
72
137
|
}
|
|
73
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Disconnect from the wallet and refresh connection state.
|
|
141
|
+
* @param {Object} [params]
|
|
142
|
+
* @returns {Promise<*>}
|
|
143
|
+
*/
|
|
74
144
|
async disconnect(params) {
|
|
75
145
|
const res = await this.getFeature(Feature.DISCONNECT).disconnect(params);
|
|
76
146
|
this.connectionUpdated();
|
|
77
147
|
return res;
|
|
78
148
|
}
|
|
79
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Return the Chrome Web Store download URL, or null if not configured.
|
|
152
|
+
* @returns {?string}
|
|
153
|
+
*/
|
|
80
154
|
getDownloadURL() {
|
|
81
155
|
if (this._downloadUrls && this._downloadUrls.chrome) {
|
|
82
156
|
return this._downloadUrls.chrome;
|
|
@@ -84,25 +158,34 @@ export default class SuiInBrowserAdapter extends SuiCommonMethods {
|
|
|
84
158
|
return null;
|
|
85
159
|
}
|
|
86
160
|
|
|
161
|
+
/**
|
|
162
|
+
* True when no underlying adapter has been attached (i.e. this is a "not installed" placeholder).
|
|
163
|
+
* @returns {boolean}
|
|
164
|
+
*/
|
|
87
165
|
get isDefault() {
|
|
88
|
-
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
return false;
|
|
166
|
+
return !this._standardAdapter;
|
|
92
167
|
}
|
|
93
168
|
|
|
169
|
+
/** @returns {?string} currently connected Sui address, or null */
|
|
94
170
|
get connectedAddress() {
|
|
95
171
|
return this._connectedAddress;
|
|
96
172
|
}
|
|
97
173
|
|
|
174
|
+
/** @returns {?string} currently connected chain identifier (e.g. `'sui:mainnet'`), or null */
|
|
98
175
|
get connectedChain() {
|
|
99
176
|
return this._connectedChain;
|
|
100
177
|
}
|
|
101
178
|
|
|
179
|
+
/** @returns {boolean} true if the wallet is connected and an address is available */
|
|
102
180
|
get isConnected() {
|
|
103
181
|
return this._isConnected;
|
|
104
182
|
}
|
|
105
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Request connection to the wallet. Errors are swallowed; connection state is refreshed
|
|
186
|
+
* via `connectionUpdated` regardless.
|
|
187
|
+
* @returns {Promise<void>}
|
|
188
|
+
*/
|
|
106
189
|
async connect() {
|
|
107
190
|
try {
|
|
108
191
|
await this.getFeature(Feature.CONNECT).connect();
|
|
@@ -113,14 +196,19 @@ export default class SuiInBrowserAdapter extends SuiCommonMethods {
|
|
|
113
196
|
this.connectionUpdated();
|
|
114
197
|
}
|
|
115
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Read the current connection state from the underlying adapter and update
|
|
201
|
+
* `connectedAddress`, `connectedChain`, and `isConnected`. Emits `'connected'` or
|
|
202
|
+
* `'disconnected'` if the state changed.
|
|
203
|
+
*/
|
|
116
204
|
connectionUpdated() {
|
|
117
205
|
const wasConnectedAddress = ''+this._connectedAddress;
|
|
118
206
|
const wasConnectedChain = ''+this._connectedChain;
|
|
119
207
|
|
|
120
208
|
try {
|
|
121
|
-
if (this.
|
|
122
|
-
this._connectedAddress = this.
|
|
123
|
-
this._connectedChain = this.
|
|
209
|
+
if (this._standardAdapter && this._standardAdapter.accounts && this._standardAdapter.accounts.length) {
|
|
210
|
+
this._connectedAddress = this._standardAdapter.accounts[0].address;
|
|
211
|
+
this._connectedChain = this._standardAdapter.accounts[0].chains[0];
|
|
124
212
|
} else {
|
|
125
213
|
this._connectedAddress = null;
|
|
126
214
|
this._connectedChain = null;
|
|
@@ -141,16 +229,23 @@ export default class SuiInBrowserAdapter extends SuiCommonMethods {
|
|
|
141
229
|
}
|
|
142
230
|
}
|
|
143
231
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
232
|
+
/**
|
|
233
|
+
* Attach a Wallet Standard adapter to this instance. No-op if already attached.
|
|
234
|
+
* Returns false and does nothing if the adapter has no `sui:` features.
|
|
235
|
+
* Subscribes to adapter `'change'` events to keep connection state up to date.
|
|
236
|
+
*
|
|
237
|
+
* @param {Object} standardAdapter - raw adapter from `@wallet-standard/core`
|
|
238
|
+
* @returns {boolean} false if the adapter lacks Sui features, undefined on success
|
|
239
|
+
*/
|
|
240
|
+
setStandartAdapter(standardAdapter) {
|
|
241
|
+
if (this._standardAdapter) {
|
|
147
242
|
// no need to re-attach
|
|
148
243
|
return true;
|
|
149
244
|
}
|
|
150
245
|
|
|
151
246
|
// check if it has sui: features
|
|
152
247
|
let hasSuiFeatures = false;
|
|
153
|
-
for (const key in
|
|
248
|
+
for (const key in standardAdapter.features) {
|
|
154
249
|
if ((''+key).indexOf('sui:') === 0) {
|
|
155
250
|
hasSuiFeatures = true;
|
|
156
251
|
}
|
|
@@ -160,65 +255,97 @@ export default class SuiInBrowserAdapter extends SuiCommonMethods {
|
|
|
160
255
|
return false;
|
|
161
256
|
}
|
|
162
257
|
|
|
163
|
-
this.
|
|
164
|
-
if (!this.
|
|
165
|
-
this.
|
|
258
|
+
this._standardAdapter = standardAdapter;
|
|
259
|
+
if (!this.__standardAdapterChangeListener) {
|
|
260
|
+
this.__standardAdapterChangeListener = () => {
|
|
166
261
|
this.connectionUpdated();
|
|
167
262
|
};
|
|
168
263
|
}
|
|
169
|
-
this.getFeature(Feature.EVENTS).on('change', this.
|
|
264
|
+
this.getFeature(Feature.EVENTS).on('change', this.__standardAdapterChangeListener);
|
|
170
265
|
|
|
171
266
|
this.connectionUpdated();
|
|
172
267
|
}
|
|
173
268
|
|
|
269
|
+
/**
|
|
270
|
+
* True if the adapter is installed and supports the minimum required Sui features
|
|
271
|
+
* (`sui:signAndExecuteTransaction` or `sui:signAndExecuteTransactionBlock`, plus `standard:events`).
|
|
272
|
+
* @returns {boolean}
|
|
273
|
+
*/
|
|
174
274
|
get okForSui() {
|
|
175
275
|
if (!this.isInstalled) {
|
|
176
276
|
return false;
|
|
177
277
|
}
|
|
178
278
|
|
|
179
|
-
return this.hasFeature(Feature.SUI_SIGN_AND_EXECUTE_TX_BLOCK) && this.hasFeature(Feature.EVENTS);
|
|
279
|
+
return (this.hasFeature(Feature.SUI_SIGN_AND_EXECUTE_TX_BLOCK) || this.hasFeature(Feature.SUI_SIGN_AND_EXECUTE_TX)) && this.hasFeature(Feature.EVENTS);
|
|
180
280
|
}
|
|
181
281
|
|
|
282
|
+
/** @returns {boolean} true if a Wallet Standard adapter has been attached */
|
|
182
283
|
get isInstalled() {
|
|
183
|
-
|
|
184
|
-
return true;
|
|
185
|
-
}
|
|
186
|
-
return false;
|
|
284
|
+
return !!this._standardAdapter;
|
|
187
285
|
}
|
|
188
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Feature map from the underlying adapter, or an empty object if not installed.
|
|
289
|
+
* Keys are Wallet Standard feature strings (e.g. `'sui:signAndExecuteTransaction'`).
|
|
290
|
+
* @returns {Object}
|
|
291
|
+
*/
|
|
189
292
|
get features() {
|
|
190
|
-
if (this.
|
|
191
|
-
return this.
|
|
293
|
+
if (this._standardAdapter) {
|
|
294
|
+
return this._standardAdapter.features;
|
|
192
295
|
}
|
|
193
296
|
return {};
|
|
194
297
|
}
|
|
195
298
|
|
|
299
|
+
/**
|
|
300
|
+
* Display name — from the adapter if installed, otherwise from the constructor param.
|
|
301
|
+
* @returns {?string}
|
|
302
|
+
*/
|
|
196
303
|
get name() {
|
|
197
|
-
if (this.
|
|
198
|
-
return this.
|
|
304
|
+
if (this._standardAdapter) {
|
|
305
|
+
return this._standardAdapter.name;
|
|
199
306
|
} else {
|
|
200
307
|
return this._name;
|
|
201
308
|
}
|
|
202
309
|
}
|
|
203
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Data-URI icon — from the adapter if installed, otherwise from the constructor param.
|
|
313
|
+
* @returns {?string}
|
|
314
|
+
*/
|
|
204
315
|
get icon() {
|
|
205
|
-
if (this.
|
|
206
|
-
return this.
|
|
316
|
+
if (this._standardAdapter) {
|
|
317
|
+
return this._standardAdapter.icon;
|
|
207
318
|
} else {
|
|
208
319
|
return this._icon;
|
|
209
320
|
}
|
|
210
321
|
}
|
|
211
322
|
|
|
323
|
+
/**
|
|
324
|
+
* Wallet version string from the adapter, or undefined if not installed.
|
|
325
|
+
* @returns {?string}
|
|
326
|
+
*/
|
|
212
327
|
get version() {
|
|
213
|
-
if (this.
|
|
214
|
-
return this.
|
|
328
|
+
if (this._standardAdapter) {
|
|
329
|
+
return this._standardAdapter.version;
|
|
215
330
|
}
|
|
216
331
|
}
|
|
217
332
|
|
|
333
|
+
/**
|
|
334
|
+
* Returns true if this adapter supports the given feature.
|
|
335
|
+
* Accepts either a `Feature` enum key (e.g. `'SUI_SIGN_TX'`) or a raw feature string.
|
|
336
|
+
* @param {string} featureName
|
|
337
|
+
* @returns {boolean}
|
|
338
|
+
*/
|
|
218
339
|
hasFeature(featureName) {
|
|
219
340
|
return (!!this.getFeature(featureName));
|
|
220
341
|
}
|
|
221
342
|
|
|
343
|
+
/**
|
|
344
|
+
* Return the feature object for `featureName`, or null if not available.
|
|
345
|
+
* Accepts either a `Feature` enum key (e.g. `'SUI_SIGN_TX'`) or a raw feature string.
|
|
346
|
+
* @param {string} featureName
|
|
347
|
+
* @returns {?Object}
|
|
348
|
+
*/
|
|
222
349
|
getFeature(featureName) {
|
|
223
350
|
const features = this.features;
|
|
224
351
|
|
|
@@ -2,29 +2,55 @@ import SuiCliCommands from "./SuiCliCommands.js";
|
|
|
2
2
|
import SuiCommonMethods from "./SuiCommonMethods.js";
|
|
3
3
|
import SuiUtils from "./SuiUtils.js";
|
|
4
4
|
|
|
5
|
+
/** @typedef {import("@mysten/sui/grpc").SuiGrpcClient} SuiGrpcClient */
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Manages a local `sui start` test-validator process. The singleton pattern (`launch` / `stop`)
|
|
9
|
+
* means only one validator runs per test suite even when called from multiple test files.
|
|
10
|
+
*
|
|
11
|
+
* When `testFallbackEnabled` is true and `sui start` fails (e.g. Sui CLI not installed),
|
|
12
|
+
* the instance transparently switches to `sui:devnet` so tests can still run against a live node.
|
|
13
|
+
*/
|
|
5
14
|
export default class SuiLocalTestValidator extends SuiCommonMethods {
|
|
15
|
+
/**
|
|
16
|
+
* @param {Object} [params]
|
|
17
|
+
* @param {boolean} [params.testFallbackEnabled] - fall back to devnet if the local node can't start
|
|
18
|
+
* @param {?number} [params.epochDuration] - custom epoch duration in ms (only valid with `--force-regenesis`)
|
|
19
|
+
* @param {boolean} [params.debug]
|
|
20
|
+
*/
|
|
6
21
|
constructor(params = {}) {
|
|
7
22
|
super(params);
|
|
8
23
|
|
|
24
|
+
/** @type {?Object} spawned child process */
|
|
9
25
|
this._child = null;
|
|
26
|
+
/** @type {boolean} */
|
|
10
27
|
this._active = false;
|
|
11
28
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
29
|
+
/**
|
|
30
|
+
* When true, falls back to sui:devnet if the local node can't be started.
|
|
31
|
+
* @type {boolean}
|
|
32
|
+
*/
|
|
33
|
+
this._testFallbackEnabled = !!params.testFallbackEnabled;
|
|
18
34
|
|
|
35
|
+
/** @type {?number} */
|
|
19
36
|
this._epochDuration = params.epochDuration || null;
|
|
20
37
|
|
|
38
|
+
/** @type {string} */
|
|
21
39
|
this._providerName = 'sui:localnet';
|
|
22
40
|
}
|
|
23
41
|
|
|
42
|
+
/** @returns {string} active chain identifier, e.g. `'sui:localnet'` or `'sui:devnet'` after fallback */
|
|
24
43
|
get providerName() {
|
|
25
44
|
return this._providerName;
|
|
26
45
|
}
|
|
27
46
|
|
|
47
|
+
/** @type {?SuiLocalTestValidator} */
|
|
48
|
+
static __instance = null;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* gRPC client for the currently active chain.
|
|
52
|
+
* @returns {SuiGrpcClient}
|
|
53
|
+
*/
|
|
28
54
|
get client() {
|
|
29
55
|
if (this._providerName === 'sui:localnet') {
|
|
30
56
|
return SuiUtils.suiClientFor('localnet');
|
|
@@ -34,15 +60,19 @@ export default class SuiLocalTestValidator extends SuiCommonMethods {
|
|
|
34
60
|
}
|
|
35
61
|
}
|
|
36
62
|
|
|
63
|
+
/** @returns {boolean} true once the node is up and accepting transactions */
|
|
37
64
|
get active() {
|
|
38
65
|
return this._active;
|
|
39
66
|
}
|
|
40
67
|
|
|
41
68
|
/**
|
|
42
|
-
* Launch
|
|
43
|
-
* Don't forget to
|
|
44
|
-
*
|
|
45
|
-
* @
|
|
69
|
+
* Launch the local sui node (singleton). If already running, returns the existing instance.
|
|
70
|
+
* Don't forget to call `.stop()` after usage.
|
|
71
|
+
*
|
|
72
|
+
* @param {Object} [params]
|
|
73
|
+
* @param {boolean} [params.testFallbackEnabled]
|
|
74
|
+
* @param {?number} [params.epochDuration]
|
|
75
|
+
* @returns {Promise<SuiLocalTestValidator>}
|
|
46
76
|
*/
|
|
47
77
|
static async launch(params = {}) {
|
|
48
78
|
if (SuiLocalTestValidator.__instance) {
|
|
@@ -54,7 +84,8 @@ export default class SuiLocalTestValidator extends SuiCommonMethods {
|
|
|
54
84
|
}
|
|
55
85
|
|
|
56
86
|
/**
|
|
57
|
-
* Stop the local sui node
|
|
87
|
+
* Stop the singleton local sui node if running.
|
|
88
|
+
* @returns {Promise<void>}
|
|
58
89
|
*/
|
|
59
90
|
static async stop() {
|
|
60
91
|
if (SuiLocalTestValidator.__instance) {
|
|
@@ -62,10 +93,20 @@ export default class SuiLocalTestValidator extends SuiCommonMethods {
|
|
|
62
93
|
}
|
|
63
94
|
}
|
|
64
95
|
|
|
96
|
+
/**
|
|
97
|
+
* @param {number} port
|
|
98
|
+
* @returns {Promise<boolean>} true if the port accepts a TCP connection within 3 seconds
|
|
99
|
+
*/
|
|
65
100
|
async isPortThere(port) {
|
|
66
101
|
return await SuiCliCommands.isPortThere(port);
|
|
67
102
|
}
|
|
68
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Poll `isPortThere` every 500 ms until the port is open or the timeout elapses.
|
|
106
|
+
* @param {number} port
|
|
107
|
+
* @param {number} timeout - total wait time in ms
|
|
108
|
+
* @returns {Promise<boolean>}
|
|
109
|
+
*/
|
|
69
110
|
async waitForPort(port, timeout) {
|
|
70
111
|
this.log('waiting for port', port);
|
|
71
112
|
const startedCheckingAt = (new Date()).getTime();
|
|
@@ -82,9 +123,13 @@ export default class SuiLocalTestValidator extends SuiCommonMethods {
|
|
|
82
123
|
}
|
|
83
124
|
|
|
84
125
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
126
|
+
* Start `sui start --with-faucet --with-indexer --with-graphql --force-regenesis`,
|
|
127
|
+
* wait for the faucet (port 9123) and GraphQL (port 9125) to come up,
|
|
128
|
+
* then return this instance with `active === true`.
|
|
129
|
+
*
|
|
130
|
+
* If `testFallbackEnabled` is set and the spawn fails, silently switches to devnet.
|
|
131
|
+
*
|
|
132
|
+
* @returns {Promise<SuiLocalTestValidator>}
|
|
88
133
|
*/
|
|
89
134
|
async launch() {
|
|
90
135
|
if (this._active) {
|
|
@@ -98,6 +143,8 @@ export default class SuiLocalTestValidator extends SuiCommonMethods {
|
|
|
98
143
|
const params = [];
|
|
99
144
|
params.push('start');
|
|
100
145
|
params.push('--with-faucet');
|
|
146
|
+
params.push('--with-indexer');
|
|
147
|
+
params.push('--with-graphql');
|
|
101
148
|
params.push('--force-regenesis');
|
|
102
149
|
this._child = await SuiCliCommands.spawn('sui', params, { RUST_LOG: 'off,sui_node=info' });
|
|
103
150
|
} catch (e) {
|
|
@@ -120,22 +167,37 @@ export default class SuiLocalTestValidator extends SuiCommonMethods {
|
|
|
120
167
|
this.log(`child process exited with code ${code}`);
|
|
121
168
|
});
|
|
122
169
|
|
|
170
|
+
// @ts-ignore — process is a Node.js global; not available in TypeScript without @types/node
|
|
123
171
|
process.on('exit', ()=>{
|
|
124
172
|
if (this._child) {
|
|
125
173
|
this._child.kill();
|
|
126
174
|
}
|
|
127
175
|
});
|
|
176
|
+
// @ts-ignore
|
|
128
177
|
const cleanExit = function() { process.exit() };
|
|
178
|
+
// @ts-ignore
|
|
129
179
|
process.on('SIGINT', cleanExit); // catch ctrl-c
|
|
180
|
+
// @ts-ignore
|
|
130
181
|
process.on('SIGTERM', cleanExit); // catch kill
|
|
131
182
|
|
|
132
183
|
this._active = await this.waitForPort(9123, 30000);
|
|
133
184
|
|
|
185
|
+
if (this._active) {
|
|
186
|
+
const graphqlUp = await this.waitForPort(9125, 30000);
|
|
187
|
+
if (!graphqlUp) {
|
|
188
|
+
this.log('warning: GraphQL port 9125 did not come up in time');
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
134
192
|
// await this.__readyLaunchedPromise;
|
|
135
193
|
|
|
136
194
|
return this;
|
|
137
195
|
}
|
|
138
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Kill the child `sui start` process if it is running.
|
|
199
|
+
* @returns {Promise<void>}
|
|
200
|
+
*/
|
|
139
201
|
async stop() {
|
|
140
202
|
if (this._child) {
|
|
141
203
|
await this._child.kill();
|