@msafe/sui3-sdk 1.0.18 → 1.0.20

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.18",
3
+ "version": "1.0.20",
4
4
  "description": "SDK for MSafe SUI V3",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",
@@ -340,15 +340,9 @@ export class MSafeAccount {
340
340
  throw new Error('Already rejected');
341
341
  }
342
342
 
343
+ // API independently rebuilds via buildRejectTxb() + build() and compares digest.
344
+ // Do not set gas / prepareGasFunding here — that changes payment and breaks the check.
343
345
  const rejectTxb = toSuiTransaction(buildRejectTxb(this.address));
344
- rejectTxb.setGasPrice(input.gasPrice);
345
- await prepareGasFunding({
346
- tx: rejectTxb,
347
- suiClient: this.suiClient,
348
- owner: this.address,
349
- gasPrice: input.gasPrice,
350
- gasBudget: input.gasBudget,
351
- });
352
346
  const digest = await rejectTxb.getDigest({ client: this.suiClient });
353
347
  const payload = await rejectTxb.build({ client: this.suiClient });
354
348
  const signature = await this.wallet.signTransactionBlock({ transactionBlock: payload });
@@ -1,7 +1,7 @@
1
1
  import type { SuiClientTypes } from '@mysten/sui/client';
2
2
  import type { SuiGrpcClient } from '@mysten/sui/grpc';
3
3
  import { Transaction } from '@mysten/sui/transactions';
4
- import { normalizeSuiObjectId } from '@mysten/sui/utils';
4
+ import { normalizeStructTag, normalizeSuiObjectId } from '@mysten/sui/utils';
5
5
 
6
6
  import { createCoinReservationRef } from '@/utils/coinReservation';
7
7
  import { getAllCoins, SUI_COIN } from '@/utils/sui';
@@ -73,6 +73,29 @@ function collectUsedObjectIds(tx: Transaction): Set<string> {
73
73
  }, new Set<string>());
74
74
  }
75
75
 
76
+ /**
77
+ * Mysten CoinWithBalance with useGasCoin=false (type is 0x2::sui::SUI, not "gas")
78
+ * loads every unused SUI coin as a mutable input at resolve time. Those coins
79
+ * cannot also be gas payment or the node rejects:
80
+ * "Mutable object ... cannot appear more than one in one transaction".
81
+ */
82
+ function txConsumesOwnedSuiCoins(tx: Transaction): boolean {
83
+ return tx.getData().commands.some((cmd) => {
84
+ if (cmd.$kind !== '$Intent' || cmd.$Intent.name !== 'CoinWithBalance') {
85
+ return false;
86
+ }
87
+ const type = (cmd.$Intent.data as { type?: string } | undefined)?.type;
88
+ if (!type || type === 'gas') {
89
+ return false;
90
+ }
91
+ try {
92
+ return normalizeStructTag(type) === normalizeStructTag(SUI_COIN);
93
+ } catch {
94
+ return false;
95
+ }
96
+ });
97
+ }
98
+
76
99
  async function loadSuiGasFunding(suiClient: SuiGrpcClient, owner: string, tx: Transaction): Promise<SuiGasFunding> {
77
100
  const usedObjectIds = collectUsedObjectIds(tx);
78
101
  const [coins, balanceRes] = await Promise.all([
@@ -80,6 +103,18 @@ async function loadSuiGasFunding(suiClient: SuiGrpcClient, owner: string, tx: Tr
80
103
  suiClient.getBalance({ owner, coinType: SUI_COIN }),
81
104
  ]);
82
105
 
106
+ const addressBalance = BigInt(balanceRes.balance.addressBalance);
107
+
108
+ // Intent will take every owned SUI coin at resolve time — leave them off gas payment.
109
+ if (txConsumesOwnedSuiCoins(tx)) {
110
+ return {
111
+ paymentCoins: [],
112
+ coinBalance: 0n,
113
+ addressBalance,
114
+ total: addressBalance,
115
+ };
116
+ }
117
+
83
118
  const paymentCoins = coins
84
119
  .filter((coin) => !usedObjectIds.has(normalizeSuiObjectId(coin.objectId)) && BigInt(coin.balance) > 0n)
85
120
  .map((coin) => ({
@@ -90,7 +125,6 @@ async function loadSuiGasFunding(suiClient: SuiGrpcClient, owner: string, tx: Tr
90
125
  }));
91
126
 
92
127
  const coinBalance = paymentCoins.reduce((sum, coin) => sum + coin.balance, 0n);
93
- const addressBalance = BigInt(balanceRes.balance.addressBalance);
94
128
  return {
95
129
  paymentCoins,
96
130
  coinBalance,