suidouble 1.45.2 → 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.
Files changed (59) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/README.md +222 -131
  3. package/index.js +1 -3
  4. package/lib/SuiCliCommands.js +18 -25
  5. package/lib/SuiCoin.js +86 -138
  6. package/lib/SuiCoins.js +70 -31
  7. package/lib/SuiCommonMethods.js +40 -3
  8. package/lib/SuiEvent.js +54 -6
  9. package/lib/SuiInBrowser.js +145 -46
  10. package/lib/SuiInBrowserAdapter.js +164 -37
  11. package/lib/SuiLocalTestValidator.js +78 -25
  12. package/lib/SuiMaster.js +351 -126
  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 -124
  21. package/package.json +30 -14
  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 -21
  35. package/test/test_move_contracts/different_types/sources/different_types.move +12 -12
  36. package/test/test_move_contracts/suidouble_chat/Move.lock +18 -22
  37. package/test/test_move_contracts/suidouble_chat/sources/suidouble_chat.move +9 -8
  38. package/tsconfig.json +15 -0
  39. package/types/index.d.ts +15 -0
  40. package/types/lib/SuiCliCommands.d.ts +6 -0
  41. package/types/lib/SuiCoin.d.ts +183 -0
  42. package/types/lib/SuiCoins.d.ts +93 -0
  43. package/types/lib/SuiCommonMethods.d.ts +37 -0
  44. package/types/lib/SuiEvent.d.ts +95 -0
  45. package/types/lib/SuiInBrowser.d.ts +189 -0
  46. package/types/lib/SuiInBrowserAdapter.d.ts +167 -0
  47. package/types/lib/SuiLocalTestValidator.d.ts +92 -0
  48. package/types/lib/SuiMaster.d.ts +333 -0
  49. package/types/lib/SuiMemoryObjectStorage.d.ts +96 -0
  50. package/types/lib/SuiObject.d.ts +135 -0
  51. package/types/lib/SuiPackage.d.ts +233 -0
  52. package/types/lib/SuiPackageModule.d.ts +139 -0
  53. package/types/lib/SuiPaginatedResponse.d.ts +148 -0
  54. package/types/lib/SuiPseudoRandomAddress.d.ts +33 -0
  55. package/types/lib/SuiTransaction.d.ts +92 -0
  56. package/types/lib/SuiUtils.d.ts +152 -0
  57. package/types/lib/data/icons.d.ts +12 -0
  58. package/lib/SuiTestScenario.js +0 -169
  59. 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
