@msafe/sui3-sdk 1.0.20 → 1.0.22
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 +200 -92
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -1
- package/dist/index.d.ts +48 -1
- package/dist/index.js +197 -89
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/MSafeAccount.ts +80 -70
- package/src/simulate/simulator.ts +19 -2
- package/src/utils/gasFunding.ts +125 -16
- package/src/utils/transaction.ts +32 -0
package/dist/index.d.cts
CHANGED
|
@@ -352,6 +352,18 @@ declare class InsufficientGasFundsError extends Error {
|
|
|
352
352
|
* storageRebate is refunded after execution and must not reduce the budget.
|
|
353
353
|
*/
|
|
354
354
|
declare function computeGasBudget(gasUsed: Pick<SuiClientTypes.GasCostSummary, 'computationCost' | 'storageCost'>, gasPrice: bigint): bigint;
|
|
355
|
+
/** Object IDs a built payload already pins (inputs + gas payment). */
|
|
356
|
+
declare function collectPayloadObjectIds(payload: string | Uint8Array): string[];
|
|
357
|
+
/**
|
|
358
|
+
* Parked queue item: intention was saved with a built hex payload + digest
|
|
359
|
+
* so build-next can promote it without rebuilding.
|
|
360
|
+
*/
|
|
361
|
+
declare function parkedPayloadHex(intention: unknown): string | undefined;
|
|
362
|
+
/** Coins already pinned by the current pending tx and any parked future payloads. */
|
|
363
|
+
declare function collectQueueExcludeObjectIds(input: {
|
|
364
|
+
pendingPayload?: string;
|
|
365
|
+
parkedPayloads?: Array<string | undefined>;
|
|
366
|
+
}): string[];
|
|
355
367
|
/**
|
|
356
368
|
* Select gas funding before tx.build() according to mixed coin/addressBalance policy:
|
|
357
369
|
* 1) budget without storageRebate (caller supplies computeGasBudget result)
|
|
@@ -365,12 +377,15 @@ declare function selectGasFunding(input: {
|
|
|
365
377
|
suiClient: SuiGrpcClient;
|
|
366
378
|
owner: string;
|
|
367
379
|
gasBudget: bigint;
|
|
380
|
+
excludeObjectIds?: Iterable<string>;
|
|
368
381
|
}): Promise<GasFundingResult>;
|
|
369
382
|
declare function estimateGasBudget(input: {
|
|
370
383
|
tx: Transaction;
|
|
371
384
|
suiClient: SuiGrpcClient;
|
|
372
385
|
owner: string;
|
|
373
386
|
gasPrice: bigint;
|
|
387
|
+
excludeObjectIds?: Iterable<string>;
|
|
388
|
+
preferAddressBalance?: boolean;
|
|
374
389
|
}): Promise<bigint>;
|
|
375
390
|
/**
|
|
376
391
|
* Resolve gasBudget (no rebate) and apply gas funding selection before build.
|
|
@@ -381,6 +396,16 @@ declare function prepareGasFunding(input: {
|
|
|
381
396
|
owner: string;
|
|
382
397
|
gasPrice: bigint;
|
|
383
398
|
gasBudget?: bigint;
|
|
399
|
+
/**
|
|
400
|
+
* Force Address Balance gas (`payment: []`). Prefer {@link excludeObjectIds}
|
|
401
|
+
* for queue-behind-pending so unused SUI coins can still pay.
|
|
402
|
+
*/
|
|
403
|
+
preferAddressBalance?: boolean;
|
|
404
|
+
/**
|
|
405
|
+
* Queue-behind-pending: do not pick coins the current pending / parked
|
|
406
|
+
* payloads already pin. Those versions will change when the earlier tx executes.
|
|
407
|
+
*/
|
|
408
|
+
excludeObjectIds?: Iterable<string>;
|
|
384
409
|
}): Promise<GasFundingResult>;
|
|
385
410
|
/**
|
|
386
411
|
* @deprecated Use {@link prepareGasFunding} / {@link selectGasFunding}.
|
|
@@ -398,7 +423,12 @@ declare class Simulator {
|
|
|
398
423
|
simulate(input: {
|
|
399
424
|
txb: Transaction;
|
|
400
425
|
sender: string;
|
|
426
|
+
preferAddressBalance?: boolean;
|
|
427
|
+
excludeObjectIds?: Iterable<string>;
|
|
401
428
|
}): Promise<SimulationResult>;
|
|
429
|
+
/** Dry-run a frozen payload without re-selecting gas. */
|
|
430
|
+
simulateBuilt(built: Uint8Array): Promise<SimulationResult>;
|
|
431
|
+
private inspectBuilt;
|
|
402
432
|
private getGasPrice;
|
|
403
433
|
private toGasBudget;
|
|
404
434
|
private copyTransaction;
|
|
@@ -440,10 +470,14 @@ declare class MSafeAccount {
|
|
|
440
470
|
nextSequenceNumber(): Promise<number>;
|
|
441
471
|
simulateIntention(request: Omit<IProposeIntentionRequest, 'msafeAddress' | 'signature'> & {
|
|
442
472
|
txb?: Transaction;
|
|
473
|
+
preferAddressBalance?: boolean;
|
|
474
|
+
excludeObjectIds?: Iterable<string>;
|
|
443
475
|
}): Promise<SimulationResult>;
|
|
444
476
|
proposeIntention(input: Omit<IProposeIntentionRequest, 'signature' | 'msafeAddress'>): Promise<void>;
|
|
445
477
|
proposeIntentionAndBuildVote(input: Omit<IProposeIntentionAndBuildAndVoteRequest, 'signature' | 'msafeAddress' | 'payload' | 'digest'> & {
|
|
446
478
|
txb?: Transaction;
|
|
479
|
+
preferAddressBalance?: boolean;
|
|
480
|
+
excludeObjectIds?: Iterable<string>;
|
|
447
481
|
}): Promise<void>;
|
|
448
482
|
simulateCoinTransferIntention(intention: CoinTransferIntention): Promise<SimulationResult>;
|
|
449
483
|
proposeCoinTransferIntention(intention: CoinTransferIntention): Promise<void>;
|
|
@@ -467,6 +501,13 @@ declare class MSafeAccount {
|
|
|
467
501
|
events: true;
|
|
468
502
|
}>>;
|
|
469
503
|
dashboard(): Promise<_msafe_sui3_utils.IGetDashboardResp>;
|
|
504
|
+
/**
|
|
505
|
+
* Resolve a Transaction from propose/simulate input.
|
|
506
|
+
* 1. Caller-supplied `txb` (generic store path — do not rebuild).
|
|
507
|
+
* 2. Registered app helper `build`.
|
|
508
|
+
* 3. Unregistered app: restore from `intention.content` (JSON or hex).
|
|
509
|
+
*/
|
|
510
|
+
private buildTxFromIntention;
|
|
470
511
|
private calculateWeightFromVotes;
|
|
471
512
|
private calculateWeight;
|
|
472
513
|
get address(): string;
|
|
@@ -595,5 +636,11 @@ declare function createCoinReservationRef(reservedBalance: bigint, owner: string
|
|
|
595
636
|
* (V1 drops CallArg::FundsWithdrawal).
|
|
596
637
|
*/
|
|
597
638
|
declare function toSuiTransaction(txb: Transaction | unknown): Transaction;
|
|
639
|
+
declare function getIntentionContent(intention: unknown): unknown;
|
|
640
|
+
/**
|
|
641
|
+
* Restore a Transaction from plain-tx `intention.content`.
|
|
642
|
+
* Accepts V2 JSON (`tx.toJSON()`), hex BCS bytes, or a JSON object.
|
|
643
|
+
*/
|
|
644
|
+
declare function transactionFromContent(content: unknown): Transaction;
|
|
598
645
|
|
|
599
|
-
export { AddressBookSDK, COIN_RESERVATION_MAGIC, COIN_TYPE_ARG_REGEX, Coin, CoinHelper, CreateHelper, type CreateMSafeInfo, DEV_API_URL, DEV_SYNCING_URL, ENV_CONFIGS, Formatter, type FutureIntention, type GasFundingMode, type GasFundingResult, type GasObjectReference, HexToUint8Array, type HistorySendTx, type HistoryVote, type IWallet, InfoTypeEnabledDto, InfoTypeKey, InsufficientGasFundsError, LOCAL_API_URL, LOCAL_SYNCING_URL, MAINNET_RPC_URL, MSafeAccount, MSafeClient, type MSafeConfig, type MSafeConfigOptions, MSafeEnabledDto, MSafeEnv, MSafeGlobals, type NotificationData, type NotificationInfo, NotificationSubscribeDto, NotificationUpdateDto, PREV_API_URL, PROD_API_URL, type Pagination, type PendingTx, type PendingVote, type ProposeIntention, type ReceiveTransaction, SUI_COIN, SignatureVerifier, type SimulateDryRunResponse, type SimulationFailedResult, type SimulationOption, type SimulationResult, type SimulationSuccessResult, TESTNET_RPC_URL, Uint8ArrayToHex, addPrefix, computeGasBudget, createCoinReservationRef, estimateGasBudget, getAllCoins, getMSafeConfig, getPublicKeyFromChain, httpUrlToGrpcBaseUrl, isCoinReservationDigest, msafeChainToSuiNetwork, preferClassicGasPayment, prepareGasFunding, selectGasFunding, stringToBuffer, toSuiTransaction };
|
|
646
|
+
export { AddressBookSDK, COIN_RESERVATION_MAGIC, COIN_TYPE_ARG_REGEX, Coin, CoinHelper, CreateHelper, type CreateMSafeInfo, DEV_API_URL, DEV_SYNCING_URL, ENV_CONFIGS, Formatter, type FutureIntention, type GasFundingMode, type GasFundingResult, type GasObjectReference, HexToUint8Array, type HistorySendTx, type HistoryVote, type IWallet, InfoTypeEnabledDto, InfoTypeKey, InsufficientGasFundsError, LOCAL_API_URL, LOCAL_SYNCING_URL, MAINNET_RPC_URL, MSafeAccount, MSafeClient, type MSafeConfig, type MSafeConfigOptions, MSafeEnabledDto, MSafeEnv, MSafeGlobals, type NotificationData, type NotificationInfo, NotificationSubscribeDto, NotificationUpdateDto, PREV_API_URL, PROD_API_URL, type Pagination, type PendingTx, type PendingVote, type ProposeIntention, type ReceiveTransaction, SUI_COIN, SignatureVerifier, type SimulateDryRunResponse, type SimulationFailedResult, type SimulationOption, type SimulationResult, type SimulationSuccessResult, TESTNET_RPC_URL, Uint8ArrayToHex, addPrefix, collectPayloadObjectIds, collectQueueExcludeObjectIds, computeGasBudget, createCoinReservationRef, estimateGasBudget, getAllCoins, getIntentionContent, getMSafeConfig, getPublicKeyFromChain, httpUrlToGrpcBaseUrl, isCoinReservationDigest, msafeChainToSuiNetwork, parkedPayloadHex, preferClassicGasPayment, prepareGasFunding, selectGasFunding, stringToBuffer, toSuiTransaction, transactionFromContent };
|
package/dist/index.d.ts
CHANGED
|
@@ -352,6 +352,18 @@ declare class InsufficientGasFundsError extends Error {
|
|
|
352
352
|
* storageRebate is refunded after execution and must not reduce the budget.
|
|
353
353
|
*/
|
|
354
354
|
declare function computeGasBudget(gasUsed: Pick<SuiClientTypes.GasCostSummary, 'computationCost' | 'storageCost'>, gasPrice: bigint): bigint;
|
|
355
|
+
/** Object IDs a built payload already pins (inputs + gas payment). */
|
|
356
|
+
declare function collectPayloadObjectIds(payload: string | Uint8Array): string[];
|
|
357
|
+
/**
|
|
358
|
+
* Parked queue item: intention was saved with a built hex payload + digest
|
|
359
|
+
* so build-next can promote it without rebuilding.
|
|
360
|
+
*/
|
|
361
|
+
declare function parkedPayloadHex(intention: unknown): string | undefined;
|
|
362
|
+
/** Coins already pinned by the current pending tx and any parked future payloads. */
|
|
363
|
+
declare function collectQueueExcludeObjectIds(input: {
|
|
364
|
+
pendingPayload?: string;
|
|
365
|
+
parkedPayloads?: Array<string | undefined>;
|
|
366
|
+
}): string[];
|
|
355
367
|
/**
|
|
356
368
|
* Select gas funding before tx.build() according to mixed coin/addressBalance policy:
|
|
357
369
|
* 1) budget without storageRebate (caller supplies computeGasBudget result)
|
|
@@ -365,12 +377,15 @@ declare function selectGasFunding(input: {
|
|
|
365
377
|
suiClient: SuiGrpcClient;
|
|
366
378
|
owner: string;
|
|
367
379
|
gasBudget: bigint;
|
|
380
|
+
excludeObjectIds?: Iterable<string>;
|
|
368
381
|
}): Promise<GasFundingResult>;
|
|
369
382
|
declare function estimateGasBudget(input: {
|
|
370
383
|
tx: Transaction;
|
|
371
384
|
suiClient: SuiGrpcClient;
|
|
372
385
|
owner: string;
|
|
373
386
|
gasPrice: bigint;
|
|
387
|
+
excludeObjectIds?: Iterable<string>;
|
|
388
|
+
preferAddressBalance?: boolean;
|
|
374
389
|
}): Promise<bigint>;
|
|
375
390
|
/**
|
|
376
391
|
* Resolve gasBudget (no rebate) and apply gas funding selection before build.
|
|
@@ -381,6 +396,16 @@ declare function prepareGasFunding(input: {
|
|
|
381
396
|
owner: string;
|
|
382
397
|
gasPrice: bigint;
|
|
383
398
|
gasBudget?: bigint;
|
|
399
|
+
/**
|
|
400
|
+
* Force Address Balance gas (`payment: []`). Prefer {@link excludeObjectIds}
|
|
401
|
+
* for queue-behind-pending so unused SUI coins can still pay.
|
|
402
|
+
*/
|
|
403
|
+
preferAddressBalance?: boolean;
|
|
404
|
+
/**
|
|
405
|
+
* Queue-behind-pending: do not pick coins the current pending / parked
|
|
406
|
+
* payloads already pin. Those versions will change when the earlier tx executes.
|
|
407
|
+
*/
|
|
408
|
+
excludeObjectIds?: Iterable<string>;
|
|
384
409
|
}): Promise<GasFundingResult>;
|
|
385
410
|
/**
|
|
386
411
|
* @deprecated Use {@link prepareGasFunding} / {@link selectGasFunding}.
|
|
@@ -398,7 +423,12 @@ declare class Simulator {
|
|
|
398
423
|
simulate(input: {
|
|
399
424
|
txb: Transaction;
|
|
400
425
|
sender: string;
|
|
426
|
+
preferAddressBalance?: boolean;
|
|
427
|
+
excludeObjectIds?: Iterable<string>;
|
|
401
428
|
}): Promise<SimulationResult>;
|
|
429
|
+
/** Dry-run a frozen payload without re-selecting gas. */
|
|
430
|
+
simulateBuilt(built: Uint8Array): Promise<SimulationResult>;
|
|
431
|
+
private inspectBuilt;
|
|
402
432
|
private getGasPrice;
|
|
403
433
|
private toGasBudget;
|
|
404
434
|
private copyTransaction;
|
|
@@ -440,10 +470,14 @@ declare class MSafeAccount {
|
|
|
440
470
|
nextSequenceNumber(): Promise<number>;
|
|
441
471
|
simulateIntention(request: Omit<IProposeIntentionRequest, 'msafeAddress' | 'signature'> & {
|
|
442
472
|
txb?: Transaction;
|
|
473
|
+
preferAddressBalance?: boolean;
|
|
474
|
+
excludeObjectIds?: Iterable<string>;
|
|
443
475
|
}): Promise<SimulationResult>;
|
|
444
476
|
proposeIntention(input: Omit<IProposeIntentionRequest, 'signature' | 'msafeAddress'>): Promise<void>;
|
|
445
477
|
proposeIntentionAndBuildVote(input: Omit<IProposeIntentionAndBuildAndVoteRequest, 'signature' | 'msafeAddress' | 'payload' | 'digest'> & {
|
|
446
478
|
txb?: Transaction;
|
|
479
|
+
preferAddressBalance?: boolean;
|
|
480
|
+
excludeObjectIds?: Iterable<string>;
|
|
447
481
|
}): Promise<void>;
|
|
448
482
|
simulateCoinTransferIntention(intention: CoinTransferIntention): Promise<SimulationResult>;
|
|
449
483
|
proposeCoinTransferIntention(intention: CoinTransferIntention): Promise<void>;
|
|
@@ -467,6 +501,13 @@ declare class MSafeAccount {
|
|
|
467
501
|
events: true;
|
|
468
502
|
}>>;
|
|
469
503
|
dashboard(): Promise<_msafe_sui3_utils.IGetDashboardResp>;
|
|
504
|
+
/**
|
|
505
|
+
* Resolve a Transaction from propose/simulate input.
|
|
506
|
+
* 1. Caller-supplied `txb` (generic store path — do not rebuild).
|
|
507
|
+
* 2. Registered app helper `build`.
|
|
508
|
+
* 3. Unregistered app: restore from `intention.content` (JSON or hex).
|
|
509
|
+
*/
|
|
510
|
+
private buildTxFromIntention;
|
|
470
511
|
private calculateWeightFromVotes;
|
|
471
512
|
private calculateWeight;
|
|
472
513
|
get address(): string;
|
|
@@ -595,5 +636,11 @@ declare function createCoinReservationRef(reservedBalance: bigint, owner: string
|
|
|
595
636
|
* (V1 drops CallArg::FundsWithdrawal).
|
|
596
637
|
*/
|
|
597
638
|
declare function toSuiTransaction(txb: Transaction | unknown): Transaction;
|
|
639
|
+
declare function getIntentionContent(intention: unknown): unknown;
|
|
640
|
+
/**
|
|
641
|
+
* Restore a Transaction from plain-tx `intention.content`.
|
|
642
|
+
* Accepts V2 JSON (`tx.toJSON()`), hex BCS bytes, or a JSON object.
|
|
643
|
+
*/
|
|
644
|
+
declare function transactionFromContent(content: unknown): Transaction;
|
|
598
645
|
|
|
599
|
-
export { AddressBookSDK, COIN_RESERVATION_MAGIC, COIN_TYPE_ARG_REGEX, Coin, CoinHelper, CreateHelper, type CreateMSafeInfo, DEV_API_URL, DEV_SYNCING_URL, ENV_CONFIGS, Formatter, type FutureIntention, type GasFundingMode, type GasFundingResult, type GasObjectReference, HexToUint8Array, type HistorySendTx, type HistoryVote, type IWallet, InfoTypeEnabledDto, InfoTypeKey, InsufficientGasFundsError, LOCAL_API_URL, LOCAL_SYNCING_URL, MAINNET_RPC_URL, MSafeAccount, MSafeClient, type MSafeConfig, type MSafeConfigOptions, MSafeEnabledDto, MSafeEnv, MSafeGlobals, type NotificationData, type NotificationInfo, NotificationSubscribeDto, NotificationUpdateDto, PREV_API_URL, PROD_API_URL, type Pagination, type PendingTx, type PendingVote, type ProposeIntention, type ReceiveTransaction, SUI_COIN, SignatureVerifier, type SimulateDryRunResponse, type SimulationFailedResult, type SimulationOption, type SimulationResult, type SimulationSuccessResult, TESTNET_RPC_URL, Uint8ArrayToHex, addPrefix, computeGasBudget, createCoinReservationRef, estimateGasBudget, getAllCoins, getMSafeConfig, getPublicKeyFromChain, httpUrlToGrpcBaseUrl, isCoinReservationDigest, msafeChainToSuiNetwork, preferClassicGasPayment, prepareGasFunding, selectGasFunding, stringToBuffer, toSuiTransaction };
|
|
646
|
+
export { AddressBookSDK, COIN_RESERVATION_MAGIC, COIN_TYPE_ARG_REGEX, Coin, CoinHelper, CreateHelper, type CreateMSafeInfo, DEV_API_URL, DEV_SYNCING_URL, ENV_CONFIGS, Formatter, type FutureIntention, type GasFundingMode, type GasFundingResult, type GasObjectReference, HexToUint8Array, type HistorySendTx, type HistoryVote, type IWallet, InfoTypeEnabledDto, InfoTypeKey, InsufficientGasFundsError, LOCAL_API_URL, LOCAL_SYNCING_URL, MAINNET_RPC_URL, MSafeAccount, MSafeClient, type MSafeConfig, type MSafeConfigOptions, MSafeEnabledDto, MSafeEnv, MSafeGlobals, type NotificationData, type NotificationInfo, NotificationSubscribeDto, NotificationUpdateDto, PREV_API_URL, PROD_API_URL, type Pagination, type PendingTx, type PendingVote, type ProposeIntention, type ReceiveTransaction, SUI_COIN, SignatureVerifier, type SimulateDryRunResponse, type SimulationFailedResult, type SimulationOption, type SimulationResult, type SimulationSuccessResult, TESTNET_RPC_URL, Uint8ArrayToHex, addPrefix, collectPayloadObjectIds, collectQueueExcludeObjectIds, computeGasBudget, createCoinReservationRef, estimateGasBudget, getAllCoins, getIntentionContent, getMSafeConfig, getPublicKeyFromChain, httpUrlToGrpcBaseUrl, isCoinReservationDigest, msafeChainToSuiNetwork, parkedPayloadHex, preferClassicGasPayment, prepareGasFunding, selectGasFunding, stringToBuffer, toSuiTransaction, transactionFromContent };
|
package/dist/index.js
CHANGED
|
@@ -134,7 +134,7 @@ import {
|
|
|
134
134
|
isSameAddress as isSameAddress2
|
|
135
135
|
} from "@msafe/sui3-utils";
|
|
136
136
|
import { Transaction as Transaction4 } from "@mysten/sui/transactions";
|
|
137
|
-
import { fromHex as
|
|
137
|
+
import { fromHex as fromHex4, normalizeStructTag as normalizeStructTag4, toHex as toHex2 } from "@mysten/sui/utils";
|
|
138
138
|
import { SUI_MAINNET_CHAIN, SUI_TESTNET_CHAIN } from "@mysten/wallet-standard";
|
|
139
139
|
|
|
140
140
|
// src/simulate/simulator.ts
|
|
@@ -142,7 +142,7 @@ import { Transaction as Transaction2 } from "@mysten/sui/transactions";
|
|
|
142
142
|
|
|
143
143
|
// src/utils/gasFunding.ts
|
|
144
144
|
import { Transaction } from "@mysten/sui/transactions";
|
|
145
|
-
import { normalizeStructTag as normalizeStructTag3, normalizeSuiObjectId } from "@mysten/sui/utils";
|
|
145
|
+
import { fromHex as fromHex2, normalizeStructTag as normalizeStructTag3, normalizeSuiObjectId } from "@mysten/sui/utils";
|
|
146
146
|
|
|
147
147
|
// src/utils/coinReservation.ts
|
|
148
148
|
import { bcs, TypeTagSerializer } from "@mysten/sui/bcs";
|
|
@@ -437,18 +437,66 @@ function computeGasBudget(gasUsed, gasPrice) {
|
|
|
437
437
|
return BigInt(computationCost) + BigInt(storageCost) + safeOverhead;
|
|
438
438
|
}
|
|
439
439
|
function collectUsedObjectIds(tx) {
|
|
440
|
-
|
|
440
|
+
const used = tx.getData().inputs.reduce((acc, input) => {
|
|
441
441
|
const immOrOwned = input.Object?.ImmOrOwnedObject?.objectId;
|
|
442
442
|
if (immOrOwned) {
|
|
443
|
-
|
|
444
|
-
return
|
|
443
|
+
acc.add(normalizeSuiObjectId(immOrOwned));
|
|
444
|
+
return acc;
|
|
445
445
|
}
|
|
446
446
|
const unresolved = input.UnresolvedObject?.objectId;
|
|
447
447
|
if (unresolved) {
|
|
448
|
-
|
|
448
|
+
acc.add(normalizeSuiObjectId(unresolved));
|
|
449
449
|
}
|
|
450
|
-
return
|
|
450
|
+
return acc;
|
|
451
451
|
}, /* @__PURE__ */ new Set());
|
|
452
|
+
(tx.getData().gasData.payment ?? []).forEach((payment) => {
|
|
453
|
+
if (payment.objectId) {
|
|
454
|
+
used.add(normalizeSuiObjectId(payment.objectId));
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
return used;
|
|
458
|
+
}
|
|
459
|
+
function addExcludeObjectIds(used, excludeObjectIds) {
|
|
460
|
+
Array.from(excludeObjectIds ?? [], (id) => used.add(normalizeSuiObjectId(id)));
|
|
461
|
+
return used;
|
|
462
|
+
}
|
|
463
|
+
function payloadToTransaction(payload) {
|
|
464
|
+
if (typeof payload !== "string") {
|
|
465
|
+
return Transaction.from(payload);
|
|
466
|
+
}
|
|
467
|
+
if (/^[0-9a-fA-F]+$/.test(payload) && payload.length % 2 === 0) {
|
|
468
|
+
return Transaction.from(fromHex2(payload));
|
|
469
|
+
}
|
|
470
|
+
return Transaction.from(payload);
|
|
471
|
+
}
|
|
472
|
+
function collectPayloadObjectIds(payload) {
|
|
473
|
+
return [...collectUsedObjectIds(payloadToTransaction(payload))];
|
|
474
|
+
}
|
|
475
|
+
function parkedPayloadHex(intention) {
|
|
476
|
+
if (!intention || typeof intention !== "object") {
|
|
477
|
+
return void 0;
|
|
478
|
+
}
|
|
479
|
+
const { content, digest } = intention;
|
|
480
|
+
if (typeof content !== "string" || typeof digest !== "string" || !digest) {
|
|
481
|
+
return void 0;
|
|
482
|
+
}
|
|
483
|
+
if (!/^[0-9a-fA-F]+$/.test(content) || content.length < 64) {
|
|
484
|
+
return void 0;
|
|
485
|
+
}
|
|
486
|
+
return content;
|
|
487
|
+
}
|
|
488
|
+
function collectQueueExcludeObjectIds(input) {
|
|
489
|
+
const ids = /* @__PURE__ */ new Set();
|
|
490
|
+
if (input.pendingPayload) {
|
|
491
|
+
collectPayloadObjectIds(input.pendingPayload).forEach((id) => ids.add(id));
|
|
492
|
+
}
|
|
493
|
+
(input.parkedPayloads ?? []).forEach((payload) => {
|
|
494
|
+
if (!payload) {
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
collectPayloadObjectIds(payload).forEach((id) => ids.add(id));
|
|
498
|
+
});
|
|
499
|
+
return [...ids];
|
|
452
500
|
}
|
|
453
501
|
function txConsumesOwnedSuiCoins(tx) {
|
|
454
502
|
return tx.getData().commands.some((cmd) => {
|
|
@@ -466,8 +514,8 @@ function txConsumesOwnedSuiCoins(tx) {
|
|
|
466
514
|
}
|
|
467
515
|
});
|
|
468
516
|
}
|
|
469
|
-
async function loadSuiGasFunding(suiClient, owner, tx) {
|
|
470
|
-
const usedObjectIds = collectUsedObjectIds(tx);
|
|
517
|
+
async function loadSuiGasFunding(suiClient, owner, tx, excludeObjectIds) {
|
|
518
|
+
const usedObjectIds = addExcludeObjectIds(collectUsedObjectIds(tx), excludeObjectIds);
|
|
471
519
|
const [coins, balanceRes] = await Promise.all([
|
|
472
520
|
getAllCoins({ suiClient, owner, coinType: SUI_COIN }),
|
|
473
521
|
suiClient.getBalance({ owner, coinType: SUI_COIN })
|
|
@@ -518,7 +566,7 @@ async function selectGasFunding(input) {
|
|
|
518
566
|
const { tx, suiClient, owner, gasBudget } = input;
|
|
519
567
|
const { payment } = tx.getData().gasData;
|
|
520
568
|
if (payment != null && payment.length > 0) {
|
|
521
|
-
const funding2 = await loadSuiGasFunding(suiClient, owner, tx);
|
|
569
|
+
const funding2 = await loadSuiGasFunding(suiClient, owner, tx, input.excludeObjectIds);
|
|
522
570
|
return {
|
|
523
571
|
mode: "classic",
|
|
524
572
|
gasBudget,
|
|
@@ -526,7 +574,7 @@ async function selectGasFunding(input) {
|
|
|
526
574
|
addressBalance: funding2.addressBalance
|
|
527
575
|
};
|
|
528
576
|
}
|
|
529
|
-
const funding = await loadSuiGasFunding(suiClient, owner, tx);
|
|
577
|
+
const funding = await loadSuiGasFunding(suiClient, owner, tx, input.excludeObjectIds);
|
|
530
578
|
const { paymentCoins, coinBalance, addressBalance, total } = funding;
|
|
531
579
|
if (total < gasBudget) {
|
|
532
580
|
throw new InsufficientGasFundsError(gasBudget, coinBalance, addressBalance);
|
|
@@ -572,8 +620,13 @@ function isPositiveBudget(budget) {
|
|
|
572
620
|
}
|
|
573
621
|
async function estimateGasBudget(input) {
|
|
574
622
|
const { tx, suiClient, owner, gasPrice } = input;
|
|
575
|
-
const funding =
|
|
576
|
-
|
|
623
|
+
const funding = input.preferAddressBalance ? {
|
|
624
|
+
...await loadSuiGasFunding(suiClient, owner, tx, input.excludeObjectIds),
|
|
625
|
+
paymentCoins: [],
|
|
626
|
+
coinBalance: 0n
|
|
627
|
+
} : await loadSuiGasFunding(suiClient, owner, tx, input.excludeObjectIds);
|
|
628
|
+
const fundingTotal = input.preferAddressBalance ? funding.addressBalance : funding.total;
|
|
629
|
+
if (fundingTotal <= 0n) {
|
|
577
630
|
throw new InsufficientGasFundsError(0n, funding.coinBalance, funding.addressBalance);
|
|
578
631
|
}
|
|
579
632
|
const { budget, payment } = tx.getData().gasData;
|
|
@@ -606,7 +659,7 @@ async function estimateGasBudget(input) {
|
|
|
606
659
|
return computeGasBudget(effects.gasUsed, gasPrice);
|
|
607
660
|
}
|
|
608
661
|
async function prepareGasFunding(input) {
|
|
609
|
-
const { tx, suiClient, owner, gasPrice } = input;
|
|
662
|
+
const { tx, suiClient, owner, gasPrice, excludeObjectIds } = input;
|
|
610
663
|
const { payment, budget: existingBudget } = tx.getData().gasData;
|
|
611
664
|
const bakedAddressBalanceGas = payment != null && payment.length === 0;
|
|
612
665
|
let { gasBudget } = input;
|
|
@@ -616,7 +669,14 @@ async function prepareGasFunding(input) {
|
|
|
616
669
|
const existingPositive = isPositiveBudget(existingBudget) ? BigInt(existingBudget) : null;
|
|
617
670
|
if (gasBudget == null) {
|
|
618
671
|
if (bakedAddressBalanceGas || existingPositive == null) {
|
|
619
|
-
gasBudget = await estimateGasBudget({
|
|
672
|
+
gasBudget = await estimateGasBudget({
|
|
673
|
+
tx,
|
|
674
|
+
suiClient,
|
|
675
|
+
owner,
|
|
676
|
+
gasPrice,
|
|
677
|
+
excludeObjectIds,
|
|
678
|
+
preferAddressBalance: input.preferAddressBalance
|
|
679
|
+
});
|
|
620
680
|
} else {
|
|
621
681
|
gasBudget = existingPositive;
|
|
622
682
|
}
|
|
@@ -625,7 +685,20 @@ async function prepareGasFunding(input) {
|
|
|
625
685
|
if (bakedAddressBalanceGas) {
|
|
626
686
|
tx.setExpiration(null);
|
|
627
687
|
}
|
|
628
|
-
|
|
688
|
+
if (input.preferAddressBalance) {
|
|
689
|
+
const funding = await loadSuiGasFunding(suiClient, owner, tx, excludeObjectIds);
|
|
690
|
+
if (funding.addressBalance < gasBudget) {
|
|
691
|
+
throw new InsufficientGasFundsError(gasBudget, funding.coinBalance, funding.addressBalance);
|
|
692
|
+
}
|
|
693
|
+
tx.setGasPayment([]);
|
|
694
|
+
return {
|
|
695
|
+
mode: "addressBalance",
|
|
696
|
+
gasBudget,
|
|
697
|
+
coinBalance: funding.coinBalance,
|
|
698
|
+
addressBalance: funding.addressBalance
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
return selectGasFunding({ tx, suiClient, owner, gasBudget, excludeObjectIds });
|
|
629
702
|
}
|
|
630
703
|
async function preferClassicGasPayment(input) {
|
|
631
704
|
const { tx, suiClient, owner } = input;
|
|
@@ -668,7 +741,9 @@ var Simulator = class {
|
|
|
668
741
|
tx,
|
|
669
742
|
suiClient,
|
|
670
743
|
owner: input.sender,
|
|
671
|
-
gasPrice
|
|
744
|
+
gasPrice,
|
|
745
|
+
preferAddressBalance: input.preferAddressBalance,
|
|
746
|
+
excludeObjectIds: input.excludeObjectIds
|
|
672
747
|
});
|
|
673
748
|
} catch (e) {
|
|
674
749
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -689,9 +764,17 @@ var Simulator = class {
|
|
|
689
764
|
simulationError: message
|
|
690
765
|
};
|
|
691
766
|
}
|
|
767
|
+
return this.inspectBuilt(built, gasPrice);
|
|
768
|
+
}
|
|
769
|
+
/** Dry-run a frozen payload without re-selecting gas. */
|
|
770
|
+
async simulateBuilt(built) {
|
|
771
|
+
const gasPrice = await this.getGasPrice();
|
|
772
|
+
return this.inspectBuilt(built, gasPrice);
|
|
773
|
+
}
|
|
774
|
+
async inspectBuilt(built, gasPrice) {
|
|
692
775
|
let inspectResult;
|
|
693
776
|
try {
|
|
694
|
-
inspectResult = await suiClient.simulateTransaction({
|
|
777
|
+
inspectResult = await this.globals.suiClient.simulateTransaction({
|
|
695
778
|
transaction: built,
|
|
696
779
|
include: {
|
|
697
780
|
effects: true,
|
|
@@ -802,6 +885,7 @@ var SignatureVerifier = class _SignatureVerifier {
|
|
|
802
885
|
|
|
803
886
|
// src/utils/transaction.ts
|
|
804
887
|
import { Transaction as Transaction3, isTransaction } from "@mysten/sui/transactions";
|
|
888
|
+
import { fromHex as fromHex3 } from "@mysten/sui/utils";
|
|
805
889
|
function toSuiTransaction(txb) {
|
|
806
890
|
if (isTransaction(txb)) {
|
|
807
891
|
return txb;
|
|
@@ -815,6 +899,30 @@ function toSuiTransaction(txb) {
|
|
|
815
899
|
}
|
|
816
900
|
throw new Error("Unsupported transaction value for toSuiTransaction");
|
|
817
901
|
}
|
|
902
|
+
function isHex(str) {
|
|
903
|
+
return /^[0-9a-fA-F]+$/.test(str);
|
|
904
|
+
}
|
|
905
|
+
function getIntentionContent(intention) {
|
|
906
|
+
if (intention && typeof intention === "object" && "content" in intention) {
|
|
907
|
+
return intention.content;
|
|
908
|
+
}
|
|
909
|
+
return void 0;
|
|
910
|
+
}
|
|
911
|
+
function transactionFromContent(content) {
|
|
912
|
+
if (content instanceof Uint8Array) {
|
|
913
|
+
return Transaction3.from(content);
|
|
914
|
+
}
|
|
915
|
+
if (typeof content === "string") {
|
|
916
|
+
if (isHex(content)) {
|
|
917
|
+
return Transaction3.from(fromHex3(content));
|
|
918
|
+
}
|
|
919
|
+
return Transaction3.from(content);
|
|
920
|
+
}
|
|
921
|
+
if (content && typeof content === "object") {
|
|
922
|
+
return Transaction3.from(JSON.stringify(content));
|
|
923
|
+
}
|
|
924
|
+
throw new Error("Invalid transaction content");
|
|
925
|
+
}
|
|
818
926
|
|
|
819
927
|
// src/utils/iter/iterator.ts
|
|
820
928
|
var REQUEST_PAGE_SIZE = 25;
|
|
@@ -1037,32 +1145,14 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
1037
1145
|
return this.backend.getNextSequenceNumber(this.address);
|
|
1038
1146
|
}
|
|
1039
1147
|
async simulateIntention(request) {
|
|
1040
|
-
|
|
1041
|
-
if (request.txb) {
|
|
1042
|
-
txb = request.txb;
|
|
1043
|
-
} else {
|
|
1044
|
-
const appHelper = appHelpers.getAppHelper(request.application);
|
|
1045
|
-
if (!appHelper) {
|
|
1046
|
-
throw new Error(`Can't find app helper for application ${request.application}`);
|
|
1047
|
-
}
|
|
1048
|
-
txb = toSuiTransaction(
|
|
1049
|
-
await appHelper.build({
|
|
1050
|
-
network: this.globals.config.network,
|
|
1051
|
-
intentionData: request.intention,
|
|
1052
|
-
txType: request.txType,
|
|
1053
|
-
txSubType: request.txSubType,
|
|
1054
|
-
clientUrl: this.globals.config.suiClient.url,
|
|
1055
|
-
account: {
|
|
1056
|
-
address: this.address,
|
|
1057
|
-
publicKey: fromHex2(this.address),
|
|
1058
|
-
chains: [SUI_MAINNET_CHAIN, SUI_TESTNET_CHAIN],
|
|
1059
|
-
features: []
|
|
1060
|
-
}
|
|
1061
|
-
})
|
|
1062
|
-
);
|
|
1063
|
-
}
|
|
1148
|
+
const txb = await this.buildTxFromIntention(request);
|
|
1064
1149
|
txb.setSender(this.address);
|
|
1065
|
-
return this.simulator.simulate({
|
|
1150
|
+
return this.simulator.simulate({
|
|
1151
|
+
txb,
|
|
1152
|
+
sender: this.address,
|
|
1153
|
+
preferAddressBalance: request.preferAddressBalance,
|
|
1154
|
+
excludeObjectIds: request.excludeObjectIds
|
|
1155
|
+
});
|
|
1066
1156
|
}
|
|
1067
1157
|
async proposeIntention(input) {
|
|
1068
1158
|
const message = SigningMessageHelper3.proposeIntentionMessage({
|
|
@@ -1080,30 +1170,7 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
1080
1170
|
});
|
|
1081
1171
|
}
|
|
1082
1172
|
async proposeIntentionAndBuildVote(input) {
|
|
1083
|
-
|
|
1084
|
-
if (input.txb) {
|
|
1085
|
-
txb = input.txb;
|
|
1086
|
-
} else {
|
|
1087
|
-
const appHelper = appHelpers.getAppHelper(input.application);
|
|
1088
|
-
if (!appHelper) {
|
|
1089
|
-
throw new Error(`Can't find app helper for application ${input.application}`);
|
|
1090
|
-
}
|
|
1091
|
-
txb = toSuiTransaction(
|
|
1092
|
-
await appHelper.build({
|
|
1093
|
-
network: this.globals.config.network,
|
|
1094
|
-
intentionData: input.intention,
|
|
1095
|
-
txType: input.txType,
|
|
1096
|
-
txSubType: input.txSubType,
|
|
1097
|
-
clientUrl: this.globals.config.suiClient.url,
|
|
1098
|
-
account: {
|
|
1099
|
-
address: this.address,
|
|
1100
|
-
publicKey: fromHex2(this.address),
|
|
1101
|
-
chains: [SUI_MAINNET_CHAIN, SUI_TESTNET_CHAIN],
|
|
1102
|
-
features: []
|
|
1103
|
-
}
|
|
1104
|
-
})
|
|
1105
|
-
);
|
|
1106
|
-
}
|
|
1173
|
+
const txb = await this.buildTxFromIntention(input);
|
|
1107
1174
|
txb.setGasPrice(input.gasPrice);
|
|
1108
1175
|
txb.setSender(this.address);
|
|
1109
1176
|
await prepareGasFunding({
|
|
@@ -1111,13 +1178,19 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
1111
1178
|
suiClient: this.globals.suiClient,
|
|
1112
1179
|
owner: this.address,
|
|
1113
1180
|
gasPrice: input.gasPrice,
|
|
1114
|
-
gasBudget: input.gasBudget
|
|
1181
|
+
gasBudget: input.gasBudget,
|
|
1182
|
+
preferAddressBalance: input.preferAddressBalance,
|
|
1183
|
+
excludeObjectIds: input.excludeObjectIds
|
|
1115
1184
|
});
|
|
1116
1185
|
const payload = await txb.build({ client: this.globals.suiClient });
|
|
1117
1186
|
const digest = await txb.getDigest({ client: this.globals.suiClient });
|
|
1118
1187
|
const signature = await this.wallet.signTransactionBlock({ transactionBlock: payload });
|
|
1188
|
+
const apiInput = { ...input };
|
|
1189
|
+
delete apiInput.txb;
|
|
1190
|
+
delete apiInput.preferAddressBalance;
|
|
1191
|
+
delete apiInput.excludeObjectIds;
|
|
1119
1192
|
return this.backend.proposeIntentionAndBuildVote({
|
|
1120
|
-
...
|
|
1193
|
+
...apiInput,
|
|
1121
1194
|
payload: toHex2(payload),
|
|
1122
1195
|
digest,
|
|
1123
1196
|
msafeAddress: this.address,
|
|
@@ -1225,25 +1298,16 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
1225
1298
|
}
|
|
1226
1299
|
async simulateBuildTransaction() {
|
|
1227
1300
|
const intention = await this.backend.getNextIntention({ msafeAddress: this.address });
|
|
1228
|
-
const
|
|
1229
|
-
if (
|
|
1230
|
-
|
|
1231
|
-
}
|
|
1232
|
-
const txb =
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
clientUrl: this.globals.config.suiClient.url,
|
|
1239
|
-
account: {
|
|
1240
|
-
address: this.address,
|
|
1241
|
-
publicKey: fromHex2(this.address),
|
|
1242
|
-
chains: [SUI_MAINNET_CHAIN, SUI_TESTNET_CHAIN],
|
|
1243
|
-
features: []
|
|
1244
|
-
}
|
|
1245
|
-
})
|
|
1246
|
-
);
|
|
1301
|
+
const parked = parkedPayloadHex(intention.intention);
|
|
1302
|
+
if (parked) {
|
|
1303
|
+
return this.simulator.simulateBuilt(fromHex4(parked));
|
|
1304
|
+
}
|
|
1305
|
+
const txb = await this.buildTxFromIntention({
|
|
1306
|
+
application: intention.application,
|
|
1307
|
+
intention: intention.intention,
|
|
1308
|
+
txType: intention.txType,
|
|
1309
|
+
txSubType: intention.txSubType
|
|
1310
|
+
});
|
|
1247
1311
|
txb.setSender(this.address);
|
|
1248
1312
|
return this.simulator.simulate({ txb, sender: this.address });
|
|
1249
1313
|
}
|
|
@@ -1288,6 +1352,45 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
1288
1352
|
msafeAddress: this.address
|
|
1289
1353
|
});
|
|
1290
1354
|
}
|
|
1355
|
+
/**
|
|
1356
|
+
* Resolve a Transaction from propose/simulate input.
|
|
1357
|
+
* 1. Caller-supplied `txb` (generic store path — do not rebuild).
|
|
1358
|
+
* 2. Registered app helper `build`.
|
|
1359
|
+
* 3. Unregistered app: restore from `intention.content` (JSON or hex).
|
|
1360
|
+
*/
|
|
1361
|
+
async buildTxFromIntention(input) {
|
|
1362
|
+
if (input.txb) {
|
|
1363
|
+
return input.txb;
|
|
1364
|
+
}
|
|
1365
|
+
let appHelper;
|
|
1366
|
+
try {
|
|
1367
|
+
appHelper = appHelpers.getAppHelper(input.application);
|
|
1368
|
+
} catch {
|
|
1369
|
+
appHelper = void 0;
|
|
1370
|
+
}
|
|
1371
|
+
if (appHelper) {
|
|
1372
|
+
return toSuiTransaction(
|
|
1373
|
+
await appHelper.build({
|
|
1374
|
+
network: this.globals.config.network,
|
|
1375
|
+
intentionData: input.intention,
|
|
1376
|
+
txType: input.txType,
|
|
1377
|
+
txSubType: input.txSubType,
|
|
1378
|
+
clientUrl: this.globals.config.suiClient.url,
|
|
1379
|
+
account: {
|
|
1380
|
+
address: this.address,
|
|
1381
|
+
publicKey: fromHex4(this.address),
|
|
1382
|
+
chains: [SUI_MAINNET_CHAIN, SUI_TESTNET_CHAIN],
|
|
1383
|
+
features: []
|
|
1384
|
+
}
|
|
1385
|
+
})
|
|
1386
|
+
);
|
|
1387
|
+
}
|
|
1388
|
+
const content = getIntentionContent(input.intention);
|
|
1389
|
+
if (content != null) {
|
|
1390
|
+
return transactionFromContent(content);
|
|
1391
|
+
}
|
|
1392
|
+
throw new Error(`Can't find app helper for application ${input.application}`);
|
|
1393
|
+
}
|
|
1291
1394
|
calculateWeightFromVotes(votes) {
|
|
1292
1395
|
return this.calculateWeight(votes.map((vote) => vote.userAddress));
|
|
1293
1396
|
}
|
|
@@ -2018,19 +2121,24 @@ export {
|
|
|
2018
2121
|
TESTNET_RPC_URL,
|
|
2019
2122
|
Uint8ArrayToHex,
|
|
2020
2123
|
addPrefix,
|
|
2124
|
+
collectPayloadObjectIds,
|
|
2125
|
+
collectQueueExcludeObjectIds,
|
|
2021
2126
|
computeGasBudget,
|
|
2022
2127
|
createCoinReservationRef,
|
|
2023
2128
|
estimateGasBudget,
|
|
2024
2129
|
getAllCoins,
|
|
2130
|
+
getIntentionContent,
|
|
2025
2131
|
getMSafeConfig,
|
|
2026
2132
|
getPublicKeyFromChain,
|
|
2027
2133
|
httpUrlToGrpcBaseUrl,
|
|
2028
2134
|
isCoinReservationDigest,
|
|
2029
2135
|
msafeChainToSuiNetwork,
|
|
2136
|
+
parkedPayloadHex,
|
|
2030
2137
|
preferClassicGasPayment,
|
|
2031
2138
|
prepareGasFunding,
|
|
2032
2139
|
selectGasFunding,
|
|
2033
2140
|
stringToBuffer,
|
|
2034
|
-
toSuiTransaction
|
|
2141
|
+
toSuiTransaction,
|
|
2142
|
+
transactionFromContent
|
|
2035
2143
|
};
|
|
2036
2144
|
//# sourceMappingURL=index.js.map
|