@dynamic-labs-wallet/browser 0.0.260 → 0.0.262
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 +205 -96
- package/index.esm.js +206 -98
- package/package.json +2 -2
- package/src/backup/encryption/core.d.ts.map +1 -1
- package/src/client.d.ts +14 -0
- package/src/client.d.ts.map +1 -1
- package/src/normalizeAddress.d.ts +7 -0
- package/src/normalizeAddress.d.ts.map +1 -0
- package/src/queue.d.ts.map +1 -1
- package/src/utils.d.ts +11 -1
- package/src/utils.d.ts.map +1 -1
package/index.cjs.js
CHANGED
|
@@ -221,6 +221,11 @@ const ensureBase64Padding = (str)=>{
|
|
|
221
221
|
]);
|
|
222
222
|
};
|
|
223
223
|
|
|
224
|
+
const INVALID_PASSWORD_ERROR = 'Decryption failed: Invalid password. Please check your password and try again.';
|
|
225
|
+
/**
|
|
226
|
+
* Check if an error is an OperationError from SubtleCrypto.decrypt,
|
|
227
|
+
* which indicates authentication failure (wrong password/derived key)
|
|
228
|
+
*/ const isInvalidPasswordError = (error)=>error instanceof Error && error.name === 'OperationError';
|
|
224
229
|
/**
|
|
225
230
|
* Get the appropriate key derivation function based on the encryption config
|
|
226
231
|
*/ const getKey = async (params, encryptionConfig)=>{
|
|
@@ -309,10 +314,15 @@ const ensureBase64Padding = (str)=>{
|
|
|
309
314
|
}, key, cipherBytes);
|
|
310
315
|
return new TextDecoder().decode(decryptedData);
|
|
311
316
|
} catch (retryError) {
|
|
312
|
-
|
|
317
|
+
if (isInvalidPasswordError(retryError)) {
|
|
318
|
+
throw new Error(INVALID_PASSWORD_ERROR);
|
|
319
|
+
}
|
|
313
320
|
throw new Error(`Decryption failed after retry with parallelism=1: ${retryError}`);
|
|
314
321
|
}
|
|
315
322
|
}
|
|
323
|
+
if (isInvalidPasswordError(error)) {
|
|
324
|
+
throw new Error(INVALID_PASSWORD_ERROR);
|
|
325
|
+
}
|
|
316
326
|
throw new Error('Decryption failed: ' + error);
|
|
317
327
|
}
|
|
318
328
|
};
|
|
@@ -505,6 +515,12 @@ const ERROR_EXPORT_PRIVATE_KEY = '[DynamicWaasWalletClient]: Error exporting pri
|
|
|
505
515
|
const ERROR_IMPORT_PRIVATE_KEY = '[DynamicWaasWalletClient]: Error importing private key';
|
|
506
516
|
const ERROR_PUBLIC_KEY_MISMATCH = 'Mismatch between the public keys of the server and the ones provided';
|
|
507
517
|
|
|
518
|
+
/**
|
|
519
|
+
* Normalizes an address to lowercase for consistent map key lookups.
|
|
520
|
+
* This ensures that addresses with different casing (e.g., EIP-55 checksummed vs lowercase)
|
|
521
|
+
* resolve to the same wallet entry.
|
|
522
|
+
*/ const normalizeAddress = (address)=>address.toLowerCase();
|
|
523
|
+
|
|
508
524
|
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
509
525
|
const isBrowser = ()=>typeof window !== 'undefined';
|
|
510
526
|
/**
|
|
@@ -695,6 +711,16 @@ const downloadStringAsFile = ({ filename, content, mimeType = 'application/json'
|
|
|
695
711
|
a.click();
|
|
696
712
|
URL.revokeObjectURL(url);
|
|
697
713
|
};
|
|
714
|
+
/**
|
|
715
|
+
* Checks if a wallet has cached encrypted shares in storage.
|
|
716
|
+
*/ const hasEncryptedSharesCached = async ({ accountAddress, backupInfo, storage })=>{
|
|
717
|
+
if (!(backupInfo == null ? void 0 : backupInfo.passwordEncrypted)) {
|
|
718
|
+
return false;
|
|
719
|
+
}
|
|
720
|
+
const encryptedStorageKey = `${normalizeAddress(accountAddress)}${core.ENCRYPTED_SHARES_STORAGE_SUFFIX}`;
|
|
721
|
+
const encryptedData = await storage.getItem(encryptedStorageKey);
|
|
722
|
+
return !!encryptedData;
|
|
723
|
+
};
|
|
698
724
|
/**
|
|
699
725
|
* Checks if an error is a public key mismatch error that can be recovered
|
|
700
726
|
* by re-fetching the client key share from backup.
|
|
@@ -1239,6 +1265,7 @@ const hasDelegatedBackup = (backupInfo)=>{
|
|
|
1239
1265
|
* Get or create the heavy operation queue for a wallet.
|
|
1240
1266
|
* Heavy operations (refresh/reshare/recover) run with concurrency=1.
|
|
1241
1267
|
*/ static getHeavyOpQueue(accountAddress) {
|
|
1268
|
+
accountAddress = normalizeAddress(accountAddress);
|
|
1242
1269
|
if (!this.heavyOpQueues.has(accountAddress)) {
|
|
1243
1270
|
const queue = new PQueue({
|
|
1244
1271
|
concurrency: 1,
|
|
@@ -1258,6 +1285,7 @@ const hasDelegatedBackup = (backupInfo)=>{
|
|
|
1258
1285
|
* Get or create the sign queue for a wallet.
|
|
1259
1286
|
* Sign operations run with unlimited concurrency (they're read-only on key shares).
|
|
1260
1287
|
*/ static getSignQueue(accountAddress) {
|
|
1288
|
+
accountAddress = normalizeAddress(accountAddress);
|
|
1261
1289
|
if (!this.signQueues.has(accountAddress)) {
|
|
1262
1290
|
const queue = new PQueue({
|
|
1263
1291
|
concurrency: Infinity,
|
|
@@ -1276,12 +1304,14 @@ const hasDelegatedBackup = (backupInfo)=>{
|
|
|
1276
1304
|
/**
|
|
1277
1305
|
* Check if wallet has heavy operations in progress
|
|
1278
1306
|
*/ static isHeavyOpInProgress(accountAddress) {
|
|
1307
|
+
accountAddress = normalizeAddress(accountAddress);
|
|
1279
1308
|
const queue = this.heavyOpQueues.get(accountAddress);
|
|
1280
1309
|
return queue ? queue.size > 0 || queue.pending > 0 : false;
|
|
1281
1310
|
}
|
|
1282
1311
|
/**
|
|
1283
1312
|
* Check if wallet has operations in any queue (heavy or sign)
|
|
1284
1313
|
*/ static isWalletBusy(accountAddress) {
|
|
1314
|
+
accountAddress = normalizeAddress(accountAddress);
|
|
1285
1315
|
const heavyQueue = this.heavyOpQueues.get(accountAddress);
|
|
1286
1316
|
const signQueue = this.signQueues.get(accountAddress);
|
|
1287
1317
|
const heavyBusy = heavyQueue ? heavyQueue.size > 0 || heavyQueue.pending > 0 : false;
|
|
@@ -1291,22 +1321,22 @@ const hasDelegatedBackup = (backupInfo)=>{
|
|
|
1291
1321
|
/**
|
|
1292
1322
|
* Check if recovery is in progress for a wallet
|
|
1293
1323
|
*/ static isRecoveryInProgress(accountAddress) {
|
|
1294
|
-
return this.pendingRecoveryPromises.has(accountAddress);
|
|
1324
|
+
return this.pendingRecoveryPromises.has(normalizeAddress(accountAddress));
|
|
1295
1325
|
}
|
|
1296
1326
|
/**
|
|
1297
1327
|
* Get existing pending recovery promise if one exists
|
|
1298
1328
|
*/ static getPendingRecoveryPromise(accountAddress) {
|
|
1299
|
-
return this.pendingRecoveryPromises.get(accountAddress);
|
|
1329
|
+
return this.pendingRecoveryPromises.get(normalizeAddress(accountAddress));
|
|
1300
1330
|
}
|
|
1301
1331
|
/**
|
|
1302
1332
|
* Track a pending recovery promise
|
|
1303
1333
|
*/ static setPendingRecoveryPromise(accountAddress, promise) {
|
|
1304
|
-
this.pendingRecoveryPromises.set(accountAddress, promise);
|
|
1334
|
+
this.pendingRecoveryPromises.set(normalizeAddress(accountAddress), promise);
|
|
1305
1335
|
}
|
|
1306
1336
|
/**
|
|
1307
1337
|
* Clear pending recovery promise for a wallet
|
|
1308
1338
|
*/ static clearPendingRecoveryPromise(accountAddress) {
|
|
1309
|
-
this.pendingRecoveryPromises.delete(accountAddress);
|
|
1339
|
+
this.pendingRecoveryPromises.delete(normalizeAddress(accountAddress));
|
|
1310
1340
|
}
|
|
1311
1341
|
/**
|
|
1312
1342
|
* Queue a heavy operation with type validation.
|
|
@@ -1318,6 +1348,7 @@ const hasDelegatedBackup = (backupInfo)=>{
|
|
|
1318
1348
|
* @param callback - The operation to execute
|
|
1319
1349
|
* @throws Error if operation is not a valid heavy queue operation
|
|
1320
1350
|
*/ static async queueHeavyOperation(accountAddress, operation, callback) {
|
|
1351
|
+
accountAddress = normalizeAddress(accountAddress);
|
|
1321
1352
|
// Runtime validation to catch any type assertion bypasses
|
|
1322
1353
|
if (!isHeavyQueueOperation(operation)) {
|
|
1323
1354
|
throw new Error(`Invalid heavy queue operation: ${operation}. Must be REFRESH, RESHARE, or RECOVER.`);
|
|
@@ -1348,6 +1379,7 @@ const hasDelegatedBackup = (backupInfo)=>{
|
|
|
1348
1379
|
* @throws Error if operation is not a valid sign queue operation
|
|
1349
1380
|
* @returns Promise resolving to the sign result
|
|
1350
1381
|
*/ static async queueSignOperation(accountAddress, operation, callback) {
|
|
1382
|
+
accountAddress = normalizeAddress(accountAddress);
|
|
1351
1383
|
// Runtime validation to catch any type assertion bypasses
|
|
1352
1384
|
if (!isSignQueueOperation(operation)) {
|
|
1353
1385
|
throw new Error(`Invalid sign queue operation: ${operation}. Must be SIGN_MESSAGE or SIGN_TRANSACTION.`);
|
|
@@ -1383,6 +1415,7 @@ const hasDelegatedBackup = (backupInfo)=>{
|
|
|
1383
1415
|
* @throws Error if operation is not a valid recover queue operation
|
|
1384
1416
|
* @returns Promise resolving to the recovery result
|
|
1385
1417
|
*/ static async queueRecoverOperation(accountAddress, operation, callback) {
|
|
1418
|
+
accountAddress = normalizeAddress(accountAddress);
|
|
1386
1419
|
// Runtime validation to catch any type assertion bypasses
|
|
1387
1420
|
if (!isRecoverQueueOperation(operation)) {
|
|
1388
1421
|
throw new Error(`Invalid recover queue operation: ${operation}. Must be RECOVER.`);
|
|
@@ -1667,6 +1700,19 @@ class DynamicWalletClient {
|
|
|
1667
1700
|
*/ static resetStaticState() {
|
|
1668
1701
|
WalletQueueManager.resetForTesting();
|
|
1669
1702
|
}
|
|
1703
|
+
/**
|
|
1704
|
+
* Get wallet properties from the wallet map using normalized address.
|
|
1705
|
+
* Normalizes the address to lowercase for consistent lookups regardless of input casing.
|
|
1706
|
+
*/ getWalletFromMap(accountAddress) {
|
|
1707
|
+
return this.walletMap[normalizeAddress(accountAddress)];
|
|
1708
|
+
}
|
|
1709
|
+
/**
|
|
1710
|
+
* Update wallet properties in the wallet map using normalized address.
|
|
1711
|
+
* Normalizes the address to lowercase for consistent storage regardless of input casing.
|
|
1712
|
+
*/ updateWalletMap(accountAddress, updates) {
|
|
1713
|
+
const normalizedAddr = normalizeAddress(accountAddress);
|
|
1714
|
+
this.walletMap[normalizedAddr] = _extends({}, this.walletMap[normalizedAddr], updates);
|
|
1715
|
+
}
|
|
1670
1716
|
getAuthMode() {
|
|
1671
1717
|
return this.authMode;
|
|
1672
1718
|
}
|
|
@@ -2365,7 +2411,7 @@ class DynamicWalletClient {
|
|
|
2365
2411
|
* from walletMap, with fallback to deriving it from derivationPath.
|
|
2366
2412
|
*/ getBitcoinConfigForChain(chainName, accountAddress) {
|
|
2367
2413
|
if (chainName !== 'BTC') return undefined;
|
|
2368
|
-
const walletProperties = this.
|
|
2414
|
+
const walletProperties = this.getWalletFromMap(accountAddress);
|
|
2369
2415
|
let addressType = walletProperties == null ? void 0 : walletProperties.addressType;
|
|
2370
2416
|
// Fallback: derive addressType from derivationPath if not explicitly set
|
|
2371
2417
|
if (!addressType && (walletProperties == null ? void 0 : walletProperties.derivationPath)) {
|
|
@@ -2684,7 +2730,7 @@ class DynamicWalletClient {
|
|
|
2684
2730
|
allShares: allClientShares
|
|
2685
2731
|
});
|
|
2686
2732
|
}
|
|
2687
|
-
this.
|
|
2733
|
+
this.updateWalletMap(accountAddress, {
|
|
2688
2734
|
thresholdSignatureScheme: newThresholdSignatureScheme
|
|
2689
2735
|
});
|
|
2690
2736
|
// store client key shares to storage (localStorage or secureStorage)
|
|
@@ -2713,7 +2759,7 @@ class DynamicWalletClient {
|
|
|
2713
2759
|
}
|
|
2714
2760
|
});
|
|
2715
2761
|
// reset user wallet when reshare fails, this would allow the client to recover wallets from an active state
|
|
2716
|
-
this.
|
|
2762
|
+
this.updateWalletMap(accountAddress, {
|
|
2717
2763
|
thresholdSignatureScheme: oldThresholdSignatureScheme
|
|
2718
2764
|
});
|
|
2719
2765
|
await this.setClientKeySharesToStorage({
|
|
@@ -2726,7 +2772,6 @@ class DynamicWalletClient {
|
|
|
2726
2772
|
}
|
|
2727
2773
|
async performDelegationOperation({ accountAddress, password, signedSessionId, mfaToken, newThresholdSignatureScheme, revokeDelegation = false, operationName }) {
|
|
2728
2774
|
try {
|
|
2729
|
-
var _this_walletMap_accountAddress;
|
|
2730
2775
|
const delegateToProjectEnvironment = this.featureFlags && this.featureFlags[core.FEATURE_FLAGS.ENABLE_DELEGATED_KEY_SHARES_FLAG] === true;
|
|
2731
2776
|
if (!delegateToProjectEnvironment) {
|
|
2732
2777
|
throw new Error('Delegation is not allowed for this project environment');
|
|
@@ -2740,11 +2785,12 @@ class DynamicWalletClient {
|
|
|
2740
2785
|
if (wallet.chainName === 'SUI') {
|
|
2741
2786
|
throw new Error('Delegation is not allowed for SUI');
|
|
2742
2787
|
}
|
|
2743
|
-
const
|
|
2788
|
+
const walletData = this.getWalletFromMap(accountAddress);
|
|
2789
|
+
const currentThresholdSignatureScheme = walletData.thresholdSignatureScheme;
|
|
2744
2790
|
// Get active cloud providers to maintain existing backups
|
|
2745
|
-
const activeProviders = getActiveCloudProviders(
|
|
2791
|
+
const activeProviders = getActiveCloudProviders(walletData == null ? void 0 : walletData.clientKeySharesBackupInfo);
|
|
2746
2792
|
await this.reshare({
|
|
2747
|
-
chainName:
|
|
2793
|
+
chainName: walletData.chainName,
|
|
2748
2794
|
accountAddress,
|
|
2749
2795
|
oldThresholdSignatureScheme: currentThresholdSignatureScheme,
|
|
2750
2796
|
newThresholdSignatureScheme,
|
|
@@ -2775,7 +2821,7 @@ class DynamicWalletClient {
|
|
|
2775
2821
|
newThresholdSignatureScheme: core.ThresholdSignatureScheme.TWO_OF_THREE,
|
|
2776
2822
|
operationName: 'delegateKeyShares'
|
|
2777
2823
|
});
|
|
2778
|
-
const backupInfo = this.
|
|
2824
|
+
const backupInfo = this.getWalletFromMap(accountAddress).clientKeySharesBackupInfo;
|
|
2779
2825
|
const delegatedKeyShares = backupInfo.backups[core.BackupLocation.DELEGATED] || [];
|
|
2780
2826
|
return delegatedKeyShares;
|
|
2781
2827
|
}
|
|
@@ -2974,6 +3020,7 @@ class DynamicWalletClient {
|
|
|
2974
3020
|
/**
|
|
2975
3021
|
* helper function to store encrypted backup by wallet from iframe local storage
|
|
2976
3022
|
*/ async getClientKeySharesFromLocalStorage({ accountAddress }) {
|
|
3023
|
+
accountAddress = normalizeAddress(accountAddress);
|
|
2977
3024
|
const walletObject = await this.storage.getItem(accountAddress);
|
|
2978
3025
|
if (!walletObject) {
|
|
2979
3026
|
this.logger.debug(`[DynamicWaasWalletClient] No item found in iframe local storage for accountAddress: ${accountAddress}`);
|
|
@@ -3002,6 +3049,7 @@ class DynamicWalletClient {
|
|
|
3002
3049
|
* Helper function to get client key shares from storage.
|
|
3003
3050
|
* Uses secureStorage when available (mobile), otherwise falls back to localStorage (browser).
|
|
3004
3051
|
*/ async getClientKeySharesFromStorage({ accountAddress }) {
|
|
3052
|
+
accountAddress = normalizeAddress(accountAddress);
|
|
3005
3053
|
// Use secure storage if available (mobile)
|
|
3006
3054
|
if (this.secureStorage) {
|
|
3007
3055
|
try {
|
|
@@ -3034,7 +3082,7 @@ class DynamicWalletClient {
|
|
|
3034
3082
|
* @param derivationPath - Optional derivation path (will be computed from chainConfig if not provided)
|
|
3035
3083
|
* @param additionalProps - Any chain-specific additional properties to merge
|
|
3036
3084
|
*/ initializeWalletMapEntry({ accountAddress, walletId, chainName, thresholdSignatureScheme, derivationPath, additionalProps = {} }) {
|
|
3037
|
-
this.
|
|
3085
|
+
this.updateWalletMap(accountAddress, _extends({
|
|
3038
3086
|
accountAddress,
|
|
3039
3087
|
walletId,
|
|
3040
3088
|
chainName,
|
|
@@ -3043,7 +3091,7 @@ class DynamicWalletClient {
|
|
|
3043
3091
|
derivationPath
|
|
3044
3092
|
} : {}, {
|
|
3045
3093
|
clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
|
|
3046
|
-
}, additionalProps);
|
|
3094
|
+
}, additionalProps));
|
|
3047
3095
|
this.logger.debug('walletMap initialized for wallet', {
|
|
3048
3096
|
context: {
|
|
3049
3097
|
accountAddress,
|
|
@@ -3057,6 +3105,7 @@ class DynamicWalletClient {
|
|
|
3057
3105
|
* Helper function to store client key shares in storage.
|
|
3058
3106
|
* Uses secureStorage when available (mobile), otherwise falls back to localStorage (browser).
|
|
3059
3107
|
*/ async setClientKeySharesToLocalStorage({ accountAddress, clientKeyShares, overwriteOrMerge = 'merge' }) {
|
|
3108
|
+
accountAddress = normalizeAddress(accountAddress);
|
|
3060
3109
|
const stringifiedClientKeyShares = JSON.stringify({
|
|
3061
3110
|
clientKeyShares: overwriteOrMerge === 'overwrite' ? clientKeyShares : mergeUniqueKeyShares(await this.getClientKeySharesFromLocalStorage({
|
|
3062
3111
|
accountAddress
|
|
@@ -3068,6 +3117,7 @@ class DynamicWalletClient {
|
|
|
3068
3117
|
* Helper function to store client key shares in storage.
|
|
3069
3118
|
* Uses secureStorage when available (mobile), otherwise falls back to localStorage (browser).
|
|
3070
3119
|
*/ async setClientKeySharesToStorage({ accountAddress, clientKeyShares, overwriteOrMerge = 'merge' }) {
|
|
3120
|
+
accountAddress = normalizeAddress(accountAddress);
|
|
3071
3121
|
// Use secure storage if available (mobile)
|
|
3072
3122
|
if (this.secureStorage) {
|
|
3073
3123
|
try {
|
|
@@ -3113,8 +3163,8 @@ class DynamicWalletClient {
|
|
|
3113
3163
|
async backupSharesWithDistribution({ accountAddress, password, signedSessionId, distribution, preserveDelegatedLocation = false }) {
|
|
3114
3164
|
const dynamicRequestId = uuid.v4();
|
|
3115
3165
|
try {
|
|
3116
|
-
|
|
3117
|
-
if (!(
|
|
3166
|
+
const walletData = this.getWalletFromMap(accountAddress);
|
|
3167
|
+
if (!(walletData == null ? void 0 : walletData.walletId)) {
|
|
3118
3168
|
const error = new Error(`WalletId not found for accountAddress ${accountAddress}`);
|
|
3119
3169
|
logError({
|
|
3120
3170
|
message: 'Error in backupSharesWithDistribution, wallet or walletId not found from the wallet map',
|
|
@@ -3134,7 +3184,7 @@ class DynamicWalletClient {
|
|
|
3134
3184
|
password
|
|
3135
3185
|
})));
|
|
3136
3186
|
const data = await this.apiClient.storeEncryptedBackupByWallet({
|
|
3137
|
-
walletId:
|
|
3187
|
+
walletId: walletData.walletId,
|
|
3138
3188
|
encryptedKeyShares: encryptedDynamicShares,
|
|
3139
3189
|
passwordEncrypted: isPasswordEncrypted,
|
|
3140
3190
|
encryptionVersion: ENCRYPTION_VERSION_CURRENT,
|
|
@@ -3180,7 +3230,7 @@ class DynamicWalletClient {
|
|
|
3180
3230
|
var _publicKey_key_keyId;
|
|
3181
3231
|
const encryptedDelegatedKeyShareEnvelope = await encryptDelegatedKeyShare(JSON.stringify(distribution.delegatedShare), publicKey == null ? void 0 : (_publicKey_key1 = publicKey.key) == null ? void 0 : _publicKey_key1.publicKeyPemB64, (_publicKey_key_keyId = publicKey == null ? void 0 : (_publicKey_key2 = publicKey.key) == null ? void 0 : _publicKey_key2.keyId) != null ? _publicKey_key_keyId : publicKey == null ? void 0 : publicKey.keyId);
|
|
3182
3232
|
const { status } = await this.apiClient.publishDelegatedKeyShare({
|
|
3183
|
-
walletId:
|
|
3233
|
+
walletId: walletData.walletId,
|
|
3184
3234
|
encryptedKeyShare: encryptedDelegatedKeyShareEnvelope,
|
|
3185
3235
|
signedSessionId,
|
|
3186
3236
|
requiresSignedSessionId: this.requiresSignedSessionId(),
|
|
@@ -3202,23 +3252,23 @@ class DynamicWalletClient {
|
|
|
3202
3252
|
});
|
|
3203
3253
|
}
|
|
3204
3254
|
const backupData = await this.apiClient.markKeySharesAsBackedUp({
|
|
3205
|
-
walletId:
|
|
3255
|
+
walletId: walletData.walletId,
|
|
3206
3256
|
locations,
|
|
3207
3257
|
dynamicRequestId
|
|
3208
3258
|
});
|
|
3209
3259
|
const updatedBackupInfo = getClientKeyShareBackupInfo({
|
|
3210
3260
|
walletProperties: {
|
|
3211
|
-
derivationPath:
|
|
3261
|
+
derivationPath: walletData.derivationPath,
|
|
3212
3262
|
keyShares: backupData.locationsWithKeyShares.map((ks)=>({
|
|
3213
3263
|
id: ks.keyShareId,
|
|
3214
3264
|
backupLocation: ks.location,
|
|
3215
3265
|
externalKeyShareId: ks.externalKeyShareId,
|
|
3216
3266
|
passwordEncrypted: isPasswordEncrypted
|
|
3217
3267
|
})),
|
|
3218
|
-
thresholdSignatureScheme:
|
|
3268
|
+
thresholdSignatureScheme: walletData.thresholdSignatureScheme
|
|
3219
3269
|
}
|
|
3220
3270
|
});
|
|
3221
|
-
this.
|
|
3271
|
+
this.updateWalletMap(accountAddress, {
|
|
3222
3272
|
clientKeySharesBackupInfo: updatedBackupInfo
|
|
3223
3273
|
});
|
|
3224
3274
|
await this.storage.setItem(this.storageKey, JSON.stringify(this.walletMap));
|
|
@@ -3266,16 +3316,17 @@ class DynamicWalletClient {
|
|
|
3266
3316
|
* @param params.backupToGoogleDrive - Whether to backup to Google Drive (defaults to false)
|
|
3267
3317
|
* @returns Promise with backup metadata including share locations and IDs
|
|
3268
3318
|
*/ async storeEncryptedBackupByWallet({ accountAddress, clientKeyShares = undefined, password = undefined, signedSessionId, cloudProviders = [], delegatedKeyshare = undefined }) {
|
|
3269
|
-
var
|
|
3319
|
+
var _this_getWalletFromMap;
|
|
3270
3320
|
const keySharesToBackup = clientKeyShares != null ? clientKeyShares : await this.getClientKeySharesFromStorage({
|
|
3271
3321
|
accountAddress
|
|
3272
3322
|
});
|
|
3273
3323
|
// Check if we should backup to cloud providers (either requested or already exists)
|
|
3274
|
-
const
|
|
3324
|
+
const walletBackupInfo = (_this_getWalletFromMap = this.getWalletFromMap(accountAddress)) == null ? void 0 : _this_getWalletFromMap.clientKeySharesBackupInfo;
|
|
3325
|
+
const activeCloudProviders = getActiveCloudProviders(walletBackupInfo);
|
|
3275
3326
|
const shouldBackupToCloudProviders = cloudProviders.length > 0 || activeCloudProviders.length > 0;
|
|
3276
3327
|
// Use requested providers, or fall back to existing active providers
|
|
3277
3328
|
const providersToBackup = cloudProviders.length > 0 ? cloudProviders : activeCloudProviders;
|
|
3278
|
-
const hasExistingDelegation = hasDelegatedBackup(
|
|
3329
|
+
const hasExistingDelegation = hasDelegatedBackup(walletBackupInfo);
|
|
3279
3330
|
let distribution;
|
|
3280
3331
|
let preserveDelegatedLocation = false;
|
|
3281
3332
|
// Generic distribution logic - works with any cloud providers
|
|
@@ -3439,7 +3490,7 @@ class DynamicWalletClient {
|
|
|
3439
3490
|
}
|
|
3440
3491
|
async internalRecoverEncryptedBackupByWallet({ accountAddress, password, walletOperation, signedSessionId, shareCount = undefined, storeRecoveredShares = true, mfaToken }) {
|
|
3441
3492
|
try {
|
|
3442
|
-
const wallet = this.
|
|
3493
|
+
const wallet = this.getWalletFromMap(accountAddress);
|
|
3443
3494
|
this.logger.debug(`recoverEncryptedBackupByWallet wallet: ${walletOperation}`, wallet);
|
|
3444
3495
|
const { shares } = this.recoverStrategy({
|
|
3445
3496
|
clientKeyShareBackupInfo: wallet.clientKeySharesBackupInfo,
|
|
@@ -3487,7 +3538,12 @@ class DynamicWalletClient {
|
|
|
3487
3538
|
if (!wallets) {
|
|
3488
3539
|
return;
|
|
3489
3540
|
}
|
|
3490
|
-
|
|
3541
|
+
const parsedWallets = JSON.parse(wallets);
|
|
3542
|
+
this.walletMap = Object.keys(parsedWallets).reduce((acc, key)=>{
|
|
3543
|
+
const normalizedKey = normalizeAddress(key);
|
|
3544
|
+
acc[normalizedKey] = parsedWallets[key];
|
|
3545
|
+
return acc;
|
|
3546
|
+
}, {});
|
|
3491
3547
|
}
|
|
3492
3548
|
/**
|
|
3493
3549
|
* Internal helper method that handles the complete flow for ensuring wallet key shares are backed up to a cloud provider.
|
|
@@ -3501,11 +3557,12 @@ class DynamicWalletClient {
|
|
|
3501
3557
|
password,
|
|
3502
3558
|
signedSessionId
|
|
3503
3559
|
});
|
|
3504
|
-
const
|
|
3560
|
+
const walletData = this.getWalletFromMap(accountAddress);
|
|
3561
|
+
const currentThresholdSignatureScheme = walletData.thresholdSignatureScheme;
|
|
3505
3562
|
if (currentThresholdSignatureScheme === core.ThresholdSignatureScheme.TWO_OF_TWO) {
|
|
3506
3563
|
// Reshare to 2-of-3, which will automatically handle the backup distribution
|
|
3507
3564
|
await this.reshare({
|
|
3508
|
-
chainName:
|
|
3565
|
+
chainName: walletData.chainName,
|
|
3509
3566
|
accountAddress,
|
|
3510
3567
|
oldThresholdSignatureScheme: currentThresholdSignatureScheme,
|
|
3511
3568
|
newThresholdSignatureScheme: core.ThresholdSignatureScheme.TWO_OF_THREE,
|
|
@@ -3615,7 +3672,7 @@ class DynamicWalletClient {
|
|
|
3615
3672
|
const accessToken = await this.apiClient.getAccessToken({
|
|
3616
3673
|
oauthAccountId
|
|
3617
3674
|
});
|
|
3618
|
-
const thresholdSignatureScheme = this.
|
|
3675
|
+
const thresholdSignatureScheme = this.getWalletFromMap(accountAddress).thresholdSignatureScheme;
|
|
3619
3676
|
const fileName = getClientKeyShareExportFileName({
|
|
3620
3677
|
thresholdSignatureScheme,
|
|
3621
3678
|
accountAddress,
|
|
@@ -3655,7 +3712,7 @@ class DynamicWalletClient {
|
|
|
3655
3712
|
if (encryptedKeyShares.length === 0) {
|
|
3656
3713
|
throw new Error('No key shares found');
|
|
3657
3714
|
}
|
|
3658
|
-
const thresholdSignatureScheme = this.
|
|
3715
|
+
const thresholdSignatureScheme = this.getWalletFromMap(accountAddress).thresholdSignatureScheme;
|
|
3659
3716
|
const backupData = createBackupData({
|
|
3660
3717
|
encryptedKeyShares,
|
|
3661
3718
|
accountAddress,
|
|
@@ -3684,7 +3741,7 @@ class DynamicWalletClient {
|
|
|
3684
3741
|
const accessToken = await this.apiClient.getAccessToken({
|
|
3685
3742
|
oauthAccountId
|
|
3686
3743
|
});
|
|
3687
|
-
const thresholdSignatureScheme = this.
|
|
3744
|
+
const thresholdSignatureScheme = this.getWalletFromMap(accountAddress).thresholdSignatureScheme;
|
|
3688
3745
|
const backupFileName = getClientKeyShareExportFileName({
|
|
3689
3746
|
thresholdSignatureScheme,
|
|
3690
3747
|
accountAddress,
|
|
@@ -3760,6 +3817,7 @@ class DynamicWalletClient {
|
|
|
3760
3817
|
}
|
|
3761
3818
|
}
|
|
3762
3819
|
async exportClientKeyshares({ accountAddress, password, signedSessionId }) {
|
|
3820
|
+
var _this_getWalletFromMap;
|
|
3763
3821
|
await this.verifyPassword({
|
|
3764
3822
|
accountAddress,
|
|
3765
3823
|
password,
|
|
@@ -3771,7 +3829,7 @@ class DynamicWalletClient {
|
|
|
3771
3829
|
}
|
|
3772
3830
|
// Ensure client key shares exist before export
|
|
3773
3831
|
const clientKeyShares = await this.ensureClientShare(accountAddress);
|
|
3774
|
-
const derivationPath = this.
|
|
3832
|
+
const derivationPath = (_this_getWalletFromMap = this.getWalletFromMap(accountAddress)) == null ? void 0 : _this_getWalletFromMap.derivationPath;
|
|
3775
3833
|
const text = JSON.stringify({
|
|
3776
3834
|
keyShares: clientKeyShares,
|
|
3777
3835
|
derivationPath
|
|
@@ -3804,7 +3862,7 @@ class DynamicWalletClient {
|
|
|
3804
3862
|
let thresholdSignatureSchemeCheck = false;
|
|
3805
3863
|
let derivationPathCheck = false;
|
|
3806
3864
|
// check if wallet exists
|
|
3807
|
-
const existingWallet = this.
|
|
3865
|
+
const existingWallet = this.getWalletFromMap(accountAddress);
|
|
3808
3866
|
if (existingWallet) {
|
|
3809
3867
|
walletCheck = true;
|
|
3810
3868
|
}
|
|
@@ -3842,7 +3900,7 @@ class DynamicWalletClient {
|
|
|
3842
3900
|
* and decryption without storing the restored key shares. If unsuccessful, it throws an error.
|
|
3843
3901
|
*/ async verifyPassword({ accountAddress, password = undefined, walletOperation = core.WalletOperation.NO_OPERATION, signedSessionId }) {
|
|
3844
3902
|
// Only load wallet if it's not already loaded (to avoid double eager loading)
|
|
3845
|
-
if (!this.
|
|
3903
|
+
if (!this.getWalletFromMap(accountAddress)) {
|
|
3846
3904
|
await this.getWallet({
|
|
3847
3905
|
accountAddress,
|
|
3848
3906
|
walletOperation,
|
|
@@ -3901,7 +3959,7 @@ class DynamicWalletClient {
|
|
|
3901
3959
|
});
|
|
3902
3960
|
const { requiredShareCount } = this.recoverStrategy({
|
|
3903
3961
|
clientKeyShareBackupInfo: clientKeySharesBackupInfo,
|
|
3904
|
-
thresholdSignatureScheme: this.
|
|
3962
|
+
thresholdSignatureScheme: this.getWalletFromMap(accountAddress).thresholdSignatureScheme,
|
|
3905
3963
|
walletOperation
|
|
3906
3964
|
});
|
|
3907
3965
|
if (clientKeyShares.length >= requiredShareCount) {
|
|
@@ -3912,10 +3970,11 @@ class DynamicWalletClient {
|
|
|
3912
3970
|
async getWalletClientKeyShareBackupInfo({ accountAddress }) {
|
|
3913
3971
|
const dynamicRequestId = uuid.v4();
|
|
3914
3972
|
try {
|
|
3915
|
-
var
|
|
3973
|
+
var _this_getWalletFromMap, _walletBackupInfo_backups_BackupLocation_DYNAMIC, _walletBackupInfo_backups, _user_verifiedCredentials;
|
|
3916
3974
|
// Return existing backup info if it exists
|
|
3917
|
-
|
|
3918
|
-
|
|
3975
|
+
const walletBackupInfo = (_this_getWalletFromMap = this.getWalletFromMap(accountAddress)) == null ? void 0 : _this_getWalletFromMap.clientKeySharesBackupInfo;
|
|
3976
|
+
if (walletBackupInfo && ((_walletBackupInfo_backups = walletBackupInfo.backups) == null ? void 0 : (_walletBackupInfo_backups_BackupLocation_DYNAMIC = _walletBackupInfo_backups[core.BackupLocation.DYNAMIC]) == null ? void 0 : _walletBackupInfo_backups_BackupLocation_DYNAMIC.length) > 0) {
|
|
3977
|
+
return walletBackupInfo;
|
|
3919
3978
|
}
|
|
3920
3979
|
// Get backup info from server
|
|
3921
3980
|
const user = await this.apiClient.getUser(dynamicRequestId);
|
|
@@ -3946,30 +4005,36 @@ class DynamicWalletClient {
|
|
|
3946
4005
|
});
|
|
3947
4006
|
if (existingWalletCheck) {
|
|
3948
4007
|
this.logger.debug(`[DynamicWaasWalletClient] Wallet ${accountAddress} already exists`);
|
|
3949
|
-
|
|
4008
|
+
const wallet = this.getWalletFromMap(accountAddress);
|
|
4009
|
+
if (!wallet) {
|
|
4010
|
+
throw new Error(`Wallet not found for address: ${accountAddress}`);
|
|
4011
|
+
}
|
|
4012
|
+
return wallet;
|
|
3950
4013
|
}
|
|
3951
|
-
// Fetch and restore
|
|
4014
|
+
// Fetch and restore all waas wallets from server
|
|
3952
4015
|
const user = await this.apiClient.getUser(dynamicRequestId);
|
|
3953
|
-
const
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
4016
|
+
const waasWallets = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.filter((vc)=>vc.walletName === 'dynamicwaas');
|
|
4017
|
+
for (const vc of waasWallets != null ? waasWallets : []){
|
|
4018
|
+
const addr = vc.address;
|
|
4019
|
+
const props = vc.walletProperties;
|
|
4020
|
+
this.updateWalletMap(addr, {
|
|
4021
|
+
walletId: vc.id,
|
|
4022
|
+
chainName: core.verifiedCredentialNameToChainEnum[vc.chain],
|
|
4023
|
+
accountAddress: addr,
|
|
4024
|
+
thresholdSignatureScheme: props == null ? void 0 : props.thresholdSignatureScheme,
|
|
4025
|
+
derivationPath: props == null ? void 0 : props.derivationPath,
|
|
4026
|
+
clientKeySharesBackupInfo: getClientKeyShareBackupInfo({
|
|
4027
|
+
walletProperties: props
|
|
4028
|
+
}),
|
|
4029
|
+
addressType: props == null ? void 0 : props.addressType
|
|
4030
|
+
});
|
|
4031
|
+
}
|
|
3967
4032
|
if (walletOperation !== core.WalletOperation.NO_OPERATION && await this.requiresRestoreBackupSharesForOperation({
|
|
3968
4033
|
accountAddress,
|
|
3969
4034
|
walletOperation
|
|
3970
4035
|
})) {
|
|
3971
4036
|
var _walletData_clientKeySharesBackupInfo;
|
|
3972
|
-
const walletData = this.
|
|
4037
|
+
const walletData = this.getWalletFromMap(accountAddress);
|
|
3973
4038
|
var _walletData_clientKeySharesBackupInfo_passwordEncrypted;
|
|
3974
4039
|
const isPasswordEncrypted = (_walletData_clientKeySharesBackupInfo_passwordEncrypted = (_walletData_clientKeySharesBackupInfo = walletData.clientKeySharesBackupInfo) == null ? void 0 : _walletData_clientKeySharesBackupInfo.passwordEncrypted) != null ? _walletData_clientKeySharesBackupInfo_passwordEncrypted : false;
|
|
3975
4040
|
// Password-encrypted wallet without password - fetch and cache for eager loading
|
|
@@ -3987,14 +4052,19 @@ class DynamicWalletClient {
|
|
|
3987
4052
|
requiresSignedSessionId: this.requiresSignedSessionId()
|
|
3988
4053
|
});
|
|
3989
4054
|
// Cache encrypted shares for later decryption by unlockWallet
|
|
3990
|
-
const encryptedStorageKey = `${accountAddress}${core.ENCRYPTED_SHARES_STORAGE_SUFFIX}`;
|
|
4055
|
+
const encryptedStorageKey = `${normalizeAddress(accountAddress)}${core.ENCRYPTED_SHARES_STORAGE_SUFFIX}`;
|
|
3991
4056
|
await this.storage.setItem(encryptedStorageKey, JSON.stringify(data));
|
|
3992
4057
|
// Update wallet state to locked
|
|
3993
|
-
this.
|
|
4058
|
+
this.updateWalletMap(accountAddress, {
|
|
3994
4059
|
walletReadyState: core.WalletReadyState.ENCRYPTED
|
|
3995
4060
|
});
|
|
4061
|
+
await this.storage.setItem(this.storageKey, JSON.stringify(this.walletMap));
|
|
3996
4062
|
// Return wallet in locked state (no error for eager loading)
|
|
3997
|
-
|
|
4063
|
+
const wallet = this.getWalletFromMap(accountAddress);
|
|
4064
|
+
if (!wallet) {
|
|
4065
|
+
throw new Error(`Wallet not found for address: ${accountAddress}`);
|
|
4066
|
+
}
|
|
4067
|
+
return wallet;
|
|
3998
4068
|
}
|
|
3999
4069
|
// TODO(zfaizal2): throw error if signedSessionId is not provided after service deploy
|
|
4000
4070
|
const decryptedKeyShares = await this.recoverEncryptedBackupByWallet({
|
|
@@ -4021,7 +4091,11 @@ class DynamicWalletClient {
|
|
|
4021
4091
|
if (walletCount === 1) {
|
|
4022
4092
|
return Object.values(this.walletMap)[0];
|
|
4023
4093
|
}
|
|
4024
|
-
|
|
4094
|
+
const wallet = this.getWalletFromMap(accountAddress);
|
|
4095
|
+
if (!wallet) {
|
|
4096
|
+
throw new Error(`Wallet not found for address: ${accountAddress}`);
|
|
4097
|
+
}
|
|
4098
|
+
return wallet;
|
|
4025
4099
|
} catch (error) {
|
|
4026
4100
|
logError({
|
|
4027
4101
|
message: 'Error in getWallet',
|
|
@@ -4052,17 +4126,21 @@ class DynamicWalletClient {
|
|
|
4052
4126
|
* @returns WalletRecoveryState indicating the wallet's lock state and share availability
|
|
4053
4127
|
* @throws Error if recovery fails or no shares available after recovery
|
|
4054
4128
|
*/ async getWalletRecoveryState({ accountAddress, signedSessionId, password }) {
|
|
4055
|
-
const walletData = this.
|
|
4129
|
+
const walletData = this.getWalletFromMap(accountAddress);
|
|
4056
4130
|
if (!walletData) {
|
|
4057
4131
|
throw new Error(`Wallet not found for address: ${accountAddress}`);
|
|
4058
4132
|
}
|
|
4059
4133
|
let clientKeyShares = await this.getClientKeySharesFromStorage({
|
|
4060
4134
|
accountAddress
|
|
4061
4135
|
});
|
|
4062
|
-
|
|
4136
|
+
let hasEncryptedShares = await hasEncryptedSharesCached({
|
|
4137
|
+
accountAddress,
|
|
4138
|
+
backupInfo: walletData.clientKeySharesBackupInfo,
|
|
4139
|
+
storage: this.storage
|
|
4140
|
+
});
|
|
4141
|
+
// If no local shares and no cached encrypted shares, trigger recovery via getWallet
|
|
4063
4142
|
// getWallet -> recoverEncryptedBackupByWallet handles deduplication via inFlightRecovery
|
|
4064
|
-
if (clientKeyShares.length === 0 && signedSessionId) {
|
|
4065
|
-
var _walletData_clientKeySharesBackupInfo;
|
|
4143
|
+
if (clientKeyShares.length === 0 && !hasEncryptedShares && signedSessionId) {
|
|
4066
4144
|
await this.getWallet({
|
|
4067
4145
|
accountAddress,
|
|
4068
4146
|
walletOperation: core.WalletOperation.RECOVER,
|
|
@@ -4073,15 +4151,11 @@ class DynamicWalletClient {
|
|
|
4073
4151
|
clientKeyShares = await this.getClientKeySharesFromStorage({
|
|
4074
4152
|
accountAddress
|
|
4075
4153
|
});
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
const encryptedStorageKey = `${accountAddress}${core.ENCRYPTED_SHARES_STORAGE_SUFFIX}`;
|
|
4082
|
-
const encryptedData = await this.storage.getItem(encryptedStorageKey);
|
|
4083
|
-
hasEncryptedShares = !!encryptedData;
|
|
4084
|
-
}
|
|
4154
|
+
hasEncryptedShares = await hasEncryptedSharesCached({
|
|
4155
|
+
accountAddress,
|
|
4156
|
+
backupInfo: walletData.clientKeySharesBackupInfo,
|
|
4157
|
+
storage: this.storage
|
|
4158
|
+
});
|
|
4085
4159
|
if (clientKeyShares.length === 0 && !hasEncryptedShares) {
|
|
4086
4160
|
throw new Error(`No key shares available for wallet ${accountAddress} after recovery`);
|
|
4087
4161
|
}
|
|
@@ -4102,15 +4176,15 @@ class DynamicWalletClient {
|
|
|
4102
4176
|
*/ async unlockWallet({ accountAddress, password, signedSessionId }) {
|
|
4103
4177
|
const dynamicRequestId = uuid.v4();
|
|
4104
4178
|
try {
|
|
4105
|
-
if (!this.
|
|
4179
|
+
if (!this.getWalletFromMap(accountAddress)) {
|
|
4106
4180
|
await this.getWallet({
|
|
4107
4181
|
accountAddress,
|
|
4108
4182
|
walletOperation: core.WalletOperation.NO_OPERATION,
|
|
4109
4183
|
signedSessionId
|
|
4110
4184
|
});
|
|
4111
4185
|
}
|
|
4112
|
-
const
|
|
4113
|
-
const encryptedStorageKey = `${
|
|
4186
|
+
const normalizedAccountAddress = normalizeAddress(accountAddress);
|
|
4187
|
+
const encryptedStorageKey = `${normalizedAccountAddress}${core.ENCRYPTED_SHARES_STORAGE_SUFFIX}`;
|
|
4114
4188
|
let encryptedData = await this.storage.getItem(encryptedStorageKey);
|
|
4115
4189
|
// If no cached encrypted shares, fetch via getWallet with RECOVER
|
|
4116
4190
|
if (!encryptedData) {
|
|
@@ -4124,24 +4198,41 @@ class DynamicWalletClient {
|
|
|
4124
4198
|
if (!encryptedData) {
|
|
4125
4199
|
throw new Error('No encrypted shares found for wallet');
|
|
4126
4200
|
}
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
const decryptedKeyShares = await Promise.all(data.keyShares.map((keyShare)=>this.decryptKeyShare({
|
|
4130
|
-
keyShare: keyShare.encryptedAccountCredential,
|
|
4131
|
-
password
|
|
4132
|
-
})));
|
|
4133
|
-
await this.setClientKeySharesToStorage({
|
|
4201
|
+
// Decrypt the requested wallet
|
|
4202
|
+
await this.decryptAndStoreWalletShares({
|
|
4134
4203
|
accountAddress,
|
|
4135
|
-
|
|
4204
|
+
encryptedData,
|
|
4205
|
+
password
|
|
4136
4206
|
});
|
|
4137
|
-
|
|
4138
|
-
|
|
4207
|
+
// Decrypt all other password-encrypted wallets with the same password
|
|
4208
|
+
const otherEncryptedWallets = Object.entries(this.walletMap).filter(([addr, w])=>{
|
|
4209
|
+
var _w_clientKeySharesBackupInfo;
|
|
4210
|
+
return addr !== normalizedAccountAddress && w.walletReadyState !== core.WalletReadyState.READY && ((_w_clientKeySharesBackupInfo = w.clientKeySharesBackupInfo) == null ? void 0 : _w_clientKeySharesBackupInfo.passwordEncrypted);
|
|
4139
4211
|
});
|
|
4212
|
+
await Promise.all(otherEncryptedWallets.map(async ([otherAddr])=>{
|
|
4213
|
+
try {
|
|
4214
|
+
const otherEncryptedStorageKey = `${otherAddr}${core.ENCRYPTED_SHARES_STORAGE_SUFFIX}`;
|
|
4215
|
+
const otherEncryptedData = await this.storage.getItem(otherEncryptedStorageKey);
|
|
4216
|
+
if (!otherEncryptedData) {
|
|
4217
|
+
return;
|
|
4218
|
+
}
|
|
4219
|
+
await this.decryptAndStoreWalletShares({
|
|
4220
|
+
accountAddress: otherAddr,
|
|
4221
|
+
encryptedData: otherEncryptedData,
|
|
4222
|
+
password
|
|
4223
|
+
});
|
|
4224
|
+
} catch (err) {
|
|
4225
|
+
this.logger.debug('[DynamicWaasWalletClient] Failed to unlock additional wallet', {
|
|
4226
|
+
accountAddress: otherAddr,
|
|
4227
|
+
error: err
|
|
4228
|
+
});
|
|
4229
|
+
}
|
|
4230
|
+
}));
|
|
4140
4231
|
await this.storage.setItem(this.storageKey, JSON.stringify(this.walletMap));
|
|
4141
4232
|
this.logger.debug('[DynamicWaasWalletClient] Wallet unlocked successfully', {
|
|
4142
4233
|
accountAddress
|
|
4143
4234
|
});
|
|
4144
|
-
return this.
|
|
4235
|
+
return this.getWalletFromMap(accountAddress);
|
|
4145
4236
|
} catch (error) {
|
|
4146
4237
|
logError({
|
|
4147
4238
|
message: 'Error in unlockWallet',
|
|
@@ -4154,6 +4245,22 @@ class DynamicWalletClient {
|
|
|
4154
4245
|
throw error;
|
|
4155
4246
|
}
|
|
4156
4247
|
}
|
|
4248
|
+
/**
|
|
4249
|
+
* Decrypts cached encrypted key shares for a wallet and stores them locally.
|
|
4250
|
+
*/ async decryptAndStoreWalletShares({ accountAddress, encryptedData, password }) {
|
|
4251
|
+
const data = JSON.parse(encryptedData);
|
|
4252
|
+
const decryptedKeyShares = await Promise.all(data.keyShares.map((keyShare)=>this.decryptKeyShare({
|
|
4253
|
+
keyShare: keyShare.encryptedAccountCredential,
|
|
4254
|
+
password
|
|
4255
|
+
})));
|
|
4256
|
+
await this.setClientKeySharesToStorage({
|
|
4257
|
+
accountAddress,
|
|
4258
|
+
clientKeyShares: decryptedKeyShares
|
|
4259
|
+
});
|
|
4260
|
+
this.updateWalletMap(accountAddress, {
|
|
4261
|
+
walletReadyState: core.WalletReadyState.READY
|
|
4262
|
+
});
|
|
4263
|
+
}
|
|
4157
4264
|
async getWallets() {
|
|
4158
4265
|
const dynamicRequestId = uuid.v4();
|
|
4159
4266
|
try {
|
|
@@ -4162,8 +4269,8 @@ class DynamicWalletClient {
|
|
|
4162
4269
|
this.userId = user.id;
|
|
4163
4270
|
const waasWallets = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.filter((vc)=>vc.walletName === 'dynamicwaas');
|
|
4164
4271
|
const wallets = waasWallets.map((vc)=>{
|
|
4165
|
-
var
|
|
4166
|
-
var
|
|
4272
|
+
var _this_getWalletFromMap, _vc_walletProperties, _vc_walletProperties1;
|
|
4273
|
+
var _this_getWalletFromMap_derivationPath;
|
|
4167
4274
|
return {
|
|
4168
4275
|
walletId: vc.id,
|
|
4169
4276
|
chainName: vc.chain,
|
|
@@ -4171,23 +4278,24 @@ class DynamicWalletClient {
|
|
|
4171
4278
|
clientKeySharesBackupInfo: getClientKeyShareBackupInfo({
|
|
4172
4279
|
walletProperties: vc.walletProperties || {}
|
|
4173
4280
|
}),
|
|
4174
|
-
derivationPath: (
|
|
4281
|
+
derivationPath: (_this_getWalletFromMap_derivationPath = (_this_getWalletFromMap = this.getWalletFromMap(vc.address)) == null ? void 0 : _this_getWalletFromMap.derivationPath) != null ? _this_getWalletFromMap_derivationPath : undefined,
|
|
4175
4282
|
thresholdSignatureScheme: (_vc_walletProperties = vc.walletProperties) == null ? void 0 : _vc_walletProperties.thresholdSignatureScheme,
|
|
4176
4283
|
addressType: (_vc_walletProperties1 = vc.walletProperties) == null ? void 0 : _vc_walletProperties1.addressType
|
|
4177
4284
|
};
|
|
4178
4285
|
});
|
|
4286
|
+
const existingWalletMap = this.walletMap;
|
|
4179
4287
|
this.walletMap = wallets.reduce((acc, wallet)=>{
|
|
4180
|
-
|
|
4181
|
-
const
|
|
4182
|
-
acc[
|
|
4288
|
+
const normalizedAddress = normalizeAddress(wallet.accountAddress);
|
|
4289
|
+
const existingWallet = existingWalletMap[normalizedAddress];
|
|
4290
|
+
acc[normalizedAddress] = {
|
|
4183
4291
|
walletId: wallet.walletId,
|
|
4184
4292
|
chainName: wallet.chainName,
|
|
4185
4293
|
accountAddress: wallet.accountAddress,
|
|
4186
4294
|
clientKeySharesBackupInfo: wallet.clientKeySharesBackupInfo,
|
|
4187
|
-
derivationPath:
|
|
4295
|
+
derivationPath: existingWallet == null ? void 0 : existingWallet.derivationPath,
|
|
4188
4296
|
thresholdSignatureScheme: wallet.thresholdSignatureScheme,
|
|
4189
4297
|
addressType: wallet.addressType,
|
|
4190
|
-
walletReadyState:
|
|
4298
|
+
walletReadyState: existingWallet == null ? void 0 : existingWallet.walletReadyState
|
|
4191
4299
|
};
|
|
4192
4300
|
return acc;
|
|
4193
4301
|
}, {});
|
|
@@ -4472,6 +4580,7 @@ exports.getMPCSignatureScheme = getMPCSignatureScheme;
|
|
|
4472
4580
|
exports.getMPCSigner = getMPCSigner;
|
|
4473
4581
|
exports.hasCloudProviderBackup = hasCloudProviderBackup;
|
|
4474
4582
|
exports.hasDelegatedBackup = hasDelegatedBackup;
|
|
4583
|
+
exports.hasEncryptedSharesCached = hasEncryptedSharesCached;
|
|
4475
4584
|
exports.initializeCloudKit = initializeCloudKit;
|
|
4476
4585
|
exports.isBrowser = isBrowser;
|
|
4477
4586
|
exports.isHeavyQueueOperation = isHeavyQueueOperation;
|