suidouble 2.5.0 → 2.17.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 (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 +143 -15
  10. package/lib/SuiInBrowserAdapter.js +185 -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 +189 -0
  44. package/types/lib/SuiInBrowserAdapter.d.ts +171 -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
@@ -1,11 +1,17 @@
1
1
  import SuiObject from './SuiObject.js';
2
2
  import SuiCommonMethods from './SuiCommonMethods.js';
3
3
  import SuiPaginatedResponse from './SuiPaginatedResponse.js';
4
- import SuiEvent from './SuiEvent.js';
5
4
  import { Transaction } from '@mysten/sui/transactions';
6
5
  import { normalizeSuiAddress } from './SuiUtils.js';
7
- import SuiMaster from './SuiMaster.js';
8
- import SuiPackage from './SuiPackage.js';
6
+
7
+ /**
8
+ * @typedef {import("./SuiTransaction.js").default} SuiTransaction
9
+ * @typedef {import("./SuiMaster.js").default} SuiMaster
10
+ * @typedef {import("./SuiPackage.js").default} SuiPackage
11
+ * @typedef {import("./SuiEvent.js").default} SuiEvent
12
+ * @typedef {import("./SuiMemoryObjectStorage.js").default} SuiMemoryObjectStorage
13
+ * @typedef {import("@mysten/sui/transactions").CallArg} CallArg
14
+ */
9
15
 
10
16
  export default class SuiPackageModule extends SuiCommonMethods {
11
17
 
@@ -15,8 +21,9 @@ export default class SuiPackageModule extends SuiCommonMethods {
15
21
  * @param {SuiPackage} params.package - instance of SuiPackage this module is part of
16
22
  * @param {SuiMaster} params.suiMaster - instance of SuiMaster
17
23
  * @param {string} params.moduleName - name of the Move module
24
+ * @param {boolean} [params.debug]
18
25
  */
19
- constructor(params = {}) {
26
+ constructor(params) {
20
27
  super(params);
21
28
 
22
29
  this._package = params.package;
@@ -26,96 +33,58 @@ export default class SuiPackageModule extends SuiCommonMethods {
26
33
 
27
34
  this._suiMaster = params.suiMaster;
28
35
  if (!this._suiMaster) {
29
- throw new Error('suiMaster is requried for SuiPackageModule');
36
+ throw new Error('suiMaster is required for SuiPackageModule');
30
37
  }
31
38
  this._moduleName = params.moduleName;
32
39
  if (!this._moduleName) {
33
40
  throw new Error('moduleName is required for SuiPackageModule');
34
41
  }
35
42
 
36
- // we need to get very first version's address of this package to use for types, so we are doing this in separate call
37
- this._checkedOnChain = false;
38
- this._normalizedMoveModule = {};
39
-
40
- this._unsubscribeFunction = null;
41
43
  }
42
44
 
45
+ /**
46
+ * Shortcut for `suiMaster.utils.pureInput(type, value)` — build a BCS-serialised Pure input
47
+ * to use as a moveCall parameter.
48
+ * @param {string} type - BCS type name, e.g. `'u64'`, `'address'`, `'string'`
49
+ * @param {*} value
50
+ * @returns {CallArg}
51
+ */
43
52
  arg(type, value) {
44
53
  return this._suiMaster.utils.pureInput(type, value);
45
54
  }
46
55
 
47
- async getNormalizedMoveFunction(methodName) {
48
- const normalizedPackageAddress = await this.getNormalizedPackageAddress();
49
-
50
- const ret = await this._suiMaster._client.getMoveFunctionArgTypes({
51
- package: normalizedPackageAddress,
52
- module: this._moduleName,
53
- function: methodName,
54
- });
55
-
56
- return ret;
57
- }
58
-
59
- async subscribeEvents() {
60
- this.log('subscribing to events of module', this._moduleName);
61
-
62
- // we need very first package version's id here. So we are getting it from normalized data
63
- const normalizedPackageAddress = await this.getNormalizedPackageAddress();
64
-
65
- const onMessage = (rawEvent) => {
66
- const suiEvent = new SuiEvent({
67
- suiMaster: this._suiMaster,
68
- debug: this._debug,
69
- data: rawEvent,
70
- });
71
-
72
- const eventTypeName = suiEvent.typeName;
73
- this.log('got event', eventTypeName);
74
-
75
- this.emit(eventTypeName, suiEvent); // emit specific event name
76
- this.emit('event', suiEvent, true); // emit to common events flow
77
- };
78
-
79
- this._unsubscribeFunction = await this._suiMaster._client.subscribeEvent({
80
- filter: {"MoveModule": {"package": normalizedPackageAddress, "module": this._moduleName} },
81
- onMessage: onMessage,
82
- });
83
- }
84
-
85
- async unsubscribeEvents() {
86
- if (this._unsubscribeFunction) {
87
- await this._unsubscribeFunction();
88
- this._unsubscribeFunction = null;
89
-
90
- return true;
91
- }
92
-
93
- return false;
94
- }
95
-
56
+ /** @returns {SuiMemoryObjectStorage} shared object storage for this suiMaster */
96
57
  get objectStorage() {
97
58
  return this._suiMaster.objectStorage;
98
59
  }
99
60
 
61
+ /** @returns {Object.<string, SuiObject>} raw map of address → SuiObject */
100
62
  get objects() {
101
63
  return this.objectStorage._objects;
102
64
  }
103
65
 
66
+ /** @returns {SuiObject[]} all objects in storage as an array */
104
67
  get objectsArray() {
105
68
  return this.objectStorage.asArray();
106
69
  }
107
70
 
71
+ /**
72
+ * Add an object to the shared objectStorage by address or SuiObject instance.
73
+ * If the object is already stored, returns the existing instance.
74
+ * Emits `'added'` if a new bare SuiObject is created from an id string.
75
+ *
76
+ * @param {SuiObject | string} suiObjectOrAddress
77
+ * @returns {?SuiObject}
78
+ */
108
79
  pushObject(suiObjectOrAddress) {
109
- let address = `${suiObjectOrAddress}`;
110
- if (suiObjectOrAddress.address) {
111
- address = suiObjectOrAddress.address;
112
- }
80
+ const a = /** @type {any} */ (suiObjectOrAddress);
81
+ let address = a.address ?? `${a}`;
113
82
  try {
114
83
  address = normalizeSuiAddress(address);
115
84
  if (!this.objectStorage.byAddress(address)) {
116
- if (suiObjectOrAddress.address) {
85
+ if (a.address) {
117
86
  // instance of suiObject
118
- this.objectStorage.push(suiObjectOrAddress);
87
+ this.objectStorage.push(a);
119
88
  } else {
120
89
  const obj = new SuiObject({
121
90
  suiMaster: this._suiMaster,
@@ -135,170 +104,175 @@ export default class SuiPackageModule extends SuiCommonMethods {
135
104
  return null;
136
105
  }
137
106
 
107
+ /**
108
+ * Execute a Move function on this module.
109
+ *
110
+ * Builds a `Transaction` from `params`, signs and executes it, then syncs the local
111
+ * `objectStorage` with the effects.
112
+ *
113
+ * After the call the following events are emitted on this module:
114
+ * - `'added'` — for each created or first-seen-mutated SuiObject (payload: SuiObject)
115
+ * - `'created'` — for each chain-created SuiObject (payload: SuiObject)
116
+ * - `'deleted'` — for each deleted SuiObject (payload: SuiObject)
117
+ *
118
+ * `params` element shapes:
119
+ * - `{ type, amount }` — coin argument; converted via `SuiCoin.coinOfAmountToTxCoin`
120
+ * - `[{ type, amount }]` — single-element array → `vector<Coin<T>>` via `makeMoveVec`
121
+ * - `'0x…'` string → `tx.object(id)`
122
+ * - `{ Pure: { bytes } }` → already-serialised Pure input
123
+ * - anything else → `tx.pure(value)`
124
+ *
125
+ * @param {string} methodName - name of the Move function to call
126
+ * @param {Array} params - call arguments
127
+ * @param {string[]} [typeArguments] - Move type parameters, e.g. `['0x2::sui::SUI']`
128
+ * @returns {Promise<SuiTransaction>}
129
+ */
138
130
  async moveCall(methodName, params, typeArguments) {
139
131
  await this._package.checkOnChainIfNeeded();
140
132
 
141
- let tx = null;
142
- if (params.tx) {
143
- tx = params.tx;
144
- } else {
145
- tx = new Transaction();
146
-
147
- const callArgs = [];
148
-
149
- for (let param of params) {
150
- if (param && param.type && param.amount) {
151
- const ownerAddress = this._suiMaster.address;
152
-
153
- const suiCoin = await this._suiMaster.suiCoins.get(param.type);
154
- const txCoinToSend = await suiCoin.coinOfAmountToTxCoin(tx, ownerAddress, param.amount);
155
-
156
- callArgs.push(txCoinToSend);
157
- } else if (param && Array.isArray(param) && param.length == 1 && param[0].type && param[0].amount) {
158
- // vector<Coin<SUI>>
159
- const ownerAddress = this._suiMaster.address;
160
-
161
- const suiCoin = await this._suiMaster.suiCoins.get(param[0].type);
162
- const txCoinToSend = await suiCoin.coinOfAmountToTxCoin(tx, ownerAddress, param[0].amount);
163
-
164
- callArgs.push(tx.makeMoveVec({ type: suiCoin.coinObjectType, elements: [txCoinToSend]}));
165
- } else if (typeof param === 'string' && param.indexOf('0x') === 0) {
166
- callArgs.push(tx.object(param));
167
- } else if (param && param.Pure && param.Pure.bytes) {
168
- // already Pure
169
- callArgs.push(this._suiMaster.utils.txInput(tx, param));
170
- } else {
171
- callArgs.push(tx.pure(param));
172
- }
133
+ const tx = new Transaction();
134
+
135
+ const callArgs = [];
136
+
137
+ for (let param of params) {
138
+ if (param && param.type && param.amount) {
139
+ const suiCoin = this._suiMaster.suiCoins.get(param.type);
140
+ const txCoinToSend = await suiCoin.coinOfAmountToTxCoin(tx, this._suiMaster.address, param.amount);
141
+ callArgs.push(txCoinToSend);
142
+ } else if (param && Array.isArray(param) && param.length == 1 && param[0].type && param[0].amount) {
143
+ // vector<Coin<T>>
144
+ const suiCoin = this._suiMaster.suiCoins.get(param[0].type);
145
+ const txCoinToSend = await suiCoin.coinOfAmountToTxCoin(tx, this._suiMaster.address, param[0].amount);
146
+ callArgs.push(tx.makeMoveVec({ type: suiCoin.coinObjectType, elements: [txCoinToSend] }));
147
+ } else if (typeof param === 'string' && param.indexOf('0x') === 0) {
148
+ callArgs.push(tx.object(param));
149
+ } else if (param && param.Pure && param.Pure.bytes) {
150
+ // already Pure
151
+ callArgs.push(this._suiMaster.utils.txInput(tx, param));
152
+ } else {
153
+ callArgs.push(tx.pure(param));
173
154
  }
174
-
175
- tx.moveCall({
176
- target: `${this._package.address}::${this._moduleName}::${methodName}`,
177
- arguments: callArgs,
178
- typeArguments: typeArguments,
179
- });
180
155
  }
181
156
 
182
- const result = await this._suiMaster.signAndExecuteTransaction({
157
+ tx.moveCall({
158
+ target: `${this._package.address}::${this._moduleName}::${methodName}`,
159
+ arguments: callArgs,
160
+ typeArguments: typeArguments,
161
+ });
162
+
163
+ return await this.executeTransaction(tx);
164
+ }
165
+
166
+ /**
167
+ * Sign and execute a pre-built Transaction, then sync `objectStorage` with the effects and
168
+ * emit change events on this module.
169
+ *
170
+ * Emits per-object events:
171
+ * - `'added'` — created objects not yet in storage, and first-seen mutated objects
172
+ * - `'created'` — every chain-created object
173
+ * - `'deleted'` — every deleted object
174
+ *
175
+ * @param {Transaction} tx
176
+ * @returns {Promise<SuiTransaction>}
177
+ */
178
+ async executeTransaction(tx) {
179
+ const resultTransaction = await this._suiMaster.signAndExecuteTransaction({
183
180
  transaction: tx,
184
181
  requestType: 'WaitForLocalExecution',
185
- options: {
186
- "showEffects": true, // @todo: remove?
187
- "showEvents": true, // @todo: remove?
188
- "showObjectChanges": true,
189
- showType: true,
190
- showContent: true,
191
- showOwner: true,
192
- showDisplay: true,
182
+ include: {
183
+ effects: true,
184
+ objectTypes: true,
185
+ transaction: true,
186
+ bcs: true,
187
+ balanceChanges: true,
188
+ events: true,
193
189
  },
194
190
  });
195
191
 
196
- const suiTransaction = new this._suiMaster.SuiTransaction({
197
- suiMaster: this._suiMaster,
198
- debug: this._debug,
199
- data: result,
200
- });
201
- const status = suiTransaction.status;
202
-
203
- const listCreated = [];
204
- const listMutated = [];
205
- const listDeleted = [];
206
-
207
- for (const obj of suiTransaction.results.objects) {
208
- if (this.objectStorage.byAddress(obj.id)) {
209
- this.objectStorage.byAddress(obj.id).replaceWithSuiObjectIfNeeded(obj);
192
+ for (const suiObject of resultTransaction.created) {
193
+ if (this.objectStorage.byAddress(suiObject.id)) {
194
+ this.objectStorage.byAddress(suiObject.id).replaceWithSuiObjectIfNeeded(suiObject);
210
195
  } else {
211
- this.objectStorage.push(obj);
212
- this.emit('added', obj);
196
+ this.objectStorage.push(suiObject);
197
+ this.emit('added', suiObject);
213
198
  }
199
+ this.emit('created', this.objectStorage.byAddress(suiObject.id));
214
200
  }
215
-
216
- for (const obj of suiTransaction.results.deleted) {
217
- if (this.objectStorage.byAddress(obj.id)) {
218
- this.objectStorage.byAddress(obj.id).markAsDeleted();
219
- listDeleted.push(this.objectStorage.byAddress(obj.id));
220
- this.emit('deleted', this.objectStorage.byAddress(obj.id));
201
+ for (const suiObject of resultTransaction.deleted) {
202
+ if (this.objectStorage.byAddress(suiObject.id)) {
203
+ this.objectStorage.byAddress(suiObject.id).markAsDeleted();
204
+ this.emit('deleted', this.objectStorage.byAddress(suiObject.id));
221
205
  }
222
206
  }
223
-
224
- await this.fetchObjects();
225
-
226
- for (const obj of suiTransaction.results.created) {
227
- if (this.objectStorage.byAddress(obj.id)) {
228
- listCreated.push(this.objectStorage.byAddress(obj.id)); // it's probably the same instance as it's just created. @todo: check
229
- this.emit('created', this.objectStorage.byAddress(obj.id));
207
+ for (const suiObject of resultTransaction.mutated) {
208
+ if (this.objectStorage.byAddress(suiObject.id)) {
209
+ this.objectStorage.byAddress(suiObject.id).replaceWithSuiObjectIfNeeded(suiObject);
230
210
  } else {
231
- throw new Error('something is wrong!');
211
+ this.objectStorage.push(suiObject);
212
+ this.emit('added', suiObject);
232
213
  }
233
214
  }
234
215
 
235
- for (const obj of suiTransaction.results.mutated) {
236
- if (this.objectStorage.byAddress(obj.id)) {
237
- listMutated.push(this.objectStorage.byAddress(obj.id)); // it may be a different entity, updated via .replaceWithSuiObjectIfNeeded above
238
- this.emit('mutated', this.objectStorage.byAddress(obj.id));
239
- } else {
240
- throw new Error('something is wrong!');
241
- }
242
- }
243
-
244
- for (const suiEvent of suiTransaction.events) {
245
- this.emit(suiEvent.typeName, suiEvent);
246
- }
247
-
248
- return suiTransaction;
216
+ return resultTransaction;
249
217
  }
250
218
 
219
+ /**
220
+ * List objects of this module owned by the current SuiMaster address.
221
+ * Uses the original (first-version) package id so the filter is stable across upgrades.
222
+ *
223
+ * @param {Object} [params]
224
+ * @param {?string} [params.typeName] - If set, narrows the type filter to `<pkg>::<module>::<typeName>`.
225
+ * Otherwise filters by `<pkg>::<module>`.
226
+ * @param {number} [params.limit=50]
227
+ * @param {string} [params.order]
228
+ * @returns {Promise<SuiPaginatedResponse<SuiObject>>}
229
+ */
251
230
  async getOwnedObjects(params = {}) {
252
- ///
253
- /// the pagination is not accurate, because previous page may have
254
- /// been updated when the next page is fetched. Please use suix_queryObjects if this is a concern.
255
- ///
256
- const normalizedPackageAddress = await this.getNormalizedPackageAddress();
257
- const queryParams = {
231
+ const originalPackageId = await this._package.getOriginalPackageId();
232
+ const type = params.typeName
233
+ ? `${originalPackageId}::${this._moduleName}::${params.typeName}`
234
+ : `${originalPackageId}::${this._moduleName}`;
235
+
236
+ return await this._suiMaster.getOwnedObjects({
258
237
  owner: this._suiMaster.address,
259
- filter: { MoveModule: { package: normalizedPackageAddress, module: this._moduleName } },
260
- limit: 50, // max limit is 50
261
- options: {
262
- showType: true,
263
- showContent: true,
264
- showOwner: true,
265
- showDisplay: true,
238
+ type,
239
+ limit: params.limit || 50,
240
+ include: {
241
+ content: true,
242
+ json: true,
243
+ display: true,
266
244
  },
267
- };
268
-
269
- if (params.typeName) {
270
- queryParams.filter = { StructType: `${normalizedPackageAddress}::${this._moduleName}::${params.typeName}`};
271
- }
272
-
273
- const paginatedResponse = new SuiPaginatedResponse({
274
- debug: this._debug,
275
- suiMaster: this._suiMaster,
276
- params: queryParams,
277
- method: 'getOwnedObjects',
278
- order: params.order,
279
- });
280
-
281
- await paginatedResponse.fetch();
282
-
283
- return paginatedResponse;
245
+ }, { order: params.order });
284
246
  }
285
247
 
248
+ /**
249
+ * Fetch events emitted by this module, via the GraphQL `events` query.
250
+ * Uses the original (first-version) package id of the parent SuiPackage so the filter
251
+ * is stable across upgrades.
252
+ *
253
+ * @param {Object} [params]
254
+ * @param {?string} [params.eventTypeName] - If set, narrows the filter to a single event struct
255
+ * (`<pkg>::<module>::<EventName>`). Otherwise fetches
256
+ * all events emitted by any function in this module.
257
+ * @param {number} [params.limit=50]
258
+ * @param {string} [params.order] - Passed through to the underlying paginated response
259
+ * @returns {Promise<SuiPaginatedResponse<SuiEvent>>}
260
+ */
286
261
  async fetchEvents(params = {}) {
287
- const moduleFilter = {};
262
+ const filter = {};
288
263
 
289
- // we need very first package version's id here. So we are getting it from normalized data
290
- let normalizedPackageAddress = await this.getNormalizedPackageAddress();
264
+ // we need very first package version's id here so the filter is stable across upgrades
265
+ const originalPackageId = await this._package.getOriginalPackageId();
291
266
  if (params.eventTypeName) {
292
- moduleFilter.MoveEventType = `${normalizedPackageAddress}::${this._moduleName}::${params.eventTypeName}`;
293
- this.log('queriying for events of type: ', moduleFilter.MoveEventType);
267
+ filter.type = `${originalPackageId}::${this._moduleName}::${params.eventTypeName}`;
268
+ this.log('querying for events of type: ', filter.type);
294
269
  } else {
295
- moduleFilter.MoveModule = { package: normalizedPackageAddress, module: this._moduleName };
296
- this.log('queriying for all events of module: ', this._moduleName);
270
+ filter.module = `${originalPackageId}::${this._moduleName}`;
271
+ this.log('querying for all events of module: ', filter.module);
297
272
  }
298
273
 
299
274
  const queryParams = {
300
- descending_order: false,
301
- query: moduleFilter,
275
+ filter,
302
276
  limit: params.limit || 50,
303
277
  };
304
278
 
@@ -306,42 +280,23 @@ export default class SuiPackageModule extends SuiCommonMethods {
306
280
  debug: this._debug,
307
281
  suiMaster: this._suiMaster,
308
282
  params: queryParams,
309
- method: 'queryEvents',
283
+ method: 'graphqlEvents',
310
284
  order: params.order,
311
285
  });
312
286
 
313
287
  await paginatedResponse.fetch();
314
288
 
315
- return paginatedResponse;
289
+ return /** @type {SuiPaginatedResponse<SuiEvent>} */ (/** @type {any} */ (paginatedResponse));
316
290
  }
317
291
 
292
+ /**
293
+ * Refresh all objects in the shared objectStorage from chain.
294
+ * Delegates to `SuiMemoryObjectStorage.fetchObjects()`.
295
+ * @returns {Promise<SuiObject[]>}
296
+ */
318
297
  async fetchObjects() {
319
298
  return await this.objectStorage.fetchObjects();
320
299
  }
321
300
 
322
- async getNormalizedPackageAddress() {
323
- await this.checkOnChainIfNeeded();
324
- if (this._normalizedMoveModule && this._normalizedMoveModule.address) {
325
- return this._normalizedMoveModule.address;
326
- }
327
- }
328
-
329
- async checkOnChainIfNeeded() {
330
- if (this._checkedOnChain) {
331
- return true;
332
- }
333
-
334
- const normalized = await this._suiMaster._client.getNormalizedMoveModule({
335
- package: this._package.address,
336
- module: this._moduleName,
337
- });
338
-
339
- if (normalized && normalized.address) {
340
- this._normalizedMoveModule = normalized;
341
- this._checkedOnChain = true;
342
- }
343
-
344
- return true;
345
- }
346
301
 
347
302
  };