@msafe/sui3-sdk 0.0.12-pre-0fb7c20.0 → 0.0.12
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 +699 -689
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +708 -695
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/backend/BackendImpl.ts +6 -0
- package/src/backend/PseudoBackend.ts +3 -0
- package/src/backend/interface.ts +3 -0
- package/src/core/MSafeAccount.ts +14 -2
- package/src/globals/const.ts +2 -0
package/dist/index.js
CHANGED
|
@@ -536,806 +536,818 @@ var AddressBookSDK = class {
|
|
|
536
536
|
};
|
|
537
537
|
|
|
538
538
|
// src/core/MSafeAccount.ts
|
|
539
|
-
import {
|
|
539
|
+
import {
|
|
540
|
+
buildIntentionTransaction,
|
|
541
|
+
getIntentionType,
|
|
542
|
+
MultisigAccountManager as MultisigAccountManager2
|
|
543
|
+
} from "@msafe/sui3-utils";
|
|
540
544
|
import { normalizeStructTag as normalizeStructTag3 } from "@mysten/sui.js/utils";
|
|
541
545
|
|
|
542
|
-
// src/
|
|
543
|
-
var
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
546
|
+
// src/globals/const.ts
|
|
547
|
+
var MSafeEnv = /* @__PURE__ */ ((MSafeEnv3) => {
|
|
548
|
+
MSafeEnv3["local"] = "local";
|
|
549
|
+
MSafeEnv3["unit"] = "unit";
|
|
550
|
+
MSafeEnv3["dev"] = "dev";
|
|
551
|
+
MSafeEnv3["prev"] = "prev";
|
|
552
|
+
MSafeEnv3["prod"] = "prod";
|
|
553
|
+
return MSafeEnv3;
|
|
554
|
+
})(MSafeEnv || {});
|
|
555
|
+
var UNIT_DATABASE_CONFIG = {
|
|
556
|
+
type: "sqlite",
|
|
557
|
+
database: ":memory:",
|
|
558
|
+
logging: false
|
|
559
|
+
};
|
|
560
|
+
var LOCAL_DATABASE_CONFIG = {
|
|
561
|
+
type: "mysql",
|
|
562
|
+
host: "127.0.0.1",
|
|
563
|
+
port: 3306,
|
|
564
|
+
username: "msafe",
|
|
565
|
+
password: "msafe",
|
|
566
|
+
database: "msafe_sui_local",
|
|
567
|
+
logging: false
|
|
568
|
+
};
|
|
569
|
+
var DEV_DATABASE_CONFIG = {
|
|
570
|
+
type: "mysql",
|
|
571
|
+
host: "msafe-dev-database.cluster-caos3ssocrx6.us-west-1.rds.amazonaws.com",
|
|
572
|
+
port: 3306,
|
|
573
|
+
username: "msafe",
|
|
574
|
+
password: "Momentum.Safe2022",
|
|
575
|
+
database: "msafe_sui_dev",
|
|
576
|
+
logging: false
|
|
577
|
+
};
|
|
578
|
+
var MSAFE_APPLICATION = "msafe";
|
|
579
|
+
var TESTNET_RPC_URL = "https://sui-testnet.blockvision.org/v1/2Sgk89ivT64MnKdcGzjmyjY2ndD";
|
|
580
|
+
var MAINNET_RPC_URL = "https://sui-mainnet.blockvision.org/v1/2Sgk7NPvqkd7mESYkxF01yX15l7";
|
|
581
|
+
var LOCAL_API_URL = "http://127.0.0.1:3000";
|
|
582
|
+
var LOCAL_SYNCING_URL = "http://127.0.0.1:3001";
|
|
583
|
+
var DEV_API_URL = "http://13.56.226.148";
|
|
584
|
+
var DEV_SYNCING_URL = "http://52.53.228.20";
|
|
585
|
+
var ENV_CONFIGS = /* @__PURE__ */ new Map([
|
|
586
|
+
[
|
|
587
|
+
"unit" /* unit */,
|
|
588
|
+
{
|
|
589
|
+
suiClient: {
|
|
590
|
+
url: TESTNET_RPC_URL
|
|
591
|
+
},
|
|
592
|
+
backend: LOCAL_DATABASE_CONFIG,
|
|
593
|
+
apiURL: LOCAL_API_URL,
|
|
594
|
+
syncingURL: LOCAL_SYNCING_URL
|
|
595
|
+
}
|
|
596
|
+
],
|
|
597
|
+
[
|
|
598
|
+
"local" /* local */,
|
|
599
|
+
{
|
|
600
|
+
suiClient: {
|
|
601
|
+
url: TESTNET_RPC_URL
|
|
602
|
+
},
|
|
603
|
+
backend: LOCAL_DATABASE_CONFIG,
|
|
604
|
+
apiURL: LOCAL_API_URL,
|
|
605
|
+
syncingURL: LOCAL_SYNCING_URL
|
|
606
|
+
}
|
|
607
|
+
],
|
|
608
|
+
[
|
|
609
|
+
"dev" /* dev */,
|
|
610
|
+
{
|
|
611
|
+
suiClient: {
|
|
612
|
+
url: TESTNET_RPC_URL
|
|
613
|
+
},
|
|
614
|
+
backend: DEV_DATABASE_CONFIG,
|
|
615
|
+
apiURL: DEV_API_URL,
|
|
616
|
+
syncingURL: DEV_SYNCING_URL
|
|
617
|
+
}
|
|
618
|
+
]
|
|
619
|
+
]);
|
|
620
|
+
function getMSafeConfig(env, options) {
|
|
621
|
+
const config = ENV_CONFIGS.get(env);
|
|
622
|
+
if (!config) {
|
|
623
|
+
throw new Error("Unknown environment");
|
|
549
624
|
}
|
|
550
|
-
if (
|
|
551
|
-
|
|
625
|
+
if (options?.suiClient?.url) {
|
|
626
|
+
config.suiClient.url = options.suiClient.url;
|
|
552
627
|
}
|
|
553
|
-
|
|
628
|
+
if (options?.backend) {
|
|
629
|
+
config.backend = options.backend;
|
|
630
|
+
}
|
|
631
|
+
return config;
|
|
554
632
|
}
|
|
555
|
-
var
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
633
|
+
var AUTH_SIGN_MESSAGE = "Welcome to MSafe";
|
|
634
|
+
|
|
635
|
+
// src/globals/MSafeGlobals.ts
|
|
636
|
+
import { SuiClient } from "@mysten/sui.js/client";
|
|
637
|
+
|
|
638
|
+
// src/backend/BackendImpl.ts
|
|
639
|
+
import axios from "axios";
|
|
640
|
+
var BackendImpl = class {
|
|
641
|
+
constructor(apiURL) {
|
|
642
|
+
this.apiURL = apiURL;
|
|
560
643
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
if (
|
|
565
|
-
|
|
566
|
-
this.curPage = await this.requester.doNextRequest();
|
|
567
|
-
}
|
|
568
|
-
return !!this.curPage.data?.length || this.curPage.hasNext;
|
|
569
|
-
}
|
|
570
|
-
if (!this.curPage) {
|
|
571
|
-
throw new Error("invalid implementation of iterator");
|
|
644
|
+
_token;
|
|
645
|
+
async authSign(input) {
|
|
646
|
+
const res = await axios.post(`${this.apiURL}/auth/login`, input);
|
|
647
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
648
|
+
throw new Error(`invalid authSign return: ${res}`);
|
|
572
649
|
}
|
|
573
|
-
|
|
650
|
+
this._token = res.data.accessToken;
|
|
651
|
+
return this._token;
|
|
574
652
|
}
|
|
575
|
-
async
|
|
576
|
-
|
|
577
|
-
this.
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
return this.curPage.data;
|
|
653
|
+
async verifyToken(jwt) {
|
|
654
|
+
try {
|
|
655
|
+
const res = await axios.get(`${this.apiURL}/auth`, { headers: this.headers(jwt) });
|
|
656
|
+
return res.status === 200;
|
|
657
|
+
} catch (_) {
|
|
658
|
+
return false;
|
|
582
659
|
}
|
|
583
|
-
this.curPage = await this.requester.doNextRequest();
|
|
584
|
-
return this.curPage.data;
|
|
585
660
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
constructor(requester) {
|
|
589
|
-
this.requester = requester;
|
|
590
|
-
this.pager = new PagedIterator(requester);
|
|
591
|
-
this.curData = [];
|
|
592
|
-
this.cursor = 0;
|
|
661
|
+
setJWTToken(token) {
|
|
662
|
+
this._token = token;
|
|
593
663
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
curData;
|
|
597
|
-
async hasNext() {
|
|
598
|
-
if (this.cursor < this.curData.length - 1) {
|
|
599
|
-
return true;
|
|
600
|
-
}
|
|
601
|
-
return this.pager.hasNext();
|
|
664
|
+
async getPublicKey(address) {
|
|
665
|
+
return (await this.getPublicKeyBatch([address]))[0];
|
|
602
666
|
}
|
|
603
|
-
async
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
this.curData = await this.pager.next();
|
|
610
|
-
this.cursor = 0;
|
|
667
|
+
async getPublicKeyBatch(addresses) {
|
|
668
|
+
const res = await axios.post(
|
|
669
|
+
`${this.apiURL}/account/getPublicKeyBatch`,
|
|
670
|
+
addresses,
|
|
671
|
+
{
|
|
672
|
+
headers: this.headers()
|
|
611
673
|
}
|
|
674
|
+
);
|
|
675
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
676
|
+
throw new Error(`invalid getPublicKeyBatch return: ${res}`);
|
|
612
677
|
}
|
|
613
|
-
return
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
// src/utils/iter/object.ts
|
|
618
|
-
async function getAllOwnedObjects(provider, owner, options) {
|
|
619
|
-
const iter = new OwnedObjectIterator(provider, owner, options);
|
|
620
|
-
return await getAllFromIterator(iter);
|
|
621
|
-
}
|
|
622
|
-
var OwnedObjectIterator = class extends EntryIterator {
|
|
623
|
-
constructor(provider, owner, options) {
|
|
624
|
-
super(new OwnedObjectRequester(provider, owner, options));
|
|
625
|
-
this.provider = provider;
|
|
626
|
-
this.owner = owner;
|
|
627
|
-
this.options = options;
|
|
678
|
+
return res.data?.map(
|
|
679
|
+
(publicKeyWithSchema) => publicKeyWithSchema ? PublicKeySerde.de({ ...publicKeyWithSchema }) : void 0
|
|
680
|
+
);
|
|
628
681
|
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
682
|
+
async getMSafeAccountInfo(msafeAddress) {
|
|
683
|
+
const res = await axios.get(
|
|
684
|
+
`${this.apiURL}/account/getMSafeAccountInfo/${msafeAddress}`,
|
|
685
|
+
{
|
|
686
|
+
headers: this.headers()
|
|
687
|
+
}
|
|
688
|
+
);
|
|
689
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
690
|
+
throw new Error(`invalid getPublicKeyBatch return: ${res}`);
|
|
691
|
+
}
|
|
692
|
+
const msafeResp = res.data;
|
|
693
|
+
return {
|
|
694
|
+
address: msafeResp.address,
|
|
695
|
+
ownersWithWeightPK: msafeResp.ownersWithWeightPKEncoded.map(
|
|
696
|
+
(owner) => ({
|
|
697
|
+
publicKey: PublicKeySerde.de({ publicKey: owner.publicKeyEncoded, scheme: owner.schema }),
|
|
698
|
+
address: owner.address,
|
|
699
|
+
weight: owner.weight
|
|
700
|
+
})
|
|
701
|
+
),
|
|
702
|
+
threshold: msafeResp.threshold,
|
|
703
|
+
name: msafeResp.name,
|
|
704
|
+
description: msafeResp.description,
|
|
705
|
+
creationNonce: msafeResp.creationNonce
|
|
641
706
|
};
|
|
642
707
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
objectOptions;
|
|
647
|
-
async doNextRequest() {
|
|
648
|
-
const res = await this.provider.getOwnedObjects({
|
|
649
|
-
owner: this.owner,
|
|
650
|
-
options: this.objectOptions,
|
|
651
|
-
cursor: this.nextCursor,
|
|
652
|
-
limit: this.pageSize
|
|
708
|
+
async getUserInfo(userAddress) {
|
|
709
|
+
const res = await axios.get(`${this.apiURL}/account/user/${userAddress}`, {
|
|
710
|
+
headers: this.headers()
|
|
653
711
|
});
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
if (this.filter) {
|
|
657
|
-
const { filter } = this;
|
|
658
|
-
filtered = res.data.filter((obj) => filter?.(obj));
|
|
659
|
-
} else {
|
|
660
|
-
filtered = res.data;
|
|
712
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
713
|
+
throw new Error(`invalid getPublicKeyBatch return: ${res}`);
|
|
661
714
|
}
|
|
662
715
|
return {
|
|
663
|
-
|
|
664
|
-
|
|
716
|
+
address: res.data.address,
|
|
717
|
+
publicKey: res.data.publicKey,
|
|
718
|
+
schema: res.data.schema,
|
|
719
|
+
creationNonce: res.data.creationNonce,
|
|
720
|
+
ownedMSafe: res.data.ownedMSafe.map(
|
|
721
|
+
(msafe) => ({
|
|
722
|
+
address: msafe.address,
|
|
723
|
+
ownersWithWeightPK: msafe.ownersWithWeightPKEncoded.map(
|
|
724
|
+
(owner) => ({
|
|
725
|
+
publicKey: PublicKeySerde.de({ publicKey: owner.publicKeyEncoded, scheme: owner.schema }),
|
|
726
|
+
address: owner.address,
|
|
727
|
+
weight: owner.weight
|
|
728
|
+
})
|
|
729
|
+
),
|
|
730
|
+
threshold: msafe.threshold,
|
|
731
|
+
name: msafe.name,
|
|
732
|
+
description: msafe.description,
|
|
733
|
+
creationNonce: msafe.creationNonce
|
|
734
|
+
})
|
|
735
|
+
)
|
|
665
736
|
};
|
|
666
737
|
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
var MSafeAccount = class {
|
|
671
|
-
constructor(globals, info) {
|
|
672
|
-
this.globals = globals;
|
|
673
|
-
this.info = info;
|
|
674
|
-
this.multisigManager = new MultisigAccountManager2({
|
|
675
|
-
threshold: info.threshold,
|
|
676
|
-
ownersWithWeight: info.ownersWithWeightPK,
|
|
677
|
-
creationNonce: info.creationNonce
|
|
738
|
+
async getPendingTransactions(msafeAddress) {
|
|
739
|
+
const res = await axios.get(`${this.apiURL}/transaction/pending/${msafeAddress}`, {
|
|
740
|
+
headers: this.headers()
|
|
678
741
|
});
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
static async new(globals, address) {
|
|
684
|
-
return globals.backend.getMSafeAccountInfo(address);
|
|
742
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
743
|
+
throw new Error(`invalid getPublicKeyBatch return: ${res}`);
|
|
744
|
+
}
|
|
745
|
+
return res.data;
|
|
685
746
|
}
|
|
686
|
-
async
|
|
687
|
-
const
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
};
|
|
697
|
-
})
|
|
747
|
+
async getHistoryTransactions(msafeAddress, paginationOption) {
|
|
748
|
+
const res = await axios.get(
|
|
749
|
+
`${this.apiURL}/transaction/history?address=${msafeAddress}`,
|
|
750
|
+
{
|
|
751
|
+
params: {
|
|
752
|
+
page: paginationOption?.page,
|
|
753
|
+
limit: paginationOption?.limit
|
|
754
|
+
},
|
|
755
|
+
headers: this.headers()
|
|
756
|
+
}
|
|
698
757
|
);
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
const filterCoinObjectOptions = {
|
|
702
|
-
filter: (objRes) => !objRes?.data?.type?.startsWith("0x2::coin::Coin"),
|
|
703
|
-
...options
|
|
704
|
-
};
|
|
705
|
-
return getAllOwnedObjects(this.suiClient, this.address, filterCoinObjectOptions);
|
|
706
|
-
}
|
|
707
|
-
async pendingTransaction() {
|
|
708
|
-
const pendings = await this.backend.getPendingTransactions(this.address);
|
|
709
|
-
if (pendings.length > 2) {
|
|
710
|
-
throw new Error(`invalid backend getPendingTransactions resp, length should not > 2: ${pendings}`);
|
|
711
|
-
}
|
|
712
|
-
if (pendings.length === 0) {
|
|
713
|
-
return void 0;
|
|
758
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
759
|
+
throw new Error(`invalid getCurrentSequenceNumber return: ${res}`);
|
|
714
760
|
}
|
|
715
|
-
|
|
716
|
-
const rejectPending = pendings.find((tx) => tx.isRejectTx);
|
|
717
|
-
return {
|
|
718
|
-
...pendingTx,
|
|
719
|
-
rejectDigest: rejectPending?.digest ?? "",
|
|
720
|
-
rejectPayload: rejectPending?.payload ?? "",
|
|
721
|
-
rejectVotes: rejectPending?.votes ?? []
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
async historyTransaction(paginationOption) {
|
|
725
|
-
return this.backend.getHistoryTransactions(this.address, paginationOption);
|
|
726
|
-
}
|
|
727
|
-
async futureIntentions(paginationOption) {
|
|
728
|
-
const paginatedIntentions = await this.backend.getFutureIntentions(this.address, paginationOption);
|
|
729
|
-
return paginatedIntentions.data;
|
|
730
|
-
}
|
|
731
|
-
async currentSequenceNumber() {
|
|
732
|
-
return this.backend.getCurrentSequenceNumber(this.address);
|
|
733
|
-
}
|
|
734
|
-
async nextSequenceNumber() {
|
|
735
|
-
return this.backend.getNextSequenceNumber(this.address);
|
|
761
|
+
return res.data;
|
|
736
762
|
}
|
|
737
|
-
async
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
messageStr: message
|
|
745
|
-
});
|
|
746
|
-
await this.backend.proposeIntention({
|
|
747
|
-
intention,
|
|
748
|
-
sequenceNumber,
|
|
749
|
-
msafeAddress: this.address,
|
|
750
|
-
userAddress: await this.userAddress(),
|
|
751
|
-
signature: signature.signature
|
|
763
|
+
async getFutureIntentions(msafeAddress, paginationOption) {
|
|
764
|
+
const res = await axios.get(`${this.apiURL}/transaction/intention/${msafeAddress}`, {
|
|
765
|
+
params: {
|
|
766
|
+
page: paginationOption?.page,
|
|
767
|
+
limit: paginationOption?.limit
|
|
768
|
+
},
|
|
769
|
+
headers: this.headers()
|
|
752
770
|
});
|
|
771
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
772
|
+
throw new Error(`invalid getCurrentSequenceNumber return: ${res}`);
|
|
773
|
+
}
|
|
774
|
+
return res.data;
|
|
753
775
|
}
|
|
754
|
-
async
|
|
755
|
-
const
|
|
756
|
-
|
|
757
|
-
return this.backend.voteForTransaction({
|
|
758
|
-
msafeAddress: this.address,
|
|
759
|
-
userAddress: await this.userAddress(),
|
|
760
|
-
txDigest: digest,
|
|
761
|
-
signature: signature.signature
|
|
776
|
+
async getCurrentSequenceNumber(msafeAddress) {
|
|
777
|
+
const res = await axios.get(`${this.apiURL}/transaction/sn/current/${msafeAddress}`, {
|
|
778
|
+
headers: this.headers()
|
|
762
779
|
});
|
|
780
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
781
|
+
throw new Error(`invalid getCurrentSequenceNumber return: ${res}`);
|
|
782
|
+
}
|
|
783
|
+
return res.data;
|
|
763
784
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
const txb = await IntentionHelper.buildTxb({
|
|
768
|
-
suiClient: this.suiClient,
|
|
769
|
-
intention,
|
|
770
|
-
sender: this.address
|
|
785
|
+
async getNextSequenceNumber(msafeAddress) {
|
|
786
|
+
const res = await axios.get(`${this.apiURL}/transaction/sn/next/${msafeAddress}`, {
|
|
787
|
+
headers: this.headers()
|
|
771
788
|
});
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
return
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
signature: signature.signature
|
|
789
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
790
|
+
throw new Error(`invalid getNextSequenceNumber return: ${res}`);
|
|
791
|
+
}
|
|
792
|
+
return res.data;
|
|
793
|
+
}
|
|
794
|
+
async createMSafeAccount(input) {
|
|
795
|
+
const res = await axios.post(`${this.apiURL}/account`, input, {
|
|
796
|
+
headers: this.headers()
|
|
781
797
|
});
|
|
798
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
799
|
+
throw new Error(`invalid createMSafeAccount return: ${res}`);
|
|
800
|
+
}
|
|
782
801
|
}
|
|
783
|
-
async
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
802
|
+
async proposeIntention(input) {
|
|
803
|
+
try {
|
|
804
|
+
const res = await axios.post(
|
|
805
|
+
`${this.apiURL}/transaction/intention`,
|
|
806
|
+
{
|
|
807
|
+
intention: input.intention,
|
|
808
|
+
sequenceNumber: input.sequenceNumber,
|
|
809
|
+
address: input.msafeAddress,
|
|
810
|
+
signature: input.signature,
|
|
811
|
+
application: input.application,
|
|
812
|
+
txType: input.txType,
|
|
813
|
+
txSubType: input.txSubType
|
|
814
|
+
},
|
|
815
|
+
{ headers: this.headers() }
|
|
816
|
+
);
|
|
817
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
818
|
+
throw new Error(`invalid proposeIntention return: ${res}`);
|
|
794
819
|
}
|
|
795
|
-
|
|
820
|
+
} catch (e) {
|
|
821
|
+
console.log(e);
|
|
796
822
|
}
|
|
797
|
-
const rejectTxb = await IntentionHelper.buildRejectTransaction({
|
|
798
|
-
msafeAddress: this.address,
|
|
799
|
-
payloadToReject
|
|
800
|
-
});
|
|
801
|
-
const digest = await rejectTxb.getDigest({ client: this.suiClient });
|
|
802
|
-
const payload = await rejectTxb.build({ client: this.suiClient });
|
|
803
|
-
const signature = await this.wallet.signTransactionBlock({ transactionBlock: payload });
|
|
804
|
-
return this.backend.rejectCurrentTx({
|
|
805
|
-
msafeAddress: this.address,
|
|
806
|
-
userAddress: await this.userAddress(),
|
|
807
|
-
digest,
|
|
808
|
-
signature: signature.signature
|
|
809
|
-
});
|
|
810
|
-
}
|
|
811
|
-
async buildNextIntentionAndAddToPending() {
|
|
812
|
-
return this.backend.buildNextIntentionAndAddToPending({ msafeAddress: this.address });
|
|
813
823
|
}
|
|
814
|
-
|
|
815
|
-
|
|
824
|
+
// TODO later
|
|
825
|
+
async proposePendingTransaction(input) {
|
|
816
826
|
}
|
|
817
|
-
async
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
827
|
+
async rejectCurrentTx(input) {
|
|
828
|
+
try {
|
|
829
|
+
const res = await axios.post(
|
|
830
|
+
`${this.apiURL}/transaction/pending/reject`,
|
|
831
|
+
{
|
|
832
|
+
address: input.msafeAddress,
|
|
833
|
+
digest: input.digest,
|
|
834
|
+
signature: input.signature
|
|
835
|
+
},
|
|
836
|
+
{
|
|
837
|
+
headers: this.headers()
|
|
838
|
+
}
|
|
839
|
+
);
|
|
840
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
841
|
+
throw new Error(`invalid voteForTransaction return: ${res}`);
|
|
842
|
+
}
|
|
843
|
+
} catch (e) {
|
|
844
|
+
console.log("e:", e);
|
|
822
845
|
}
|
|
823
|
-
const payload = await txb.build({ client: this.suiClient });
|
|
824
|
-
const dryRunResult = await this.suiClient.dryRunTransactionBlock({ transactionBlock: payload });
|
|
825
|
-
const success = dryRunResult.effects.status.status === "success";
|
|
826
|
-
const errorMsg = dryRunResult.effects.status.error;
|
|
827
|
-
const gasPrice = BigInt(txb.blockData.gasConfig.price);
|
|
828
|
-
const { gasUsed } = dryRunResult.effects;
|
|
829
|
-
return {
|
|
830
|
-
success,
|
|
831
|
-
errorMsg,
|
|
832
|
-
gasPrice,
|
|
833
|
-
gasUsed,
|
|
834
|
-
dryRunResult
|
|
835
|
-
};
|
|
836
846
|
}
|
|
837
|
-
async
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
throw new Error("Not enough signatures");
|
|
848
|
-
}
|
|
849
|
-
const sigs = [];
|
|
850
|
-
for (let i = 0; i < this.info.ownersWithWeightPK.length; i++) {
|
|
851
|
-
const owner = this.info.ownersWithWeightPK[i];
|
|
852
|
-
const signature = gotSigs.get(owner.publicKey.toSuiAddress());
|
|
853
|
-
if (signature) {
|
|
854
|
-
sigs.push(signature);
|
|
847
|
+
async voteForTransaction(input) {
|
|
848
|
+
const res = await axios.post(
|
|
849
|
+
`${this.apiURL}/transaction/pending/vote`,
|
|
850
|
+
{
|
|
851
|
+
address: input.msafeAddress,
|
|
852
|
+
digest: input.txDigest,
|
|
853
|
+
signature: input.signature
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
headers: this.headers()
|
|
855
857
|
}
|
|
858
|
+
);
|
|
859
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
860
|
+
throw new Error(`invalid voteForTransaction return: ${res}`);
|
|
856
861
|
}
|
|
857
|
-
const multiSignature = this.multisigManager.combinePartialSignatures(sigs);
|
|
858
|
-
return this.suiClient.executeTransactionBlock({
|
|
859
|
-
transactionBlock: HexToUint8Array(payload),
|
|
860
|
-
signature: multiSignature,
|
|
861
|
-
options: { showEffects: true }
|
|
862
|
-
});
|
|
863
|
-
}
|
|
864
|
-
get address() {
|
|
865
|
-
return this.info.address;
|
|
866
|
-
}
|
|
867
|
-
get backend() {
|
|
868
|
-
return this.globals.backend;
|
|
869
|
-
}
|
|
870
|
-
get wallet() {
|
|
871
|
-
return this.globals.wallet;
|
|
872
|
-
}
|
|
873
|
-
async userAddress() {
|
|
874
|
-
return this.globals.wallet.address();
|
|
875
|
-
}
|
|
876
|
-
get suiClient() {
|
|
877
|
-
return this.globals.suiClient;
|
|
878
|
-
}
|
|
879
|
-
};
|
|
880
|
-
|
|
881
|
-
// src/core/PublicKeyHelper.ts
|
|
882
|
-
var PublicKeyHelper = class {
|
|
883
|
-
constructor(globals) {
|
|
884
|
-
this.globals = globals;
|
|
885
|
-
this.knownPublicKeys = /* @__PURE__ */ new Map();
|
|
886
862
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
863
|
+
async buildNextIntentionAndAddToPending(input) {
|
|
864
|
+
const res = await axios.post(
|
|
865
|
+
`${this.apiURL}/transaction/pending/build`,
|
|
866
|
+
{
|
|
867
|
+
address: input.msafeAddress
|
|
868
|
+
},
|
|
869
|
+
{ headers: this.headers() }
|
|
870
|
+
);
|
|
871
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
872
|
+
throw new Error(`invalid buildNextIntentionAndAddToPending return: ${res}`);
|
|
896
873
|
}
|
|
897
|
-
return pk;
|
|
898
874
|
}
|
|
899
|
-
async
|
|
900
|
-
const
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
results[index] = backendResult[i];
|
|
910
|
-
}
|
|
911
|
-
for (let i = 0; i < results.length; i++) {
|
|
912
|
-
if (results[i] === void 0) {
|
|
913
|
-
results[i] = await this.getPublicKeyFromChain(addresses[i]);
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
for (let i = 0; i < addresses.length; i++) {
|
|
917
|
-
if (results[i]) {
|
|
918
|
-
this.knownPublicKeys.set(addresses[i], results[i]);
|
|
919
|
-
}
|
|
875
|
+
async skipNextFailedIntention(input) {
|
|
876
|
+
const res = await axios.post(
|
|
877
|
+
`${this.apiURL}/transaction/pending/skip`,
|
|
878
|
+
{
|
|
879
|
+
msafeAddress: input.msafeAddress
|
|
880
|
+
},
|
|
881
|
+
{ headers: this.headers() }
|
|
882
|
+
);
|
|
883
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
884
|
+
throw new Error(`invalid skipNextFailedIntention return: ${res}`);
|
|
920
885
|
}
|
|
921
|
-
return results;
|
|
922
886
|
}
|
|
923
|
-
async
|
|
924
|
-
const
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
return pkChain;
|
|
887
|
+
async getAddressBookEntries(pagination) {
|
|
888
|
+
const res = await axios.get(`${this.apiURL}/address-book`, {
|
|
889
|
+
headers: this.headers(),
|
|
890
|
+
params: pagination
|
|
891
|
+
});
|
|
892
|
+
if (res.status !== 200) {
|
|
893
|
+
throw new Error(`Invalid address-book return: ${res}`);
|
|
931
894
|
}
|
|
932
|
-
return
|
|
895
|
+
return res.data;
|
|
933
896
|
}
|
|
934
|
-
async
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
return
|
|
938
|
-
} catch (_) {
|
|
939
|
-
return void 0;
|
|
897
|
+
async updateAddressBook(input) {
|
|
898
|
+
const res = await axios.post(`${this.apiURL}/address-book`, input, { headers: this.headers() });
|
|
899
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
900
|
+
throw new Error(`invalid updateAddressBook return: ${res}`);
|
|
940
901
|
}
|
|
941
902
|
}
|
|
942
|
-
async
|
|
943
|
-
|
|
903
|
+
async processExecutedTransaction(digest) {
|
|
904
|
+
}
|
|
905
|
+
headers(token) {
|
|
906
|
+
return { Authorization: `Bearer ${token || this._token}` };
|
|
944
907
|
}
|
|
945
908
|
};
|
|
946
909
|
|
|
947
910
|
// src/globals/MSafeGlobals.ts
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
constructor(
|
|
954
|
-
this.
|
|
911
|
+
var MSafeGlobals = class _MSafeGlobals {
|
|
912
|
+
backend;
|
|
913
|
+
suiClient;
|
|
914
|
+
config;
|
|
915
|
+
_wallet;
|
|
916
|
+
constructor(input) {
|
|
917
|
+
this.backend = input.backend;
|
|
918
|
+
this.suiClient = input.suiClient;
|
|
919
|
+
this.config = input.config;
|
|
955
920
|
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
const
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
921
|
+
static async New(env, options) {
|
|
922
|
+
const config = getMSafeConfig(env, options);
|
|
923
|
+
const suiClient = new SuiClient(config.suiClient);
|
|
924
|
+
const backend = new BackendImpl(config.apiURL);
|
|
925
|
+
return new _MSafeGlobals({
|
|
926
|
+
backend,
|
|
927
|
+
suiClient,
|
|
928
|
+
config
|
|
929
|
+
});
|
|
964
930
|
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
931
|
+
connectWallet(wallet) {
|
|
932
|
+
this._wallet = wallet;
|
|
933
|
+
}
|
|
934
|
+
get wallet() {
|
|
935
|
+
if (!this._wallet) {
|
|
936
|
+
throw new Error("wallet not connected");
|
|
971
937
|
}
|
|
938
|
+
return this._wallet;
|
|
972
939
|
}
|
|
973
|
-
|
|
974
|
-
this.
|
|
940
|
+
set wallet(val) {
|
|
941
|
+
this._wallet = val;
|
|
975
942
|
}
|
|
976
|
-
|
|
977
|
-
|
|
943
|
+
};
|
|
944
|
+
|
|
945
|
+
// src/utils/iter/iterator.ts
|
|
946
|
+
var REQUEST_PAGE_SIZE = 25;
|
|
947
|
+
async function getAllFromIterator(it) {
|
|
948
|
+
const res = [];
|
|
949
|
+
while (await it.hasNext()) {
|
|
950
|
+
const val = await it.next();
|
|
951
|
+
res.push(val);
|
|
978
952
|
}
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
953
|
+
if (res && Array.isArray(res[0])) {
|
|
954
|
+
return res.flat(1);
|
|
955
|
+
}
|
|
956
|
+
return res;
|
|
957
|
+
}
|
|
958
|
+
var PagedIterator = class {
|
|
959
|
+
constructor(requester) {
|
|
960
|
+
this.requester = requester;
|
|
961
|
+
this.curPage = void 0;
|
|
962
|
+
this.init = true;
|
|
963
|
+
}
|
|
964
|
+
curPage;
|
|
965
|
+
init;
|
|
966
|
+
async hasNext() {
|
|
967
|
+
if (this.init) {
|
|
968
|
+
if (!this.curPage) {
|
|
969
|
+
this.curPage = await this.requester.doNextRequest();
|
|
985
970
|
}
|
|
986
|
-
|
|
987
|
-
if (res.status !== 200 && res.status !== 201) {
|
|
988
|
-
throw new Error(`invalid getPublicKeyBatch return: ${res}`);
|
|
971
|
+
return !!this.curPage.data?.length || this.curPage.hasNext;
|
|
989
972
|
}
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
973
|
+
if (!this.curPage) {
|
|
974
|
+
throw new Error("invalid implementation of iterator");
|
|
975
|
+
}
|
|
976
|
+
return this.curPage.hasNext;
|
|
993
977
|
}
|
|
994
|
-
async
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
{
|
|
998
|
-
|
|
978
|
+
async next() {
|
|
979
|
+
if (this.init) {
|
|
980
|
+
this.init = false;
|
|
981
|
+
if (!this.curPage) {
|
|
982
|
+
this.curPage = await this.requester.doNextRequest();
|
|
999
983
|
}
|
|
1000
|
-
|
|
1001
|
-
if (res.status !== 200 && res.status !== 201) {
|
|
1002
|
-
throw new Error(`invalid getPublicKeyBatch return: ${res}`);
|
|
984
|
+
return this.curPage.data;
|
|
1003
985
|
}
|
|
1004
|
-
|
|
1005
|
-
return
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
986
|
+
this.curPage = await this.requester.doNextRequest();
|
|
987
|
+
return this.curPage.data;
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
var EntryIterator = class {
|
|
991
|
+
constructor(requester) {
|
|
992
|
+
this.requester = requester;
|
|
993
|
+
this.pager = new PagedIterator(requester);
|
|
994
|
+
this.curData = [];
|
|
995
|
+
this.cursor = 0;
|
|
996
|
+
}
|
|
997
|
+
cursor;
|
|
998
|
+
pager;
|
|
999
|
+
curData;
|
|
1000
|
+
async hasNext() {
|
|
1001
|
+
if (this.cursor < this.curData.length - 1) {
|
|
1002
|
+
return true;
|
|
1003
|
+
}
|
|
1004
|
+
return this.pager.hasNext();
|
|
1005
|
+
}
|
|
1006
|
+
async next() {
|
|
1007
|
+
this.cursor += 1;
|
|
1008
|
+
while (this.cursor >= this.curData.length) {
|
|
1009
|
+
if (!await this.pager.hasNext()) {
|
|
1010
|
+
throw new Error("not more data");
|
|
1011
|
+
} else {
|
|
1012
|
+
this.curData = await this.pager.next();
|
|
1013
|
+
this.cursor = 0;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
return this.curData[this.cursor];
|
|
1017
|
+
}
|
|
1018
|
+
};
|
|
1019
|
+
|
|
1020
|
+
// src/utils/iter/object.ts
|
|
1021
|
+
async function getAllOwnedObjects(provider, owner, options) {
|
|
1022
|
+
const iter = new OwnedObjectIterator(provider, owner, options);
|
|
1023
|
+
return await getAllFromIterator(iter);
|
|
1024
|
+
}
|
|
1025
|
+
var OwnedObjectIterator = class extends EntryIterator {
|
|
1026
|
+
constructor(provider, owner, options) {
|
|
1027
|
+
super(new OwnedObjectRequester(provider, owner, options));
|
|
1028
|
+
this.provider = provider;
|
|
1029
|
+
this.owner = owner;
|
|
1030
|
+
this.options = options;
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
var OwnedObjectRequester = class {
|
|
1034
|
+
constructor(provider, owner, options) {
|
|
1035
|
+
this.provider = provider;
|
|
1036
|
+
this.owner = owner;
|
|
1037
|
+
this.options = options;
|
|
1038
|
+
this.nextCursor = null;
|
|
1039
|
+
this.filter = options?.filter;
|
|
1040
|
+
this.pageSize = options?.pageSize || REQUEST_PAGE_SIZE;
|
|
1041
|
+
this.objectOptions = options?.objectOptions || {
|
|
1042
|
+
showType: true,
|
|
1043
|
+
showContent: true
|
|
1018
1044
|
};
|
|
1019
1045
|
}
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1046
|
+
nextCursor;
|
|
1047
|
+
filter;
|
|
1048
|
+
pageSize;
|
|
1049
|
+
objectOptions;
|
|
1050
|
+
async doNextRequest() {
|
|
1051
|
+
const res = await this.provider.getOwnedObjects({
|
|
1052
|
+
owner: this.owner,
|
|
1053
|
+
options: this.objectOptions,
|
|
1054
|
+
cursor: this.nextCursor,
|
|
1055
|
+
limit: this.pageSize
|
|
1023
1056
|
});
|
|
1024
|
-
|
|
1025
|
-
|
|
1057
|
+
this.nextCursor = res.nextCursor;
|
|
1058
|
+
let filtered;
|
|
1059
|
+
if (this.filter) {
|
|
1060
|
+
const { filter } = this;
|
|
1061
|
+
filtered = res.data.filter((obj) => filter?.(obj));
|
|
1062
|
+
} else {
|
|
1063
|
+
filtered = res.data;
|
|
1026
1064
|
}
|
|
1027
1065
|
return {
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
schema: res.data.schema,
|
|
1031
|
-
creationNonce: res.data.creationNonce,
|
|
1032
|
-
ownedMSafe: res.data.ownedMSafe.map(
|
|
1033
|
-
(msafe) => ({
|
|
1034
|
-
address: msafe.address,
|
|
1035
|
-
ownersWithWeightPK: msafe.ownersWithWeightPKEncoded.map(
|
|
1036
|
-
(owner) => ({
|
|
1037
|
-
publicKey: PublicKeySerde.de({ publicKey: owner.publicKeyEncoded, scheme: owner.schema }),
|
|
1038
|
-
address: owner.address,
|
|
1039
|
-
weight: owner.weight
|
|
1040
|
-
})
|
|
1041
|
-
),
|
|
1042
|
-
threshold: msafe.threshold,
|
|
1043
|
-
name: msafe.name,
|
|
1044
|
-
description: msafe.description,
|
|
1045
|
-
creationNonce: msafe.creationNonce
|
|
1046
|
-
})
|
|
1047
|
-
)
|
|
1066
|
+
data: filtered.map((r) => r.data).filter((data) => data),
|
|
1067
|
+
hasNext: res.hasNextPage
|
|
1048
1068
|
};
|
|
1049
1069
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1070
|
+
};
|
|
1071
|
+
|
|
1072
|
+
// src/core/MSafeAccount.ts
|
|
1073
|
+
var MSafeAccount = class {
|
|
1074
|
+
constructor(globals, info) {
|
|
1075
|
+
this.globals = globals;
|
|
1076
|
+
this.info = info;
|
|
1077
|
+
this.multisigManager = new MultisigAccountManager2({
|
|
1078
|
+
threshold: info.threshold,
|
|
1079
|
+
ownersWithWeight: info.ownersWithWeightPK,
|
|
1080
|
+
creationNonce: info.creationNonce
|
|
1053
1081
|
});
|
|
1054
|
-
|
|
1055
|
-
throw new Error(`invalid getPublicKeyBatch return: ${res}`);
|
|
1056
|
-
}
|
|
1057
|
-
return res.data;
|
|
1082
|
+
this.coinHelper = new CoinHelper(this.suiClient);
|
|
1058
1083
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1084
|
+
multisigManager;
|
|
1085
|
+
coinHelper;
|
|
1086
|
+
static async new(globals, address) {
|
|
1087
|
+
return globals.backend.getMSafeAccountInfo(address);
|
|
1088
|
+
}
|
|
1089
|
+
async ownedCoins() {
|
|
1090
|
+
const balances = await this.suiClient.getAllBalances({ owner: this.address });
|
|
1091
|
+
return Promise.all(
|
|
1092
|
+
balances.map(async (balance) => {
|
|
1093
|
+
const meta = await this.coinHelper.getCoinMeta(balance.coinType);
|
|
1094
|
+
const unlockedBalance = balance.lockedBalance.number ? BigInt(balance.totalBalance) - BigInt(balance.lockedBalance.number) : BigInt(balance.totalBalance);
|
|
1095
|
+
return {
|
|
1096
|
+
type: normalizeStructTag3(balance.coinType),
|
|
1097
|
+
balance: BigInt(unlockedBalance),
|
|
1098
|
+
metadata: meta
|
|
1099
|
+
};
|
|
1100
|
+
})
|
|
1069
1101
|
);
|
|
1070
|
-
if (res.status !== 200 && res.status !== 201) {
|
|
1071
|
-
throw new Error(`invalid getCurrentSequenceNumber return: ${res}`);
|
|
1072
|
-
}
|
|
1073
|
-
return res.data;
|
|
1074
1102
|
}
|
|
1075
|
-
async
|
|
1076
|
-
const
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
headers: this.headers()
|
|
1082
|
-
});
|
|
1083
|
-
if (res.status !== 200 && res.status !== 201) {
|
|
1084
|
-
throw new Error(`invalid getCurrentSequenceNumber return: ${res}`);
|
|
1085
|
-
}
|
|
1086
|
-
return res.data;
|
|
1103
|
+
async ownedObjects(options) {
|
|
1104
|
+
const filterCoinObjectOptions = {
|
|
1105
|
+
filter: (objRes) => !objRes?.data?.type?.startsWith("0x2::coin::Coin"),
|
|
1106
|
+
...options
|
|
1107
|
+
};
|
|
1108
|
+
return getAllOwnedObjects(this.suiClient, this.address, filterCoinObjectOptions);
|
|
1087
1109
|
}
|
|
1088
|
-
async
|
|
1089
|
-
const
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
if (res.status !== 200 && res.status !== 201) {
|
|
1093
|
-
throw new Error(`invalid getCurrentSequenceNumber return: ${res}`);
|
|
1110
|
+
async pendingTransaction() {
|
|
1111
|
+
const pendings = await this.backend.getPendingTransactions(this.address);
|
|
1112
|
+
if (pendings.length > 2) {
|
|
1113
|
+
throw new Error(`invalid backend getPendingTransactions resp, length should not > 2: ${pendings}`);
|
|
1094
1114
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
async getNextSequenceNumber(msafeAddress) {
|
|
1098
|
-
const res = await axios.get(`${this.apiURL}/transaction/sn/next/${msafeAddress}`, {
|
|
1099
|
-
headers: this.headers()
|
|
1100
|
-
});
|
|
1101
|
-
if (res.status !== 200 && res.status !== 201) {
|
|
1102
|
-
throw new Error(`invalid getNextSequenceNumber return: ${res}`);
|
|
1115
|
+
if (pendings.length === 0) {
|
|
1116
|
+
return void 0;
|
|
1103
1117
|
}
|
|
1104
|
-
|
|
1118
|
+
const pendingTx = pendings.find((tx) => !tx.isRejectTx);
|
|
1119
|
+
const rejectPending = pendings.find((tx) => tx.isRejectTx);
|
|
1120
|
+
return {
|
|
1121
|
+
...pendingTx,
|
|
1122
|
+
rejectDigest: rejectPending?.digest ?? "",
|
|
1123
|
+
rejectPayload: rejectPending?.payload ?? "",
|
|
1124
|
+
rejectVotes: rejectPending?.votes ?? []
|
|
1125
|
+
};
|
|
1105
1126
|
}
|
|
1106
|
-
async
|
|
1107
|
-
|
|
1108
|
-
headers: this.headers()
|
|
1109
|
-
});
|
|
1110
|
-
if (res.status !== 200 && res.status !== 201) {
|
|
1111
|
-
throw new Error(`invalid createMSafeAccount return: ${res}`);
|
|
1112
|
-
}
|
|
1127
|
+
async historyTransaction(paginationOption) {
|
|
1128
|
+
return this.backend.getHistoryTransactions(this.address, paginationOption);
|
|
1113
1129
|
}
|
|
1114
|
-
async
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
`${this.apiURL}/transaction/intention`,
|
|
1118
|
-
{
|
|
1119
|
-
intention: input.intention,
|
|
1120
|
-
sequenceNumber: input.sequenceNumber,
|
|
1121
|
-
address: input.msafeAddress,
|
|
1122
|
-
signature: input.signature
|
|
1123
|
-
},
|
|
1124
|
-
{ headers: this.headers() }
|
|
1125
|
-
);
|
|
1126
|
-
if (res.status !== 200 && res.status !== 201) {
|
|
1127
|
-
throw new Error(`invalid proposeIntention return: ${res}`);
|
|
1128
|
-
}
|
|
1129
|
-
} catch (e) {
|
|
1130
|
-
console.log(e);
|
|
1131
|
-
}
|
|
1130
|
+
async futureIntentions(paginationOption) {
|
|
1131
|
+
const paginatedIntentions = await this.backend.getFutureIntentions(this.address, paginationOption);
|
|
1132
|
+
return paginatedIntentions.data;
|
|
1132
1133
|
}
|
|
1133
|
-
|
|
1134
|
-
|
|
1134
|
+
async currentSequenceNumber() {
|
|
1135
|
+
return this.backend.getCurrentSequenceNumber(this.address);
|
|
1135
1136
|
}
|
|
1136
|
-
async
|
|
1137
|
-
|
|
1138
|
-
const res = await axios.post(
|
|
1139
|
-
`${this.apiURL}/transaction/pending/reject`,
|
|
1140
|
-
{
|
|
1141
|
-
address: input.msafeAddress,
|
|
1142
|
-
digest: input.digest,
|
|
1143
|
-
signature: input.signature
|
|
1144
|
-
},
|
|
1145
|
-
{
|
|
1146
|
-
headers: this.headers()
|
|
1147
|
-
}
|
|
1148
|
-
);
|
|
1149
|
-
if (res.status !== 200 && res.status !== 201) {
|
|
1150
|
-
throw new Error(`invalid voteForTransaction return: ${res}`);
|
|
1151
|
-
}
|
|
1152
|
-
} catch (e) {
|
|
1153
|
-
console.log("e:", e);
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
async voteForTransaction(input) {
|
|
1157
|
-
const res = await axios.post(
|
|
1158
|
-
`${this.apiURL}/transaction/pending/vote`,
|
|
1159
|
-
{
|
|
1160
|
-
address: input.msafeAddress,
|
|
1161
|
-
digest: input.txDigest,
|
|
1162
|
-
signature: input.signature
|
|
1163
|
-
},
|
|
1164
|
-
{
|
|
1165
|
-
headers: this.headers()
|
|
1166
|
-
}
|
|
1167
|
-
);
|
|
1168
|
-
if (res.status !== 200 && res.status !== 201) {
|
|
1169
|
-
throw new Error(`invalid voteForTransaction return: ${res}`);
|
|
1170
|
-
}
|
|
1137
|
+
async nextSequenceNumber() {
|
|
1138
|
+
return this.backend.getNextSequenceNumber(this.address);
|
|
1171
1139
|
}
|
|
1172
|
-
async
|
|
1173
|
-
const
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1140
|
+
async proposeIntention(intention, sequenceNumber) {
|
|
1141
|
+
const message = MessageHelper.proposeIntentionMessage({
|
|
1142
|
+
intention,
|
|
1143
|
+
sn: sequenceNumber,
|
|
1144
|
+
msafeAddress: this.address
|
|
1145
|
+
});
|
|
1146
|
+
const signature = await this.wallet.signPersonalMessage({
|
|
1147
|
+
messageStr: message
|
|
1148
|
+
});
|
|
1149
|
+
const txType = getIntentionType(intention);
|
|
1150
|
+
await this.backend.proposeIntention({
|
|
1151
|
+
intention,
|
|
1152
|
+
sequenceNumber,
|
|
1153
|
+
msafeAddress: this.address,
|
|
1154
|
+
userAddress: await this.userAddress(),
|
|
1155
|
+
signature: signature.signature,
|
|
1156
|
+
application: MSAFE_APPLICATION,
|
|
1157
|
+
txType: txType.txType,
|
|
1158
|
+
txSubType: txType.txSubType
|
|
1159
|
+
});
|
|
1183
1160
|
}
|
|
1184
|
-
async
|
|
1185
|
-
const
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
throw new Error(`invalid skipNextFailedIntention return: ${res}`);
|
|
1194
|
-
}
|
|
1161
|
+
async voteForTransaction(digest, payload) {
|
|
1162
|
+
const payloadBytes = HexToUint8Array(payload);
|
|
1163
|
+
const signature = await this.wallet.signTransactionBlock({ transactionBlock: payloadBytes });
|
|
1164
|
+
return this.backend.voteForTransaction({
|
|
1165
|
+
msafeAddress: this.address,
|
|
1166
|
+
userAddress: await this.userAddress(),
|
|
1167
|
+
txDigest: digest,
|
|
1168
|
+
signature: signature.signature
|
|
1169
|
+
});
|
|
1195
1170
|
}
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1171
|
+
// Shortcut for proposing a transaction to be a pending transaction, and add user vote to it.
|
|
1172
|
+
// Requires the multi-sig to be empty in pending transaction.
|
|
1173
|
+
async proposePendingTransaction(intention) {
|
|
1174
|
+
const txb = await IntentionHelper.buildTxb({
|
|
1175
|
+
suiClient: this.suiClient,
|
|
1176
|
+
intention,
|
|
1177
|
+
sender: this.address
|
|
1178
|
+
});
|
|
1179
|
+
const payload = await txb.build({ client: this.suiClient });
|
|
1180
|
+
const digest = await txb.getDigest({ client: this.suiClient });
|
|
1181
|
+
const signature = await this.wallet.signTransactionBlock({ transactionBlock: payload });
|
|
1182
|
+
return this.backend.proposePendingTransaction({
|
|
1183
|
+
msafeAddress: this.address,
|
|
1184
|
+
userAddress: await this.userAddress(),
|
|
1185
|
+
intention,
|
|
1186
|
+
digest,
|
|
1187
|
+
signature: signature.signature
|
|
1200
1188
|
});
|
|
1201
|
-
if (res.status !== 200) {
|
|
1202
|
-
throw new Error(`Invalid address-book return: ${res}`);
|
|
1203
|
-
}
|
|
1204
|
-
return res.data;
|
|
1205
1189
|
}
|
|
1206
|
-
async
|
|
1207
|
-
|
|
1208
|
-
if (
|
|
1209
|
-
|
|
1190
|
+
async rejectCurrentTx(pending) {
|
|
1191
|
+
let payloadToReject;
|
|
1192
|
+
if (pending) {
|
|
1193
|
+
if (pending.isRejectTx) {
|
|
1194
|
+
throw new Error("Pending not reject transaction");
|
|
1195
|
+
}
|
|
1196
|
+
payloadToReject = pending.payload;
|
|
1197
|
+
} else {
|
|
1198
|
+
const pendingTx = await this.pendingTransaction();
|
|
1199
|
+
if (!pendingTx || pendingTx.rejectDigest !== "") {
|
|
1200
|
+
throw new Error("Already rejected");
|
|
1201
|
+
}
|
|
1202
|
+
payloadToReject = pendingTx.payload;
|
|
1210
1203
|
}
|
|
1204
|
+
const rejectTxb = await IntentionHelper.buildRejectTransaction({
|
|
1205
|
+
msafeAddress: this.address,
|
|
1206
|
+
payloadToReject
|
|
1207
|
+
});
|
|
1208
|
+
const digest = await rejectTxb.getDigest({ client: this.suiClient });
|
|
1209
|
+
const payload = await rejectTxb.build({ client: this.suiClient });
|
|
1210
|
+
const signature = await this.wallet.signTransactionBlock({ transactionBlock: payload });
|
|
1211
|
+
return this.backend.rejectCurrentTx({
|
|
1212
|
+
msafeAddress: this.address,
|
|
1213
|
+
userAddress: await this.userAddress(),
|
|
1214
|
+
digest,
|
|
1215
|
+
signature: signature.signature
|
|
1216
|
+
});
|
|
1211
1217
|
}
|
|
1212
|
-
async
|
|
1218
|
+
async buildNextIntentionAndAddToPending() {
|
|
1219
|
+
return this.backend.buildNextIntentionAndAddToPending({ msafeAddress: this.address });
|
|
1213
1220
|
}
|
|
1214
|
-
|
|
1215
|
-
return {
|
|
1221
|
+
async skipNextFailedIntention() {
|
|
1222
|
+
return this.backend.skipNextFailedIntention({ msafeAddress: this.address, userAddress: await this.userAddress() });
|
|
1216
1223
|
}
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
MSafeEnv3["unit"] = "unit";
|
|
1223
|
-
MSafeEnv3["dev"] = "dev";
|
|
1224
|
-
MSafeEnv3["prev"] = "prev";
|
|
1225
|
-
MSafeEnv3["prod"] = "prod";
|
|
1226
|
-
return MSafeEnv3;
|
|
1227
|
-
})(MSafeEnv || {});
|
|
1228
|
-
var UNIT_DATABASE_CONFIG = {
|
|
1229
|
-
type: "sqlite",
|
|
1230
|
-
database: ":memory:",
|
|
1231
|
-
logging: false
|
|
1232
|
-
};
|
|
1233
|
-
var LOCAL_DATABASE_CONFIG = {
|
|
1234
|
-
type: "mysql",
|
|
1235
|
-
host: "127.0.0.1",
|
|
1236
|
-
port: 3306,
|
|
1237
|
-
username: "msafe",
|
|
1238
|
-
password: "msafe",
|
|
1239
|
-
database: "msafe_sui_local",
|
|
1240
|
-
logging: false
|
|
1241
|
-
};
|
|
1242
|
-
var DEV_DATABASE_CONFIG = {
|
|
1243
|
-
type: "mysql",
|
|
1244
|
-
host: "msafe-dev-database.cluster-caos3ssocrx6.us-west-1.rds.amazonaws.com",
|
|
1245
|
-
port: 3306,
|
|
1246
|
-
username: "msafe",
|
|
1247
|
-
password: "Momentum.Safe2022",
|
|
1248
|
-
database: "msafe_sui_dev",
|
|
1249
|
-
logging: false
|
|
1250
|
-
};
|
|
1251
|
-
var TESTNET_RPC_URL = "https://sui-testnet.blockvision.org/v1/2Sgk89ivT64MnKdcGzjmyjY2ndD";
|
|
1252
|
-
var MAINNET_RPC_URL = "https://sui-mainnet.blockvision.org/v1/2Sgk7NPvqkd7mESYkxF01yX15l7";
|
|
1253
|
-
var LOCAL_API_URL = "http://127.0.0.1:3000";
|
|
1254
|
-
var LOCAL_SYNCING_URL = "http://127.0.0.1:3001";
|
|
1255
|
-
var DEV_API_URL = "http://13.56.226.148";
|
|
1256
|
-
var DEV_SYNCING_URL = "http://52.53.228.20";
|
|
1257
|
-
var ENV_CONFIGS = /* @__PURE__ */ new Map([
|
|
1258
|
-
[
|
|
1259
|
-
"unit" /* unit */,
|
|
1260
|
-
{
|
|
1261
|
-
suiClient: {
|
|
1262
|
-
url: TESTNET_RPC_URL
|
|
1263
|
-
},
|
|
1264
|
-
backend: LOCAL_DATABASE_CONFIG,
|
|
1265
|
-
apiURL: LOCAL_API_URL,
|
|
1266
|
-
syncingURL: LOCAL_SYNCING_URL
|
|
1224
|
+
async simulateIntention(intention) {
|
|
1225
|
+
const txb = await buildIntentionTransaction(this.suiClient, intention, this.address);
|
|
1226
|
+
if (!txb.blockData.gasConfig.price) {
|
|
1227
|
+
const refGas = await this.suiClient.getReferenceGasPrice();
|
|
1228
|
+
txb.setGasPrice(refGas);
|
|
1267
1229
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1230
|
+
const payload = await txb.build({ client: this.suiClient });
|
|
1231
|
+
const dryRunResult = await this.suiClient.dryRunTransactionBlock({ transactionBlock: payload });
|
|
1232
|
+
const success = dryRunResult.effects.status.status === "success";
|
|
1233
|
+
const errorMsg = dryRunResult.effects.status.error;
|
|
1234
|
+
const gasPrice = BigInt(txb.blockData.gasConfig.price);
|
|
1235
|
+
const { gasUsed } = dryRunResult.effects;
|
|
1236
|
+
return {
|
|
1237
|
+
success,
|
|
1238
|
+
errorMsg,
|
|
1239
|
+
gasPrice,
|
|
1240
|
+
gasUsed,
|
|
1241
|
+
dryRunResult
|
|
1242
|
+
};
|
|
1243
|
+
}
|
|
1244
|
+
async executePendingTx(pending) {
|
|
1245
|
+
let gotSigs;
|
|
1246
|
+
let payload;
|
|
1247
|
+
if (pending.votes.length >= this.info.threshold) {
|
|
1248
|
+
gotSigs = new Map(pending.votes.map((vote) => [vote.userAddress, vote.signature]));
|
|
1249
|
+
payload = pending.payload;
|
|
1250
|
+
} else if (pending.rejectVotes && pending.rejectPayload && pending.rejectVotes?.length >= this.info.threshold) {
|
|
1251
|
+
gotSigs = new Map(pending.rejectVotes.map((vote) => [vote.userAddress, vote.signature]));
|
|
1252
|
+
payload = pending.rejectPayload;
|
|
1253
|
+
} else {
|
|
1254
|
+
throw new Error("Not enough signatures");
|
|
1278
1255
|
}
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
}
|
|
1286
|
-
backend: DEV_DATABASE_CONFIG,
|
|
1287
|
-
apiURL: DEV_API_URL,
|
|
1288
|
-
syncingURL: DEV_SYNCING_URL
|
|
1256
|
+
const sigs = [];
|
|
1257
|
+
for (let i = 0; i < this.info.ownersWithWeightPK.length; i++) {
|
|
1258
|
+
const owner = this.info.ownersWithWeightPK[i];
|
|
1259
|
+
const signature = gotSigs.get(owner.publicKey.toSuiAddress());
|
|
1260
|
+
if (signature) {
|
|
1261
|
+
sigs.push(signature);
|
|
1262
|
+
}
|
|
1289
1263
|
}
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1264
|
+
const multiSignature = this.multisigManager.combinePartialSignatures(sigs);
|
|
1265
|
+
return this.suiClient.executeTransactionBlock({
|
|
1266
|
+
transactionBlock: HexToUint8Array(payload),
|
|
1267
|
+
signature: multiSignature,
|
|
1268
|
+
options: { showEffects: true }
|
|
1269
|
+
});
|
|
1296
1270
|
}
|
|
1297
|
-
|
|
1298
|
-
|
|
1271
|
+
get address() {
|
|
1272
|
+
return this.info.address;
|
|
1299
1273
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1274
|
+
get backend() {
|
|
1275
|
+
return this.globals.backend;
|
|
1302
1276
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1277
|
+
get wallet() {
|
|
1278
|
+
return this.globals.wallet;
|
|
1279
|
+
}
|
|
1280
|
+
async userAddress() {
|
|
1281
|
+
return this.globals.wallet.address();
|
|
1282
|
+
}
|
|
1283
|
+
get suiClient() {
|
|
1284
|
+
return this.globals.suiClient;
|
|
1285
|
+
}
|
|
1286
|
+
};
|
|
1306
1287
|
|
|
1307
|
-
// src/
|
|
1308
|
-
var
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
_wallet;
|
|
1313
|
-
constructor(input) {
|
|
1314
|
-
this.backend = input.backend;
|
|
1315
|
-
this.suiClient = input.suiClient;
|
|
1316
|
-
this.config = input.config;
|
|
1288
|
+
// src/core/PublicKeyHelper.ts
|
|
1289
|
+
var PublicKeyHelper = class {
|
|
1290
|
+
constructor(globals) {
|
|
1291
|
+
this.globals = globals;
|
|
1292
|
+
this.knownPublicKeys = /* @__PURE__ */ new Map();
|
|
1317
1293
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
const
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1294
|
+
knownPublicKeys;
|
|
1295
|
+
async getPublicKey(address) {
|
|
1296
|
+
const cached = this.knownPublicKeys.get(address);
|
|
1297
|
+
if (cached) {
|
|
1298
|
+
return cached;
|
|
1299
|
+
}
|
|
1300
|
+
const pk = await this._getPublicKey(address);
|
|
1301
|
+
if (pk) {
|
|
1302
|
+
this.knownPublicKeys.set(address, pk);
|
|
1303
|
+
}
|
|
1304
|
+
return pk;
|
|
1327
1305
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1306
|
+
async getPublicKeyBatch(addresses) {
|
|
1307
|
+
const results = new Array(addresses.length).fill(void 0);
|
|
1308
|
+
for (let i = 0; i < addresses.length; i++) {
|
|
1309
|
+
const address = addresses[i];
|
|
1310
|
+
results[i] = this.knownPublicKeys.get(address);
|
|
1311
|
+
}
|
|
1312
|
+
const emptyIndexes = results.map((elem, index) => elem === void 0 ? index : -1).filter((index) => index !== -1);
|
|
1313
|
+
const backendResult = await this.globals.backend.getPublicKeyBatch(emptyIndexes.map((index) => addresses[index]));
|
|
1314
|
+
for (let i = 0; i < emptyIndexes.length; i++) {
|
|
1315
|
+
const index = emptyIndexes[i];
|
|
1316
|
+
results[index] = backendResult[i];
|
|
1317
|
+
}
|
|
1318
|
+
for (let i = 0; i < results.length; i++) {
|
|
1319
|
+
if (results[i] === void 0) {
|
|
1320
|
+
results[i] = await this.getPublicKeyFromChain(addresses[i]);
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
for (let i = 0; i < addresses.length; i++) {
|
|
1324
|
+
if (results[i]) {
|
|
1325
|
+
this.knownPublicKeys.set(addresses[i], results[i]);
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
return results;
|
|
1330
1329
|
}
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1330
|
+
async _getPublicKey(address) {
|
|
1331
|
+
const pkBackend = await this.getPublicKeyFromBackend(address);
|
|
1332
|
+
if (pkBackend) {
|
|
1333
|
+
return pkBackend;
|
|
1334
1334
|
}
|
|
1335
|
-
|
|
1335
|
+
const pkChain = await this.getPublicKeyFromChain(address);
|
|
1336
|
+
if (pkChain) {
|
|
1337
|
+
return pkChain;
|
|
1338
|
+
}
|
|
1339
|
+
return void 0;
|
|
1336
1340
|
}
|
|
1337
|
-
|
|
1338
|
-
|
|
1341
|
+
async getPublicKeyFromBackend(address) {
|
|
1342
|
+
try {
|
|
1343
|
+
const pk = await this.globals.backend.getPublicKey(address);
|
|
1344
|
+
return pk;
|
|
1345
|
+
} catch (_) {
|
|
1346
|
+
return void 0;
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
async getPublicKeyFromChain(address) {
|
|
1350
|
+
return getPublicKeyFromChain(this.globals.suiClient, address);
|
|
1339
1351
|
}
|
|
1340
1352
|
};
|
|
1341
1353
|
|
|
@@ -1444,6 +1456,7 @@ export {
|
|
|
1444
1456
|
LOCAL_DATABASE_CONFIG,
|
|
1445
1457
|
LOCAL_SYNCING_URL,
|
|
1446
1458
|
MAINNET_RPC_URL,
|
|
1459
|
+
MSAFE_APPLICATION,
|
|
1447
1460
|
MSafeAccount,
|
|
1448
1461
|
MSafeClient,
|
|
1449
1462
|
MSafeEnv,
|