@msafe/sui3-sdk 0.0.21 → 0.0.23

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 CHANGED
@@ -52,6 +52,7 @@ __export(src_exports, {
52
52
  SignatureVerifier: () => SignatureVerifier,
53
53
  TESTNET_RPC_URL: () => TESTNET_RPC_URL,
54
54
  Uint8ArrayToHex: () => Uint8ArrayToHex,
55
+ addPrefix: () => addPrefix,
55
56
  getAllCoins: () => getAllCoins,
56
57
  getMSafeConfig: () => getMSafeConfig,
57
58
  getPublicKeyFromChain: () => getPublicKeyFromChain,
@@ -244,6 +245,12 @@ var Formatter = class {
244
245
  return Coin.isCoin(struct);
245
246
  }
246
247
  };
248
+ function addPrefix(s, prefix) {
249
+ if (s.startsWith(prefix)) {
250
+ return s;
251
+ }
252
+ return prefix + s;
253
+ }
247
254
 
248
255
  // src/utils/crypto.ts
249
256
  var SignatureVerifier = class _SignatureVerifier {
@@ -531,6 +538,7 @@ var MSafeAccount = class _MSafeAccount {
531
538
  };
532
539
  return getAllOwnedObjects(this.suiClient, this.address, filterCoinObjectOptions);
533
540
  }
541
+ // TODO: Calculate the votes
534
542
  async pendingTransaction() {
535
543
  const res = await this.backend.getPendingTransactions({ msafeAddress: this.address });
536
544
  if (!res.pending) {
@@ -548,12 +556,15 @@ var MSafeAccount = class _MSafeAccount {
548
556
  sequenceNumber: pendingTx.sequenceNumber,
549
557
  payload: pendingTx.payload,
550
558
  votes: pendingTx.votes,
559
+ approvalWeight: this.calculateWeightFromVotes(pendingTx.votes),
551
560
  msafeAddress: pendingTx.msafeAddress,
552
561
  rejectDigest: rejectPending?.digest ?? "",
553
562
  rejectPayload: rejectPending?.payload ?? "",
554
- rejectVotes: rejectPending?.votes ?? []
563
+ rejectVotes: rejectPending?.votes ?? [],
564
+ rejectWeight: this.calculateWeightFromVotes(rejectPending?.votes ?? [])
555
565
  };
556
566
  }
567
+ // TODO: Calculate the votes.
557
568
  async historyTransaction(pagination) {
558
569
  return this.backend.getHistoryTransactions({
559
570
  msafeAddress: this.address,
@@ -672,33 +683,41 @@ var MSafeAccount = class _MSafeAccount {
672
683
  dryRunResult
673
684
  };
674
685
  }
675
- async executePendingTx(pending) {
676
- let gotSigs;
677
- let payload;
678
- if (pending.votes.length >= this.info.threshold) {
679
- gotSigs = new Map(pending.votes.map((vote) => [vote.userAddress, vote.signature]));
680
- payload = pending.payload;
681
- } else if (pending.rejectVotes && pending.rejectPayload && pending.rejectVotes?.length >= this.info.threshold) {
682
- gotSigs = new Map(pending.rejectVotes.map((vote) => [vote.userAddress, vote.signature]));
683
- payload = pending.rejectPayload;
684
- } else {
685
- throw new Error("Not enough signatures");
686
+ async executePendingTx(pending, isRejectTx = false) {
687
+ const votes = isRejectTx ? pending.rejectVotes : pending.votes;
688
+ const payload = isRejectTx ? pending.rejectPayload : pending.payload;
689
+ if (this.calculateWeightFromVotes(votes) < this.info.threshold) {
690
+ throw new Error("Not enough signature");
686
691
  }
687
- const sigs = [];
692
+ const sortedSigs = [];
693
+ const gotSigs = new Map(votes.map((vote) => [vote.userAddress, vote.signature]));
688
694
  for (let i = 0; i < this.info.owners.length; i++) {
689
695
  const owner = this.info.owners[i];
690
696
  const signature = gotSigs.get(owner.address);
691
697
  if (signature) {
692
- sigs.push(signature);
698
+ sortedSigs.push(signature);
693
699
  }
694
700
  }
695
- const multiSignature = this.multiSig.combinePartialSignatures(sigs);
701
+ const multiSignature = this.multiSig.combinePartialSignatures(sortedSigs);
696
702
  return this.suiClient.executeTransactionBlock({
697
703
  transactionBlock: HexToUint8Array(payload),
698
704
  signature: multiSignature,
699
705
  options: { showEffects: true }
700
706
  });
701
707
  }
708
+ calculateWeightFromVotes(votes) {
709
+ return this.calculateWeight(votes.map((vote) => vote.userAddress));
710
+ }
711
+ calculateWeight(addressList) {
712
+ let gotWeight = 0;
713
+ for (let i = 0; i < addressList.length; i++) {
714
+ const found = this.info.owners.find((owner) => (0, import_sui3_utils4.isSameAddress)(owner.address, addressList[i]));
715
+ if (found) {
716
+ gotWeight += found.weight;
717
+ }
718
+ }
719
+ return gotWeight;
720
+ }
702
721
  get address() {
703
722
  return this.multiSig.address;
704
723
  }
@@ -797,16 +816,13 @@ var BackendImpl = class _BackendImpl {
797
816
  }
798
817
  _token;
799
818
  async authSign(input) {
800
- const res = await import_axios.default.post(`${this.apiURL}/auth/login`, input);
801
- if (res.status !== 200 && res.status !== 201) {
802
- throw new Error(`invalid authSign return: ${res}`);
803
- }
819
+ const res = await this.post(`/auth/login`, input);
804
820
  this._token = res.data.accessToken;
805
821
  return this._token;
806
822
  }
807
823
  async verifyToken(jwt) {
808
824
  try {
809
- const res = await import_axios.default.get(`${this.apiURL}/auth`, { headers: this.headers(jwt) });
825
+ const res = await this.get(`/auth`, { headers: this.headers(jwt) });
810
826
  return res.status === 200;
811
827
  } catch (_) {
812
828
  return false;
@@ -822,13 +838,10 @@ var BackendImpl = class _BackendImpl {
822
838
  const query = {
823
839
  userAddressList: addresses
824
840
  };
825
- const res = await import_axios.default.get(`${this.apiURL}/user/public-keys`, {
841
+ const res = await this.get(`/user/public-keys`, {
826
842
  params: query,
827
843
  headers: this.headers()
828
844
  });
829
- if (res.status !== 200 && res.status !== 201) {
830
- throw new Error(`invalid getPublicKeyBatch return: ${res}`);
831
- }
832
845
  return res.data?.map(
833
846
  (publicKeyWithSchema) => publicKeyWithSchema ? import_sui3_utils5.PublicKeySerde.de(publicKeyWithSchema) : void 0
834
847
  );
@@ -837,22 +850,16 @@ var BackendImpl = class _BackendImpl {
837
850
  const q = {
838
851
  msafeAddress
839
852
  };
840
- const res = await import_axios.default.get(`${this.apiURL}/msafe`, {
853
+ const res = await this.get(`/msafe`, {
841
854
  params: q,
842
855
  headers: this.headers()
843
856
  });
844
- if (res.status !== 200 && res.status !== 201) {
845
- throw new Error(`invalid getPublicKeyBatch return: ${res}`);
846
- }
847
857
  return _BackendImpl.toMSafeConfig(res.data);
848
858
  }
849
859
  async getUserInfo() {
850
- const userRes = await import_axios.default.get(`${this.apiURL}/user`, {
860
+ const userRes = await this.get(`/user`, {
851
861
  headers: this.headers()
852
862
  });
853
- if (userRes.status !== 200 && userRes.status !== 201) {
854
- throw new Error(`invalid getPublicKeyBatch return: ${userRes}`);
855
- }
856
863
  return userRes.data;
857
864
  }
858
865
  async getOwnedMSafeByStatus(input) {
@@ -863,13 +870,10 @@ var BackendImpl = class _BackendImpl {
863
870
  limit: input.pagination.limit.toString()
864
871
  } : {}
865
872
  };
866
- const res = await import_axios.default.get(`${this.apiURL}/msafe/owned`, {
873
+ const res = await this.get(`/msafe/owned`, {
867
874
  params: q,
868
875
  headers: this.headers()
869
876
  });
870
- if (res.status !== 200 && res.status !== 201) {
871
- throw new Error(`invalid getOwnedMSafeByStatus return: ${res}`);
872
- }
873
877
  return {
874
878
  data: res.data.data.map(_BackendImpl.toMSafeConfig),
875
879
  meta: res.data.meta
@@ -877,78 +881,54 @@ var BackendImpl = class _BackendImpl {
877
881
  }
878
882
  async updateMSafeStatus(input) {
879
883
  const p = input;
880
- const res = await import_axios.default.post(`${this.apiURL}/msafe/status`, p, { headers: this.headers() });
881
- if (res.status !== 200 && res.status !== 201) {
882
- throw new Error(`Invalid updateMSafeStatus return: ${res}`);
883
- }
884
+ await this.post(`/msafe/status`, p, { headers: this.headers() });
884
885
  }
885
886
  async getPendingTransactions(input) {
886
- const res = await import_axios.default.get(`${this.apiURL}/transaction/pending`, {
887
+ const res = await this.get(`/transaction/pending`, {
887
888
  params: input,
888
889
  headers: this.headers()
889
890
  });
890
- if (res.status !== 200 && res.status !== 201) {
891
- throw new Error(`invalid getPublicKeyBatch return: ${res}`);
892
- }
893
891
  return res.data;
894
892
  }
895
893
  async getHistoryTransactions(input) {
896
- const res = await import_axios.default.get(`${this.apiURL}/transaction/history`, {
894
+ const res = await this.get(`/transaction/history`, {
897
895
  params: input,
898
896
  headers: this.headers()
899
897
  });
900
- if (res.status !== 200 && res.status !== 201) {
901
- throw new Error(`invalid getCurrentSequenceNumber return: ${res}`);
902
- }
903
898
  return res.data;
904
899
  }
905
900
  async getFutureIntentions(input) {
906
- const res = await import_axios.default.get(`${this.apiURL}/transaction/intention`, {
901
+ const res = await this.get(`/transaction/intention`, {
907
902
  params: input,
908
903
  headers: this.headers()
909
904
  });
910
- if (res.status !== 200 && res.status !== 201) {
911
- throw new Error(`invalid getCurrentSequenceNumber return: ${res}`);
912
- }
913
905
  return res.data;
914
906
  }
915
907
  async getCurrentSequenceNumber(address) {
916
- const res = await import_axios.default.get(`${this.apiURL}/transaction/sn/current`, {
908
+ const res = await this.get(`/transaction/sn/current`, {
917
909
  params: {
918
910
  msafeAddress: address
919
911
  },
920
912
  headers: this.headers()
921
913
  });
922
- if (res.status !== 200 && res.status !== 201) {
923
- throw new Error(`invalid getCurrentSequenceNumber return: ${res}`);
924
- }
925
914
  return res.data;
926
915
  }
927
916
  async getNextSequenceNumber(address) {
928
- const res = await import_axios.default.get(`${this.apiURL}/transaction/sn/next`, {
917
+ const res = await this.get(`/transaction/sn/next`, {
929
918
  params: {
930
919
  msafeAddress: address
931
920
  },
932
921
  headers: this.headers()
933
922
  });
934
- if (res.status !== 200 && res.status !== 201) {
935
- throw new Error(`invalid getNextSequenceNumber return: ${res}`);
936
- }
937
923
  return res.data;
938
924
  }
939
925
  async createMSafeAccount(input) {
940
- const res = await import_axios.default.post(`${this.apiURL}/msafe/create`, input, {
926
+ await this.post(`/msafe/create`, input, {
941
927
  headers: this.headers()
942
928
  });
943
- if (res.status !== 200 && res.status !== 201) {
944
- throw new Error(`invalid createMSafeAccount return: ${res}`);
945
- }
946
929
  }
947
930
  async proposeIntention(input) {
948
- const res = await import_axios.default.post(`${this.apiURL}/transaction/intention`, input, { headers: this.headers() });
949
- if (res.status !== 200 && res.status !== 201) {
950
- throw new Error(`invalid proposeIntention return: ${res}`);
951
- }
931
+ await this.post(`/transaction/intention`, input, { headers: this.headers() });
952
932
  }
953
933
  // TODO later
954
934
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -956,52 +936,30 @@ var BackendImpl = class _BackendImpl {
956
936
  return void 0;
957
937
  }
958
938
  async rejectCurrentTx(input) {
959
- const res = await import_axios.default.post(`${this.apiURL}/transaction/pending/reject`, input, {
939
+ await this.post(`/transaction/pending/reject`, input, {
960
940
  headers: this.headers()
961
941
  });
962
- if (res.status !== 200 && res.status !== 201) {
963
- throw new Error(`invalid voteForTransaction return: ${res}`);
964
- }
965
942
  }
966
943
  async voteForTransaction(input) {
967
- const res = await import_axios.default.post(`${this.apiURL}/transaction/pending/vote`, input, {
944
+ await this.post(`/transaction/pending/vote`, input, {
968
945
  headers: this.headers()
969
946
  });
970
- if (res.status !== 200 && res.status !== 201) {
971
- throw new Error(`invalid voteForTransaction return: ${res}`);
972
- }
973
947
  }
974
948
  async buildNextIntentionAndAddToPending(input) {
975
- const res = await import_axios.default.post(`${this.apiURL}/transaction/pending/build`, input, { headers: this.headers() });
976
- if (res.status !== 200 && res.status !== 201) {
977
- throw new Error(`invalid buildNextIntentionAndAddToPending return: ${res}`);
978
- }
949
+ await this.post(`/transaction/pending/build`, input, { headers: this.headers() });
979
950
  }
980
951
  async skipNextFailedIntention(input) {
981
- const res = await import_axios.default.post(`${this.apiURL}/transaction/pending/skip`, input, { headers: this.headers() });
982
- if (res.status !== 200 && res.status !== 201) {
983
- throw new Error(`invalid skipNextFailedIntention return: ${res}`);
984
- }
952
+ await this.post(`/transaction/pending/skip`, input, { headers: this.headers() });
985
953
  }
986
954
  async getAddressBookEntries(pagination) {
987
- const res = await import_axios.default.get(`${this.apiURL}/address-book`, {
955
+ const res = await this.get(`/address-book`, {
988
956
  headers: this.headers(),
989
957
  params: pagination
990
958
  });
991
- if (res.status !== 200) {
992
- throw new Error(`Invalid address-book return: ${res}`);
993
- }
994
959
  return res.data;
995
960
  }
996
961
  async updateAddressBook(input) {
997
- const res = await import_axios.default.post(`${this.apiURL}/address-book`, input, { headers: this.headers() });
998
- if (res.status !== 200 && res.status !== 201) {
999
- throw new Error(`invalid updateAddressBook return: ${res}`);
1000
- }
1001
- }
1002
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1003
- async processExecutedTransaction(_digest) {
1004
- return void 0;
962
+ await this.post(`/address-book`, input, { headers: this.headers() });
1005
963
  }
1006
964
  headers(token) {
1007
965
  return { Authorization: `Bearer ${token || this._token}` };
@@ -1019,6 +977,57 @@ var BackendImpl = class _BackendImpl {
1019
977
  }))
1020
978
  };
1021
979
  }
980
+ async get(url, config) {
981
+ const fullUrl = this.getFullUrl(url);
982
+ try {
983
+ return await import_axios.default.get(fullUrl, config);
984
+ } catch (e) {
985
+ throw BackendError.fromError(e) ?? e;
986
+ }
987
+ }
988
+ async post(url, data, config) {
989
+ const fullUrl = this.getFullUrl(url);
990
+ try {
991
+ return await import_axios.default.post(fullUrl, data, config);
992
+ } catch (e) {
993
+ throw BackendError.fromError(e) ?? e;
994
+ }
995
+ }
996
+ getFullUrl(url) {
997
+ return url.startsWith(this.apiURL) ? url : `${this.apiURL}${addPrefix(url, "/")}`;
998
+ }
999
+ };
1000
+ var BackendError = class _BackendError extends Error {
1001
+ constructor(e) {
1002
+ super();
1003
+ this.e = e;
1004
+ Error.captureStackTrace(this, this.constructor);
1005
+ }
1006
+ name;
1007
+ static fromError(e) {
1008
+ if (import_axios.default.isAxiosError(e) && e?.response?.data && "message" in e.response.data) {
1009
+ return new _BackendError(e);
1010
+ }
1011
+ return void 0;
1012
+ }
1013
+ get status() {
1014
+ return this.e.response?.status ?? void 0;
1015
+ }
1016
+ get message() {
1017
+ return `Request to ${this.endpoint} failed: ${this.status} ${this.respMessage() ?? "Unknown resp"}`;
1018
+ }
1019
+ respMessage() {
1020
+ if (!this.e.response?.data) {
1021
+ return void 0;
1022
+ }
1023
+ return (this.e.response?.data).message ?? void 0;
1024
+ }
1025
+ get endpoint() {
1026
+ return this.e.config?.url ?? "";
1027
+ }
1028
+ toString() {
1029
+ return this.message;
1030
+ }
1022
1031
  };
1023
1032
 
1024
1033
  // src/globals/const.ts
@@ -1234,6 +1243,7 @@ var MSafeClient = class _MSafeClient {
1234
1243
  SignatureVerifier,
1235
1244
  TESTNET_RPC_URL,
1236
1245
  Uint8ArrayToHex,
1246
+ addPrefix,
1237
1247
  getAllCoins,
1238
1248
  getMSafeConfig,
1239
1249
  getPublicKeyFromChain,