@dynamic-labs-wallet/browser 0.0.84 → 0.0.86
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/index.cjs.js +662 -467
- package/index.esm.js +656 -469
- package/package.json +2 -2
- package/src/client.d.ts.map +1 -1
- package/src/errorConstants.d.ts +9 -0
- package/src/errorConstants.d.ts.map +1 -0
- package/src/index.d.ts +1 -0
- package/src/index.d.ts.map +1 -1
package/index.cjs.js
CHANGED
|
@@ -520,6 +520,7 @@ class DynamicWalletClient {
|
|
|
520
520
|
onError,
|
|
521
521
|
onCeremonyComplete
|
|
522
522
|
});
|
|
523
|
+
this.logger.debug(`[DynamicWaasWalletClient] Initialized client key generation with IDs: ${clientKeygenIds.join(', ')} for chain: ${chainName} using scheme: ${thresholdSignatureScheme}`);
|
|
523
524
|
return data;
|
|
524
525
|
}
|
|
525
526
|
async clientInitializeKeyGen({ chainName, thresholdSignatureScheme }) {
|
|
@@ -591,12 +592,23 @@ class DynamicWalletClient {
|
|
|
591
592
|
thresholdSignatureScheme
|
|
592
593
|
});
|
|
593
594
|
const clientKeygenIds = clientKeygenInitResults.map((result)=>result.keygenId);
|
|
595
|
+
this.logger.debug('[DynamicWaasWalletClient] Initialized client key generation', {
|
|
596
|
+
clientKeygenIds: clientKeygenIds.join(', '),
|
|
597
|
+
chainName,
|
|
598
|
+
thresholdSignatureScheme
|
|
599
|
+
});
|
|
594
600
|
const { roomId, serverKeygenIds } = await this.serverInitializeKeyGen({
|
|
595
601
|
chainName,
|
|
596
602
|
clientKeygenIds,
|
|
597
603
|
thresholdSignatureScheme,
|
|
598
604
|
onCeremonyComplete
|
|
599
605
|
});
|
|
606
|
+
this.logger.debug('[DynamicWaasWalletClient] Server key generation initialized', {
|
|
607
|
+
roomId,
|
|
608
|
+
clientKeygenIds: clientKeygenIds.join(', '),
|
|
609
|
+
serverKeygenIds: serverKeygenIds.join(', '),
|
|
610
|
+
chainName
|
|
611
|
+
});
|
|
600
612
|
const { rawPublicKey, clientKeygenResults: clientKeyShares } = await this.clientKeyGen({
|
|
601
613
|
chainName,
|
|
602
614
|
roomId,
|
|
@@ -604,60 +616,99 @@ class DynamicWalletClient {
|
|
|
604
616
|
clientKeygenInitResults,
|
|
605
617
|
thresholdSignatureScheme
|
|
606
618
|
});
|
|
619
|
+
this.logger.debug('[DynamicWaasWalletClient] Client key generation completed', {
|
|
620
|
+
roomId,
|
|
621
|
+
serverKeygenIds: serverKeygenIds.join(', '),
|
|
622
|
+
clientKeygenIds: clientKeygenIds.join(', '),
|
|
623
|
+
chainName,
|
|
624
|
+
thresholdSignatureScheme,
|
|
625
|
+
rawPublicKey,
|
|
626
|
+
clientKeySharesCount: clientKeyShares.length
|
|
627
|
+
});
|
|
607
628
|
return {
|
|
608
629
|
rawPublicKey,
|
|
609
630
|
clientKeyShares
|
|
610
631
|
};
|
|
611
632
|
} catch (error) {
|
|
612
|
-
this.logger.error('Error keygen', error);
|
|
633
|
+
this.logger.error('[DynamicWaasWalletClient]: Error keygen', error);
|
|
634
|
+
if (error instanceof core.AxiosError) {
|
|
635
|
+
core.handleAxiosError(error);
|
|
636
|
+
}
|
|
613
637
|
throw error;
|
|
614
638
|
}
|
|
615
639
|
}
|
|
616
640
|
async importRawPrivateKey({ chainName, privateKey, thresholdSignatureScheme, onError, onCeremonyComplete }) {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
641
|
+
try {
|
|
642
|
+
const mpcSigner = getMPCSigner({
|
|
643
|
+
chainName,
|
|
644
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
645
|
+
});
|
|
646
|
+
const clientKeygenInitResults = await this.clientInitializeKeyGen({
|
|
647
|
+
chainName,
|
|
648
|
+
thresholdSignatureScheme
|
|
649
|
+
});
|
|
650
|
+
const clientKeygenIds = clientKeygenInitResults.map((result)=>result.keygenId);
|
|
651
|
+
this.logger.debug('[DynamicWaasWalletClient] Client key generation initialized', {
|
|
652
|
+
clientKeygenIds: clientKeygenIds.join(', '),
|
|
653
|
+
chainName,
|
|
654
|
+
thresholdSignatureScheme
|
|
655
|
+
});
|
|
656
|
+
const { roomId, serverKeygenIds } = await this.apiClient.importPrivateKey({
|
|
657
|
+
chainName,
|
|
658
|
+
clientKeygenIds,
|
|
659
|
+
thresholdSignatureScheme,
|
|
660
|
+
onError,
|
|
661
|
+
onCeremonyComplete
|
|
662
|
+
});
|
|
663
|
+
this.logger.debug('[DynamicWaasWalletClient] Server key generation initialized', {
|
|
664
|
+
roomId,
|
|
665
|
+
clientKeygenIds: clientKeygenIds.join(', '),
|
|
666
|
+
serverKeygenIds: serverKeygenIds.join(', '),
|
|
667
|
+
chainName
|
|
668
|
+
});
|
|
669
|
+
const { threshold } = core.getTSSConfig(thresholdSignatureScheme);
|
|
670
|
+
const clientKeygenResults = await Promise.all(clientKeygenInitResults.map(async (currentInit, index)=>{
|
|
671
|
+
const otherClientKeygenIds = clientKeygenInitResults.filter((init)=>init.keygenId !== currentInit.keygenId).map((init)=>init.keygenId);
|
|
672
|
+
if (index === 0) {
|
|
673
|
+
const otherKeyGenIds = [
|
|
674
|
+
...serverKeygenIds,
|
|
675
|
+
...otherClientKeygenIds
|
|
676
|
+
];
|
|
677
|
+
const importerKeygenResult = await mpcSigner.importPrivateKeyImporter(roomId, threshold, privateKey, currentInit, otherKeyGenIds);
|
|
678
|
+
return importerKeygenResult;
|
|
679
|
+
} else {
|
|
680
|
+
const recipientKeygenResult = await mpcSigner.importPrivateKeyRecipient(roomId, threshold, currentInit, [
|
|
681
|
+
...serverKeygenIds,
|
|
682
|
+
...otherClientKeygenIds
|
|
683
|
+
]);
|
|
684
|
+
return recipientKeygenResult;
|
|
685
|
+
}
|
|
686
|
+
}));
|
|
687
|
+
const [clientKeygenResult] = clientKeygenResults;
|
|
688
|
+
const rawPublicKey = await this.derivePublicKey({
|
|
689
|
+
chainName,
|
|
690
|
+
keyShare: clientKeygenResult,
|
|
691
|
+
derivationPath: undefined
|
|
692
|
+
});
|
|
693
|
+
this.logger.debug('[DynamicWaasWalletClient] Completed import of raw private key', {
|
|
694
|
+
rawPublicKey,
|
|
695
|
+
chainName,
|
|
696
|
+
thresholdSignatureScheme,
|
|
697
|
+
roomId,
|
|
698
|
+
serverKeygenIds: serverKeygenIds.join(', '),
|
|
699
|
+
clientKeygenIds: clientKeygenIds.join(', ')
|
|
700
|
+
});
|
|
701
|
+
return {
|
|
702
|
+
rawPublicKey,
|
|
703
|
+
clientKeyShares: clientKeygenResults
|
|
704
|
+
};
|
|
705
|
+
} catch (error) {
|
|
706
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in importRawPrivateKey', error);
|
|
707
|
+
if (error instanceof core.AxiosError) {
|
|
708
|
+
core.handleAxiosError(error);
|
|
649
709
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
const rawPublicKey = await this.derivePublicKey({
|
|
653
|
-
chainName,
|
|
654
|
-
keyShare: clientKeygenResult,
|
|
655
|
-
derivationPath: undefined
|
|
656
|
-
});
|
|
657
|
-
return {
|
|
658
|
-
rawPublicKey,
|
|
659
|
-
clientKeyShares: clientKeygenResults
|
|
660
|
-
};
|
|
710
|
+
throw error;
|
|
711
|
+
}
|
|
661
712
|
}
|
|
662
713
|
async serverSign({ walletId, message, isFormatted }) {
|
|
663
714
|
// Create the room and sign the message
|
|
@@ -678,87 +729,123 @@ class DynamicWalletClient {
|
|
|
678
729
|
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
679
730
|
});
|
|
680
731
|
const formattedMessage = isFormatted ? new web.MessageHash(message) : formatMessage(chainName, message);
|
|
732
|
+
this.logger.debug('[DynamicWaasWalletClient] Starting client sign', {
|
|
733
|
+
chainName,
|
|
734
|
+
message,
|
|
735
|
+
roomId,
|
|
736
|
+
derivationPath,
|
|
737
|
+
isFormatted
|
|
738
|
+
});
|
|
681
739
|
const signature = await mpcSigner.sign(roomId, keyShare, formattedMessage, derivationPath);
|
|
682
740
|
return signature;
|
|
683
741
|
} catch (error) {
|
|
684
|
-
this.logger.error('Error in clientSign
|
|
742
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in clientSign', error);
|
|
685
743
|
throw error;
|
|
686
744
|
}
|
|
687
745
|
}
|
|
688
746
|
//todo: need to modify with imported flag
|
|
689
747
|
async sign({ accountAddress, message, chainName, password = undefined, isFormatted = false, signedSessionId }) {
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
748
|
+
try {
|
|
749
|
+
await this.verifyPassword({
|
|
750
|
+
accountAddress,
|
|
751
|
+
password,
|
|
752
|
+
walletOperation: core.WalletOperation.SIGN_MESSAGE,
|
|
753
|
+
signedSessionId
|
|
754
|
+
});
|
|
755
|
+
const wallet = await this.getWallet({
|
|
756
|
+
accountAddress,
|
|
757
|
+
password,
|
|
758
|
+
walletOperation: core.WalletOperation.SIGN_MESSAGE,
|
|
759
|
+
signedSessionId
|
|
760
|
+
});
|
|
761
|
+
// Perform the server sign
|
|
762
|
+
const data = await this.serverSign({
|
|
763
|
+
walletId: wallet.walletId,
|
|
764
|
+
message,
|
|
765
|
+
isFormatted
|
|
766
|
+
});
|
|
767
|
+
this.logger.debug('[DynamicWaasWalletClient] Server sign completed', {
|
|
768
|
+
message,
|
|
769
|
+
accountAddress,
|
|
770
|
+
walletId: wallet.walletId,
|
|
771
|
+
roomId: data.roomId
|
|
772
|
+
});
|
|
773
|
+
const derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
|
|
774
|
+
// Perform the client sign and return the signature
|
|
775
|
+
const clientKeyShares = await this.getClientKeySharesFromLocalStorage({
|
|
776
|
+
accountAddress
|
|
777
|
+
});
|
|
778
|
+
const signature = await this.clientSign({
|
|
779
|
+
chainName,
|
|
780
|
+
message,
|
|
781
|
+
roomId: data.roomId,
|
|
782
|
+
keyShare: clientKeyShares[0],
|
|
783
|
+
derivationPath,
|
|
784
|
+
isFormatted
|
|
785
|
+
});
|
|
786
|
+
this.logger.debug('[DynamicWaasWalletClient] Client sign completed', {
|
|
787
|
+
chainName,
|
|
788
|
+
message,
|
|
789
|
+
roomId: data.roomId,
|
|
790
|
+
derivationPath,
|
|
791
|
+
isFormatted
|
|
792
|
+
});
|
|
793
|
+
return signature;
|
|
794
|
+
} catch (error) {
|
|
795
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in sign', error);
|
|
796
|
+
if (error instanceof core.AxiosError) {
|
|
797
|
+
core.handleAxiosError(error);
|
|
798
|
+
}
|
|
799
|
+
throw error;
|
|
800
|
+
}
|
|
722
801
|
}
|
|
723
802
|
async refreshWalletAccountShares({ accountAddress, chainName, password = undefined, signedSessionId }) {
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
803
|
+
try {
|
|
804
|
+
await this.verifyPassword({
|
|
805
|
+
accountAddress,
|
|
806
|
+
password,
|
|
807
|
+
walletOperation: core.WalletOperation.REFRESH,
|
|
808
|
+
signedSessionId
|
|
809
|
+
});
|
|
810
|
+
const wallet = await this.getWallet({
|
|
811
|
+
accountAddress,
|
|
812
|
+
walletOperation: core.WalletOperation.NO_OPERATION,
|
|
813
|
+
password,
|
|
814
|
+
signedSessionId
|
|
815
|
+
});
|
|
816
|
+
const mpcSigner = getMPCSigner({
|
|
817
|
+
chainName,
|
|
818
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
819
|
+
});
|
|
820
|
+
// Create the room and refresh the shares
|
|
821
|
+
const data = await this.apiClient.refreshWalletAccountShares({
|
|
822
|
+
walletId: wallet.walletId
|
|
823
|
+
});
|
|
824
|
+
const roomId = data.roomId;
|
|
825
|
+
const clientKeyShares = await this.getClientKeySharesFromLocalStorage({
|
|
826
|
+
accountAddress
|
|
827
|
+
});
|
|
828
|
+
const refreshResults = await Promise.all(clientKeyShares.map((clientKeyShare)=>mpcSigner.refresh(roomId, clientKeyShare)));
|
|
829
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
830
|
+
clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
|
|
831
|
+
});
|
|
832
|
+
await this.setClientKeySharesToLocalStorage({
|
|
833
|
+
accountAddress,
|
|
834
|
+
clientKeyShares: refreshResults,
|
|
835
|
+
overwriteOrMerge: 'overwrite'
|
|
836
|
+
});
|
|
837
|
+
await this.storeEncryptedBackupByWallet({
|
|
838
|
+
accountAddress,
|
|
839
|
+
password: password != null ? password : this.environmentId,
|
|
840
|
+
signedSessionId
|
|
841
|
+
});
|
|
842
|
+
} catch (error) {
|
|
843
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in refreshWalletAccountShares', error);
|
|
844
|
+
if (error instanceof core.AxiosError) {
|
|
845
|
+
core.handleAxiosError(error);
|
|
846
|
+
}
|
|
847
|
+
throw error;
|
|
848
|
+
}
|
|
762
849
|
}
|
|
763
850
|
async getExportId({ chainName, clientKeyShare }) {
|
|
764
851
|
const mpcSigner = getMPCSigner({
|
|
@@ -812,107 +899,137 @@ class DynamicWalletClient {
|
|
|
812
899
|
};
|
|
813
900
|
}
|
|
814
901
|
async reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined, signedSessionId }) {
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
902
|
+
try {
|
|
903
|
+
await this.verifyPassword({
|
|
904
|
+
accountAddress,
|
|
905
|
+
password,
|
|
906
|
+
walletOperation: core.WalletOperation.RESHARE,
|
|
907
|
+
signedSessionId
|
|
908
|
+
});
|
|
909
|
+
const { existingClientShareCount } = core.getReshareConfig({
|
|
910
|
+
oldThresholdSignatureScheme,
|
|
911
|
+
newThresholdSignatureScheme
|
|
912
|
+
});
|
|
913
|
+
const wallet = await this.getWallet({
|
|
914
|
+
accountAddress,
|
|
915
|
+
walletOperation: core.WalletOperation.NO_OPERATION,
|
|
916
|
+
shareCount: existingClientShareCount,
|
|
917
|
+
password,
|
|
918
|
+
signedSessionId
|
|
919
|
+
});
|
|
920
|
+
const { newClientInitKeygenResults, newClientKeygenIds, existingClientKeygenIds, existingClientKeyShares } = await this.reshareStrategy({
|
|
921
|
+
chainName,
|
|
922
|
+
accountAddress,
|
|
923
|
+
wallet,
|
|
924
|
+
oldThresholdSignatureScheme,
|
|
925
|
+
newThresholdSignatureScheme
|
|
926
|
+
});
|
|
927
|
+
const clientKeygenIds = [
|
|
928
|
+
...newClientKeygenIds,
|
|
929
|
+
...existingClientKeygenIds
|
|
930
|
+
];
|
|
931
|
+
// Server to create the room and complete the server reshare logics
|
|
932
|
+
const data = await this.apiClient.reshare({
|
|
933
|
+
walletId: wallet.walletId,
|
|
934
|
+
clientKeygenIds: clientKeygenIds,
|
|
935
|
+
oldThresholdSignatureScheme,
|
|
936
|
+
newThresholdSignatureScheme
|
|
937
|
+
});
|
|
938
|
+
const { roomId, serverKeygenIds, newServerKeygenIds = [] } = data;
|
|
939
|
+
// Get the MPC config for the threshold signature scheme
|
|
940
|
+
const oldMpcConfig = core.MPC_CONFIG[oldThresholdSignatureScheme];
|
|
941
|
+
const newMpcConfig = core.MPC_CONFIG[newThresholdSignatureScheme];
|
|
942
|
+
const allPartyKeygenIds = [
|
|
943
|
+
...clientKeygenIds,
|
|
944
|
+
...serverKeygenIds,
|
|
945
|
+
...newServerKeygenIds
|
|
946
|
+
];
|
|
947
|
+
const mpcSigner = getMPCSigner({
|
|
948
|
+
chainName,
|
|
949
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
950
|
+
});
|
|
951
|
+
const reshareResults = await Promise.all([
|
|
952
|
+
...newClientInitKeygenResults.map((keygenResult)=>mpcSigner.reshareNewParty(roomId, oldMpcConfig.threshold, newMpcConfig.threshold, keygenResult, allPartyKeygenIds)),
|
|
953
|
+
...existingClientKeyShares.map((keyShare)=>mpcSigner.reshareRemainingParty(roomId, newMpcConfig.threshold, keyShare, allPartyKeygenIds))
|
|
954
|
+
]);
|
|
955
|
+
await this.setClientKeySharesToLocalStorage({
|
|
956
|
+
accountAddress,
|
|
957
|
+
clientKeyShares: reshareResults,
|
|
958
|
+
overwriteOrMerge: 'overwrite'
|
|
959
|
+
});
|
|
960
|
+
await this.storeEncryptedBackupByWallet({
|
|
961
|
+
accountAddress,
|
|
962
|
+
password,
|
|
963
|
+
signedSessionId
|
|
964
|
+
});
|
|
965
|
+
} catch (error) {
|
|
966
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in reshare', error);
|
|
967
|
+
if (error instanceof core.AxiosError) {
|
|
968
|
+
core.handleAxiosError(error);
|
|
969
|
+
}
|
|
970
|
+
throw error;
|
|
971
|
+
}
|
|
877
972
|
}
|
|
878
973
|
async exportKey({ accountAddress, chainName, password = undefined, signedSessionId }) {
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
974
|
+
try {
|
|
975
|
+
const wallet = await this.getWallet({
|
|
976
|
+
accountAddress,
|
|
977
|
+
password,
|
|
978
|
+
walletOperation: core.WalletOperation.EXPORT_PRIVATE_KEY,
|
|
979
|
+
signedSessionId
|
|
980
|
+
});
|
|
981
|
+
const mpcSigner = getMPCSigner({
|
|
982
|
+
chainName,
|
|
983
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
984
|
+
});
|
|
985
|
+
const clientKeyShares = await this.getClientKeySharesFromLocalStorage({
|
|
986
|
+
accountAddress
|
|
987
|
+
});
|
|
988
|
+
const exportId = await this.getExportId({
|
|
989
|
+
chainName,
|
|
990
|
+
clientKeyShare: clientKeyShares[0]
|
|
991
|
+
});
|
|
992
|
+
const data = await this.apiClient.exportKey({
|
|
993
|
+
walletId: wallet.walletId,
|
|
994
|
+
exportId
|
|
995
|
+
});
|
|
996
|
+
this.logger.debug('[DynamicWaasWalletClient] Starting export of private key', {
|
|
997
|
+
accountAddress,
|
|
998
|
+
chainName,
|
|
999
|
+
walletId: wallet.walletId,
|
|
1000
|
+
exportId,
|
|
1001
|
+
roomId: data.roomId
|
|
1002
|
+
});
|
|
1003
|
+
const keyExportRaw = await mpcSigner.exportFullPrivateKey(data.roomId, clientKeyShares[0], exportId);
|
|
1004
|
+
if (!keyExportRaw) {
|
|
1005
|
+
throw new Error('Error exporting private key');
|
|
1006
|
+
}
|
|
1007
|
+
this.logger.debug('[DynamicWaasWalletClient] Completed export of private key', {
|
|
1008
|
+
accountAddress,
|
|
1009
|
+
chainName,
|
|
1010
|
+
walletId: wallet.walletId,
|
|
1011
|
+
exportId,
|
|
1012
|
+
roomId: data.roomId
|
|
1013
|
+
});
|
|
1014
|
+
const derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
|
|
1015
|
+
let derivedPrivateKey;
|
|
1016
|
+
if (mpcSigner instanceof web.Ecdsa) {
|
|
1017
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
1018
|
+
} else if (mpcSigner instanceof web.ExportableEd25519) {
|
|
1019
|
+
derivedPrivateKey = keyExportRaw;
|
|
1020
|
+
} else if (mpcSigner instanceof web.BIP340) {
|
|
1021
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
1022
|
+
}
|
|
1023
|
+
return {
|
|
1024
|
+
derivedPrivateKey
|
|
1025
|
+
};
|
|
1026
|
+
} catch (error) {
|
|
1027
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in exportKey', error);
|
|
1028
|
+
if (error instanceof core.AxiosError) {
|
|
1029
|
+
core.handleAxiosError(error);
|
|
1030
|
+
}
|
|
1031
|
+
throw error;
|
|
912
1032
|
}
|
|
913
|
-
return {
|
|
914
|
-
derivedPrivateKey
|
|
915
|
-
};
|
|
916
1033
|
}
|
|
917
1034
|
async offlineExportKey({ chainName, keyShares, derivationPath }) {
|
|
918
1035
|
try {
|
|
@@ -950,7 +1067,7 @@ class DynamicWalletClient {
|
|
|
950
1067
|
rawPublicKey
|
|
951
1068
|
};
|
|
952
1069
|
} catch (error) {
|
|
953
|
-
this.logger.error('Error in offlineExportKey
|
|
1070
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in offlineExportKey', error);
|
|
954
1071
|
throw error;
|
|
955
1072
|
}
|
|
956
1073
|
}
|
|
@@ -1015,47 +1132,55 @@ class DynamicWalletClient {
|
|
|
1015
1132
|
* @param {string} params.accountAddress - The account address of the wallet to backup
|
|
1016
1133
|
* @param {string} [params.password] - Optional password for encrypting the key shares
|
|
1017
1134
|
*/ async storeEncryptedBackupByWallet({ accountAddress, clientKeyShares = undefined, password = undefined, signedSessionId }) {
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
});
|
|
1035
|
-
const hasGoogleDriveBackup = this.walletMap[accountAddress].clientKeySharesBackupInfo.backups[core.BackupLocation.GOOGLE_DRIVE].length > 0;
|
|
1036
|
-
if (hasGoogleDriveBackup) {
|
|
1037
|
-
const googleDriveKeyShareIds = await this.backupKeySharesToGoogleDrive({
|
|
1038
|
-
accountAddress,
|
|
1039
|
-
password,
|
|
1135
|
+
try {
|
|
1136
|
+
const keySharesToBackup = clientKeyShares != null ? clientKeyShares : await this.getClientKeySharesFromLocalStorage({
|
|
1137
|
+
accountAddress
|
|
1138
|
+
});
|
|
1139
|
+
const encryptedKeyShares = await Promise.all(keySharesToBackup.map((keyShare)=>this.encryptKeyShare({
|
|
1140
|
+
keyShare,
|
|
1141
|
+
password
|
|
1142
|
+
})));
|
|
1143
|
+
if (!this.walletMap[accountAddress].walletId) {
|
|
1144
|
+
throw new Error(`WalletId not found for accountAddress: ${accountAddress}`);
|
|
1145
|
+
}
|
|
1146
|
+
// TODO(zfaizal2): throw error if signedSessionId is not provided after service deploy
|
|
1147
|
+
const data = await this.apiClient.storeEncryptedBackupByWallet({
|
|
1148
|
+
walletId: this.walletMap[accountAddress].walletId,
|
|
1149
|
+
encryptedKeyShares,
|
|
1150
|
+
passwordEncrypted: Boolean(password) && password !== this.environmentId,
|
|
1040
1151
|
signedSessionId
|
|
1041
1152
|
});
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1153
|
+
const hasGoogleDriveBackup = this.walletMap[accountAddress].clientKeySharesBackupInfo.backups[core.BackupLocation.GOOGLE_DRIVE].length > 0;
|
|
1154
|
+
if (hasGoogleDriveBackup) {
|
|
1155
|
+
const googleDriveKeyShareIds = await this.backupKeySharesToGoogleDrive({
|
|
1156
|
+
accountAddress,
|
|
1157
|
+
password,
|
|
1158
|
+
signedSessionId
|
|
1159
|
+
});
|
|
1160
|
+
data.keyShares.push({
|
|
1161
|
+
backupLocation: core.BackupLocation.GOOGLE_DRIVE,
|
|
1162
|
+
id: googleDriveKeyShareIds
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
const updatedBackupInfo = getClientKeyShareBackupInfo({
|
|
1166
|
+
walletProperties: {
|
|
1167
|
+
derivationPath: this.walletMap[accountAddress].derivationPath,
|
|
1168
|
+
keyShares: data.keyShares,
|
|
1169
|
+
thresholdSignatureScheme: this.walletMap[accountAddress].thresholdSignatureScheme
|
|
1170
|
+
}
|
|
1045
1171
|
});
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1172
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
1173
|
+
clientKeySharesBackupInfo: updatedBackupInfo
|
|
1174
|
+
});
|
|
1175
|
+
await this.storage.setItem(this.storageKey, JSON.stringify(this.walletMap));
|
|
1176
|
+
return data;
|
|
1177
|
+
} catch (error) {
|
|
1178
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in storeEncryptedBackupByWallet', error);
|
|
1179
|
+
if (error instanceof core.AxiosError) {
|
|
1180
|
+
core.handleAxiosError(error);
|
|
1052
1181
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
clientKeySharesBackupInfo: updatedBackupInfo
|
|
1056
|
-
});
|
|
1057
|
-
await this.storage.setItem(this.storageKey, JSON.stringify(this.walletMap));
|
|
1058
|
-
return data;
|
|
1182
|
+
throw error;
|
|
1183
|
+
}
|
|
1059
1184
|
}
|
|
1060
1185
|
async storeEncryptedBackupByWalletWithRetry({ accountAddress, clientKeyShares, password, signedSessionId }) {
|
|
1061
1186
|
await retryPromise(()=>this.storeEncryptedBackupByWallet({
|
|
@@ -1102,16 +1227,24 @@ class DynamicWalletClient {
|
|
|
1102
1227
|
* @returns The Google OAuth Account ID
|
|
1103
1228
|
* @throws Error if no Google OAuth account ID is found
|
|
1104
1229
|
*/ async getGoogleOauthAccountIdOrThrow(accountAddress) {
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1230
|
+
try {
|
|
1231
|
+
const user = await this.apiClient.getUser();
|
|
1232
|
+
const oauthAccountId = getGoogleOAuthAccountId(user == null ? void 0 : user.verifiedCredentials);
|
|
1233
|
+
if (!oauthAccountId) {
|
|
1234
|
+
this.logger.error('No Google OAuth account ID found', {
|
|
1235
|
+
user,
|
|
1236
|
+
accountAddress
|
|
1237
|
+
});
|
|
1238
|
+
throw new Error('No Google OAuth account ID found');
|
|
1239
|
+
}
|
|
1240
|
+
return oauthAccountId;
|
|
1241
|
+
} catch (error) {
|
|
1242
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in getGoogleOauthAccountIdOrThrow', error);
|
|
1243
|
+
if (error instanceof core.AxiosError) {
|
|
1244
|
+
core.handleAxiosError(error);
|
|
1245
|
+
}
|
|
1246
|
+
throw error;
|
|
1113
1247
|
}
|
|
1114
|
-
return oauthAccountId;
|
|
1115
1248
|
}
|
|
1116
1249
|
/**
|
|
1117
1250
|
* Helper function to determine keyshare recovery strategy for dynamic shares.
|
|
@@ -1141,34 +1274,39 @@ class DynamicWalletClient {
|
|
|
1141
1274
|
};
|
|
1142
1275
|
}
|
|
1143
1276
|
async recoverEncryptedBackupByWallet({ accountAddress, password, walletOperation, signedSessionId, shareCount = undefined, storeRecoveredShares = true }) {
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
const { dynamic: dynamicKeyShareIds } = shares;
|
|
1153
|
-
const data = await this.apiClient.recoverEncryptedBackupByWallet({
|
|
1154
|
-
walletId: wallet.walletId,
|
|
1155
|
-
keyShareIds: dynamicKeyShareIds,
|
|
1156
|
-
signedSessionId
|
|
1157
|
-
});
|
|
1158
|
-
const dynamicKeyShares = data.keyShares.filter((keyShare)=>keyShare.encryptedAccountCredential !== null && keyShare.backupLocation === core.BackupLocation.DYNAMIC);
|
|
1159
|
-
const decryptedKeyShares = await Promise.all(dynamicKeyShares.map((keyShare)=>this.decryptKeyShare({
|
|
1160
|
-
keyShare: keyShare.encryptedAccountCredential,
|
|
1161
|
-
password: password != null ? password : this.environmentId
|
|
1162
|
-
})));
|
|
1163
|
-
if (storeRecoveredShares) {
|
|
1164
|
-
await this.setClientKeySharesToLocalStorage({
|
|
1165
|
-
accountAddress,
|
|
1166
|
-
clientKeyShares: decryptedKeyShares,
|
|
1167
|
-
overwriteOrMerge: 'merge'
|
|
1277
|
+
try {
|
|
1278
|
+
const wallet = this.walletMap[accountAddress];
|
|
1279
|
+
this.logger.debug(`recoverEncryptedBackupByWallet wallet: ${walletOperation}`, wallet);
|
|
1280
|
+
const { shares } = this.recoverStrategy({
|
|
1281
|
+
clientKeyShareBackupInfo: wallet.clientKeySharesBackupInfo,
|
|
1282
|
+
thresholdSignatureScheme: wallet.thresholdSignatureScheme,
|
|
1283
|
+
walletOperation,
|
|
1284
|
+
shareCount
|
|
1168
1285
|
});
|
|
1169
|
-
|
|
1286
|
+
const { dynamic: dynamicKeyShareIds } = shares;
|
|
1287
|
+
const data = await this.apiClient.recoverEncryptedBackupByWallet({
|
|
1288
|
+
walletId: wallet.walletId,
|
|
1289
|
+
keyShareIds: dynamicKeyShareIds,
|
|
1290
|
+
signedSessionId
|
|
1291
|
+
});
|
|
1292
|
+
const dynamicKeyShares = data.keyShares.filter((keyShare)=>keyShare.encryptedAccountCredential !== null && keyShare.backupLocation === core.BackupLocation.DYNAMIC);
|
|
1293
|
+
const decryptedKeyShares = await Promise.all(dynamicKeyShares.map((keyShare)=>this.decryptKeyShare({
|
|
1294
|
+
keyShare: keyShare.encryptedAccountCredential,
|
|
1295
|
+
password: password != null ? password : this.environmentId
|
|
1296
|
+
})));
|
|
1297
|
+
if (storeRecoveredShares) {
|
|
1298
|
+
await this.setClientKeySharesToLocalStorage({
|
|
1299
|
+
accountAddress,
|
|
1300
|
+
clientKeyShares: decryptedKeyShares,
|
|
1301
|
+
overwriteOrMerge: 'merge'
|
|
1302
|
+
});
|
|
1303
|
+
await this.storage.setItem(this.storageKey, JSON.stringify(this.walletMap));
|
|
1304
|
+
}
|
|
1305
|
+
return decryptedKeyShares;
|
|
1306
|
+
} catch (error) {
|
|
1307
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in recoverEncryptedBackupByWallet', error);
|
|
1308
|
+
throw error;
|
|
1170
1309
|
}
|
|
1171
|
-
return decryptedKeyShares;
|
|
1172
1310
|
}
|
|
1173
1311
|
async restoreWallets() {
|
|
1174
1312
|
const wallets = await this.storage.getItem(this.storageKey);
|
|
@@ -1178,107 +1316,123 @@ class DynamicWalletClient {
|
|
|
1178
1316
|
this.walletMap = JSON.parse(wallets);
|
|
1179
1317
|
}
|
|
1180
1318
|
async backupKeySharesToGoogleDrive({ accountAddress, password, signedSessionId }) {
|
|
1181
|
-
await this.getWallet({
|
|
1182
|
-
accountAddress,
|
|
1183
|
-
walletOperation: core.WalletOperation.REACH_ALL_PARTIES,
|
|
1184
|
-
password,
|
|
1185
|
-
signedSessionId
|
|
1186
|
-
});
|
|
1187
|
-
const clientKeyShares = await this.getClientKeySharesFromLocalStorage({
|
|
1188
|
-
accountAddress
|
|
1189
|
-
});
|
|
1190
|
-
if (clientKeyShares.length === 0) {
|
|
1191
|
-
throw new Error('No key shares found');
|
|
1192
|
-
}
|
|
1193
|
-
const encryptedKeyShares = await Promise.all(clientKeyShares.map((keyShare)=>this.encryptKeyShare({
|
|
1194
|
-
keyShare,
|
|
1195
|
-
password
|
|
1196
|
-
})));
|
|
1197
|
-
const oauthAccountId = await this.getGoogleOauthAccountIdOrThrow(accountAddress);
|
|
1198
|
-
const accessToken = await this.apiClient.getAccessToken({
|
|
1199
|
-
oauthAccountId
|
|
1200
|
-
});
|
|
1201
|
-
const thresholdSignatureScheme = this.walletMap[accountAddress].thresholdSignatureScheme;
|
|
1202
|
-
const fileName = getClientKeyShareExportFileName({
|
|
1203
|
-
thresholdSignatureScheme,
|
|
1204
|
-
accountAddress
|
|
1205
|
-
});
|
|
1206
|
-
const backupData = createBackupData({
|
|
1207
|
-
encryptedKeyShares,
|
|
1208
|
-
accountAddress,
|
|
1209
|
-
thresholdSignatureScheme
|
|
1210
|
-
});
|
|
1211
|
-
await uploadBackupToGoogleDrive({
|
|
1212
|
-
accessToken,
|
|
1213
|
-
fileName,
|
|
1214
|
-
backupData,
|
|
1215
|
-
accountAddress
|
|
1216
|
-
});
|
|
1217
|
-
const data = await this.apiClient.markKeySharesAsBackedUpGoogleDrive({
|
|
1218
|
-
walletId: this.walletMap[accountAddress].walletId
|
|
1219
|
-
});
|
|
1220
|
-
await updateWalletMapWithBackupInfo({
|
|
1221
|
-
data,
|
|
1222
|
-
walletMap: this.walletMap,
|
|
1223
|
-
accountAddress,
|
|
1224
|
-
storage: this.storage,
|
|
1225
|
-
storageKey: this.storageKey
|
|
1226
|
-
});
|
|
1227
|
-
}
|
|
1228
|
-
async restoreBackupFromGoogleDrive({ accountAddress, password, signedSessionId }) {
|
|
1229
|
-
await this.getWallet({
|
|
1230
|
-
accountAddress,
|
|
1231
|
-
signedSessionId
|
|
1232
|
-
});
|
|
1233
|
-
const oauthAccountId = await this.getGoogleOauthAccountIdOrThrow(accountAddress);
|
|
1234
|
-
const accessToken = await this.apiClient.getAccessToken({
|
|
1235
|
-
oauthAccountId
|
|
1236
|
-
});
|
|
1237
|
-
const thresholdSignatureScheme = this.walletMap[accountAddress].thresholdSignatureScheme;
|
|
1238
|
-
const fileName = getClientKeyShareExportFileName({
|
|
1239
|
-
thresholdSignatureScheme,
|
|
1240
|
-
accountAddress
|
|
1241
|
-
});
|
|
1242
|
-
let backupData = null;
|
|
1243
1319
|
try {
|
|
1244
|
-
|
|
1245
|
-
accessToken,
|
|
1246
|
-
fileName
|
|
1247
|
-
}));
|
|
1248
|
-
} catch (error) {
|
|
1249
|
-
this.logger.error('Failed to download backup from Google Drive', {
|
|
1320
|
+
await this.getWallet({
|
|
1250
1321
|
accountAddress,
|
|
1322
|
+
walletOperation: core.WalletOperation.REACH_ALL_PARTIES,
|
|
1323
|
+
password,
|
|
1324
|
+
signedSessionId
|
|
1325
|
+
});
|
|
1326
|
+
const clientKeyShares = await this.getClientKeySharesFromLocalStorage({
|
|
1327
|
+
accountAddress
|
|
1328
|
+
});
|
|
1329
|
+
if (clientKeyShares.length === 0) {
|
|
1330
|
+
throw new Error('No key shares found');
|
|
1331
|
+
}
|
|
1332
|
+
const encryptedKeyShares = await Promise.all(clientKeyShares.map((keyShare)=>this.encryptKeyShare({
|
|
1333
|
+
keyShare,
|
|
1334
|
+
password
|
|
1335
|
+
})));
|
|
1336
|
+
const oauthAccountId = await this.getGoogleOauthAccountIdOrThrow(accountAddress);
|
|
1337
|
+
const accessToken = await this.apiClient.getAccessToken({
|
|
1338
|
+
oauthAccountId
|
|
1339
|
+
});
|
|
1340
|
+
const thresholdSignatureScheme = this.walletMap[accountAddress].thresholdSignatureScheme;
|
|
1341
|
+
const fileName = getClientKeyShareExportFileName({
|
|
1342
|
+
thresholdSignatureScheme,
|
|
1343
|
+
accountAddress
|
|
1344
|
+
});
|
|
1345
|
+
const backupData = createBackupData({
|
|
1346
|
+
encryptedKeyShares,
|
|
1347
|
+
accountAddress,
|
|
1348
|
+
thresholdSignatureScheme
|
|
1349
|
+
});
|
|
1350
|
+
await uploadBackupToGoogleDrive({
|
|
1351
|
+
accessToken,
|
|
1251
1352
|
fileName,
|
|
1252
|
-
|
|
1353
|
+
backupData,
|
|
1354
|
+
accountAddress
|
|
1253
1355
|
});
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1356
|
+
const data = await this.apiClient.markKeySharesAsBackedUpGoogleDrive({
|
|
1357
|
+
walletId: this.walletMap[accountAddress].walletId
|
|
1358
|
+
});
|
|
1359
|
+
await updateWalletMapWithBackupInfo({
|
|
1360
|
+
data,
|
|
1361
|
+
walletMap: this.walletMap,
|
|
1258
1362
|
accountAddress,
|
|
1259
|
-
|
|
1363
|
+
storage: this.storage,
|
|
1364
|
+
storageKey: this.storageKey
|
|
1260
1365
|
});
|
|
1261
|
-
|
|
1366
|
+
} catch (error) {
|
|
1367
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in backupKeySharesToGoogleDrive', error);
|
|
1368
|
+
if (error instanceof core.AxiosError) {
|
|
1369
|
+
core.handleAxiosError(error);
|
|
1370
|
+
}
|
|
1371
|
+
throw error;
|
|
1262
1372
|
}
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1373
|
+
}
|
|
1374
|
+
async restoreBackupFromGoogleDrive({ accountAddress, password, signedSessionId }) {
|
|
1375
|
+
try {
|
|
1376
|
+
await this.getWallet({
|
|
1377
|
+
accountAddress,
|
|
1378
|
+
signedSessionId
|
|
1379
|
+
});
|
|
1380
|
+
const oauthAccountId = await this.getGoogleOauthAccountIdOrThrow(accountAddress);
|
|
1381
|
+
const accessToken = await this.apiClient.getAccessToken({
|
|
1382
|
+
oauthAccountId
|
|
1383
|
+
});
|
|
1384
|
+
const thresholdSignatureScheme = this.walletMap[accountAddress].thresholdSignatureScheme;
|
|
1385
|
+
const fileName = getClientKeyShareExportFileName({
|
|
1386
|
+
thresholdSignatureScheme,
|
|
1387
|
+
accountAddress
|
|
1388
|
+
});
|
|
1389
|
+
let backupData = null;
|
|
1390
|
+
try {
|
|
1391
|
+
backupData = await retryPromise(()=>downloadFileFromGoogleDrive({
|
|
1392
|
+
accessToken,
|
|
1393
|
+
fileName
|
|
1394
|
+
}));
|
|
1395
|
+
} catch (error) {
|
|
1396
|
+
this.logger.error('Failed to download backup from Google Drive', {
|
|
1397
|
+
accountAddress,
|
|
1398
|
+
fileName,
|
|
1399
|
+
error
|
|
1400
|
+
});
|
|
1401
|
+
throw new Error('Failed to restore backup from Google Drive');
|
|
1402
|
+
}
|
|
1403
|
+
if (!backupData) {
|
|
1404
|
+
this.logger.error('No backup file found', {
|
|
1405
|
+
accountAddress,
|
|
1406
|
+
fileName
|
|
1407
|
+
});
|
|
1408
|
+
throw new Error('No backup file found');
|
|
1409
|
+
}
|
|
1410
|
+
// Validate the backup data structure
|
|
1411
|
+
if (!backupData.keyShares || !backupData.metadata) {
|
|
1412
|
+
this.logger.error('Invalid backup format: missing keyShares or metadata', {
|
|
1413
|
+
accountAddress,
|
|
1414
|
+
fileName
|
|
1415
|
+
});
|
|
1416
|
+
throw new Error('Invalid backup format: missing keyShares or metadata');
|
|
1417
|
+
}
|
|
1418
|
+
const { keyShares } = backupData;
|
|
1419
|
+
const decryptedKeyShares = await Promise.all(keyShares.map((keyShare)=>this.decryptKeyShare({
|
|
1420
|
+
keyShare,
|
|
1421
|
+
password
|
|
1422
|
+
})));
|
|
1423
|
+
await this.setClientKeySharesToLocalStorage({
|
|
1266
1424
|
accountAddress,
|
|
1267
|
-
|
|
1425
|
+
clientKeyShares: decryptedKeyShares,
|
|
1426
|
+
overwriteOrMerge: 'merge'
|
|
1268
1427
|
});
|
|
1269
|
-
|
|
1428
|
+
return decryptedKeyShares;
|
|
1429
|
+
} catch (error) {
|
|
1430
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in restoreBackupFromGoogleDrive', error);
|
|
1431
|
+
if (error instanceof core.AxiosError) {
|
|
1432
|
+
core.handleAxiosError(error);
|
|
1433
|
+
}
|
|
1434
|
+
throw error;
|
|
1270
1435
|
}
|
|
1271
|
-
const { keyShares } = backupData;
|
|
1272
|
-
const decryptedKeyShares = await Promise.all(keyShares.map((keyShare)=>this.decryptKeyShare({
|
|
1273
|
-
keyShare,
|
|
1274
|
-
password
|
|
1275
|
-
})));
|
|
1276
|
-
await this.setClientKeySharesToLocalStorage({
|
|
1277
|
-
accountAddress,
|
|
1278
|
-
clientKeyShares: decryptedKeyShares,
|
|
1279
|
-
overwriteOrMerge: 'merge'
|
|
1280
|
-
});
|
|
1281
|
-
return decryptedKeyShares;
|
|
1282
1436
|
}
|
|
1283
1437
|
async exportClientKeyshares({ accountAddress, password, signedSessionId }) {
|
|
1284
1438
|
await this.verifyPassword({
|
|
@@ -1449,107 +1603,131 @@ class DynamicWalletClient {
|
|
|
1449
1603
|
return true;
|
|
1450
1604
|
}
|
|
1451
1605
|
async getWalletClientKeyShareBackupInfo({ accountAddress }) {
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1606
|
+
try {
|
|
1607
|
+
var _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups_BackupLocation_DYNAMIC, _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups, _this_walletMap_accountAddress_clientKeySharesBackupInfo, _this_walletMap_accountAddress, _user_verifiedCredentials;
|
|
1608
|
+
// Return existing backup info if it exists
|
|
1609
|
+
if (((_this_walletMap_accountAddress = this.walletMap[accountAddress]) == null ? void 0 : (_this_walletMap_accountAddress_clientKeySharesBackupInfo = _this_walletMap_accountAddress.clientKeySharesBackupInfo) == null ? void 0 : (_this_walletMap_accountAddress_clientKeySharesBackupInfo_backups = _this_walletMap_accountAddress_clientKeySharesBackupInfo.backups) == null ? void 0 : (_this_walletMap_accountAddress_clientKeySharesBackupInfo_backups_BackupLocation_DYNAMIC = _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups[core.BackupLocation.DYNAMIC]) == null ? void 0 : _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups_BackupLocation_DYNAMIC.length) > 0) {
|
|
1610
|
+
return this.walletMap[accountAddress].clientKeySharesBackupInfo;
|
|
1611
|
+
}
|
|
1612
|
+
// Get backup info from server
|
|
1613
|
+
const user = await this.apiClient.getUser();
|
|
1614
|
+
const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
|
|
1615
|
+
return getClientKeyShareBackupInfo({
|
|
1616
|
+
walletProperties: wallet == null ? void 0 : wallet.walletProperties
|
|
1617
|
+
});
|
|
1618
|
+
} catch (error) {
|
|
1619
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in getWalletClientKeyShareBackupInfo', error);
|
|
1620
|
+
if (error instanceof core.AxiosError) {
|
|
1621
|
+
core.handleAxiosError(error);
|
|
1622
|
+
}
|
|
1623
|
+
throw error;
|
|
1456
1624
|
}
|
|
1457
|
-
// Get backup info from server
|
|
1458
|
-
const user = await this.apiClient.getUser();
|
|
1459
|
-
const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
|
|
1460
|
-
return getClientKeyShareBackupInfo({
|
|
1461
|
-
walletProperties: wallet == null ? void 0 : wallet.walletProperties
|
|
1462
|
-
});
|
|
1463
1625
|
}
|
|
1464
1626
|
async getWallet({ accountAddress, walletOperation = core.WalletOperation.NO_OPERATION, shareCount = undefined, password = undefined, signedSessionId }) {
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
walletOperation,
|
|
1469
|
-
shareCount
|
|
1470
|
-
});
|
|
1471
|
-
if (existingWalletCheck) {
|
|
1472
|
-
this.logger.debug(`Wallet ${accountAddress} already exists`);
|
|
1473
|
-
return this.walletMap[accountAddress];
|
|
1474
|
-
}
|
|
1475
|
-
// Fetch and restore wallet from server
|
|
1476
|
-
const user = await this.apiClient.getUser();
|
|
1477
|
-
const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
|
|
1478
|
-
this.logger.debug('Restoring wallet', wallet);
|
|
1479
|
-
const walletProperties = wallet.walletProperties;
|
|
1480
|
-
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
1481
|
-
walletId: wallet.id,
|
|
1482
|
-
chainName: wallet.chainName,
|
|
1483
|
-
accountAddress,
|
|
1484
|
-
thresholdSignatureScheme: walletProperties.thresholdSignatureScheme,
|
|
1485
|
-
derivationPath: walletProperties.derivationPath,
|
|
1486
|
-
clientKeySharesBackupInfo: getClientKeyShareBackupInfo({
|
|
1487
|
-
walletProperties
|
|
1488
|
-
})
|
|
1489
|
-
});
|
|
1490
|
-
if (walletOperation !== core.WalletOperation.NO_OPERATION && await this.requiresRestoreBackupSharesForOperation({
|
|
1491
|
-
accountAddress,
|
|
1492
|
-
walletOperation
|
|
1493
|
-
})) {
|
|
1494
|
-
// TODO(zfaizal2): throw error if signedSessionId is not provided after service deploy
|
|
1495
|
-
const decryptedKeyShares = await this.recoverEncryptedBackupByWallet({
|
|
1627
|
+
try {
|
|
1628
|
+
var _user_verifiedCredentials;
|
|
1629
|
+
const existingWalletCheck = await this.checkWalletFields({
|
|
1496
1630
|
accountAddress,
|
|
1497
|
-
|
|
1498
|
-
walletOperation: walletOperation,
|
|
1499
|
-
signedSessionId,
|
|
1631
|
+
walletOperation,
|
|
1500
1632
|
shareCount
|
|
1501
1633
|
});
|
|
1502
|
-
|
|
1503
|
-
accountAddress
|
|
1504
|
-
|
|
1505
|
-
|
|
1634
|
+
if (existingWalletCheck) {
|
|
1635
|
+
this.logger.debug(`Wallet ${accountAddress} already exists`);
|
|
1636
|
+
return this.walletMap[accountAddress];
|
|
1637
|
+
}
|
|
1638
|
+
// Fetch and restore wallet from server
|
|
1639
|
+
const user = await this.apiClient.getUser();
|
|
1640
|
+
const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
|
|
1641
|
+
this.logger.debug('Restoring wallet', wallet);
|
|
1642
|
+
const walletProperties = wallet.walletProperties;
|
|
1643
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
1644
|
+
walletId: wallet.id,
|
|
1645
|
+
chainName: wallet.chainName,
|
|
1506
1646
|
accountAddress,
|
|
1507
|
-
|
|
1647
|
+
thresholdSignatureScheme: walletProperties.thresholdSignatureScheme,
|
|
1648
|
+
derivationPath: walletProperties.derivationPath,
|
|
1649
|
+
clientKeySharesBackupInfo: getClientKeyShareBackupInfo({
|
|
1650
|
+
walletProperties
|
|
1651
|
+
})
|
|
1508
1652
|
});
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1653
|
+
if (walletOperation !== core.WalletOperation.NO_OPERATION && await this.requiresRestoreBackupSharesForOperation({
|
|
1654
|
+
accountAddress,
|
|
1655
|
+
walletOperation
|
|
1656
|
+
})) {
|
|
1657
|
+
// TODO(zfaizal2): throw error if signedSessionId is not provided after service deploy
|
|
1658
|
+
const decryptedKeyShares = await this.recoverEncryptedBackupByWallet({
|
|
1659
|
+
accountAddress,
|
|
1660
|
+
password: password != null ? password : this.environmentId,
|
|
1661
|
+
walletOperation: walletOperation,
|
|
1662
|
+
signedSessionId,
|
|
1663
|
+
shareCount
|
|
1664
|
+
});
|
|
1665
|
+
const existingKeyShares = await this.getClientKeySharesFromLocalStorage({
|
|
1666
|
+
accountAddress
|
|
1667
|
+
});
|
|
1668
|
+
await this.setClientKeySharesToLocalStorage({
|
|
1669
|
+
accountAddress,
|
|
1670
|
+
clientKeyShares: mergeUniqueKeyShares(existingKeyShares, decryptedKeyShares)
|
|
1671
|
+
});
|
|
1672
|
+
this.logger.debug('Recovered backup', decryptedKeyShares);
|
|
1673
|
+
}
|
|
1674
|
+
const walletCount = Object.keys(this.walletMap).length;
|
|
1675
|
+
if (walletCount === 0) {
|
|
1676
|
+
throw new Error('No wallets found');
|
|
1677
|
+
}
|
|
1678
|
+
// Return the only wallet if there's just one
|
|
1679
|
+
if (walletCount === 1) {
|
|
1680
|
+
return Object.values(this.walletMap)[0];
|
|
1681
|
+
}
|
|
1682
|
+
return this.walletMap[accountAddress];
|
|
1683
|
+
} catch (error) {
|
|
1684
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in getWallet', error);
|
|
1685
|
+
if (error instanceof core.AxiosError) {
|
|
1686
|
+
core.handleAxiosError(error);
|
|
1687
|
+
}
|
|
1688
|
+
throw error;
|
|
1518
1689
|
}
|
|
1519
|
-
return this.walletMap[accountAddress];
|
|
1520
1690
|
}
|
|
1521
1691
|
async getWallets() {
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1692
|
+
try {
|
|
1693
|
+
var _user_verifiedCredentials;
|
|
1694
|
+
const user = await this.apiClient.getUser();
|
|
1695
|
+
const waasWallets = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.filter((vc)=>vc.walletName === 'dynamicwaas');
|
|
1696
|
+
const wallets = waasWallets.map((vc)=>{
|
|
1697
|
+
var _this_walletMap_vc_address, _vc_walletProperties;
|
|
1698
|
+
var _this_walletMap_vc_address_derivationPath;
|
|
1699
|
+
return {
|
|
1700
|
+
walletId: vc.id,
|
|
1701
|
+
chainName: vc.chain,
|
|
1702
|
+
accountAddress: vc.address,
|
|
1703
|
+
clientKeySharesBackupInfo: getClientKeyShareBackupInfo({
|
|
1704
|
+
walletProperties: vc.walletProperties || {}
|
|
1705
|
+
}),
|
|
1706
|
+
derivationPath: (_this_walletMap_vc_address_derivationPath = (_this_walletMap_vc_address = this.walletMap[vc.address]) == null ? void 0 : _this_walletMap_vc_address.derivationPath) != null ? _this_walletMap_vc_address_derivationPath : undefined,
|
|
1707
|
+
thresholdSignatureScheme: (_vc_walletProperties = vc.walletProperties) == null ? void 0 : _vc_walletProperties.thresholdSignatureScheme
|
|
1708
|
+
};
|
|
1709
|
+
});
|
|
1710
|
+
this.walletMap = wallets.reduce((acc, wallet)=>{
|
|
1711
|
+
var _acc_accountAddress;
|
|
1712
|
+
const accountAddress = wallet.accountAddress;
|
|
1713
|
+
acc[wallet.accountAddress] = {
|
|
1714
|
+
walletId: wallet.walletId,
|
|
1715
|
+
chainName: wallet.chainName,
|
|
1716
|
+
accountAddress: wallet.accountAddress,
|
|
1717
|
+
clientKeySharesBackupInfo: wallet.clientKeySharesBackupInfo,
|
|
1718
|
+
derivationPath: ((_acc_accountAddress = acc[accountAddress]) == null ? void 0 : _acc_accountAddress.derivationPath) || undefined,
|
|
1719
|
+
thresholdSignatureScheme: wallet.thresholdSignatureScheme
|
|
1720
|
+
};
|
|
1721
|
+
return acc;
|
|
1722
|
+
}, {});
|
|
1723
|
+
return wallets;
|
|
1724
|
+
} catch (error) {
|
|
1725
|
+
this.logger.error('[DynamicWaasWalletClient]: Error in getWallets', error);
|
|
1726
|
+
if (error instanceof core.AxiosError) {
|
|
1727
|
+
core.handleAxiosError(error);
|
|
1728
|
+
}
|
|
1729
|
+
throw error;
|
|
1730
|
+
}
|
|
1553
1731
|
}
|
|
1554
1732
|
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug }){
|
|
1555
1733
|
this.initializePromise = null;
|
|
@@ -1584,6 +1762,15 @@ class DynamicWalletClient {
|
|
|
1584
1762
|
}
|
|
1585
1763
|
}
|
|
1586
1764
|
|
|
1765
|
+
const ERROR_KEYGEN_FAILED = '[DynamicWaasWalletClient]: Error with keygen';
|
|
1766
|
+
const ERROR_CREATE_WALLET_ACCOUNT = '[DynamicWaasWalletClient]: Error creating evm wallet account';
|
|
1767
|
+
const ERROR_SIGN_MESSAGE = '[DynamicWaasWalletClient]: Error signing message';
|
|
1768
|
+
const ERROR_ACCOUNT_ADDRESS_REQUIRED = '[DynamicWaasWalletClient]: Account address is required';
|
|
1769
|
+
const ERROR_VERIFY_MESSAGE_SIGNATURE = '[DynamicWaasWalletClient]: Error verifying message signature';
|
|
1770
|
+
const ERROR_VERIFY_TRANSACTION_SIGNATURE = '[DynamicWaasWalletClient]: Error verifying transaction signature';
|
|
1771
|
+
const ERROR_EXPORT_PRIVATE_KEY = '[DynamicWaasWalletClient]: Error exporting private key';
|
|
1772
|
+
const ERROR_IMPORT_PRIVATE_KEY = '[DynamicWaasWalletClient]: Error importing private key';
|
|
1773
|
+
|
|
1587
1774
|
Object.defineProperty(exports, "BIP340", {
|
|
1588
1775
|
enumerable: true,
|
|
1589
1776
|
get: function () { return web.BIP340; }
|
|
@@ -1633,6 +1820,14 @@ Object.defineProperty(exports, "MessageHash", {
|
|
|
1633
1820
|
get: function () { return web.MessageHash; }
|
|
1634
1821
|
});
|
|
1635
1822
|
exports.DynamicWalletClient = DynamicWalletClient;
|
|
1823
|
+
exports.ERROR_ACCOUNT_ADDRESS_REQUIRED = ERROR_ACCOUNT_ADDRESS_REQUIRED;
|
|
1824
|
+
exports.ERROR_CREATE_WALLET_ACCOUNT = ERROR_CREATE_WALLET_ACCOUNT;
|
|
1825
|
+
exports.ERROR_EXPORT_PRIVATE_KEY = ERROR_EXPORT_PRIVATE_KEY;
|
|
1826
|
+
exports.ERROR_IMPORT_PRIVATE_KEY = ERROR_IMPORT_PRIVATE_KEY;
|
|
1827
|
+
exports.ERROR_KEYGEN_FAILED = ERROR_KEYGEN_FAILED;
|
|
1828
|
+
exports.ERROR_SIGN_MESSAGE = ERROR_SIGN_MESSAGE;
|
|
1829
|
+
exports.ERROR_VERIFY_MESSAGE_SIGNATURE = ERROR_VERIFY_MESSAGE_SIGNATURE;
|
|
1830
|
+
exports.ERROR_VERIFY_TRANSACTION_SIGNATURE = ERROR_VERIFY_TRANSACTION_SIGNATURE;
|
|
1636
1831
|
exports.base64ToBytes = base64ToBytes;
|
|
1637
1832
|
exports.bytesToBase64 = bytesToBase64;
|
|
1638
1833
|
exports.createBackupData = createBackupData;
|