@msafe/sui3-sdk 0.0.34 → 0.0.36
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 +141 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -8
- package/dist/index.d.ts +17 -8
- package/dist/index.js +141 -33
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/backend/BackendImpl.ts +16 -3
- package/src/backend/interface.ts +3 -0
- package/src/core/MSafeAccount.ts +61 -30
- package/src/globals/const.ts +0 -1
- package/src/simulate/simulator.ts +131 -0
- package/src/types/msafe.ts +9 -6
package/dist/index.js
CHANGED
|
@@ -122,6 +122,7 @@ var InvitationSDK = class {
|
|
|
122
122
|
};
|
|
123
123
|
|
|
124
124
|
// src/core/MSafeAccount.ts
|
|
125
|
+
import { appHelpers } from "@msafe/sui-app-store";
|
|
125
126
|
import {
|
|
126
127
|
MultiSigAccount as MultiSigAccount2,
|
|
127
128
|
SigningMessageHelper as SigningMessageHelper3,
|
|
@@ -132,9 +133,81 @@ import {
|
|
|
132
133
|
buildRejectTxb,
|
|
133
134
|
isSameAddress as isSameAddress2
|
|
134
135
|
} from "@msafe/sui3-utils";
|
|
135
|
-
import { TransactionBlock } from "@mysten/sui.js/transactions";
|
|
136
|
+
import { TransactionBlock as TransactionBlock2 } from "@mysten/sui.js/transactions";
|
|
136
137
|
import { normalizeStructTag as normalizeStructTag3 } from "@mysten/sui.js/utils";
|
|
137
138
|
|
|
139
|
+
// src/simulate/simulator.ts
|
|
140
|
+
import { TransactionBlock } from "@mysten/sui.js/transactions";
|
|
141
|
+
var GAS_SAFE_OVERHEAD = 1000n;
|
|
142
|
+
var DEF_GAS_PRICE_NUM = 120n;
|
|
143
|
+
var DEF_GAS_PRICE_DEN = 100n;
|
|
144
|
+
var DEF_GAS_PRICE_OPTION = {
|
|
145
|
+
multiplier: {
|
|
146
|
+
numerator: DEF_GAS_PRICE_NUM,
|
|
147
|
+
denominator: DEF_GAS_PRICE_DEN
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
var Simulator = class {
|
|
151
|
+
constructor(globals) {
|
|
152
|
+
this.globals = globals;
|
|
153
|
+
}
|
|
154
|
+
async simulate(input, options = DEF_GAS_PRICE_OPTION) {
|
|
155
|
+
const tx = this.copyTransactionBlock(input.txb);
|
|
156
|
+
const { suiClient } = this.globals;
|
|
157
|
+
const gasPrice = await this.getGasPrice(options);
|
|
158
|
+
tx.setGasPrice(gasPrice);
|
|
159
|
+
const inspectResult = await suiClient.devInspectTransactionBlock({ transactionBlock: tx, sender: input.sender });
|
|
160
|
+
const { gasUsed } = inspectResult.effects;
|
|
161
|
+
const gasBudget = this.toGasBudget(gasUsed, gasPrice);
|
|
162
|
+
const success = inspectResult.effects.status.status === "success";
|
|
163
|
+
let error;
|
|
164
|
+
if (!success) {
|
|
165
|
+
error = inspectResult.effects.status.error;
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
success,
|
|
169
|
+
gasPrice,
|
|
170
|
+
gasObject: inspectResult.effects.gasObject.reference,
|
|
171
|
+
gasUsed,
|
|
172
|
+
gasBudget,
|
|
173
|
+
simulationError: error
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
async getGasPrice(option) {
|
|
177
|
+
if (this.isFixedValue(option)) {
|
|
178
|
+
return option.fixedVal;
|
|
179
|
+
}
|
|
180
|
+
const refGasPrice = await this.globals.suiClient.getReferenceGasPrice();
|
|
181
|
+
return this.applyGasOption(refGasPrice, option);
|
|
182
|
+
}
|
|
183
|
+
toGasBudget(gasUsed, gasPrice) {
|
|
184
|
+
const { computationCost, storageCost } = gasUsed;
|
|
185
|
+
const safeOverhead = GAS_SAFE_OVERHEAD * gasPrice;
|
|
186
|
+
const baseComputationCostWithOverhead = BigInt(computationCost) + safeOverhead;
|
|
187
|
+
const gasBudget = baseComputationCostWithOverhead + BigInt(storageCost);
|
|
188
|
+
return gasBudget > baseComputationCostWithOverhead ? gasBudget : baseComputationCostWithOverhead;
|
|
189
|
+
}
|
|
190
|
+
isFixedValue(option) {
|
|
191
|
+
return "fixedVal" in option;
|
|
192
|
+
}
|
|
193
|
+
isMultiplier(option) {
|
|
194
|
+
return "multiplier" in option;
|
|
195
|
+
}
|
|
196
|
+
applyGasOption(val, option) {
|
|
197
|
+
if (this.isFixedValue(option)) {
|
|
198
|
+
return option.fixedVal;
|
|
199
|
+
}
|
|
200
|
+
if (this.isMultiplier(option)) {
|
|
201
|
+
const { multiplier } = option;
|
|
202
|
+
return val * multiplier.numerator / multiplier.denominator;
|
|
203
|
+
}
|
|
204
|
+
throw new Error("Sanity: Unknown gas price option");
|
|
205
|
+
}
|
|
206
|
+
copyTransactionBlock(tx) {
|
|
207
|
+
return TransactionBlock.from(tx.serialize());
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
138
211
|
// src/utils/buffer.ts
|
|
139
212
|
function stringToBuffer(s) {
|
|
140
213
|
return Buffer.from(s, "utf-8");
|
|
@@ -484,9 +557,11 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
484
557
|
creationNonce: info.creationNonce
|
|
485
558
|
});
|
|
486
559
|
this.coinHelper = new CoinHelper(this.suiClient);
|
|
560
|
+
this.simulator = new Simulator(globals);
|
|
487
561
|
}
|
|
488
562
|
multiSig;
|
|
489
563
|
coinHelper;
|
|
564
|
+
simulator;
|
|
490
565
|
static async New(globals, address) {
|
|
491
566
|
const info = await globals.backend.getMSafeAccountInfo(address);
|
|
492
567
|
const ms = new _MSafeAccount(globals, info);
|
|
@@ -515,7 +590,6 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
515
590
|
};
|
|
516
591
|
return getAllOwnedObjects(this.suiClient, this.address, filterCoinObjectOptions);
|
|
517
592
|
}
|
|
518
|
-
// TODO: Calculate the votes
|
|
519
593
|
async pendingTransaction() {
|
|
520
594
|
const res = await this.backend.getPendingTransactions({ msafeAddress: this.address });
|
|
521
595
|
if (!res.pending) {
|
|
@@ -541,7 +615,6 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
541
615
|
rejectWeight: this.calculateWeightFromVotes(rejectPending?.votes ?? [])
|
|
542
616
|
};
|
|
543
617
|
}
|
|
544
|
-
// TODO: Calculate the votes.
|
|
545
618
|
async historyTransaction(pagination) {
|
|
546
619
|
return this.backend.getHistoryTransactions({
|
|
547
620
|
msafeAddress: this.address,
|
|
@@ -557,6 +630,22 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
557
630
|
async nextSequenceNumber() {
|
|
558
631
|
return this.backend.getNextSequenceNumber(this.address);
|
|
559
632
|
}
|
|
633
|
+
async simulateIntention(request) {
|
|
634
|
+
const appHelper = appHelpers.getAppHelper(request.application);
|
|
635
|
+
if (!appHelper) {
|
|
636
|
+
throw new Error(`Can't find app helper for application ${request.application}`);
|
|
637
|
+
}
|
|
638
|
+
const txb = await appHelper.build({
|
|
639
|
+
intentionData: request.intention,
|
|
640
|
+
txType: request.txType,
|
|
641
|
+
txSubType: request.txSubType,
|
|
642
|
+
suiClient: this.globals.suiClient,
|
|
643
|
+
account: {
|
|
644
|
+
address: this.address
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
return this.simulator.simulate({ txb, sender: this.address });
|
|
648
|
+
}
|
|
560
649
|
async proposeIntention(input) {
|
|
561
650
|
const message = SigningMessageHelper3.proposeIntentionMessage({
|
|
562
651
|
msafeAddress: this.address,
|
|
@@ -566,12 +655,22 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
566
655
|
const signature = await this.wallet.signPersonalMessage({
|
|
567
656
|
messageStr: message
|
|
568
657
|
});
|
|
569
|
-
|
|
658
|
+
return this.backend.proposeIntention({
|
|
570
659
|
...input,
|
|
571
660
|
msafeAddress: this.address,
|
|
572
661
|
signature: signature.signature
|
|
573
662
|
});
|
|
574
663
|
}
|
|
664
|
+
async simulateCoinTransferIntention(intention) {
|
|
665
|
+
const sn = await this.nextSequenceNumber();
|
|
666
|
+
return this.simulateIntention({
|
|
667
|
+
application: TransactionDefaultApplication,
|
|
668
|
+
txType: TransactionType.Assets,
|
|
669
|
+
txSubType: TransactionSubTypes.assets.coin.send,
|
|
670
|
+
sequenceNumber: sn,
|
|
671
|
+
intention
|
|
672
|
+
});
|
|
673
|
+
}
|
|
575
674
|
async proposeCoinTransferIntention(intention) {
|
|
576
675
|
const sn = await this.nextSequenceNumber();
|
|
577
676
|
return this.proposeIntention({
|
|
@@ -595,7 +694,7 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
595
694
|
}
|
|
596
695
|
async proposePlainPayloadIntention(intention) {
|
|
597
696
|
const sn = await this.nextSequenceNumber();
|
|
598
|
-
const tb =
|
|
697
|
+
const tb = TransactionBlock2.from(intention.payload);
|
|
599
698
|
if (!tb.blockData.sender || !isSameAddress2(tb.blockData.sender, this.address)) {
|
|
600
699
|
throw new Error("Transaction sender is not same as the multisig address");
|
|
601
700
|
}
|
|
@@ -619,7 +718,7 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
619
718
|
// Shortcut for proposing a transaction to be a pending transaction, and add user vote to it.
|
|
620
719
|
// Requires the multi-sig to be empty in pending transaction.
|
|
621
720
|
async proposePendingTransaction(intention) {
|
|
622
|
-
const txb = new
|
|
721
|
+
const txb = new TransactionBlock2();
|
|
623
722
|
const payload = await txb.build({ client: this.suiClient });
|
|
624
723
|
const digest = await txb.getDigest({ client: this.suiClient });
|
|
625
724
|
const signature = await this.wallet.signTransactionBlock({ transactionBlock: payload });
|
|
@@ -647,33 +746,34 @@ var MSafeAccount = class _MSafeAccount {
|
|
|
647
746
|
signature: signature.signature
|
|
648
747
|
});
|
|
649
748
|
}
|
|
650
|
-
async
|
|
651
|
-
|
|
749
|
+
async simulateBuildTransaction() {
|
|
750
|
+
const intention = await this.backend.getNextIntention({ msafeAddress: this.address });
|
|
751
|
+
const appHelper = appHelpers.getAppHelper(intention.application);
|
|
752
|
+
if (!appHelper) {
|
|
753
|
+
throw new Error(`Can't find app helper for application ${intention.application}`);
|
|
754
|
+
}
|
|
755
|
+
const txb = await appHelper.build({
|
|
756
|
+
intentionData: intention.intention,
|
|
757
|
+
txType: intention.txType,
|
|
758
|
+
txSubType: intention.txSubType,
|
|
759
|
+
suiClient: this.globals.suiClient,
|
|
760
|
+
account: {
|
|
761
|
+
address: this.address
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
return this.simulator.simulate({ txb, sender: this.address });
|
|
765
|
+
}
|
|
766
|
+
async buildNextIntentionAndAddToPending(gasOption) {
|
|
767
|
+
return this.backend.buildNextIntentionAndAddToPending({
|
|
768
|
+
msafeAddress: this.address,
|
|
769
|
+
forceBuild: gasOption.forceBuild,
|
|
770
|
+
gasPrice: gasOption.gasPrice,
|
|
771
|
+
gasBudget: gasOption.gasBudget
|
|
772
|
+
});
|
|
652
773
|
}
|
|
653
774
|
async skipNextFailedIntention() {
|
|
654
775
|
return this.backend.skipNextFailedIntention({ msafeAddress: this.address });
|
|
655
776
|
}
|
|
656
|
-
async simulateIntention() {
|
|
657
|
-
const txb = new TransactionBlock();
|
|
658
|
-
txb.setSender(this.address);
|
|
659
|
-
if (!txb.blockData.gasConfig.price) {
|
|
660
|
-
const refGas = await this.suiClient.getReferenceGasPrice();
|
|
661
|
-
txb.setGasPrice(refGas);
|
|
662
|
-
}
|
|
663
|
-
const payload = await txb.build({ client: this.suiClient });
|
|
664
|
-
const dryRunResult = await this.suiClient.dryRunTransactionBlock({ transactionBlock: payload });
|
|
665
|
-
const success = dryRunResult.effects.status.status === "success";
|
|
666
|
-
const errorMsg = dryRunResult.effects.status.error;
|
|
667
|
-
const gasPrice = BigInt(txb.blockData.gasConfig.price);
|
|
668
|
-
const { gasUsed } = dryRunResult.effects;
|
|
669
|
-
return {
|
|
670
|
-
success,
|
|
671
|
-
errorMsg,
|
|
672
|
-
gasPrice,
|
|
673
|
-
gasUsed,
|
|
674
|
-
dryRunResult
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
777
|
async executePendingTx(pending, isRejectTx = false) {
|
|
678
778
|
const votes = isRejectTx ? pending.rejectVotes : pending.votes;
|
|
679
779
|
const payload = isRejectTx ? pending.rejectPayload : pending.payload;
|
|
@@ -916,6 +1016,13 @@ var BackendImpl = class _BackendImpl {
|
|
|
916
1016
|
});
|
|
917
1017
|
return res.data;
|
|
918
1018
|
}
|
|
1019
|
+
async getNextIntention(input) {
|
|
1020
|
+
const res = await this.get(`/transaction/intention/next`, {
|
|
1021
|
+
params: input,
|
|
1022
|
+
headers: this.headers()
|
|
1023
|
+
});
|
|
1024
|
+
return res.data;
|
|
1025
|
+
}
|
|
919
1026
|
async getCurrentSequenceNumber(address) {
|
|
920
1027
|
const res = await this.get(`/transaction/sn/current`, {
|
|
921
1028
|
params: {
|
|
@@ -942,7 +1049,6 @@ var BackendImpl = class _BackendImpl {
|
|
|
942
1049
|
async proposeIntention(input) {
|
|
943
1050
|
await this.post(`/transaction/intention`, input, { headers: this.headers() });
|
|
944
1051
|
}
|
|
945
|
-
// TODO later
|
|
946
1052
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
947
1053
|
async proposePendingTransaction(_input) {
|
|
948
1054
|
return void 0;
|
|
@@ -958,7 +1064,11 @@ var BackendImpl = class _BackendImpl {
|
|
|
958
1064
|
});
|
|
959
1065
|
}
|
|
960
1066
|
async buildNextIntentionAndAddToPending(input) {
|
|
961
|
-
await this.post(
|
|
1067
|
+
await this.post(
|
|
1068
|
+
`/transaction/pending/build`,
|
|
1069
|
+
{ ...input, gasPrice: input.gasPrice.toString(), gasBudget: input.gasBudget.toString() },
|
|
1070
|
+
{ headers: this.headers() }
|
|
1071
|
+
);
|
|
962
1072
|
}
|
|
963
1073
|
async skipNextFailedIntention(input) {
|
|
964
1074
|
await this.post(`/transaction/pending/skip`, input, { headers: this.headers() });
|
|
@@ -1061,7 +1171,6 @@ var MSafeEnv = /* @__PURE__ */ ((MSafeEnv3) => {
|
|
|
1061
1171
|
MSafeEnv3["prod"] = "prod";
|
|
1062
1172
|
return MSafeEnv3;
|
|
1063
1173
|
})(MSafeEnv || {});
|
|
1064
|
-
var MSAFE_APPLICATION = "msafe";
|
|
1065
1174
|
var TESTNET_RPC_URL = "https://sui-testnet.blockvision.org/v1/2Sgk89ivT64MnKdcGzjmyjY2ndD";
|
|
1066
1175
|
var MAINNET_RPC_URL = "https://sui-mainnet.blockvision.org/v1/2Sgk7NPvqkd7mESYkxF01yX15l7";
|
|
1067
1176
|
var LOCAL_API_URL = "http://127.0.0.1:3000";
|
|
@@ -1258,7 +1367,6 @@ export {
|
|
|
1258
1367
|
LOCAL_API_URL,
|
|
1259
1368
|
LOCAL_SYNCING_URL,
|
|
1260
1369
|
MAINNET_RPC_URL,
|
|
1261
|
-
MSAFE_APPLICATION,
|
|
1262
1370
|
MSafeAccount,
|
|
1263
1371
|
MSafeClient,
|
|
1264
1372
|
MSafeEnv,
|