@dynamic-labs-wallet/node 0.0.0-beta.291.7 → 0.0.0-beta.292.0
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 +202 -128
- package/index.esm.js +202 -128
- package/package.json +2 -2
- package/src/backup/encryption.d.ts +42 -2
- package/src/backup/encryption.d.ts.map +1 -1
- package/src/backup/utils.d.ts +4 -0
- package/src/backup/utils.d.ts.map +1 -0
- package/src/client.d.ts +21 -26
- package/src/client.d.ts.map +1 -1
package/index.cjs.js
CHANGED
|
@@ -160,12 +160,33 @@ const formatMessage = (chainName, message)=>{
|
|
|
160
160
|
}
|
|
161
161
|
};
|
|
162
162
|
|
|
163
|
+
const ENCRYPTION_VERSION_LEGACY = 'v1';
|
|
164
|
+
const ENCRYPTION_VERSION_CURRENT = 'v2';
|
|
163
165
|
const PBKDF2_ALGORITHM = 'PBKDF2';
|
|
164
|
-
const PBKDF2_ITERATIONS = 100000;
|
|
165
166
|
const PBKDF2_HASH_ALGORITHM = 'SHA-256';
|
|
166
167
|
const AES_GCM_ALGORITHM = 'AES-GCM';
|
|
167
168
|
const AES_GCM_LENGTH = 256;
|
|
168
|
-
const
|
|
169
|
+
const ENCRYPTION_VERSIONS = {
|
|
170
|
+
[ENCRYPTION_VERSION_LEGACY]: {
|
|
171
|
+
version: ENCRYPTION_VERSION_LEGACY,
|
|
172
|
+
algorithm: AES_GCM_ALGORITHM,
|
|
173
|
+
keyDerivation: PBKDF2_ALGORITHM,
|
|
174
|
+
iterations: 100000,
|
|
175
|
+
hashAlgorithm: PBKDF2_HASH_ALGORITHM,
|
|
176
|
+
algorithmLength: AES_GCM_LENGTH
|
|
177
|
+
},
|
|
178
|
+
[ENCRYPTION_VERSION_CURRENT]: {
|
|
179
|
+
version: ENCRYPTION_VERSION_CURRENT,
|
|
180
|
+
algorithm: AES_GCM_ALGORITHM,
|
|
181
|
+
keyDerivation: PBKDF2_ALGORITHM,
|
|
182
|
+
iterations: 1000000,
|
|
183
|
+
hashAlgorithm: PBKDF2_HASH_ALGORITHM,
|
|
184
|
+
algorithmLength: AES_GCM_LENGTH
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
ENCRYPTION_VERSIONS[ENCRYPTION_VERSION_CURRENT].iterations;
|
|
188
|
+
ENCRYPTION_VERSIONS[ENCRYPTION_VERSION_LEGACY].iterations;
|
|
189
|
+
const getKey = async ({ password, salt, encryptionConfig })=>{
|
|
169
190
|
const passwordBytes = stringToBytes(password);
|
|
170
191
|
const initialKey = await crypto.subtle.importKey('raw', passwordBytes, {
|
|
171
192
|
name: 'PBKDF2'
|
|
@@ -173,26 +194,34 @@ const getKey = async ({ password, salt })=>{
|
|
|
173
194
|
'deriveKey'
|
|
174
195
|
]);
|
|
175
196
|
return crypto.subtle.deriveKey({
|
|
176
|
-
name:
|
|
177
|
-
salt,
|
|
178
|
-
iterations:
|
|
179
|
-
hash:
|
|
197
|
+
name: encryptionConfig.keyDerivation,
|
|
198
|
+
salt: salt,
|
|
199
|
+
iterations: encryptionConfig.iterations,
|
|
200
|
+
hash: encryptionConfig.hashAlgorithm
|
|
180
201
|
}, initialKey, {
|
|
181
|
-
name:
|
|
182
|
-
length:
|
|
202
|
+
name: encryptionConfig.algorithm,
|
|
203
|
+
length: encryptionConfig.algorithmLength
|
|
183
204
|
}, false, [
|
|
184
205
|
'encrypt',
|
|
185
206
|
'decrypt'
|
|
186
207
|
]);
|
|
187
208
|
};
|
|
188
|
-
|
|
209
|
+
/**
|
|
210
|
+
* Encrypts data using the specified encryption version.
|
|
211
|
+
* Always uses the latest encryption configuration for new encryptions by default.
|
|
212
|
+
*/ const encryptData = async ({ data, password, version = ENCRYPTION_VERSION_CURRENT })=>{
|
|
213
|
+
const encryptionConfig = ENCRYPTION_VERSIONS[version];
|
|
214
|
+
if (!encryptionConfig) {
|
|
215
|
+
throw new Error(`Unsupported encryption version: ${version}`);
|
|
216
|
+
}
|
|
189
217
|
try {
|
|
190
218
|
// Generate a random salt and IV
|
|
191
219
|
const salt = crypto.getRandomValues(new Uint8Array(16));
|
|
192
220
|
const iv = crypto.getRandomValues(new Uint8Array(12)); // AES-GCM requires 12 bytes
|
|
193
221
|
const key = await getKey({
|
|
194
222
|
password,
|
|
195
|
-
salt
|
|
223
|
+
salt,
|
|
224
|
+
encryptionConfig
|
|
196
225
|
});
|
|
197
226
|
// Convert the input string to bytes
|
|
198
227
|
const dataBytes = new TextEncoder().encode(data);
|
|
@@ -205,25 +234,39 @@ const encryptData = async ({ data, password })=>{
|
|
|
205
234
|
return {
|
|
206
235
|
salt: bytesToBase64(salt),
|
|
207
236
|
iv: bytesToBase64(iv),
|
|
208
|
-
cipher: bytesToBase64(new Uint8Array(encryptedData))
|
|
237
|
+
cipher: bytesToBase64(new Uint8Array(encryptedData)),
|
|
238
|
+
version
|
|
209
239
|
};
|
|
210
240
|
} catch (error) {
|
|
211
241
|
throw new Error('Error encrypting data');
|
|
212
242
|
}
|
|
213
243
|
};
|
|
214
|
-
|
|
244
|
+
/**
|
|
245
|
+
* Decrypts data with version-based configuration.
|
|
246
|
+
* Uses the version field from the data to determine encryption parameters.
|
|
247
|
+
* Falls back to legacy version for backward compatibility if no version is specified.
|
|
248
|
+
*/ const decryptData = async ({ data, password })=>{
|
|
249
|
+
const { salt, iv, cipher, version } = data;
|
|
250
|
+
// Ensure proper base64 padding for all values
|
|
251
|
+
const paddedSalt = ensureBase64Padding(salt);
|
|
252
|
+
const paddedIv = ensureBase64Padding(iv);
|
|
253
|
+
const paddedCipher = ensureBase64Padding(cipher);
|
|
254
|
+
const saltBytes = base64ToBytes(paddedSalt);
|
|
255
|
+
const ivBytes = base64ToBytes(paddedIv);
|
|
256
|
+
const cipherBytes = base64ToBytes(paddedCipher);
|
|
257
|
+
let encryptionConfig;
|
|
258
|
+
// Use version-based configuration if available, otherwise fallback to legacy
|
|
259
|
+
if (version && ENCRYPTION_VERSIONS[version]) {
|
|
260
|
+
encryptionConfig = ENCRYPTION_VERSIONS[version];
|
|
261
|
+
} else {
|
|
262
|
+
// Fallback to legacy version for backward compatibility
|
|
263
|
+
encryptionConfig = ENCRYPTION_VERSIONS[ENCRYPTION_VERSION_LEGACY];
|
|
264
|
+
}
|
|
215
265
|
try {
|
|
216
|
-
const { salt, iv, cipher } = data;
|
|
217
|
-
// Ensure proper base64 padding for all values
|
|
218
|
-
const paddedSalt = ensureBase64Padding(salt);
|
|
219
|
-
const paddedIv = ensureBase64Padding(iv);
|
|
220
|
-
const paddedCipher = ensureBase64Padding(cipher);
|
|
221
|
-
const saltBytes = base64ToBytes(paddedSalt);
|
|
222
|
-
const ivBytes = base64ToBytes(paddedIv);
|
|
223
|
-
const cipherBytes = base64ToBytes(paddedCipher);
|
|
224
266
|
const key = await getKey({
|
|
225
267
|
password,
|
|
226
|
-
salt: saltBytes
|
|
268
|
+
salt: saltBytes,
|
|
269
|
+
encryptionConfig
|
|
227
270
|
});
|
|
228
271
|
const decryptedData = await crypto.subtle.decrypt({
|
|
229
272
|
name: AES_GCM_ALGORITHM,
|
|
@@ -231,7 +274,7 @@ const decryptData = async ({ data, password })=>{
|
|
|
231
274
|
}, key, cipherBytes);
|
|
232
275
|
return new TextDecoder().decode(decryptedData);
|
|
233
276
|
} catch (error) {
|
|
234
|
-
throw new Error('Decryption failed');
|
|
277
|
+
throw new Error('Decryption failed: ' + error);
|
|
235
278
|
}
|
|
236
279
|
};
|
|
237
280
|
|
|
@@ -464,20 +507,21 @@ class DynamicWalletClient {
|
|
|
464
507
|
throw error;
|
|
465
508
|
}
|
|
466
509
|
}
|
|
467
|
-
|
|
468
|
-
async sign({ accountAddress, externalServerKeyShares, message, chainName, password = undefined, isFormatted = false, signedSessionId }) {
|
|
510
|
+
async sign({ accountAddress, externalServerKeyShares, message, chainName, password = undefined, isFormatted = false }) {
|
|
469
511
|
await this.verifyPassword({
|
|
470
512
|
accountAddress,
|
|
471
513
|
password,
|
|
472
|
-
walletOperation: core.WalletOperation.SIGN_MESSAGE
|
|
473
|
-
signedSessionId
|
|
514
|
+
walletOperation: core.WalletOperation.SIGN_MESSAGE
|
|
474
515
|
});
|
|
475
516
|
const wallet = await this.getWallet({
|
|
476
517
|
accountAddress,
|
|
477
518
|
walletOperation: core.WalletOperation.SIGN_MESSAGE,
|
|
478
|
-
password
|
|
479
|
-
signedSessionId
|
|
519
|
+
password
|
|
480
520
|
});
|
|
521
|
+
externalServerKeyShares = externalServerKeyShares != null ? externalServerKeyShares : wallet.externalServerKeyShares;
|
|
522
|
+
if (!externalServerKeyShares) {
|
|
523
|
+
throw new Error('External server key shares are required to sign a message');
|
|
524
|
+
}
|
|
481
525
|
// Perform the dynamic server sign
|
|
482
526
|
const data = await this.dynamicServerSign({
|
|
483
527
|
walletId: wallet.walletId,
|
|
@@ -496,19 +540,17 @@ class DynamicWalletClient {
|
|
|
496
540
|
});
|
|
497
541
|
return signature;
|
|
498
542
|
}
|
|
499
|
-
async refreshWalletAccountShares({ accountAddress, chainName, password = undefined,
|
|
543
|
+
async refreshWalletAccountShares({ accountAddress, chainName, password = undefined, externalServerKeyShares, backUpToClientShareService = false }) {
|
|
500
544
|
this.ensureApiClientAuthenticated();
|
|
501
545
|
await this.verifyPassword({
|
|
502
546
|
accountAddress,
|
|
503
547
|
password,
|
|
504
|
-
walletOperation: core.WalletOperation.REFRESH
|
|
505
|
-
signedSessionId
|
|
548
|
+
walletOperation: core.WalletOperation.REFRESH
|
|
506
549
|
});
|
|
507
550
|
const wallet = await this.getWallet({
|
|
508
551
|
accountAddress,
|
|
509
552
|
walletOperation: core.WalletOperation.REFRESH,
|
|
510
|
-
password
|
|
511
|
-
signedSessionId
|
|
553
|
+
password
|
|
512
554
|
});
|
|
513
555
|
const mpcSigner = getMPCSigner({
|
|
514
556
|
chainName,
|
|
@@ -519,7 +561,11 @@ class DynamicWalletClient {
|
|
|
519
561
|
walletId: wallet.walletId
|
|
520
562
|
});
|
|
521
563
|
const roomId = data.roomId;
|
|
522
|
-
|
|
564
|
+
externalServerKeyShares = externalServerKeyShares != null ? externalServerKeyShares : wallet.externalServerKeyShares;
|
|
565
|
+
if (!externalServerKeyShares) {
|
|
566
|
+
throw new Error('External server key shares are required to refresh');
|
|
567
|
+
}
|
|
568
|
+
const refreshResults = await Promise.all(externalServerKeyShares.map((serverKeyShare)=>mpcSigner.refresh(roomId, serverKeyShare)));
|
|
523
569
|
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
524
570
|
externalServerKeyShares: refreshResults,
|
|
525
571
|
externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo()
|
|
@@ -527,7 +573,7 @@ class DynamicWalletClient {
|
|
|
527
573
|
await this.storeEncryptedBackupByWallet({
|
|
528
574
|
accountAddress,
|
|
529
575
|
password: password != null ? password : this.environmentId,
|
|
530
|
-
|
|
576
|
+
backUpToClientShareService
|
|
531
577
|
});
|
|
532
578
|
return refreshResults;
|
|
533
579
|
}
|
|
@@ -580,13 +626,12 @@ class DynamicWalletClient {
|
|
|
580
626
|
existingExternalServerKeyShares
|
|
581
627
|
};
|
|
582
628
|
}
|
|
583
|
-
async reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined,
|
|
629
|
+
async reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined, externalServerKeyShares, backUpToClientShareService = false }) {
|
|
584
630
|
this.ensureApiClientAuthenticated();
|
|
585
631
|
await this.verifyPassword({
|
|
586
632
|
accountAddress,
|
|
587
633
|
password,
|
|
588
|
-
walletOperation: core.WalletOperation.RESHARE
|
|
589
|
-
signedSessionId
|
|
634
|
+
walletOperation: core.WalletOperation.RESHARE
|
|
590
635
|
});
|
|
591
636
|
const { existingExternalServerShareCount } = core.getServerWalletReshareConfig({
|
|
592
637
|
oldThresholdSignatureScheme,
|
|
@@ -596,12 +641,17 @@ class DynamicWalletClient {
|
|
|
596
641
|
accountAddress,
|
|
597
642
|
walletOperation: core.WalletOperation.RESHARE,
|
|
598
643
|
shareCount: existingExternalServerShareCount,
|
|
599
|
-
password
|
|
600
|
-
signedSessionId
|
|
644
|
+
password
|
|
601
645
|
});
|
|
646
|
+
externalServerKeyShares = externalServerKeyShares != null ? externalServerKeyShares : wallet.externalServerKeyShares;
|
|
647
|
+
if (!externalServerKeyShares) {
|
|
648
|
+
throw new Error('External server key shares are required to reshare');
|
|
649
|
+
}
|
|
602
650
|
const { newExternalServerInitKeygenResults, newExternalServerKeygenIds, existingExternalServerKeygenIds, existingExternalServerKeyShares } = await this.reshareStrategy({
|
|
603
651
|
chainName,
|
|
604
|
-
wallet,
|
|
652
|
+
wallet: _extends({}, wallet, {
|
|
653
|
+
externalServerKeyShares
|
|
654
|
+
}),
|
|
605
655
|
oldThresholdSignatureScheme,
|
|
606
656
|
newThresholdSignatureScheme
|
|
607
657
|
});
|
|
@@ -640,24 +690,26 @@ class DynamicWalletClient {
|
|
|
640
690
|
await this.storeEncryptedBackupByWallet({
|
|
641
691
|
accountAddress,
|
|
642
692
|
password,
|
|
643
|
-
|
|
693
|
+
backUpToClientShareService
|
|
644
694
|
});
|
|
645
695
|
return reshareResults;
|
|
646
696
|
}
|
|
647
|
-
async exportKey({ accountAddress, chainName, password = undefined,
|
|
697
|
+
async exportKey({ accountAddress, chainName, password = undefined, externalServerKeyShares }) {
|
|
648
698
|
this.ensureApiClientAuthenticated();
|
|
649
699
|
await this.verifyPassword({
|
|
650
700
|
accountAddress,
|
|
651
701
|
password,
|
|
652
|
-
walletOperation: core.WalletOperation.EXPORT_PRIVATE_KEY
|
|
653
|
-
signedSessionId
|
|
702
|
+
walletOperation: core.WalletOperation.EXPORT_PRIVATE_KEY
|
|
654
703
|
});
|
|
655
704
|
const wallet = await this.getWallet({
|
|
656
705
|
accountAddress,
|
|
657
706
|
password,
|
|
658
|
-
walletOperation: core.WalletOperation.EXPORT_PRIVATE_KEY
|
|
659
|
-
signedSessionId
|
|
707
|
+
walletOperation: core.WalletOperation.EXPORT_PRIVATE_KEY
|
|
660
708
|
});
|
|
709
|
+
externalServerKeyShares = externalServerKeyShares != null ? externalServerKeyShares : wallet.externalServerKeyShares;
|
|
710
|
+
if (!externalServerKeyShares) {
|
|
711
|
+
throw new Error('External server key shares are required to export a private key');
|
|
712
|
+
}
|
|
661
713
|
const mpcSigner = getMPCSigner({
|
|
662
714
|
chainName,
|
|
663
715
|
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
@@ -742,7 +794,7 @@ class DynamicWalletClient {
|
|
|
742
794
|
throw new Error('Ceremony completion timeout');
|
|
743
795
|
}
|
|
744
796
|
}
|
|
745
|
-
async storeEncryptedBackupByWallet({ accountAddress, externalServerKeyShares = undefined, password = undefined,
|
|
797
|
+
async storeEncryptedBackupByWallet({ accountAddress, externalServerKeyShares = undefined, password = undefined, backUpToClientShareService }) {
|
|
746
798
|
this.ensureApiClientAuthenticated();
|
|
747
799
|
//add retry logic for ceremony completion to prevent race condition
|
|
748
800
|
await this.ensureCeremonyCompletionBeforeBackup({
|
|
@@ -751,7 +803,7 @@ class DynamicWalletClient {
|
|
|
751
803
|
try {
|
|
752
804
|
const keySharesToBackup = externalServerKeyShares != null ? externalServerKeyShares : await this.getExternalServerKeyShares({
|
|
753
805
|
accountAddress,
|
|
754
|
-
|
|
806
|
+
password
|
|
755
807
|
});
|
|
756
808
|
if (!keySharesToBackup || keySharesToBackup.length === 0) {
|
|
757
809
|
throw new Error(`Key shares not found for accountAddress: ${accountAddress}`);
|
|
@@ -763,27 +815,42 @@ class DynamicWalletClient {
|
|
|
763
815
|
if (!this.walletMap[accountAddress] || !this.walletMap[accountAddress].walletId) {
|
|
764
816
|
throw new Error(`WalletId not found for accountAddress: ${accountAddress}`);
|
|
765
817
|
}
|
|
766
|
-
|
|
818
|
+
const locations = [];
|
|
819
|
+
if (backUpToClientShareService) {
|
|
820
|
+
const data = await this.apiClient.storeEncryptedBackupByWallet({
|
|
821
|
+
walletId: this.walletMap[accountAddress].walletId,
|
|
822
|
+
encryptedKeyShares: encryptedKeyShares,
|
|
823
|
+
passwordEncrypted: Boolean(password) && password !== this.environmentId,
|
|
824
|
+
encryptionVersion: ENCRYPTION_VERSION_CURRENT,
|
|
825
|
+
requiresSignedSessionId: false
|
|
826
|
+
});
|
|
827
|
+
locations.push({
|
|
828
|
+
location: core.BackupLocation.DYNAMIC,
|
|
829
|
+
externalKeyShareId: data.keyShareIds[0]
|
|
830
|
+
});
|
|
831
|
+
} else {
|
|
832
|
+
locations.push({
|
|
833
|
+
location: core.BackupLocation.EXTERNAL
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
const backupData = await this.apiClient.markKeySharesAsBackedUp({
|
|
767
837
|
walletId: this.walletMap[accountAddress].walletId,
|
|
768
|
-
locations
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
838
|
+
locations
|
|
839
|
+
});
|
|
840
|
+
const updatedBackupInfo = getExternalServerKeyShareBackupInfo({
|
|
841
|
+
walletProperties: {
|
|
842
|
+
derivationPath: this.walletMap[accountAddress].derivationPath,
|
|
843
|
+
keyShares: backupData.locationsWithKeyShares.map((ks)=>({
|
|
844
|
+
id: ks.keyShareId,
|
|
845
|
+
backupLocation: ks.location,
|
|
846
|
+
externalKeyShareId: ks.externalKeyShareId,
|
|
847
|
+
passwordEncrypted: Boolean(password) && password !== this.environmentId
|
|
848
|
+
})),
|
|
849
|
+
thresholdSignatureScheme: this.walletMap[accountAddress].thresholdSignatureScheme
|
|
850
|
+
}
|
|
773
851
|
});
|
|
774
852
|
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
775
|
-
externalServerKeySharesBackupInfo:
|
|
776
|
-
walletProperties: {
|
|
777
|
-
derivationPath: this.walletMap[accountAddress].derivationPath,
|
|
778
|
-
keyShares: encryptedKeyShares.map((encryptedKeyShare)=>({
|
|
779
|
-
id: uuid.v4(),
|
|
780
|
-
encryptedKeyShare,
|
|
781
|
-
backupLocation: core.BackupLocation.EXTERNAL,
|
|
782
|
-
passwordEncrypted: Boolean(password) && password !== this.environmentId
|
|
783
|
-
})),
|
|
784
|
-
thresholdSignatureScheme: this.walletMap[accountAddress].thresholdSignatureScheme
|
|
785
|
-
}
|
|
786
|
-
})
|
|
853
|
+
externalServerKeySharesBackupInfo: updatedBackupInfo
|
|
787
854
|
});
|
|
788
855
|
return encryptedKeyShares;
|
|
789
856
|
} catch (error) {
|
|
@@ -791,43 +858,37 @@ class DynamicWalletClient {
|
|
|
791
858
|
throw error;
|
|
792
859
|
}
|
|
793
860
|
}
|
|
794
|
-
async storeEncryptedBackupByWalletWithRetry({ accountAddress, externalServerKeyShares, password,
|
|
861
|
+
async storeEncryptedBackupByWalletWithRetry({ accountAddress, externalServerKeyShares, password, backUpToClientShareService }) {
|
|
795
862
|
await retryPromise(()=>this.storeEncryptedBackupByWallet({
|
|
796
863
|
accountAddress,
|
|
797
864
|
externalServerKeyShares,
|
|
798
865
|
password,
|
|
799
|
-
|
|
866
|
+
backUpToClientShareService
|
|
800
867
|
}), {
|
|
801
868
|
operationName: 'store encrypted backup',
|
|
802
869
|
logContext: {
|
|
803
|
-
walletAddress: accountAddress
|
|
804
|
-
keyShares: externalServerKeyShares == null ? void 0 : externalServerKeyShares.map((keyShare)=>this.encryptKeyShare({
|
|
805
|
-
keyShare,
|
|
806
|
-
password
|
|
807
|
-
}))
|
|
870
|
+
walletAddress: accountAddress
|
|
808
871
|
}
|
|
809
872
|
});
|
|
810
873
|
}
|
|
811
|
-
async getExternalServerKeyShares({ accountAddress, password
|
|
874
|
+
async getExternalServerKeyShares({ accountAddress, password }) {
|
|
812
875
|
const wallet = await this.getWallet({
|
|
813
876
|
accountAddress,
|
|
814
877
|
password,
|
|
815
|
-
walletOperation: core.WalletOperation.REACH_THRESHOLD
|
|
816
|
-
signedSessionId
|
|
878
|
+
walletOperation: core.WalletOperation.REACH_THRESHOLD
|
|
817
879
|
});
|
|
818
880
|
return wallet.externalServerKeyShares;
|
|
819
881
|
}
|
|
820
|
-
async updatePassword({ accountAddress, existingPassword, newPassword,
|
|
882
|
+
async updatePassword({ accountAddress, existingPassword, newPassword, backUpToClientShareService }) {
|
|
821
883
|
await this.getWallet({
|
|
822
884
|
accountAddress,
|
|
823
885
|
password: existingPassword,
|
|
824
|
-
walletOperation: core.WalletOperation.REACH_ALL_PARTIES
|
|
825
|
-
signedSessionId
|
|
886
|
+
walletOperation: core.WalletOperation.REACH_ALL_PARTIES
|
|
826
887
|
});
|
|
827
888
|
await this.storeEncryptedBackupByWallet({
|
|
828
889
|
accountAddress,
|
|
829
890
|
password: newPassword,
|
|
830
|
-
|
|
891
|
+
backUpToClientShareService
|
|
831
892
|
});
|
|
832
893
|
}
|
|
833
894
|
async decryptKeyShare({ keyShare, password }) {
|
|
@@ -869,7 +930,7 @@ class DynamicWalletClient {
|
|
|
869
930
|
requiredShareCount
|
|
870
931
|
};
|
|
871
932
|
}
|
|
872
|
-
async recoverEncryptedBackupByWallet({ accountAddress, password, walletOperation,
|
|
933
|
+
async recoverEncryptedBackupByWallet({ accountAddress, password, walletOperation, shareCount = undefined, storeRecoveredShares = true }) {
|
|
873
934
|
this.ensureApiClientAuthenticated();
|
|
874
935
|
const wallet = this.walletMap[accountAddress];
|
|
875
936
|
this.logger.debug(`recoverEncryptedBackupByWallet wallet: ${walletOperation}`, wallet);
|
|
@@ -883,7 +944,7 @@ class DynamicWalletClient {
|
|
|
883
944
|
const data = await this.apiClient.recoverEncryptedBackupByWallet({
|
|
884
945
|
walletId: wallet.walletId,
|
|
885
946
|
keyShareIds: dynamicKeyShareIds,
|
|
886
|
-
|
|
947
|
+
requiresSignedSessionId: false
|
|
887
948
|
});
|
|
888
949
|
const dynamicKeyShares = data.keyShares.filter((keyShare)=>keyShare.encryptedAccountCredential !== null && keyShare.backupLocation === core.BackupLocation.DYNAMIC);
|
|
889
950
|
const decryptedKeyShares = await Promise.all(dynamicKeyShares.map((keyShare)=>this.decryptKeyShare({
|
|
@@ -897,17 +958,15 @@ class DynamicWalletClient {
|
|
|
897
958
|
}
|
|
898
959
|
return decryptedKeyShares;
|
|
899
960
|
}
|
|
900
|
-
async exportExternalServerKeyShares({ accountAddress, password
|
|
961
|
+
async exportExternalServerKeyShares({ accountAddress, password }) {
|
|
901
962
|
await this.verifyPassword({
|
|
902
963
|
accountAddress,
|
|
903
964
|
password,
|
|
904
|
-
walletOperation: core.WalletOperation.REACH_ALL_PARTIES
|
|
905
|
-
signedSessionId
|
|
965
|
+
walletOperation: core.WalletOperation.REACH_ALL_PARTIES
|
|
906
966
|
});
|
|
907
967
|
const externalServerKeyShares = await this.getExternalServerKeyShares({
|
|
908
968
|
accountAddress,
|
|
909
|
-
password
|
|
910
|
-
signedSessionId
|
|
969
|
+
password
|
|
911
970
|
});
|
|
912
971
|
return externalServerKeyShares;
|
|
913
972
|
}
|
|
@@ -956,12 +1015,11 @@ class DynamicWalletClient {
|
|
|
956
1015
|
* verifyPassword attempts to recover and decrypt a single client key share using the provided password.
|
|
957
1016
|
* If successful, the key share is encrypted with the new password. This method solely performs the recovery
|
|
958
1017
|
* and decryption without storing the restored key shares. If unsuccessful, it throws an error.
|
|
959
|
-
*/ async verifyPassword({ accountAddress, password = undefined, walletOperation = core.WalletOperation.NO_OPERATION
|
|
1018
|
+
*/ async verifyPassword({ accountAddress, password = undefined, walletOperation = core.WalletOperation.NO_OPERATION }) {
|
|
960
1019
|
await this.getWallet({
|
|
961
1020
|
accountAddress,
|
|
962
1021
|
password,
|
|
963
|
-
walletOperation
|
|
964
|
-
signedSessionId
|
|
1022
|
+
walletOperation
|
|
965
1023
|
});
|
|
966
1024
|
if (await this.requiresPasswordForOperation({
|
|
967
1025
|
accountAddress,
|
|
@@ -981,12 +1039,10 @@ class DynamicWalletClient {
|
|
|
981
1039
|
throw new Error('No dynamic key shares found');
|
|
982
1040
|
}
|
|
983
1041
|
try {
|
|
984
|
-
// TODO(zfaizal2): throw error if signedSessionId is not provided after service deploy
|
|
985
1042
|
await this.recoverEncryptedBackupByWallet({
|
|
986
1043
|
accountAddress,
|
|
987
1044
|
password,
|
|
988
1045
|
walletOperation,
|
|
989
|
-
signedSessionId,
|
|
990
1046
|
shareCount: 1,
|
|
991
1047
|
storeRecoveredShares: false
|
|
992
1048
|
});
|
|
@@ -1049,43 +1105,61 @@ class DynamicWalletClient {
|
|
|
1049
1105
|
walletProperties: wallet == null ? void 0 : wallet.walletProperties
|
|
1050
1106
|
});
|
|
1051
1107
|
}
|
|
1052
|
-
async getWallet({ accountAddress, walletOperation = core.WalletOperation.NO_OPERATION, shareCount = undefined }) {
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1108
|
+
async getWallet({ accountAddress, walletOperation = core.WalletOperation.NO_OPERATION, shareCount = undefined, password = undefined }) {
|
|
1109
|
+
try {
|
|
1110
|
+
var _user_verifiedCredentials;
|
|
1111
|
+
this.ensureApiClientAuthenticated();
|
|
1112
|
+
const existingWalletCheck = await this.checkWalletFields({
|
|
1113
|
+
accountAddress,
|
|
1114
|
+
walletOperation,
|
|
1115
|
+
shareCount
|
|
1116
|
+
});
|
|
1117
|
+
if (existingWalletCheck) {
|
|
1118
|
+
this.logger.debug(`Wallet ${accountAddress} already exists`);
|
|
1119
|
+
return this.walletMap[accountAddress];
|
|
1120
|
+
}
|
|
1121
|
+
//todo: Question - why don't we just call getWallets here? so then all are preloaded
|
|
1122
|
+
// Fetch and restore wallet from server
|
|
1123
|
+
const user = await this.apiClient.getUser();
|
|
1124
|
+
const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
|
|
1125
|
+
this.logger.debug('Restoring wallet', wallet);
|
|
1126
|
+
const walletProperties = wallet.walletProperties;
|
|
1127
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
1128
|
+
walletId: wallet.id,
|
|
1129
|
+
chainName: wallet.chainName,
|
|
1130
|
+
accountAddress,
|
|
1131
|
+
thresholdSignatureScheme: walletProperties.thresholdSignatureScheme,
|
|
1132
|
+
derivationPath: walletProperties.derivationPath,
|
|
1133
|
+
externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo({
|
|
1134
|
+
walletProperties
|
|
1135
|
+
})
|
|
1136
|
+
});
|
|
1137
|
+
if (walletOperation !== core.WalletOperation.NO_OPERATION && await this.requiresRestoreBackupSharesForOperation({
|
|
1138
|
+
accountAddress,
|
|
1139
|
+
walletOperation
|
|
1140
|
+
})) {
|
|
1141
|
+
const decryptedKeyShares = await this.recoverEncryptedBackupByWallet({
|
|
1142
|
+
accountAddress,
|
|
1143
|
+
password: password != null ? password : this.environmentId,
|
|
1144
|
+
walletOperation: walletOperation,
|
|
1145
|
+
shareCount
|
|
1146
|
+
});
|
|
1147
|
+
this.logger.debug('[DynamicWaasWalletClient] Recovered backup', decryptedKeyShares);
|
|
1148
|
+
}
|
|
1149
|
+
// externalServerKeyShares
|
|
1150
|
+
const walletCount = Object.keys(this.walletMap).length;
|
|
1151
|
+
if (walletCount === 0) {
|
|
1152
|
+
throw new Error('No wallets found');
|
|
1153
|
+
}
|
|
1154
|
+
// Return the only wallet if there's just one
|
|
1155
|
+
if (walletCount === 1) {
|
|
1156
|
+
return Object.values(this.walletMap)[0];
|
|
1157
|
+
}
|
|
1062
1158
|
return this.walletMap[accountAddress];
|
|
1159
|
+
} catch (error) {
|
|
1160
|
+
this.logger.error('Error in getWallet', error);
|
|
1161
|
+
throw error;
|
|
1063
1162
|
}
|
|
1064
|
-
//todo: Question - why don't we just call getWallets here? so then all are preloaded
|
|
1065
|
-
// Fetch and restore wallet from server
|
|
1066
|
-
const user = await this.apiClient.getUser();
|
|
1067
|
-
const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
|
|
1068
|
-
this.logger.debug('Restoring wallet', wallet);
|
|
1069
|
-
const walletProperties = wallet.walletProperties;
|
|
1070
|
-
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
1071
|
-
walletId: wallet.id,
|
|
1072
|
-
chainName: wallet.chainName,
|
|
1073
|
-
accountAddress,
|
|
1074
|
-
thresholdSignatureScheme: walletProperties.thresholdSignatureScheme,
|
|
1075
|
-
derivationPath: walletProperties.derivationPath,
|
|
1076
|
-
externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo({
|
|
1077
|
-
walletProperties
|
|
1078
|
-
})
|
|
1079
|
-
});
|
|
1080
|
-
const walletCount = Object.keys(this.walletMap).length;
|
|
1081
|
-
if (walletCount === 0) {
|
|
1082
|
-
throw new Error('No wallets found');
|
|
1083
|
-
}
|
|
1084
|
-
// Return the only wallet if there's just one
|
|
1085
|
-
if (walletCount === 1) {
|
|
1086
|
-
return Object.values(this.walletMap)[0];
|
|
1087
|
-
}
|
|
1088
|
-
return this.walletMap[accountAddress];
|
|
1089
1163
|
}
|
|
1090
1164
|
async getWallets() {
|
|
1091
1165
|
var _user_verifiedCredentials;
|