- this._standartAdapter = null;
20
- // params.standartAdapter || null; // instance returned from '@wallet-standard/core'
21
- if (params.standartAdapter) {
22
- this.setStandartAdapter(params.standartAdapter);
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
- async signTransactionBlock(params) {
59
- return await this.getFeature(Feature.SUI_SIGN_TX_BLOCK).signTransactionBlock(params);
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
- if (!this._standartAdapter) {
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._standartAdapter && this._standartAdapter.accounts && this._standartAdapter.accounts.length) {
122
- this._connectedAddress = this._standartAdapter.accounts[0].address;
123
- this._connectedChain = this._standartAdapter.accounts[0].chains[0];
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
- setStandartAdapter(standartAdapter) {
146
- if (this._standartAdapter) {
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 standartAdapter.features) {
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._standartAdapter = standartAdapter;
164
- if (!this.__standartAdapterChangeListener) {
165
- this.__standartAdapterChangeListener = (e) => {
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.__standartAdapterChangeListener);
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
- if (this._standartAdapter) {
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._standartAdapter) {
191
- return this._standartAdapter.features;
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._standartAdapter) {
198
- return this._standartAdapter.name;
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._standartAdapter) {
206
- return this._standartAdapter.icon;
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._standartAdapter) {
214
- return this._standartAdapter.version;
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
 
@@ -1,57 +1,78 @@
1
1
  import SuiCliCommands from "./SuiCliCommands.js";
2
2
  import SuiCommonMethods from "./SuiCommonMethods.js";
3
- import { SuiClient, getFullnodeUrl, SuiHTTPTransport } from '@mysten/sui/client';
4
3
  import SuiUtils from "./SuiUtils.js";
5
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
+ */
6
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
+ */
7
21
  constructor(params = {}) {
8
22
  super(params);
9
23
 
24
+ /** @type {?Object} spawned child process */
10
25
  this._child = null;
26
+ /** @type {boolean} */
11
27
  this._active = false;
12
28
 
13
- this._testFallbackEnabled = false;
14
- if (params.testFallbackEnabled) {
15
- // option for unit tests to fallback to sui:dev network in case
16
- // there is no local validator installed
17
- this._testFallbackEnabled = true;
18
- }
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;
19
34
 
35
+ /** @type {?number} */
20
36
  this._epochDuration = params.epochDuration || null;
21
37
 
38
+ /** @type {string} */
22
39
  this._providerName = 'sui:localnet';
23
40
  }
24
41
 
42
+ /** @returns {string} active chain identifier, e.g. `'sui:localnet'` or `'sui:devnet'` after fallback */
25
43
  get providerName() {
26
44
  return this._providerName;
27
45
  }
28
46
 
47
+ /** @type {?SuiLocalTestValidator} */
48
+ static __instance = null;
49
+
50
+ /**
51
+ * gRPC client for the currently active chain.
52
+ * @returns {SuiGrpcClient}
53
+ */
29
54
  get client() {
30
55
  if (this._providerName === 'sui:localnet') {
31
- return new SuiClient({
32
- transport: new SuiHTTPTransport({
33
- url: getFullnodeUrl('localnet'),
34
- WebSocketConstructor: SuiUtils.WebSocketConstructor(),
35
- }),
36
- });
56
+ return SuiUtils.suiClientFor('localnet');
37
57
  } else if (this._providerName === 'sui:devnet') {
38
58
  // if testFallbackEnabled == true and we can't start local node
39
- return new SuiClient({
40
- url: getFullnodeUrl('devnet'),
41
- WebSocketConstructor: SuiUtils.WebSocketConstructor(),
42
- });
59
+ return SuiUtils.suiClientFor('devnet');
43
60
  }
44
61
  }
45
62
 
63
+ /** @returns {boolean} true once the node is up and accepting transactions */
46
64
  get active() {
47
65
  return this._active;
48
66
  }
49
67
 
50
68
  /**
51
- * Launch a localnet sui and wait for it to become available to accept transactions.
52
- * Don't forget to .stop() it after usage.
53
- *
54
- * @returns {SuiLocalTestValidator}
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>}
55
76
  */
56
77
  static async launch(params = {}) {
57
78
  if (SuiLocalTestValidator.__instance) {
@@ -63,7 +84,8 @@ export default class SuiLocalTestValidator extends SuiCommonMethods {
63
84
  }
64
85
 
65
86
  /**
66
- * Stop the local sui node
87
+ * Stop the singleton local sui node if running.
88
+ * @returns {Promise<void>}
67
89
  */
68
90
  static async stop() {
69
91
  if (SuiLocalTestValidator.__instance) {
@@ -71,10 +93,20 @@ export default class SuiLocalTestValidator extends SuiCommonMethods {
71
93
  }
72
94
  }
73
95
 
96
+ /**
97
+ * @param {number} port
98
+ * @returns {Promise<boolean>} true if the port accepts a TCP connection within 3 seconds
99
+ */
74
100
  async isPortThere(port) {
75
101
  return await SuiCliCommands.isPortThere(port);
76
102
  }
77
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
+ */
78
110
  async waitForPort(port, timeout) {
79
111
  this.log('waiting for port', port);
80
112
  const startedCheckingAt = (new Date()).getTime();
@@ -91,9 +123,13 @@ export default class SuiLocalTestValidator extends SuiCommonMethods {
91
123
  }
92
124
 
93
125
  /**
94
- * Launch a local sui node and wait for it to become available to accept transactions.
95
- *
96
- * @returns {SuiLocalTestValidator}
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>}
97
133
  */
98
134
  async launch() {
99
135
  if (this._active) {
@@ -107,6 +143,8 @@ export default class SuiLocalTestValidator extends SuiCommonMethods {
107
143
  const params = [];
108
144
  params.push('start');
109
145
  params.push('--with-faucet');
146
+ params.push('--with-indexer');
147
+ params.push('--with-graphql');
110
148
  params.push('--force-regenesis');
111
149
  this._child = await SuiCliCommands.spawn('sui', params, { RUST_LOG: 'off,sui_node=info' });
112
150
  } catch (e) {
@@ -129,22 +167,37 @@ export default class SuiLocalTestValidator extends SuiCommonMethods {
129
167
  this.log(`child process exited with code ${code}`);
130
168
  });
131
169
 
170
+ // @ts-ignore — process is a Node.js global; not available in TypeScript without @types/node
132
171
  process.on('exit', ()=>{
133
172
  if (this._child) {
134
173
  this._child.kill();
135
174
  }
136
175
  });
176
+ // @ts-ignore
137
177
  const cleanExit = function() { process.exit() };
178
+ // @ts-ignore
138
179
  process.on('SIGINT', cleanExit); // catch ctrl-c
180
+ // @ts-ignore
139
181
  process.on('SIGTERM', cleanExit); // catch kill
140
182
 
141
183
  this._active = await this.waitForPort(9123, 30000);
142
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
+
143
192
  // await this.__readyLaunchedPromise;
144
193
 
145
194
  return this;
146
195
  }
147
196
 
197
+ /**
198
+ * Kill the child `sui start` process if it is running.
199
+ * @returns {Promise<void>}
200
+ */
148
201
  async stop() {
149
202
  if (this._child) {
150
203
  await this._child.kill();