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