@msafe/sui3-sdk 1.0.17 → 1.0.18

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@msafe/sui3-sdk",
3
- "version": "1.0.17",
3
+ "version": "1.0.18",
4
4
  "description": "SDK for MSafe SUI V3",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",
@@ -32,8 +32,8 @@
32
32
  "@changesets/changelog-github": "^0.7.0",
33
33
  "@changesets/cli": "^2.31.0",
34
34
  "@msafe/mpay-sdk-sui": "^1.0.25",
35
- "@msafe/sui-app-store": "0.0.338",
36
- "@msafe/sui3-utils": "^5.0.8",
35
+ "@msafe/sui-app-store": "^0.0.357",
36
+ "@msafe/sui3-utils": "^5.1.0",
37
37
  "@mysten/sui": "^2.16.2",
38
38
  "@mysten/wallet-standard": "^0.20.3",
39
39
  "@types/jest": "^30.0.0",
@@ -212,6 +212,44 @@ export async function selectGasFunding(input: {
212
212
  * cheaper payment path. Budget is left unset so Mysten can dry-run with MAX_GAS
213
213
  * overrides (avoids locking the full balance away from GasCoin splits).
214
214
  */
215
+ /**
216
+ * Clone a tx with gas budget/payment/expiration cleared.
217
+ * Needed because Mysten treats budget "0" as set (truthy) and skips re-estimation,
218
+ * and app-store helper.build() often pre-builds with payment:[] + budget:"0".
219
+ */
220
+ function cloneWithClearedGasConfig(tx: Transaction): Transaction {
221
+ const data = structuredClone(tx.getData()) as {
222
+ version: number;
223
+ sender: string | null;
224
+ expiration: unknown;
225
+ gasData: {
226
+ budget: string | null;
227
+ price: string | null;
228
+ owner: string | null;
229
+ payment: unknown;
230
+ };
231
+ inputs: unknown;
232
+ commands: unknown;
233
+ };
234
+ data.gasData.budget = null;
235
+ data.gasData.price = null;
236
+ data.gasData.payment = null;
237
+ // Address-balance gas bakes ValidDuring; clear so classic gas probe is valid.
238
+ data.expiration = null;
239
+ return Transaction.from(JSON.stringify(data));
240
+ }
241
+
242
+ function isPositiveBudget(budget: string | number | bigint | null | undefined): boolean {
243
+ if (budget == null) {
244
+ return false;
245
+ }
246
+ try {
247
+ return BigInt(budget) > 0n;
248
+ } catch {
249
+ return false;
250
+ }
251
+ }
252
+
215
253
  export async function estimateGasBudget(input: {
216
254
  tx: Transaction;
217
255
  suiClient: SuiGrpcClient;
@@ -224,7 +262,11 @@ export async function estimateGasBudget(input: {
224
262
  throw new InsufficientGasFundsError(0n, funding.coinBalance, funding.addressBalance);
225
263
  }
226
264
 
227
- const probe = Transaction.from(tx);
265
+ const { budget, payment } = tx.getData().gasData;
266
+ // app-store / Mysten pre-build can leave payment:[] with budget "0".
267
+ // Mysten's setGasBudget skips when budget is the string "0" (truthy), so clear first.
268
+ const mustResetGas = (payment != null && payment.length === 0) || (budget != null && !isPositiveBudget(budget));
269
+ const probe = mustResetGas ? cloneWithClearedGasConfig(tx) : Transaction.from(tx);
228
270
  probe.setSender(owner);
229
271
  probe.setGasPrice(gasPrice);
230
272
 
@@ -273,16 +315,27 @@ export async function prepareGasFunding(input: {
273
315
  // Never trust a budget baked into plain-tx / Mysten auto AB-gas txs.
274
316
  // Those budgets are often under-estimated for payment: [] and would skip
275
317
  // estimateGasBudget if we kept existingBudget.
318
+ // Also never trust budget "0" / 0n — Mysten treats "0" as set and skips resolve.
276
319
  let { gasBudget } = input;
320
+ if (gasBudget != null && gasBudget <= 0n) {
321
+ gasBudget = undefined;
322
+ }
323
+ const existingPositive = isPositiveBudget(existingBudget) ? BigInt(existingBudget as string) : null;
324
+
277
325
  if (gasBudget == null) {
278
- if (bakedAddressBalanceGas || existingBudget == null) {
326
+ if (bakedAddressBalanceGas || existingPositive == null) {
279
327
  gasBudget = await estimateGasBudget({ tx, suiClient, owner, gasPrice });
280
328
  } else {
281
- gasBudget = BigInt(existingBudget);
329
+ gasBudget = existingPositive;
282
330
  }
283
331
  }
284
332
 
285
333
  tx.setGasBudget(gasBudget);
334
+ // Drop ValidDuring from a prior address-balance pre-build; classic gas must not keep it,
335
+ // and AB gas will re-attach expiration during the final build when payment is [].
336
+ if (bakedAddressBalanceGas) {
337
+ tx.setExpiration(null);
338
+ }
286
339
  return selectGasFunding({ tx, suiClient, owner, gasBudget });
287
340
  }
288
341