@msafe/sui3-sdk 1.0.19 → 1.0.21
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/dist/index.cjs +80 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +76 -77
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/MSafeAccount.ts +61 -76
- package/src/utils/transaction.ts +32 -0
package/package.json
CHANGED
package/src/core/MSafeAccount.ts
CHANGED
|
@@ -27,7 +27,7 @@ import { CoinHelper } from '@/utils';
|
|
|
27
27
|
import { HexToUint8Array } from '@/utils/buffer';
|
|
28
28
|
import { prepareGasFunding } from '@/utils/gasFunding';
|
|
29
29
|
import { BatchObjectOptions, getAllOwnedObjects, type OwnedObjectData } from '@/utils/iter/object';
|
|
30
|
-
import { toSuiTransaction } from '@/utils/transaction';
|
|
30
|
+
import { getIntentionContent, toSuiTransaction, transactionFromContent } from '@/utils/transaction';
|
|
31
31
|
|
|
32
32
|
export class MSafeAccount {
|
|
33
33
|
public multiSig: MultiSigAccount;
|
|
@@ -140,30 +140,7 @@ export class MSafeAccount {
|
|
|
140
140
|
txb?: Transaction;
|
|
141
141
|
},
|
|
142
142
|
) {
|
|
143
|
-
|
|
144
|
-
if (request.txb) {
|
|
145
|
-
txb = request.txb;
|
|
146
|
-
} else {
|
|
147
|
-
const appHelper = appHelpers.getAppHelper(request.application);
|
|
148
|
-
if (!appHelper) {
|
|
149
|
-
throw new Error(`Can't find app helper for application ${request.application}`);
|
|
150
|
-
}
|
|
151
|
-
txb = toSuiTransaction(
|
|
152
|
-
await appHelper.build({
|
|
153
|
-
network: this.globals.config.network,
|
|
154
|
-
intentionData: request.intention,
|
|
155
|
-
txType: request.txType,
|
|
156
|
-
txSubType: request.txSubType,
|
|
157
|
-
clientUrl: this.globals.config.suiClient.url,
|
|
158
|
-
account: {
|
|
159
|
-
address: this.address,
|
|
160
|
-
publicKey: fromHex(this.address),
|
|
161
|
-
chains: [SUI_MAINNET_CHAIN, SUI_TESTNET_CHAIN],
|
|
162
|
-
features: [],
|
|
163
|
-
},
|
|
164
|
-
}),
|
|
165
|
-
);
|
|
166
|
-
}
|
|
143
|
+
const txb = await this.buildTxFromIntention(request);
|
|
167
144
|
txb.setSender(this.address);
|
|
168
145
|
return this.simulator.simulate({ txb, sender: this.address });
|
|
169
146
|
}
|
|
@@ -190,30 +167,7 @@ export class MSafeAccount {
|
|
|
190
167
|
txb?: Transaction;
|
|
191
168
|
},
|
|
192
169
|
): Promise<void> {
|
|
193
|
-
|
|
194
|
-
if (input.txb) {
|
|
195
|
-
txb = input.txb;
|
|
196
|
-
} else {
|
|
197
|
-
const appHelper = appHelpers.getAppHelper(input.application);
|
|
198
|
-
if (!appHelper) {
|
|
199
|
-
throw new Error(`Can't find app helper for application ${input.application}`);
|
|
200
|
-
}
|
|
201
|
-
txb = toSuiTransaction(
|
|
202
|
-
await appHelper.build({
|
|
203
|
-
network: this.globals.config.network,
|
|
204
|
-
intentionData: input.intention,
|
|
205
|
-
txType: input.txType,
|
|
206
|
-
txSubType: input.txSubType,
|
|
207
|
-
clientUrl: this.globals.config.suiClient.url,
|
|
208
|
-
account: {
|
|
209
|
-
address: this.address,
|
|
210
|
-
publicKey: fromHex(this.address),
|
|
211
|
-
chains: [SUI_MAINNET_CHAIN, SUI_TESTNET_CHAIN],
|
|
212
|
-
features: [],
|
|
213
|
-
},
|
|
214
|
-
}),
|
|
215
|
-
);
|
|
216
|
-
}
|
|
170
|
+
const txb = await this.buildTxFromIntention(input);
|
|
217
171
|
txb.setGasPrice(input.gasPrice);
|
|
218
172
|
txb.setSender(this.address);
|
|
219
173
|
await prepareGasFunding({
|
|
@@ -340,15 +294,9 @@ export class MSafeAccount {
|
|
|
340
294
|
throw new Error('Already rejected');
|
|
341
295
|
}
|
|
342
296
|
|
|
297
|
+
// API independently rebuilds via buildRejectTxb() + build() and compares digest.
|
|
298
|
+
// Do not set gas / prepareGasFunding here — that changes payment and breaks the check.
|
|
343
299
|
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
300
|
const digest = await rejectTxb.getDigest({ client: this.suiClient });
|
|
353
301
|
const payload = await rejectTxb.build({ client: this.suiClient });
|
|
354
302
|
const signature = await this.wallet.signTransactionBlock({ transactionBlock: payload });
|
|
@@ -362,25 +310,12 @@ export class MSafeAccount {
|
|
|
362
310
|
|
|
363
311
|
async simulateBuildTransaction(): Promise<SimulationResult> {
|
|
364
312
|
const intention = await this.backend.getNextIntention({ msafeAddress: this.address });
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
network: this.globals.config.network,
|
|
372
|
-
intentionData: intention.intention,
|
|
373
|
-
txType: intention.txType as TransactionType,
|
|
374
|
-
txSubType: intention.txSubType,
|
|
375
|
-
clientUrl: this.globals.config.suiClient.url,
|
|
376
|
-
account: {
|
|
377
|
-
address: this.address,
|
|
378
|
-
publicKey: fromHex(this.address),
|
|
379
|
-
chains: [SUI_MAINNET_CHAIN, SUI_TESTNET_CHAIN],
|
|
380
|
-
features: [],
|
|
381
|
-
},
|
|
382
|
-
}),
|
|
383
|
-
);
|
|
313
|
+
const txb = await this.buildTxFromIntention({
|
|
314
|
+
application: intention.application,
|
|
315
|
+
intention: intention.intention,
|
|
316
|
+
txType: intention.txType as TransactionType,
|
|
317
|
+
txSubType: intention.txSubType,
|
|
318
|
+
});
|
|
384
319
|
txb.setSender(this.address);
|
|
385
320
|
return this.simulator.simulate({ txb, sender: this.address });
|
|
386
321
|
}
|
|
@@ -433,6 +368,56 @@ export class MSafeAccount {
|
|
|
433
368
|
});
|
|
434
369
|
}
|
|
435
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Resolve a Transaction from propose/simulate input.
|
|
373
|
+
* 1. Caller-supplied `txb` (generic store path — do not rebuild).
|
|
374
|
+
* 2. Registered app helper `build`.
|
|
375
|
+
* 3. Unregistered app: restore from `intention.content` (JSON or hex).
|
|
376
|
+
*/
|
|
377
|
+
private async buildTxFromIntention(input: {
|
|
378
|
+
application: string;
|
|
379
|
+
txType: TransactionType;
|
|
380
|
+
txSubType: string;
|
|
381
|
+
intention: unknown;
|
|
382
|
+
txb?: Transaction;
|
|
383
|
+
}): Promise<Transaction> {
|
|
384
|
+
if (input.txb) {
|
|
385
|
+
return input.txb;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
let appHelper: ReturnType<typeof appHelpers.getAppHelper> | undefined;
|
|
389
|
+
try {
|
|
390
|
+
appHelper = appHelpers.getAppHelper(input.application);
|
|
391
|
+
} catch {
|
|
392
|
+
appHelper = undefined;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (appHelper) {
|
|
396
|
+
return toSuiTransaction(
|
|
397
|
+
await appHelper.build({
|
|
398
|
+
network: this.globals.config.network,
|
|
399
|
+
intentionData: input.intention,
|
|
400
|
+
txType: input.txType,
|
|
401
|
+
txSubType: input.txSubType,
|
|
402
|
+
clientUrl: this.globals.config.suiClient.url,
|
|
403
|
+
account: {
|
|
404
|
+
address: this.address,
|
|
405
|
+
publicKey: fromHex(this.address),
|
|
406
|
+
chains: [SUI_MAINNET_CHAIN, SUI_TESTNET_CHAIN],
|
|
407
|
+
features: [],
|
|
408
|
+
},
|
|
409
|
+
}),
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const content = getIntentionContent(input.intention);
|
|
414
|
+
if (content != null) {
|
|
415
|
+
return transactionFromContent(content);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
throw new Error(`Can't find app helper for application ${input.application}`);
|
|
419
|
+
}
|
|
420
|
+
|
|
436
421
|
private calculateWeightFromVotes(votes: { userAddress: string }[]) {
|
|
437
422
|
return this.calculateWeight(votes.map((vote) => vote.userAddress));
|
|
438
423
|
}
|
package/src/utils/transaction.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Transaction, isTransaction } from '@mysten/sui/transactions';
|
|
2
|
+
import { fromHex } from '@mysten/sui/utils';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Normalize a transaction value to {@link Transaction}.
|
|
@@ -23,3 +24,34 @@ export function toSuiTransaction(txb: Transaction | unknown): Transaction {
|
|
|
23
24
|
|
|
24
25
|
throw new Error('Unsupported transaction value for toSuiTransaction');
|
|
25
26
|
}
|
|
27
|
+
|
|
28
|
+
function isHex(str: string): boolean {
|
|
29
|
+
return /^[0-9a-fA-F]+$/.test(str);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getIntentionContent(intention: unknown): unknown {
|
|
33
|
+
if (intention && typeof intention === 'object' && 'content' in intention) {
|
|
34
|
+
return (intention as { content: unknown }).content;
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Restore a Transaction from plain-tx `intention.content`.
|
|
41
|
+
* Accepts V2 JSON (`tx.toJSON()`), hex BCS bytes, or a JSON object.
|
|
42
|
+
*/
|
|
43
|
+
export function transactionFromContent(content: unknown): Transaction {
|
|
44
|
+
if (content instanceof Uint8Array) {
|
|
45
|
+
return Transaction.from(content);
|
|
46
|
+
}
|
|
47
|
+
if (typeof content === 'string') {
|
|
48
|
+
if (isHex(content)) {
|
|
49
|
+
return Transaction.from(fromHex(content));
|
|
50
|
+
}
|
|
51
|
+
return Transaction.from(content);
|
|
52
|
+
}
|
|
53
|
+
if (content && typeof content === 'object') {
|
|
54
|
+
return Transaction.from(JSON.stringify(content));
|
|
55
|
+
}
|
|
56
|
+
throw new Error('Invalid transaction content');
|
|
57
|
+
}
|