@dynamic-labs-wallet/node 0.0.136 → 0.0.137
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 +187 -93
- package/index.esm.js +187 -93
- 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 +15 -8
- 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,7 +507,6 @@ class DynamicWalletClient {
|
|
|
464
507
|
throw error;
|
|
465
508
|
}
|
|
466
509
|
}
|
|
467
|
-
//todo: need to modify with imported flag
|
|
468
510
|
async sign({ accountAddress, externalServerKeyShares, message, chainName, password = undefined, isFormatted = false }) {
|
|
469
511
|
await this.verifyPassword({
|
|
470
512
|
accountAddress,
|
|
@@ -476,6 +518,10 @@ class DynamicWalletClient {
|
|
|
476
518
|
walletOperation: core.WalletOperation.SIGN_MESSAGE,
|
|
477
519
|
password
|
|
478
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
|
+
}
|
|
479
525
|
// Perform the dynamic server sign
|
|
480
526
|
const data = await this.dynamicServerSign({
|
|
481
527
|
walletId: wallet.walletId,
|
|
@@ -494,7 +540,7 @@ class DynamicWalletClient {
|
|
|
494
540
|
});
|
|
495
541
|
return signature;
|
|
496
542
|
}
|
|
497
|
-
async refreshWalletAccountShares({ accountAddress, chainName, password = undefined }) {
|
|
543
|
+
async refreshWalletAccountShares({ accountAddress, chainName, password = undefined, externalServerKeyShares, backUpToClientShareService = false }) {
|
|
498
544
|
this.ensureApiClientAuthenticated();
|
|
499
545
|
await this.verifyPassword({
|
|
500
546
|
accountAddress,
|
|
@@ -515,14 +561,19 @@ class DynamicWalletClient {
|
|
|
515
561
|
walletId: wallet.walletId
|
|
516
562
|
});
|
|
517
563
|
const roomId = data.roomId;
|
|
518
|
-
|
|
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)));
|
|
519
569
|
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
520
570
|
externalServerKeyShares: refreshResults,
|
|
521
571
|
externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo()
|
|
522
572
|
});
|
|
523
573
|
await this.storeEncryptedBackupByWallet({
|
|
524
574
|
accountAddress,
|
|
525
|
-
password: password != null ? password : this.environmentId
|
|
575
|
+
password: password != null ? password : this.environmentId,
|
|
576
|
+
backUpToClientShareService
|
|
526
577
|
});
|
|
527
578
|
return refreshResults;
|
|
528
579
|
}
|
|
@@ -575,7 +626,7 @@ class DynamicWalletClient {
|
|
|
575
626
|
existingExternalServerKeyShares
|
|
576
627
|
};
|
|
577
628
|
}
|
|
578
|
-
async reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined }) {
|
|
629
|
+
async reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined, externalServerKeyShares, backUpToClientShareService = false }) {
|
|
579
630
|
this.ensureApiClientAuthenticated();
|
|
580
631
|
await this.verifyPassword({
|
|
581
632
|
accountAddress,
|
|
@@ -592,9 +643,15 @@ class DynamicWalletClient {
|
|
|
592
643
|
shareCount: existingExternalServerShareCount,
|
|
593
644
|
password
|
|
594
645
|
});
|
|
646
|
+
externalServerKeyShares = externalServerKeyShares != null ? externalServerKeyShares : wallet.externalServerKeyShares;
|
|
647
|
+
if (!externalServerKeyShares) {
|
|
648
|
+
throw new Error('External server key shares are required to reshare');
|
|
649
|
+
}
|
|
595
650
|
const { newExternalServerInitKeygenResults, newExternalServerKeygenIds, existingExternalServerKeygenIds, existingExternalServerKeyShares } = await this.reshareStrategy({
|
|
596
651
|
chainName,
|
|
597
|
-
wallet,
|
|
652
|
+
wallet: _extends({}, wallet, {
|
|
653
|
+
externalServerKeyShares
|
|
654
|
+
}),
|
|
598
655
|
oldThresholdSignatureScheme,
|
|
599
656
|
newThresholdSignatureScheme
|
|
600
657
|
});
|
|
@@ -632,7 +689,8 @@ class DynamicWalletClient {
|
|
|
632
689
|
});
|
|
633
690
|
await this.storeEncryptedBackupByWallet({
|
|
634
691
|
accountAddress,
|
|
635
|
-
password
|
|
692
|
+
password,
|
|
693
|
+
backUpToClientShareService
|
|
636
694
|
});
|
|
637
695
|
return reshareResults;
|
|
638
696
|
}
|
|
@@ -648,6 +706,10 @@ class DynamicWalletClient {
|
|
|
648
706
|
password,
|
|
649
707
|
walletOperation: core.WalletOperation.EXPORT_PRIVATE_KEY
|
|
650
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
|
+
}
|
|
651
713
|
const mpcSigner = getMPCSigner({
|
|
652
714
|
chainName,
|
|
653
715
|
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
@@ -732,7 +794,7 @@ class DynamicWalletClient {
|
|
|
732
794
|
throw new Error('Ceremony completion timeout');
|
|
733
795
|
}
|
|
734
796
|
}
|
|
735
|
-
async storeEncryptedBackupByWallet({ accountAddress, externalServerKeyShares = undefined, password = undefined }) {
|
|
797
|
+
async storeEncryptedBackupByWallet({ accountAddress, externalServerKeyShares = undefined, password = undefined, backUpToClientShareService }) {
|
|
736
798
|
this.ensureApiClientAuthenticated();
|
|
737
799
|
//add retry logic for ceremony completion to prevent race condition
|
|
738
800
|
await this.ensureCeremonyCompletionBeforeBackup({
|
|
@@ -740,7 +802,8 @@ class DynamicWalletClient {
|
|
|
740
802
|
});
|
|
741
803
|
try {
|
|
742
804
|
const keySharesToBackup = externalServerKeyShares != null ? externalServerKeyShares : await this.getExternalServerKeyShares({
|
|
743
|
-
accountAddress
|
|
805
|
+
accountAddress,
|
|
806
|
+
password
|
|
744
807
|
});
|
|
745
808
|
if (!keySharesToBackup || keySharesToBackup.length === 0) {
|
|
746
809
|
throw new Error(`Key shares not found for accountAddress: ${accountAddress}`);
|
|
@@ -752,27 +815,42 @@ class DynamicWalletClient {
|
|
|
752
815
|
if (!this.walletMap[accountAddress] || !this.walletMap[accountAddress].walletId) {
|
|
753
816
|
throw new Error(`WalletId not found for accountAddress: ${accountAddress}`);
|
|
754
817
|
}
|
|
755
|
-
|
|
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({
|
|
756
837
|
walletId: this.walletMap[accountAddress].walletId,
|
|
757
|
-
locations
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
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
|
+
}
|
|
762
851
|
});
|
|
763
852
|
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
764
|
-
externalServerKeySharesBackupInfo:
|
|
765
|
-
walletProperties: {
|
|
766
|
-
derivationPath: this.walletMap[accountAddress].derivationPath,
|
|
767
|
-
keyShares: encryptedKeyShares.map((encryptedKeyShare)=>({
|
|
768
|
-
id: uuid.v4(),
|
|
769
|
-
encryptedKeyShare,
|
|
770
|
-
backupLocation: core.BackupLocation.EXTERNAL,
|
|
771
|
-
passwordEncrypted: Boolean(password) && password !== this.environmentId
|
|
772
|
-
})),
|
|
773
|
-
thresholdSignatureScheme: this.walletMap[accountAddress].thresholdSignatureScheme
|
|
774
|
-
}
|
|
775
|
-
})
|
|
853
|
+
externalServerKeySharesBackupInfo: updatedBackupInfo
|
|
776
854
|
});
|
|
777
855
|
return encryptedKeyShares;
|
|
778
856
|
} catch (error) {
|
|
@@ -780,19 +858,16 @@ class DynamicWalletClient {
|
|
|
780
858
|
throw error;
|
|
781
859
|
}
|
|
782
860
|
}
|
|
783
|
-
async storeEncryptedBackupByWalletWithRetry({ accountAddress, externalServerKeyShares, password }) {
|
|
861
|
+
async storeEncryptedBackupByWalletWithRetry({ accountAddress, externalServerKeyShares, password, backUpToClientShareService }) {
|
|
784
862
|
await retryPromise(()=>this.storeEncryptedBackupByWallet({
|
|
785
863
|
accountAddress,
|
|
786
864
|
externalServerKeyShares,
|
|
787
|
-
password
|
|
865
|
+
password,
|
|
866
|
+
backUpToClientShareService
|
|
788
867
|
}), {
|
|
789
868
|
operationName: 'store encrypted backup',
|
|
790
869
|
logContext: {
|
|
791
|
-
walletAddress: accountAddress
|
|
792
|
-
keyShares: externalServerKeyShares == null ? void 0 : externalServerKeyShares.map((keyShare)=>this.encryptKeyShare({
|
|
793
|
-
keyShare,
|
|
794
|
-
password
|
|
795
|
-
}))
|
|
870
|
+
walletAddress: accountAddress
|
|
796
871
|
}
|
|
797
872
|
});
|
|
798
873
|
}
|
|
@@ -804,7 +879,7 @@ class DynamicWalletClient {
|
|
|
804
879
|
});
|
|
805
880
|
return wallet.externalServerKeyShares;
|
|
806
881
|
}
|
|
807
|
-
async updatePassword({ accountAddress, existingPassword, newPassword }) {
|
|
882
|
+
async updatePassword({ accountAddress, existingPassword, newPassword, backUpToClientShareService }) {
|
|
808
883
|
await this.getWallet({
|
|
809
884
|
accountAddress,
|
|
810
885
|
password: existingPassword,
|
|
@@ -812,7 +887,8 @@ class DynamicWalletClient {
|
|
|
812
887
|
});
|
|
813
888
|
await this.storeEncryptedBackupByWallet({
|
|
814
889
|
accountAddress,
|
|
815
|
-
password: newPassword
|
|
890
|
+
password: newPassword,
|
|
891
|
+
backUpToClientShareService
|
|
816
892
|
});
|
|
817
893
|
}
|
|
818
894
|
async decryptKeyShare({ keyShare, password }) {
|
|
@@ -1029,43 +1105,61 @@ class DynamicWalletClient {
|
|
|
1029
1105
|
walletProperties: wallet == null ? void 0 : wallet.walletProperties
|
|
1030
1106
|
});
|
|
1031
1107
|
}
|
|
1032
|
-
async getWallet({ accountAddress, walletOperation = core.WalletOperation.NO_OPERATION, shareCount = undefined }) {
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
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
|
+
}
|
|
1042
1158
|
return this.walletMap[accountAddress];
|
|
1159
|
+
} catch (error) {
|
|
1160
|
+
this.logger.error('Error in getWallet', error);
|
|
1161
|
+
throw error;
|
|
1043
1162
|
}
|
|
1044
|
-
//todo: Question - why don't we just call getWallets here? so then all are preloaded
|
|
1045
|
-
// Fetch and restore wallet from server
|
|
1046
|
-
const user = await this.apiClient.getUser();
|
|
1047
|
-
const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
|
|
1048
|
-
this.logger.debug('Restoring wallet', wallet);
|
|
1049
|
-
const walletProperties = wallet.walletProperties;
|
|
1050
|
-
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
1051
|
-
walletId: wallet.id,
|
|
1052
|
-
chainName: wallet.chainName,
|
|
1053
|
-
accountAddress,
|
|
1054
|
-
thresholdSignatureScheme: walletProperties.thresholdSignatureScheme,
|
|
1055
|
-
derivationPath: walletProperties.derivationPath,
|
|
1056
|
-
externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo({
|
|
1057
|
-
walletProperties
|
|
1058
|
-
})
|
|
1059
|
-
});
|
|
1060
|
-
const walletCount = Object.keys(this.walletMap).length;
|
|
1061
|
-
if (walletCount === 0) {
|
|
1062
|
-
throw new Error('No wallets found');
|
|
1063
|
-
}
|
|
1064
|
-
// Return the only wallet if there's just one
|
|
1065
|
-
if (walletCount === 1) {
|
|
1066
|
-
return Object.values(this.walletMap)[0];
|
|
1067
|
-
}
|
|
1068
|
-
return this.walletMap[accountAddress];
|
|
1069
1163
|
}
|
|
1070
1164
|
async getWallets() {
|
|
1071
1165
|
var _user_verifiedCredentials;
|
package/index.esm.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,7 +507,6 @@ class DynamicWalletClient {
|
|
|
464
507
|
throw error;
|
|
465
508
|
}
|
|
466
509
|
}
|
|
467
|
-
//todo: need to modify with imported flag
|
|
468
510
|
async sign({ accountAddress, externalServerKeyShares, message, chainName, password = undefined, isFormatted = false }) {
|
|
469
511
|
await this.verifyPassword({
|
|
470
512
|
accountAddress,
|
|
@@ -476,6 +518,10 @@ class DynamicWalletClient {
|
|
|
476
518
|
walletOperation: WalletOperation.SIGN_MESSAGE,
|
|
477
519
|
password
|
|
478
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
|
+
}
|
|
479
525
|
// Perform the dynamic server sign
|
|
480
526
|
const data = await this.dynamicServerSign({
|
|
481
527
|
walletId: wallet.walletId,
|
|
@@ -494,7 +540,7 @@ class DynamicWalletClient {
|
|
|
494
540
|
});
|
|
495
541
|
return signature;
|
|
496
542
|
}
|
|
497
|
-
async refreshWalletAccountShares({ accountAddress, chainName, password = undefined }) {
|
|
543
|
+
async refreshWalletAccountShares({ accountAddress, chainName, password = undefined, externalServerKeyShares, backUpToClientShareService = false }) {
|
|
498
544
|
this.ensureApiClientAuthenticated();
|
|
499
545
|
await this.verifyPassword({
|
|
500
546
|
accountAddress,
|
|
@@ -515,14 +561,19 @@ class DynamicWalletClient {
|
|
|
515
561
|
walletId: wallet.walletId
|
|
516
562
|
});
|
|
517
563
|
const roomId = data.roomId;
|
|
518
|
-
|
|
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)));
|
|
519
569
|
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
520
570
|
externalServerKeyShares: refreshResults,
|
|
521
571
|
externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo()
|
|
522
572
|
});
|
|
523
573
|
await this.storeEncryptedBackupByWallet({
|
|
524
574
|
accountAddress,
|
|
525
|
-
password: password != null ? password : this.environmentId
|
|
575
|
+
password: password != null ? password : this.environmentId,
|
|
576
|
+
backUpToClientShareService
|
|
526
577
|
});
|
|
527
578
|
return refreshResults;
|
|
528
579
|
}
|
|
@@ -575,7 +626,7 @@ class DynamicWalletClient {
|
|
|
575
626
|
existingExternalServerKeyShares
|
|
576
627
|
};
|
|
577
628
|
}
|
|
578
|
-
async reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined }) {
|
|
629
|
+
async reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined, externalServerKeyShares, backUpToClientShareService = false }) {
|
|
579
630
|
this.ensureApiClientAuthenticated();
|
|
580
631
|
await this.verifyPassword({
|
|
581
632
|
accountAddress,
|
|
@@ -592,9 +643,15 @@ class DynamicWalletClient {
|
|
|
592
643
|
shareCount: existingExternalServerShareCount,
|
|
593
644
|
password
|
|
594
645
|
});
|
|
646
|
+
externalServerKeyShares = externalServerKeyShares != null ? externalServerKeyShares : wallet.externalServerKeyShares;
|
|
647
|
+
if (!externalServerKeyShares) {
|
|
648
|
+
throw new Error('External server key shares are required to reshare');
|
|
649
|
+
}
|
|
595
650
|
const { newExternalServerInitKeygenResults, newExternalServerKeygenIds, existingExternalServerKeygenIds, existingExternalServerKeyShares } = await this.reshareStrategy({
|
|
596
651
|
chainName,
|
|
597
|
-
wallet,
|
|
652
|
+
wallet: _extends({}, wallet, {
|
|
653
|
+
externalServerKeyShares
|
|
654
|
+
}),
|
|
598
655
|
oldThresholdSignatureScheme,
|
|
599
656
|
newThresholdSignatureScheme
|
|
600
657
|
});
|
|
@@ -632,7 +689,8 @@ class DynamicWalletClient {
|
|
|
632
689
|
});
|
|
633
690
|
await this.storeEncryptedBackupByWallet({
|
|
634
691
|
accountAddress,
|
|
635
|
-
password
|
|
692
|
+
password,
|
|
693
|
+
backUpToClientShareService
|
|
636
694
|
});
|
|
637
695
|
return reshareResults;
|
|
638
696
|
}
|
|
@@ -648,6 +706,10 @@ class DynamicWalletClient {
|
|
|
648
706
|
password,
|
|
649
707
|
walletOperation: WalletOperation.EXPORT_PRIVATE_KEY
|
|
650
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
|
+
}
|
|
651
713
|
const mpcSigner = getMPCSigner({
|
|
652
714
|
chainName,
|
|
653
715
|
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
@@ -732,7 +794,7 @@ class DynamicWalletClient {
|
|
|
732
794
|
throw new Error('Ceremony completion timeout');
|
|
733
795
|
}
|
|
734
796
|
}
|
|
735
|
-
async storeEncryptedBackupByWallet({ accountAddress, externalServerKeyShares = undefined, password = undefined }) {
|
|
797
|
+
async storeEncryptedBackupByWallet({ accountAddress, externalServerKeyShares = undefined, password = undefined, backUpToClientShareService }) {
|
|
736
798
|
this.ensureApiClientAuthenticated();
|
|
737
799
|
//add retry logic for ceremony completion to prevent race condition
|
|
738
800
|
await this.ensureCeremonyCompletionBeforeBackup({
|
|
@@ -740,7 +802,8 @@ class DynamicWalletClient {
|
|
|
740
802
|
});
|
|
741
803
|
try {
|
|
742
804
|
const keySharesToBackup = externalServerKeyShares != null ? externalServerKeyShares : await this.getExternalServerKeyShares({
|
|
743
|
-
accountAddress
|
|
805
|
+
accountAddress,
|
|
806
|
+
password
|
|
744
807
|
});
|
|
745
808
|
if (!keySharesToBackup || keySharesToBackup.length === 0) {
|
|
746
809
|
throw new Error(`Key shares not found for accountAddress: ${accountAddress}`);
|
|
@@ -752,27 +815,42 @@ class DynamicWalletClient {
|
|
|
752
815
|
if (!this.walletMap[accountAddress] || !this.walletMap[accountAddress].walletId) {
|
|
753
816
|
throw new Error(`WalletId not found for accountAddress: ${accountAddress}`);
|
|
754
817
|
}
|
|
755
|
-
|
|
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: BackupLocation.DYNAMIC,
|
|
829
|
+
externalKeyShareId: data.keyShareIds[0]
|
|
830
|
+
});
|
|
831
|
+
} else {
|
|
832
|
+
locations.push({
|
|
833
|
+
location: BackupLocation.EXTERNAL
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
const backupData = await this.apiClient.markKeySharesAsBackedUp({
|
|
756
837
|
walletId: this.walletMap[accountAddress].walletId,
|
|
757
|
-
locations
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
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
|
+
}
|
|
762
851
|
});
|
|
763
852
|
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
764
|
-
externalServerKeySharesBackupInfo:
|
|
765
|
-
walletProperties: {
|
|
766
|
-
derivationPath: this.walletMap[accountAddress].derivationPath,
|
|
767
|
-
keyShares: encryptedKeyShares.map((encryptedKeyShare)=>({
|
|
768
|
-
id: v4(),
|
|
769
|
-
encryptedKeyShare,
|
|
770
|
-
backupLocation: BackupLocation.EXTERNAL,
|
|
771
|
-
passwordEncrypted: Boolean(password) && password !== this.environmentId
|
|
772
|
-
})),
|
|
773
|
-
thresholdSignatureScheme: this.walletMap[accountAddress].thresholdSignatureScheme
|
|
774
|
-
}
|
|
775
|
-
})
|
|
853
|
+
externalServerKeySharesBackupInfo: updatedBackupInfo
|
|
776
854
|
});
|
|
777
855
|
return encryptedKeyShares;
|
|
778
856
|
} catch (error) {
|
|
@@ -780,19 +858,16 @@ class DynamicWalletClient {
|
|
|
780
858
|
throw error;
|
|
781
859
|
}
|
|
782
860
|
}
|
|
783
|
-
async storeEncryptedBackupByWalletWithRetry({ accountAddress, externalServerKeyShares, password }) {
|
|
861
|
+
async storeEncryptedBackupByWalletWithRetry({ accountAddress, externalServerKeyShares, password, backUpToClientShareService }) {
|
|
784
862
|
await retryPromise(()=>this.storeEncryptedBackupByWallet({
|
|
785
863
|
accountAddress,
|
|
786
864
|
externalServerKeyShares,
|
|
787
|
-
password
|
|
865
|
+
password,
|
|
866
|
+
backUpToClientShareService
|
|
788
867
|
}), {
|
|
789
868
|
operationName: 'store encrypted backup',
|
|
790
869
|
logContext: {
|
|
791
|
-
walletAddress: accountAddress
|
|
792
|
-
keyShares: externalServerKeyShares == null ? void 0 : externalServerKeyShares.map((keyShare)=>this.encryptKeyShare({
|
|
793
|
-
keyShare,
|
|
794
|
-
password
|
|
795
|
-
}))
|
|
870
|
+
walletAddress: accountAddress
|
|
796
871
|
}
|
|
797
872
|
});
|
|
798
873
|
}
|
|
@@ -804,7 +879,7 @@ class DynamicWalletClient {
|
|
|
804
879
|
});
|
|
805
880
|
return wallet.externalServerKeyShares;
|
|
806
881
|
}
|
|
807
|
-
async updatePassword({ accountAddress, existingPassword, newPassword }) {
|
|
882
|
+
async updatePassword({ accountAddress, existingPassword, newPassword, backUpToClientShareService }) {
|
|
808
883
|
await this.getWallet({
|
|
809
884
|
accountAddress,
|
|
810
885
|
password: existingPassword,
|
|
@@ -812,7 +887,8 @@ class DynamicWalletClient {
|
|
|
812
887
|
});
|
|
813
888
|
await this.storeEncryptedBackupByWallet({
|
|
814
889
|
accountAddress,
|
|
815
|
-
password: newPassword
|
|
890
|
+
password: newPassword,
|
|
891
|
+
backUpToClientShareService
|
|
816
892
|
});
|
|
817
893
|
}
|
|
818
894
|
async decryptKeyShare({ keyShare, password }) {
|
|
@@ -1029,43 +1105,61 @@ class DynamicWalletClient {
|
|
|
1029
1105
|
walletProperties: wallet == null ? void 0 : wallet.walletProperties
|
|
1030
1106
|
});
|
|
1031
1107
|
}
|
|
1032
|
-
async getWallet({ accountAddress, walletOperation = WalletOperation.NO_OPERATION, shareCount = undefined }) {
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1108
|
+
async getWallet({ accountAddress, walletOperation = 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 !== 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
|
+
}
|
|
1042
1158
|
return this.walletMap[accountAddress];
|
|
1159
|
+
} catch (error) {
|
|
1160
|
+
this.logger.error('Error in getWallet', error);
|
|
1161
|
+
throw error;
|
|
1043
1162
|
}
|
|
1044
|
-
//todo: Question - why don't we just call getWallets here? so then all are preloaded
|
|
1045
|
-
// Fetch and restore wallet from server
|
|
1046
|
-
const user = await this.apiClient.getUser();
|
|
1047
|
-
const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
|
|
1048
|
-
this.logger.debug('Restoring wallet', wallet);
|
|
1049
|
-
const walletProperties = wallet.walletProperties;
|
|
1050
|
-
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
1051
|
-
walletId: wallet.id,
|
|
1052
|
-
chainName: wallet.chainName,
|
|
1053
|
-
accountAddress,
|
|
1054
|
-
thresholdSignatureScheme: walletProperties.thresholdSignatureScheme,
|
|
1055
|
-
derivationPath: walletProperties.derivationPath,
|
|
1056
|
-
externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo({
|
|
1057
|
-
walletProperties
|
|
1058
|
-
})
|
|
1059
|
-
});
|
|
1060
|
-
const walletCount = Object.keys(this.walletMap).length;
|
|
1061
|
-
if (walletCount === 0) {
|
|
1062
|
-
throw new Error('No wallets found');
|
|
1063
|
-
}
|
|
1064
|
-
// Return the only wallet if there's just one
|
|
1065
|
-
if (walletCount === 1) {
|
|
1066
|
-
return Object.values(this.walletMap)[0];
|
|
1067
|
-
}
|
|
1068
|
-
return this.walletMap[accountAddress];
|
|
1069
1163
|
}
|
|
1070
1164
|
async getWallets() {
|
|
1071
1165
|
var _user_verifiedCredentials;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs-wallet/node",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.137",
|
|
4
4
|
"license": "Licensed under the Dynamic Labs, Inc. Terms Of Service (https://www.dynamic.xyz/terms-conditions)",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@dynamic-labs-wallet/core": "0.0.
|
|
6
|
+
"@dynamic-labs-wallet/core": "0.0.137",
|
|
7
7
|
"@dynamic-labs/logger": "^4.25.3",
|
|
8
8
|
"uuid": "11.1.0",
|
|
9
9
|
"@noble/hashes": "1.7.1"
|
|
@@ -1,22 +1,62 @@
|
|
|
1
|
+
import { EncryptionMetadata } from '@dynamic-labs-wallet/core';
|
|
2
|
+
export declare const ENCRYPTION_VERSION_LEGACY = "v1";
|
|
3
|
+
export declare const ENCRYPTION_VERSION_CURRENT = "v2";
|
|
1
4
|
export declare const PBKDF2_ALGORITHM = "PBKDF2";
|
|
2
|
-
export declare const PBKDF2_ITERATIONS = 100000;
|
|
3
5
|
export declare const PBKDF2_HASH_ALGORITHM = "SHA-256";
|
|
4
6
|
export declare const AES_GCM_ALGORITHM = "AES-GCM";
|
|
5
7
|
export declare const AES_GCM_LENGTH = 256;
|
|
6
|
-
export declare const
|
|
8
|
+
export declare const ENCRYPTION_VERSIONS: {
|
|
9
|
+
readonly v1: {
|
|
10
|
+
readonly version: "v1";
|
|
11
|
+
readonly algorithm: "AES-GCM";
|
|
12
|
+
readonly keyDerivation: "PBKDF2";
|
|
13
|
+
readonly iterations: 100000;
|
|
14
|
+
readonly hashAlgorithm: "SHA-256";
|
|
15
|
+
readonly algorithmLength: 256;
|
|
16
|
+
};
|
|
17
|
+
readonly v2: {
|
|
18
|
+
readonly version: "v2";
|
|
19
|
+
readonly algorithm: "AES-GCM";
|
|
20
|
+
readonly keyDerivation: "PBKDF2";
|
|
21
|
+
readonly iterations: 1000000;
|
|
22
|
+
readonly hashAlgorithm: "SHA-256";
|
|
23
|
+
readonly algorithmLength: 256;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export declare const PBKDF2_ITERATIONS: 1000000;
|
|
27
|
+
export declare const PBKDF2_ITERATIONS_LEGACY: 100000;
|
|
28
|
+
export type EncryptionVersion = (typeof ENCRYPTION_VERSIONS)[keyof typeof ENCRYPTION_VERSIONS];
|
|
29
|
+
/**
|
|
30
|
+
* Encrypts data using the specified encryption version.
|
|
31
|
+
* Always uses the latest encryption configuration for new encryptions by default.
|
|
32
|
+
*/
|
|
33
|
+
export declare const encryptData: ({ data, password, version, }: {
|
|
7
34
|
data: string;
|
|
8
35
|
password: string;
|
|
36
|
+
version?: string;
|
|
9
37
|
}) => Promise<{
|
|
10
38
|
salt: string;
|
|
11
39
|
iv: string;
|
|
12
40
|
cipher: string;
|
|
41
|
+
version: string;
|
|
13
42
|
}>;
|
|
43
|
+
/**
|
|
44
|
+
* Decrypts data with version-based configuration.
|
|
45
|
+
* Uses the version field from the data to determine encryption parameters.
|
|
46
|
+
* Falls back to legacy version for backward compatibility if no version is specified.
|
|
47
|
+
*/
|
|
14
48
|
export declare const decryptData: ({ data, password, }: {
|
|
15
49
|
data: {
|
|
16
50
|
salt: string;
|
|
17
51
|
iv: string;
|
|
18
52
|
cipher: string;
|
|
53
|
+
version?: string;
|
|
19
54
|
};
|
|
20
55
|
password: string;
|
|
21
56
|
}) => Promise<string>;
|
|
57
|
+
/**
|
|
58
|
+
* Gets encryption metadata for a specific version.
|
|
59
|
+
* Used when we need to include metadata in legacy systems or APIs that require it.
|
|
60
|
+
*/
|
|
61
|
+
export declare const getEncryptionMetadataForVersion: (version: string) => EncryptionMetadata;
|
|
22
62
|
//# sourceMappingURL=encryption.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/backup/encryption.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/backup/encryption.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAQ/D,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAC9C,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAE/C,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,eAAO,MAAM,qBAAqB,YAAY,CAAC;AAC/C,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAC3C,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;CAiBtB,CAAC;AAEX,eAAO,MAAM,iBAAiB,SAC8B,CAAC;AAC7D,eAAO,MAAM,wBAAwB,QACsB,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAC3B,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,OAAO,mBAAmB,CAAC,CAAC;AAsCjE;;;GAGG;AACH,eAAO,MAAM,WAAW,iCAIrB;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;;;;;EAkCA,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,wBAGrB;IACD,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,QAAQ,EAAE,MAAM,CAAC;CAClB,oBA2CA,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,+BAA+B,YACjC,MAAM,KACd,kBAcF,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ServerKeyShare } from '../mpc/types';
|
|
2
|
+
import { WalletProperties } from '../types';
|
|
3
|
+
export declare const checkIfExternalServerKeySharesAreRequired: (wallet: WalletProperties, externalServerKeyShares?: ServerKeyShare[]) => void;
|
|
4
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/backup/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,eAAO,MAAM,yCAAyC,WAC5C,gBAAgB,4BACE,cAAc,EAAE,SAkB3C,CAAC"}
|
package/src/client.d.ts
CHANGED
|
@@ -82,16 +82,18 @@ export declare class DynamicWalletClient {
|
|
|
82
82
|
}): Promise<Uint8Array | EcdsaSignature>;
|
|
83
83
|
sign({ accountAddress, externalServerKeyShares, message, chainName, password, isFormatted, }: {
|
|
84
84
|
accountAddress: string;
|
|
85
|
-
externalServerKeyShares
|
|
85
|
+
externalServerKeyShares?: ServerKeyShare[];
|
|
86
86
|
message: string | Uint8Array;
|
|
87
87
|
chainName: string;
|
|
88
88
|
password?: string;
|
|
89
89
|
isFormatted?: boolean;
|
|
90
90
|
}): Promise<Uint8Array | EcdsaSignature>;
|
|
91
|
-
refreshWalletAccountShares({ accountAddress, chainName, password, }: {
|
|
91
|
+
refreshWalletAccountShares({ accountAddress, chainName, password, externalServerKeyShares, backUpToClientShareService, }: {
|
|
92
92
|
accountAddress: string;
|
|
93
93
|
chainName: string;
|
|
94
94
|
password?: string;
|
|
95
|
+
externalServerKeyShares?: ServerKeyShare[];
|
|
96
|
+
backUpToClientShareService?: boolean;
|
|
95
97
|
}): Promise<(EcdsaKeygenResult | BIP340KeygenResult)[]>;
|
|
96
98
|
getExportId({ chainName, serverKeyShare, }: {
|
|
97
99
|
chainName: string;
|
|
@@ -122,18 +124,20 @@ export declare class DynamicWalletClient {
|
|
|
122
124
|
existingExternalServerKeygenIds: string[];
|
|
123
125
|
existingExternalServerKeyShares: ServerKeyShare[];
|
|
124
126
|
}>;
|
|
125
|
-
reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password, }: {
|
|
127
|
+
reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password, externalServerKeyShares, backUpToClientShareService, }: {
|
|
126
128
|
chainName: string;
|
|
127
129
|
accountAddress: string;
|
|
128
130
|
oldThresholdSignatureScheme: ThresholdSignatureScheme;
|
|
129
131
|
newThresholdSignatureScheme: ThresholdSignatureScheme;
|
|
130
132
|
password?: string;
|
|
133
|
+
externalServerKeyShares?: ServerKeyShare[];
|
|
134
|
+
backUpToClientShareService?: boolean;
|
|
131
135
|
}): Promise<(EcdsaKeygenResult | BIP340KeygenResult)[]>;
|
|
132
136
|
exportKey({ accountAddress, chainName, password, externalServerKeyShares, }: {
|
|
133
137
|
accountAddress: string;
|
|
134
138
|
chainName: string;
|
|
135
139
|
password?: string;
|
|
136
|
-
externalServerKeyShares
|
|
140
|
+
externalServerKeyShares?: ServerKeyShare[];
|
|
137
141
|
}): Promise<{
|
|
138
142
|
derivedPrivateKey: string | undefined;
|
|
139
143
|
}>;
|
|
@@ -151,24 +155,27 @@ export declare class DynamicWalletClient {
|
|
|
151
155
|
ensureCeremonyCompletionBeforeBackup({ accountAddress, }: {
|
|
152
156
|
accountAddress: string;
|
|
153
157
|
}): Promise<void>;
|
|
154
|
-
storeEncryptedBackupByWallet({ accountAddress, externalServerKeyShares, password, }: {
|
|
158
|
+
storeEncryptedBackupByWallet({ accountAddress, externalServerKeyShares, password, backUpToClientShareService, }: {
|
|
155
159
|
accountAddress: string;
|
|
156
160
|
externalServerKeyShares?: ServerKeyShare[];
|
|
157
161
|
password?: string;
|
|
162
|
+
backUpToClientShareService: boolean;
|
|
158
163
|
}): Promise<string[]>;
|
|
159
|
-
storeEncryptedBackupByWalletWithRetry({ accountAddress, externalServerKeyShares, password, }: {
|
|
164
|
+
storeEncryptedBackupByWalletWithRetry({ accountAddress, externalServerKeyShares, password, backUpToClientShareService, }: {
|
|
160
165
|
accountAddress: string;
|
|
161
166
|
externalServerKeyShares?: ServerKeyShare[];
|
|
162
167
|
password?: string;
|
|
168
|
+
backUpToClientShareService: boolean;
|
|
163
169
|
}): Promise<void>;
|
|
164
170
|
getExternalServerKeyShares({ accountAddress, password, }: {
|
|
165
171
|
accountAddress: string;
|
|
166
172
|
password?: string;
|
|
167
173
|
}): Promise<import("./mpc").ServerKeyShare[]>;
|
|
168
|
-
updatePassword({ accountAddress, existingPassword, newPassword, }: {
|
|
174
|
+
updatePassword({ accountAddress, existingPassword, newPassword, backUpToClientShareService, }: {
|
|
169
175
|
accountAddress: string;
|
|
170
176
|
existingPassword?: string;
|
|
171
177
|
newPassword?: string;
|
|
178
|
+
backUpToClientShareService: boolean;
|
|
172
179
|
}): Promise<void>;
|
|
173
180
|
decryptKeyShare({ keyShare, password, }: {
|
|
174
181
|
keyShare: string;
|
|
@@ -243,7 +250,7 @@ export declare class DynamicWalletClient {
|
|
|
243
250
|
getWalletExternalServerKeyShareBackupInfo({ accountAddress, }: {
|
|
244
251
|
accountAddress: string;
|
|
245
252
|
}): Promise<KeyShareBackupInfo>;
|
|
246
|
-
getWallet({ accountAddress, walletOperation, shareCount, }: {
|
|
253
|
+
getWallet({ accountAddress, walletOperation, shareCount, password, }: {
|
|
247
254
|
accountAddress: string;
|
|
248
255
|
walletOperation?: WalletOperation;
|
|
249
256
|
shareCount?: number;
|
package/src/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../packages/src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EAEd,cAAc,EAId,6BAA6B,EAC9B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAIhB,eAAe,EACf,kBAAkB,EAClB,cAAc,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../packages/src/client.ts"],"names":[],"mappings":"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"}
|