@dynamic-labs-wallet/browser 0.0.0-beta.310 → 0.0.0-beta.312

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.
Files changed (36) hide show
  1. package/index.cjs.js +621 -498
  2. package/index.esm.js +625 -498
  3. package/internal/core/package.json +17 -0
  4. package/internal/web/package.json +17 -0
  5. package/package.json +10 -3
  6. package/src/backup/encryption/argon2.d.ts +10 -0
  7. package/src/backup/encryption/argon2.d.ts.map +1 -0
  8. package/src/backup/encryption/config.d.ts +39 -0
  9. package/src/backup/encryption/config.d.ts.map +1 -0
  10. package/src/backup/encryption/constants.d.ts +35 -0
  11. package/src/backup/encryption/constants.d.ts.map +1 -0
  12. package/src/backup/encryption/core.d.ts +27 -0
  13. package/src/backup/encryption/core.d.ts.map +1 -0
  14. package/src/backup/encryption/pbkdf2.d.ts +10 -0
  15. package/src/backup/encryption/pbkdf2.d.ts.map +1 -0
  16. package/src/backup/encryption/types.d.ts +46 -0
  17. package/src/backup/encryption/types.d.ts.map +1 -0
  18. package/src/backup/encryption/utils.d.ts +9 -0
  19. package/src/backup/encryption/utils.d.ts.map +1 -0
  20. package/src/client.d.ts +11 -23
  21. package/src/client.d.ts.map +1 -1
  22. package/src/index.d.ts +6 -6
  23. package/src/index.d.ts.map +1 -1
  24. package/src/mpc/index.d.ts +3 -3
  25. package/src/mpc/index.d.ts.map +1 -1
  26. package/src/mpc/mpc.d.ts +1 -1
  27. package/src/mpc/types.d.ts +2 -2
  28. package/src/services/axiosErrorResponse.d.ts.map +1 -1
  29. package/src/services/encryption.d.ts +19 -0
  30. package/src/services/encryption.d.ts.map +1 -0
  31. package/src/types.d.ts +1 -1
  32. package/src/types.d.ts.map +1 -1
  33. package/src/utils.d.ts +3 -7
  34. package/src/utils.d.ts.map +1 -1
  35. package/src/backup/encryption.d.ts +0 -62
  36. package/src/backup/encryption.d.ts.map +0 -1
package/index.cjs.js CHANGED
@@ -1,13 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  var core = require('@dynamic-labs-wallet/core');
4
- var web = require('./internal/web');
5
- var uuid = require('uuid');
4
+ var web = require('#internal/web');
6
5
  var semver = require('semver');
6
+ var uuid = require('uuid');
7
7
  var logger$1 = require('@dynamic-labs/logger');
8
- var sdkApiCore = require('@dynamic-labs/sdk-api-core');
8
+ var loadArgon2idWasm = require('argon2id');
9
9
  var axios = require('axios');
10
10
  var createHttpError = require('http-errors');
11
+ var sdkApiCore = require('@dynamic-labs/sdk-api-core');
11
12
 
12
13
  function _extends() {
13
14
  _extends = Object.assign || function assign(target) {
@@ -41,65 +42,118 @@ const getMPCSigner = ({ chainName, baseRelayUrl })=>{
41
42
  return signatureScheme;
42
43
  };
43
44
 
44
- const DEFAULT_LOG_LEVEL = logger$1.LogLevel.DEBUG; //todo: change back to info when done debugging
45
- const STORAGE_KEY = 'dynamic-waas-wallet-client';
46
- const CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX = 'dynamicWalletKeyShareBackup';
47
- const SIGNED_SESSION_ID_MIN_VERSION = '4.25.4';
48
- // Namespace-specific version requirements
49
- const SIGNED_SESSION_ID_MIN_VERSION_BY_NAMESPACE = {
50
- WalletKit: '4.25.4',
51
- ClientSDK: '0.1.0-alpha.0'
52
- };
45
+ /**
46
+ * Encryption version identifiers
47
+ */ var EncryptionVersion = /*#__PURE__*/ function(EncryptionVersion) {
48
+ EncryptionVersion["V1_LEGACY"] = "v1";
49
+ EncryptionVersion["V2_PBKDF2"] = "v2";
50
+ EncryptionVersion["V3_ARGON2"] = "v3";
51
+ return EncryptionVersion;
52
+ }({});
53
+ /**
54
+ * Current default version for new encryptions
55
+ */ const ENCRYPTION_VERSION_CURRENT = "v3";
56
+ /**
57
+ * Algorithm constants
58
+ */ const PBKDF2_ALGORITHM = 'PBKDF2';
59
+ const HASH_ALGORITHM = 'SHA-256'; // Generic hash algorithm constant
60
+ const ARGON2_ALGORITHM = 'Argon2id';
61
+ const AES_GCM_ALGORITHM = 'AES-GCM';
62
+ const AES_GCM_LENGTH = 256;
63
+ /**
64
+ * Argon2 configuration constants, values were chosen based on RFC (https://www.rfc-editor.org/rfc/rfc9106.html#name-parameter-choice)
65
+ * taking into account that this runs in the client, possibly in smartphones with limited resources
66
+ */ const ARGON2_MEMORY_SIZE = 65536; // 64 MB in KiB
67
+ const ARGON2_ITERATIONS = 3;
68
+ const ARGON2_PARALLELISM = 2;
69
+ const ARGON2_HASH_LENGTH = 32;
70
+ /**
71
+ * PBKDF2 configuration constants
72
+ */ const PBKDF2_ITERATIONS_V1 = 100000;
73
+ const PBKDF2_ITERATIONS_V2 = 1000000;
53
74
 
54
- const handleAxiosError = (error, message, context)=>{
55
- var _error_response, _error_response1;
56
- logger.debug("[DynamicWaasWalletClient] Axios error: " + message, {
57
- error: (_error_response = error.response) == null ? void 0 : _error_response.status,
58
- message: error.message,
59
- context
75
+ /**
76
+ * Derives a key using Argon2id algorithm
77
+ * @param params - Key derivation parameters
78
+ * @param encryptionConfig - Encryption configuration
79
+ * @returns Promise<CryptoKey>
80
+ */ const deriveArgon2Key = async ({ password, salt }, encryptionConfig)=>{
81
+ const argon2id = await loadArgon2idWasm();
82
+ const argon2Config = encryptionConfig;
83
+ const passwordBytes = new TextEncoder().encode(password);
84
+ const hash = argon2id({
85
+ password: passwordBytes,
86
+ salt: salt,
87
+ parallelism: argon2Config.parallelism || ARGON2_PARALLELISM,
88
+ passes: argon2Config.iterations,
89
+ memorySize: argon2Config.memorySize || ARGON2_MEMORY_SIZE,
90
+ tagLength: argon2Config.hashLength || ARGON2_HASH_LENGTH
60
91
  });
61
- switch((_error_response1 = error.response) == null ? void 0 : _error_response1.status){
62
- case 400:
63
- throw createHttpError(400, 'Invalid request');
64
- case 401:
65
- throw createHttpError(401, 'Authorization header or cookie is required');
66
- case 403:
67
- throw createHttpError(403, 'Forbidden');
68
- case 422:
69
- throw createHttpError(422, 'Unprocessable content');
70
- case 500:
71
- throw createHttpError(500, 'Internal server error');
72
- default:
73
- throw createHttpError(500, 'Internal server error');
74
- }
92
+ return crypto.subtle.importKey('raw', new Uint8Array(hash), {
93
+ name: encryptionConfig.algorithm,
94
+ length: encryptionConfig.algorithmLength
95
+ }, false, [
96
+ 'encrypt',
97
+ 'decrypt'
98
+ ]);
75
99
  };
76
100
 
77
- const logger = new logger$1.Logger('DynamicWaasWalletClient', logger$1.LogLevel.DEBUG);
78
- const setLoggerContext = ({ environmentId, authMode = core.AuthMode.HEADER, sessionId = undefined, userId = undefined })=>{
79
- try {
80
- logger$1.Logger.setEnvironmentId(environmentId);
81
- logger$1.Logger.globalMetaData.set('sid', sessionId);
82
- logger$1.Logger.globalMetaData.set('user_id', userId);
83
- logger$1.Logger.globalMetaData.set('auth_mode', authMode);
84
- } catch (error) {
85
- logError({
86
- message: '[DynamicWaasWalletClient] Error setting logger context',
87
- error: error,
88
- context: {}
89
- });
101
+ /**
102
+ * Encryption configuration for each version
103
+ */ const ENCRYPTION_VERSIONS = {
104
+ [EncryptionVersion.V1_LEGACY]: {
105
+ version: EncryptionVersion.V1_LEGACY,
106
+ algorithm: AES_GCM_ALGORITHM,
107
+ keyDerivation: PBKDF2_ALGORITHM,
108
+ iterations: PBKDF2_ITERATIONS_V1,
109
+ hashAlgorithm: HASH_ALGORITHM,
110
+ algorithmLength: AES_GCM_LENGTH
111
+ },
112
+ [EncryptionVersion.V2_PBKDF2]: {
113
+ version: EncryptionVersion.V2_PBKDF2,
114
+ algorithm: AES_GCM_ALGORITHM,
115
+ keyDerivation: PBKDF2_ALGORITHM,
116
+ iterations: PBKDF2_ITERATIONS_V2,
117
+ hashAlgorithm: HASH_ALGORITHM,
118
+ algorithmLength: AES_GCM_LENGTH
119
+ },
120
+ [EncryptionVersion.V3_ARGON2]: {
121
+ version: EncryptionVersion.V3_ARGON2,
122
+ algorithm: AES_GCM_ALGORITHM,
123
+ keyDerivation: ARGON2_ALGORITHM,
124
+ iterations: ARGON2_ITERATIONS,
125
+ hashAlgorithm: ARGON2_ALGORITHM,
126
+ algorithmLength: AES_GCM_LENGTH,
127
+ memorySize: ARGON2_MEMORY_SIZE,
128
+ parallelism: ARGON2_PARALLELISM,
129
+ hashLength: ARGON2_HASH_LENGTH
90
130
  }
91
131
  };
92
- const logError = ({ message, error, context })=>{
93
- if (error instanceof axios.AxiosError) {
94
- handleAxiosError(error, message, context);
132
+ /**
133
+ * Helper function to get encryption configuration by version string
134
+ * @param version - The version string (e.g., 'v1', 'v2', 'v3')
135
+ * @returns The encryption configuration for the specified version
136
+ */ const getEncryptionConfig = (version)=>{
137
+ // If no version specified, use legacy for backward compatibility
138
+ if (!version) {
139
+ return ENCRYPTION_VERSIONS[EncryptionVersion.V1_LEGACY];
140
+ }
141
+ const config = ENCRYPTION_VERSIONS[version];
142
+ if (!config) {
143
+ throw new Error(`Unsupported encryption version: ${version}`);
95
144
  }
96
- logger.error(message, {
97
- error: error instanceof Error ? error.message : 'Unknown error',
98
- context
99
- });
145
+ return config;
146
+ };
147
+ /**
148
+ * Check if a configuration uses Argon2
149
+ */ const isArgon2Config = (config)=>{
150
+ return config.keyDerivation === ARGON2_ALGORITHM;
100
151
  };
101
152
 
102
- const bytesToBase64 = (arr)=>{
153
+ /**
154
+ * Utility functions for encryption operations
155
+ * These functions are separated to avoid circular dependencies
156
+ */ const bytesToBase64 = (arr)=>{
103
157
  return btoa(Array.from(arr, (b)=>String.fromCharCode(b)).join(''));
104
158
  };
105
159
  const stringToBytes = (str)=>{
@@ -112,168 +166,13 @@ const base64ToBytes = (base64)=>{
112
166
  const ensureBase64Padding = (str)=>{
113
167
  return str.padEnd(Math.ceil(str.length / 4) * 4, '=');
114
168
  };
115
- const isBrowser = ()=>typeof window !== 'undefined';
116
- const getClientKeyShareExportFileName = ({ thresholdSignatureScheme, accountAddress })=>{
117
- return `${CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX}-${thresholdSignatureScheme}-${accountAddress}.json`;
118
- };
119
- const getClientKeyShareBackupInfo = (params)=>{
120
- var _params_walletProperties, _params_walletProperties_keyShares_;
121
- const backups = {
122
- [core.BackupLocation.DYNAMIC]: [],
123
- [core.BackupLocation.GOOGLE_DRIVE]: [],
124
- [core.BackupLocation.ICLOUD]: [],
125
- [core.BackupLocation.USER]: [],
126
- [core.BackupLocation.EXTERNAL]: []
127
- };
128
- if (!(params == null ? void 0 : (_params_walletProperties = params.walletProperties) == null ? void 0 : _params_walletProperties.keyShares)) {
129
- return {
130
- backups,
131
- passwordEncrypted: false
132
- };
133
- }
134
- params.walletProperties.keyShares.forEach((keyShare)=>{
135
- if (backups[keyShare.backupLocation]) {
136
- backups[keyShare.backupLocation].push({
137
- location: keyShare.backupLocation,
138
- keyShareId: keyShare.id,
139
- externalKeyShareId: keyShare == null ? void 0 : keyShare.externalKeyShareId
140
- });
141
- }
142
- });
143
- const passwordEncrypted = Boolean((_params_walletProperties_keyShares_ = params.walletProperties.keyShares[0]) == null ? void 0 : _params_walletProperties_keyShares_.passwordEncrypted);
144
- return {
145
- backups,
146
- passwordEncrypted
147
- };
148
- };
149
- /**
150
- * Helper function to merge keyshares and remove duplicates based on pubkey and secretShare
151
- * @param existingKeyShares - Array of existing keyshares
152
- * @param newKeyShares - Array of new keyshares to merge
153
- * @returns Array of merged unique keyshares
154
- */ const mergeUniqueKeyShares = (existingKeyShares, newKeyShares)=>{
155
- const uniqueKeyShares = newKeyShares.filter((newShare)=>!existingKeyShares.some((existingShare)=>{
156
- if (!(newShare == null ? void 0 : newShare.pubkey) || !(existingShare == null ? void 0 : existingShare.pubkey)) return false;
157
- return newShare.pubkey.toString() === existingShare.pubkey.toString() && newShare.secretShare === existingShare.secretShare;
158
- }));
159
- return [
160
- ...existingKeyShares,
161
- ...uniqueKeyShares
162
- ];
163
- };
164
- const timeoutPromise = ({ timeInMs, activity = 'Ceremony' })=>{
165
- return new Promise((_, reject)=>setTimeout(()=>reject(new Error(`${activity} did not complete in ${timeInMs}ms`)), timeInMs));
166
- };
167
- /**
168
- * Generic helper function to retry a promise-based operations
169
- *
170
- * @param operation - The async operation to retry
171
- * @param config - Configuration options for retry behavior
172
- * @returns Promise with the operation result
173
- * @throws Last error encountered after all retries are exhausted
174
- */ async function retryPromise(operation, { maxAttempts = 5, retryInterval = 500, operationName = 'operation', logContext = {} } = {}) {
175
- let attempts = 0;
176
- while(attempts < maxAttempts){
177
- try {
178
- return await operation();
179
- } catch (error) {
180
- attempts++;
181
- if (attempts === maxAttempts) {
182
- logger.error(`Failed to execute ${operationName} after ${maxAttempts} attempts`, _extends({}, logContext, {
183
- error: error instanceof Error ? error.message : 'Unknown error'
184
- }));
185
- throw error;
186
- }
187
- // Calculate exponential backoff delay
188
- const exponentialDelay = retryInterval * 2 ** (attempts - 1);
189
- await new Promise((resolve)=>setTimeout(resolve, exponentialDelay));
190
- }
191
- }
192
- // TypeScript needs this even though it's unreachable
193
- throw new Error('Unreachable code');
194
- }
195
- const formatEvmMessage = (message)=>{
196
- if (typeof message === 'string' && message.startsWith('0x')) {
197
- const serializedTxBytes = Uint8Array.from(Buffer.from(message.slice(2), 'hex'));
198
- return web.MessageHash.keccak256(serializedTxBytes);
199
- }
200
- return web.MessageHash.keccak256(message);
201
- };
202
- const isHexString = (str)=>{
203
- // Remove 0x prefix if present
204
- const hex = str.startsWith('0x') ? str.slice(2) : str;
205
- // Check if string contains only hex characters
206
- return /^[0-9A-Fa-f]+$/.test(hex);
207
- };
208
- const formatSolanaMessage = (message)=>{
209
- if (typeof message === 'string') {
210
- if (!isHexString(message)) {
211
- return Buffer.from(message).toString('hex');
212
- } else {
213
- return new Uint8Array(Buffer.from(message, 'hex'));
214
- }
215
- } else {
216
- return message;
217
- }
218
- };
219
- const formatMessage = (chainName, message)=>{
220
- switch(chainName){
221
- case 'EVM':
222
- return formatEvmMessage(message);
223
- case 'SVM':
224
- return formatSolanaMessage(message);
225
- case 'SUI':
226
- return message;
227
- default:
228
- throw new Error('Unsupported chain name');
229
- }
230
- };
231
- const getGoogleOAuthAccountId = (verifiedCredentials)=>{
232
- const googleVerifiedCredential = verifiedCredentials == null ? void 0 : verifiedCredentials.find((credential)=>credential.oauthProvider === sdkApiCore.ProviderEnum.Google);
233
- return googleVerifiedCredential == null ? void 0 : googleVerifiedCredential.id;
234
- };
235
- const createBackupData = ({ encryptedKeyShares, accountAddress, thresholdSignatureScheme, hasPassword = true })=>{
236
- return {
237
- keyShares: encryptedKeyShares,
238
- metadata: {
239
- createdAt: new Date().toISOString(),
240
- accountAddress,
241
- thresholdSignatureScheme,
242
- hasPassword,
243
- encryption: getEncryptionMetadataForVersion(ENCRYPTION_VERSION_CURRENT),
244
- encryptionVersion: ENCRYPTION_VERSION_CURRENT,
245
- shareCount: encryptedKeyShares.length
246
- }
247
- };
248
- };
249
169
 
250
- const ENCRYPTION_VERSION_LEGACY = 'v1';
251
- const ENCRYPTION_VERSION_CURRENT = 'v2';
252
- const PBKDF2_ALGORITHM = 'PBKDF2';
253
- const PBKDF2_HASH_ALGORITHM = 'SHA-256';
254
- const AES_GCM_ALGORITHM = 'AES-GCM';
255
- const AES_GCM_LENGTH = 256;
256
- const ENCRYPTION_VERSIONS = {
257
- [ENCRYPTION_VERSION_LEGACY]: {
258
- version: ENCRYPTION_VERSION_LEGACY,
259
- algorithm: AES_GCM_ALGORITHM,
260
- keyDerivation: PBKDF2_ALGORITHM,
261
- iterations: 100000,
262
- hashAlgorithm: PBKDF2_HASH_ALGORITHM,
263
- algorithmLength: AES_GCM_LENGTH
264
- },
265
- [ENCRYPTION_VERSION_CURRENT]: {
266
- version: ENCRYPTION_VERSION_CURRENT,
267
- algorithm: AES_GCM_ALGORITHM,
268
- keyDerivation: PBKDF2_ALGORITHM,
269
- iterations: 1000000,
270
- hashAlgorithm: PBKDF2_HASH_ALGORITHM,
271
- algorithmLength: AES_GCM_LENGTH
272
- }
273
- };
274
- ENCRYPTION_VERSIONS[ENCRYPTION_VERSION_CURRENT].iterations;
275
- ENCRYPTION_VERSIONS[ENCRYPTION_VERSION_LEGACY].iterations;
276
- const getKey = async ({ password, salt, encryptionConfig })=>{
170
+ /**
171
+ * Derives a key using PBKDF2 algorithm
172
+ * @param params - Key derivation parameters
173
+ * @param encryptionConfig - Encryption configuration
174
+ * @returns Promise<CryptoKey>
175
+ */ const derivePBKDF2Key = async ({ password, salt }, encryptionConfig)=>{
277
176
  const passwordBytes = stringToBytes(password);
278
177
  const initialKey = await crypto.subtle.importKey('raw', passwordBytes, {
279
178
  name: 'PBKDF2'
@@ -293,23 +192,30 @@ const getKey = async ({ password, salt, encryptionConfig })=>{
293
192
  'decrypt'
294
193
  ]);
295
194
  };
195
+
196
+ /**
197
+ * Get the appropriate key derivation function based on the encryption config
198
+ */ const getKey = async (params, encryptionConfig)=>{
199
+ // Use Argon2 for v3, PBKDF2 for v1 and v2
200
+ if (encryptionConfig.keyDerivation === ARGON2_ALGORITHM) {
201
+ return deriveArgon2Key(params, encryptionConfig);
202
+ } else {
203
+ return derivePBKDF2Key(params, encryptionConfig);
204
+ }
205
+ };
296
206
  /**
297
207
  * Encrypts data using the specified encryption version.
298
208
  * Always uses the latest encryption configuration for new encryptions by default.
299
209
  */ const encryptData = async ({ data, password, version = ENCRYPTION_VERSION_CURRENT })=>{
300
- const encryptionConfig = ENCRYPTION_VERSIONS[version];
301
- if (!encryptionConfig) {
302
- throw new Error(`Unsupported encryption version: ${version}`);
303
- }
210
+ const encryptionConfig = getEncryptionConfig(version);
304
211
  try {
305
212
  // Generate a random salt and IV
306
213
  const salt = crypto.getRandomValues(new Uint8Array(16));
307
214
  const iv = crypto.getRandomValues(new Uint8Array(12)); // AES-GCM requires 12 bytes
308
215
  const key = await getKey({
309
216
  password,
310
- salt,
311
- encryptionConfig
312
- });
217
+ salt
218
+ }, encryptionConfig);
313
219
  // Convert the input string to bytes
314
220
  const dataBytes = new TextEncoder().encode(data);
315
221
  // Encrypt the data
@@ -325,13 +231,15 @@ const getKey = async ({ password, salt, encryptionConfig })=>{
325
231
  version
326
232
  };
327
233
  } catch (error) {
328
- throw new Error('Error encrypting data');
234
+ const errorMessage = error instanceof Error ? error.message : String(error);
235
+ throw new Error(`Error encrypting data: ${errorMessage} (version: ${version})`);
329
236
  }
330
237
  };
331
238
  /**
332
239
  * Decrypts data with version-based configuration.
333
240
  * Uses the version field from the data to determine encryption parameters.
334
241
  * Falls back to legacy version for backward compatibility if no version is specified.
242
+ * For v3 (Argon2), retries with parallelism=1 if an OperationError occurs.
335
243
  */ const decryptData = async ({ data, password })=>{
336
244
  const { salt, iv, cipher, version } = data;
337
245
  // Ensure proper base64 padding for all values
@@ -341,26 +249,42 @@ const getKey = async ({ password, salt, encryptionConfig })=>{
341
249
  const saltBytes = base64ToBytes(paddedSalt);
342
250
  const ivBytes = base64ToBytes(paddedIv);
343
251
  const cipherBytes = base64ToBytes(paddedCipher);
344
- let encryptionConfig;
345
- // Use version-based configuration if available, otherwise fallback to legacy
346
- if (version && ENCRYPTION_VERSIONS[version]) {
347
- encryptionConfig = ENCRYPTION_VERSIONS[version];
348
- } else {
349
- // Fallback to legacy version for backward compatibility
350
- encryptionConfig = ENCRYPTION_VERSIONS[ENCRYPTION_VERSION_LEGACY];
351
- }
252
+ // Determine which encryption configuration to use
253
+ const encryptionConfig = getEncryptionConfig(version);
352
254
  try {
353
255
  const key = await getKey({
354
256
  password,
355
- salt: saltBytes,
356
- encryptionConfig
357
- });
257
+ salt: saltBytes
258
+ }, encryptionConfig);
358
259
  const decryptedData = await crypto.subtle.decrypt({
359
260
  name: AES_GCM_ALGORITHM,
360
261
  iv: ivBytes
361
262
  }, key, cipherBytes);
362
263
  return new TextDecoder().decode(decryptedData);
363
264
  } catch (error) {
265
+ // For a short period of time we lowered the parallelism for v3 (Argon2) to 1 to try to fix issues
266
+ // for users with limited resources, however this introduced a new issue that the decryption would fail
267
+ // for existing users with v3 (Argon2) encryption, this is a fallback for a few users.
268
+ if (error instanceof Error && error.name === 'OperationError' && version === 'v3' && isArgon2Config(encryptionConfig)) {
269
+ try {
270
+ // Create a modified config with parallelism=1
271
+ const modifiedConfig = _extends({}, encryptionConfig, {
272
+ parallelism: 1
273
+ });
274
+ const key = await getKey({
275
+ password,
276
+ salt: saltBytes
277
+ }, modifiedConfig);
278
+ const decryptedData = await crypto.subtle.decrypt({
279
+ name: AES_GCM_ALGORITHM,
280
+ iv: ivBytes
281
+ }, key, cipherBytes);
282
+ return new TextDecoder().decode(decryptedData);
283
+ } catch (retryError) {
284
+ // If retry also fails, throw the original error with additional context
285
+ throw new Error(`Decryption failed after retry with parallelism=1: ${retryError}`);
286
+ }
287
+ }
364
288
  throw new Error('Decryption failed: ' + error);
365
289
  }
366
290
  };
@@ -368,17 +292,21 @@ const getKey = async ({ password, salt, encryptionConfig })=>{
368
292
  * Gets encryption metadata for a specific version.
369
293
  * Used when we need to include metadata in legacy systems or APIs that require it.
370
294
  */ const getEncryptionMetadataForVersion = (version)=>{
371
- const encryptionConfig = ENCRYPTION_VERSIONS[version];
372
- if (!encryptionConfig) {
373
- throw new Error(`Unsupported encryption version: ${version}`);
374
- }
375
- return {
295
+ const encryptionConfig = getEncryptionConfig(version);
296
+ const metadata = {
376
297
  algorithm: encryptionConfig.algorithm,
377
298
  keyDerivation: encryptionConfig.keyDerivation,
378
299
  iterations: encryptionConfig.iterations,
379
300
  hashAlgorithm: encryptionConfig.hashAlgorithm,
380
301
  algorithmLength: encryptionConfig.algorithmLength
381
302
  };
303
+ // Add Argon2-specific metadata if applicable
304
+ if (isArgon2Config(encryptionConfig)) {
305
+ metadata.memorySize = encryptionConfig.memorySize;
306
+ metadata.parallelism = encryptionConfig.parallelism;
307
+ metadata.hashLength = encryptionConfig.hashLength;
308
+ }
309
+ return metadata;
382
310
  };
383
311
 
384
312
  const GOOGLE_DRIVE_UPLOAD_API = 'https://www.googleapis.com';
@@ -429,52 +357,254 @@ const uploadFileToGoogleDrive = async ({ accessToken, fileName, jsonData, parent
429
357
  if (!response.ok) {
430
358
  throw new Error('Error uploading file');
431
359
  }
432
- const result = await response.json();
433
- return result; // Return file metadata, including file ID
360
+ const result = await response.json();
361
+ return result; // Return file metadata, including file ID
362
+ };
363
+ const listFilesFromGoogleDrive = async ({ accessToken, fileName })=>{
364
+ // Step 1: List all files inside `appDataFolder` with the specified backup filename
365
+ const resp = await fetch(`${GOOGLE_DRIVE_UPLOAD_API}/drive/v3/files?q=${encodeURIComponent(`name='${fileName}'`)}&spaces=appDataFolder&orderBy=createdTime desc`, {
366
+ headers: {
367
+ Authorization: `Bearer ${accessToken}`
368
+ }
369
+ });
370
+ const data = await resp.json();
371
+ // If no files found, return null
372
+ if (!data.files || data.files.length === 0) {
373
+ return null;
374
+ }
375
+ const files = data.files;
376
+ return files;
377
+ };
378
+ const downloadFileFromGoogleDrive = async ({ accessToken, fileName })=>{
379
+ const files = await listFilesFromGoogleDrive({
380
+ accessToken,
381
+ fileName
382
+ });
383
+ if (!files || files.length === 0) {
384
+ return null;
385
+ }
386
+ // Get the most recent file
387
+ const fileMetadata = files[0];
388
+ // Fetch the file data using the file ID
389
+ const fileRes = await fetch(`${GOOGLE_DRIVE_UPLOAD_API}/drive/v3/files/${fileMetadata.id}?alt=media`, {
390
+ headers: {
391
+ Authorization: `Bearer ${accessToken}`
392
+ }
393
+ });
394
+ // Read the file's raw data
395
+ const fileRawData = await fileRes.text();
396
+ if (fileRawData.length === 0) {
397
+ return null;
398
+ }
399
+ try {
400
+ // Just parse and return the data without validation
401
+ // The client will handle validation of the structure
402
+ return JSON.parse(fileRawData);
403
+ } catch (error) {
404
+ return null;
405
+ }
406
+ };
407
+
408
+ const handleAxiosError = (error, message, context)=>{
409
+ var _error_response, _error_response1, _error_response2;
410
+ logger.error('[DynamicWaasWalletClient] Axios error: ', {
411
+ message,
412
+ error: (_error_response = error.response) == null ? void 0 : _error_response.data,
413
+ status: (_error_response1 = error.response) == null ? void 0 : _error_response1.status,
414
+ context
415
+ });
416
+ switch((_error_response2 = error.response) == null ? void 0 : _error_response2.status){
417
+ case 400:
418
+ throw createHttpError(400, 'Invalid request');
419
+ case 401:
420
+ throw createHttpError(401, 'Authorization header or cookie is required');
421
+ case 403:
422
+ throw createHttpError(403, 'Forbidden');
423
+ case 422:
424
+ throw createHttpError(422, 'Unprocessable content');
425
+ case 500:
426
+ throw createHttpError(500, 'Internal server error');
427
+ default:
428
+ throw createHttpError(500, 'Internal server error');
429
+ }
430
+ };
431
+
432
+ const logger = new logger$1.Logger('DynamicWaasWalletClient', logger$1.LogLevel.DEBUG);
433
+ const setLoggerContext = ({ environmentId, authMode = core.AuthMode.HEADER, sessionId = undefined, userId = undefined })=>{
434
+ try {
435
+ logger$1.Logger.setEnvironmentId(environmentId);
436
+ logger$1.Logger.globalMetaData.set('sid', sessionId);
437
+ logger$1.Logger.globalMetaData.set('user_id', userId);
438
+ logger$1.Logger.globalMetaData.set('auth_mode', authMode);
439
+ } catch (error) {
440
+ logError({
441
+ message: '[DynamicWaasWalletClient] Error setting logger context',
442
+ error: error,
443
+ context: {}
444
+ });
445
+ }
446
+ };
447
+ const logError = ({ message, error, context })=>{
448
+ if (error instanceof axios.AxiosError) {
449
+ handleAxiosError(error, message, context);
450
+ }
451
+ logger.error('[DynamicWaasWalletClient] Error in browser client', {
452
+ error: error instanceof Error ? error.message : String(error),
453
+ context
454
+ });
455
+ };
456
+
457
+ const DEFAULT_LOG_LEVEL = logger$1.LogLevel.DEBUG; //todo: change back to info when done debugging
458
+ const STORAGE_KEY = 'dynamic-waas-wallet-client';
459
+ const CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX = 'dynamicWalletKeyShareBackup';
460
+ const SIGNED_SESSION_ID_MIN_VERSION = '4.25.4';
461
+ // Namespace-specific version requirements
462
+ const SIGNED_SESSION_ID_MIN_VERSION_BY_NAMESPACE = {
463
+ WalletKit: '4.25.4',
464
+ ClientSDK: '0.1.0-alpha.0'
465
+ };
466
+
467
+ const isBrowser = ()=>typeof window !== 'undefined';
468
+ const getClientKeyShareExportFileName = ({ thresholdSignatureScheme, accountAddress })=>{
469
+ return `${CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX}-${thresholdSignatureScheme}-${accountAddress}.json`;
470
+ };
471
+ const getClientKeyShareBackupInfo = (params)=>{
472
+ var _params_walletProperties, _params_walletProperties_keyShares_;
473
+ const backups = {
474
+ [core.BackupLocation.DYNAMIC]: [],
475
+ [core.BackupLocation.GOOGLE_DRIVE]: [],
476
+ [core.BackupLocation.ICLOUD]: [],
477
+ [core.BackupLocation.USER]: [],
478
+ [core.BackupLocation.EXTERNAL]: [],
479
+ [core.BackupLocation.DELEGATED]: []
480
+ };
481
+ if (!(params == null ? void 0 : (_params_walletProperties = params.walletProperties) == null ? void 0 : _params_walletProperties.keyShares)) {
482
+ return {
483
+ backups,
484
+ passwordEncrypted: false
485
+ };
486
+ }
487
+ params.walletProperties.keyShares.forEach((keyShare)=>{
488
+ if (backups[keyShare.backupLocation]) {
489
+ backups[keyShare.backupLocation].push({
490
+ location: keyShare.backupLocation,
491
+ keyShareId: keyShare.id,
492
+ externalKeyShareId: keyShare == null ? void 0 : keyShare.externalKeyShareId
493
+ });
494
+ }
495
+ });
496
+ const passwordEncrypted = Boolean((_params_walletProperties_keyShares_ = params.walletProperties.keyShares[0]) == null ? void 0 : _params_walletProperties_keyShares_.passwordEncrypted);
497
+ return {
498
+ backups,
499
+ passwordEncrypted
500
+ };
501
+ };
502
+ /**
503
+ * Helper function to merge keyshares and remove duplicates based on pubkey and secretShare
504
+ * @param existingKeyShares - Array of existing keyshares
505
+ * @param newKeyShares - Array of new keyshares to merge
506
+ * @returns Array of merged unique keyshares
507
+ */ const mergeUniqueKeyShares = (existingKeyShares, newKeyShares)=>{
508
+ const uniqueKeyShares = newKeyShares.filter((newShare)=>!existingKeyShares.some((existingShare)=>{
509
+ if (!(newShare == null ? void 0 : newShare.pubkey) || !(existingShare == null ? void 0 : existingShare.pubkey)) return false;
510
+ return newShare.pubkey.toString() === existingShare.pubkey.toString() && newShare.secretShare === existingShare.secretShare;
511
+ }));
512
+ return [
513
+ ...existingKeyShares,
514
+ ...uniqueKeyShares
515
+ ];
516
+ };
517
+ const timeoutPromise = ({ timeInMs, activity = 'Ceremony' })=>{
518
+ return new Promise((_, reject)=>setTimeout(()=>reject(new Error(`${activity} did not complete in ${timeInMs}ms`)), timeInMs));
519
+ };
520
+ /**
521
+ * Generic helper function to retry a promise-based operations
522
+ *
523
+ * @param operation - The async operation to retry
524
+ * @param config - Configuration options for retry behavior
525
+ * @returns Promise with the operation result
526
+ * @throws Last error encountered after all retries are exhausted
527
+ */ async function retryPromise(operation, { maxAttempts = 5, retryInterval = 500, operationName = 'operation', logContext = {} } = {}) {
528
+ let attempts = 0;
529
+ while(attempts < maxAttempts){
530
+ try {
531
+ return await operation();
532
+ } catch (error) {
533
+ var _error_response;
534
+ attempts++;
535
+ logger.warn(`Failed to execute ${operationName} on attempt ${attempts}`, _extends({}, logContext, {
536
+ error: error instanceof Error ? error.message : 'Unknown error',
537
+ axiosError: error instanceof axios.AxiosError ? (_error_response = error.response) == null ? void 0 : _error_response.data : undefined
538
+ }));
539
+ if (attempts === maxAttempts) {
540
+ var _error_response1;
541
+ logger.error(`Failed to execute ${operationName} after ${maxAttempts} attempts`, _extends({}, logContext, {
542
+ error: error instanceof Error ? error.message : 'Unknown error',
543
+ axiosError: error instanceof axios.AxiosError ? (_error_response1 = error.response) == null ? void 0 : _error_response1.data : undefined
544
+ }));
545
+ throw error;
546
+ }
547
+ // Calculate exponential backoff delay
548
+ const exponentialDelay = retryInterval * 2 ** (attempts - 1);
549
+ await new Promise((resolve)=>setTimeout(resolve, exponentialDelay));
550
+ }
551
+ }
552
+ // TypeScript needs this even though it's unreachable
553
+ throw new Error('Unreachable code');
554
+ }
555
+ const formatEvmMessage = (message)=>{
556
+ if (typeof message === 'string' && message.startsWith('0x')) {
557
+ const serializedTxBytes = Uint8Array.from(Buffer.from(message.slice(2), 'hex'));
558
+ return web.MessageHash.keccak256(serializedTxBytes);
559
+ }
560
+ return web.MessageHash.keccak256(message);
434
561
  };
435
- const listFilesFromGoogleDrive = async ({ accessToken, fileName })=>{
436
- // Step 1: List all files inside `appDataFolder` with the specified backup filename
437
- const resp = await fetch(`${GOOGLE_DRIVE_UPLOAD_API}/drive/v3/files?q=${encodeURIComponent(`name='${fileName}'`)}&spaces=appDataFolder&orderBy=createdTime desc`, {
438
- headers: {
439
- Authorization: `Bearer ${accessToken}`
562
+ const isHexString = (str)=>{
563
+ // Remove 0x prefix if present
564
+ const hex = str.startsWith('0x') ? str.slice(2) : str;
565
+ // Check if string contains only hex characters
566
+ return /^[0-9A-Fa-f]+$/.test(hex);
567
+ };
568
+ const formatSolanaMessage = (message)=>{
569
+ if (typeof message === 'string') {
570
+ if (!isHexString(message)) {
571
+ return Buffer.from(message).toString('hex');
572
+ } else {
573
+ return new Uint8Array(Buffer.from(message, 'hex'));
440
574
  }
441
- });
442
- const data = await resp.json();
443
- // If no files found, return null
444
- if (!data.files || data.files.length === 0) {
445
- return null;
575
+ } else {
576
+ return message;
446
577
  }
447
- const files = data.files;
448
- return files;
449
578
  };
450
- const downloadFileFromGoogleDrive = async ({ accessToken, fileName })=>{
451
- const files = await listFilesFromGoogleDrive({
452
- accessToken,
453
- fileName
454
- });
455
- if (!files || files.length === 0) {
456
- return null;
579
+ const formatMessage = (chainName, message)=>{
580
+ switch(chainName){
581
+ case 'EVM':
582
+ return formatEvmMessage(message);
583
+ case 'SVM':
584
+ return formatSolanaMessage(message);
585
+ case 'SUI':
586
+ return message;
587
+ default:
588
+ throw new Error('Unsupported chain name');
457
589
  }
458
- // Get the most recent file
459
- const fileMetadata = files[0];
460
- // Fetch the file data using the file ID
461
- const fileRes = await fetch(`${GOOGLE_DRIVE_UPLOAD_API}/drive/v3/files/${fileMetadata.id}?alt=media`, {
462
- headers: {
463
- Authorization: `Bearer ${accessToken}`
590
+ };
591
+ const getGoogleOAuthAccountId = (verifiedCredentials)=>{
592
+ const googleVerifiedCredential = verifiedCredentials == null ? void 0 : verifiedCredentials.find((credential)=>credential.oauthProvider === sdkApiCore.ProviderEnum.Google);
593
+ return googleVerifiedCredential == null ? void 0 : googleVerifiedCredential.id;
594
+ };
595
+ const createBackupData = ({ encryptedKeyShares, accountAddress, thresholdSignatureScheme, hasPassword = true })=>{
596
+ return {
597
+ keyShares: encryptedKeyShares,
598
+ metadata: {
599
+ createdAt: new Date().toISOString(),
600
+ accountAddress,
601
+ thresholdSignatureScheme,
602
+ hasPassword,
603
+ encryption: getEncryptionMetadataForVersion(ENCRYPTION_VERSION_CURRENT),
604
+ encryptionVersion: ENCRYPTION_VERSION_CURRENT,
605
+ shareCount: encryptedKeyShares.length
464
606
  }
465
- });
466
- // Read the file's raw data
467
- const fileRawData = await fileRes.text();
468
- if (fileRawData.length === 0) {
469
- return null;
470
- }
471
- try {
472
- // Just parse and return the data without validation
473
- // The client will handle validation of the structure
474
- return JSON.parse(fileRawData);
475
- } catch (error) {
476
- return null;
477
- }
607
+ };
478
608
  };
479
609
 
480
610
  /**
@@ -591,6 +721,94 @@ const localStorageWriteTest = {
591
721
  }
592
722
  });
593
723
 
724
+ /** Algorithm label for the new hybrid encryption standard */ const ALG_LABEL_RSA = 'HYBRID-RSA-AES-256';
725
+ /**
726
+ * Convert base64 to base64url encoding
727
+ */ const toBase64Url = (buffer)=>{
728
+ const base64 = Buffer.from(buffer).toString('base64');
729
+ return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
730
+ };
731
+ /**
732
+ * Convert ArrayBuffer to base64url
733
+ */ const arrayBufferToBase64Url = (buffer)=>{
734
+ return toBase64Url(buffer);
735
+ };
736
+ /**
737
+ * Import RSA public key from PEM format
738
+ */ const importRSAPublicKey = async (publicKeyPem)=>{
739
+ // Remove PEM headers and decode base64
740
+ const pemHeader = '-----BEGIN PUBLIC KEY-----';
741
+ const pemFooter = '-----END PUBLIC KEY-----';
742
+ const pemContents = publicKeyPem.replace(pemHeader, '').replace(pemFooter, '').replace(/\s/g, '');
743
+ const binaryDer = Buffer.from(pemContents, 'base64').toString('binary');
744
+ const keyData = new Uint8Array(binaryDer.length);
745
+ for(let i = 0; i < binaryDer.length; i++){
746
+ keyData[i] = binaryDer.charCodeAt(i);
747
+ }
748
+ return await crypto.subtle.importKey('spki', keyData, {
749
+ name: 'RSA-OAEP',
750
+ hash: 'SHA-256'
751
+ }, false, [
752
+ 'encrypt'
753
+ ]);
754
+ };
755
+ /**
756
+ * Creates the encoded envelope bytes from the encrypted data components
757
+ */ const createEncodedEnvelopeBytes = (iv, ciphertext, authTag, encryptedAesKey)=>{
758
+ const envelopeData = {
759
+ algorithm: ALG_LABEL_RSA,
760
+ iv: arrayBufferToBase64Url(iv.buffer),
761
+ encryptedData: arrayBufferToBase64Url(ciphertext.buffer),
762
+ authTag: arrayBufferToBase64Url(authTag.buffer),
763
+ encryptedKey: arrayBufferToBase64Url(encryptedAesKey)
764
+ };
765
+ return Buffer.from(new TextEncoder().encode(JSON.stringify(envelopeData))).toString('base64');
766
+ };
767
+ /**
768
+ * Encrypts data using HYBRID-RSA-AES-256 encryption scheme with Web Crypto API.
769
+ * 1. Generate random AES-256 key
770
+ * 2. Encrypt AES key with RSA public key
771
+ * 3. Encrypt data with AES-256-GCM
772
+ */ const encryptDelegatedKeyShare = async (data, publicKeyPem)=>{
773
+ try {
774
+ // Step 1: Generate a random AES-256 key and 16-byte IV
775
+ const aesKey = await crypto.subtle.generateKey({
776
+ name: 'AES-GCM',
777
+ length: 256
778
+ }, true, [
779
+ 'encrypt'
780
+ ]);
781
+ const iv = crypto.getRandomValues(new Uint8Array(16)); // 128-bit IV for GCM
782
+ // Step 2: Encrypt the data with AES-256-GCM
783
+ const plaintext = new TextEncoder().encode(data);
784
+ const encryptedData = await crypto.subtle.encrypt({
785
+ name: 'AES-GCM',
786
+ iv: iv
787
+ }, aesKey, plaintext);
788
+ // Extract the auth tag from the encrypted data (last 16 bytes)
789
+ const encryptedDataArray = new Uint8Array(encryptedData);
790
+ const authTag = encryptedDataArray.slice(-16);
791
+ const ciphertext = encryptedDataArray.slice(0, -16);
792
+ // Step 3: Encrypt the AES key with RSA public key
793
+ const rsaPublicKey = await importRSAPublicKey(publicKeyPem);
794
+ // Export the AES key to encrypt it
795
+ const aesKeyData = await crypto.subtle.exportKey('raw', aesKey);
796
+ const encryptedAesKey = await crypto.subtle.encrypt({
797
+ name: 'RSA-OAEP'
798
+ }, rsaPublicKey, aesKeyData);
799
+ return {
800
+ algorithm: ALG_LABEL_RSA,
801
+ iv: arrayBufferToBase64Url(iv.buffer),
802
+ encryptedData: arrayBufferToBase64Url(ciphertext.buffer),
803
+ authTag: arrayBufferToBase64Url(authTag.buffer),
804
+ encryptedKey: arrayBufferToBase64Url(encryptedAesKey),
805
+ encodedEnvelopeBytes: createEncodedEnvelopeBytes(iv, ciphertext, authTag, encryptedAesKey)
806
+ };
807
+ } catch (error) {
808
+ throw new Error(`Encryption failed: ${error instanceof Error ? error.message : String(error)}`);
809
+ }
810
+ };
811
+
594
812
  class DynamicWalletClient {
595
813
  getAuthMode() {
596
814
  return this.authMode;
@@ -656,7 +874,7 @@ class DynamicWalletClient {
656
874
  this.sessionId = sessionId;
657
875
  } catch (error) {
658
876
  logError({
659
- message: '[DynamicWaasWalletClient] Error initializing logger context',
877
+ message: 'Error initializing logger context',
660
878
  error: error,
661
879
  context: {}
662
880
  });
@@ -813,7 +1031,7 @@ class DynamicWalletClient {
813
1031
  };
814
1032
  } catch (error) {
815
1033
  logError({
816
- message: '[DynamicWaasWalletClient] Error in keyGen',
1034
+ message: 'Error in keyGen',
817
1035
  error: error,
818
1036
  context: {
819
1037
  chainName,
@@ -893,7 +1111,7 @@ class DynamicWalletClient {
893
1111
  };
894
1112
  } catch (error) {
895
1113
  logError({
896
- message: '[DynamicWaasWalletClient] Error in importRawPrivateKey',
1114
+ message: 'Error in importRawPrivateKey',
897
1115
  error: error,
898
1116
  context: {
899
1117
  chainName,
@@ -904,7 +1122,7 @@ class DynamicWalletClient {
904
1122
  throw error;
905
1123
  }
906
1124
  }
907
- async serverSign({ walletId, message, isFormatted, mfaToken, context, onError }) {
1125
+ async serverSign({ walletId, message, isFormatted, mfaToken, context, onError, dynamicRequestId }) {
908
1126
  // Create the room and sign the message
909
1127
  if (typeof message !== 'string') {
910
1128
  message = `0x${Buffer.from(message).toString('hex')}`;
@@ -913,14 +1131,14 @@ class DynamicWalletClient {
913
1131
  walletId,
914
1132
  message,
915
1133
  isFormatted,
916
- dynamicRequestId: uuid.v4(),
1134
+ dynamicRequestId,
917
1135
  mfaToken,
918
1136
  context: context ? JSON.parse(JSON.stringify(context, (_key, value)=>typeof value === 'bigint' ? value.toString() : value)) : undefined,
919
1137
  onError
920
1138
  });
921
1139
  return data;
922
1140
  }
923
- async clientSign({ chainName, message, roomId, keyShare, derivationPath, isFormatted }) {
1141
+ async clientSign({ chainName, message, roomId, keyShare, derivationPath, isFormatted, dynamicRequestId }) {
924
1142
  try {
925
1143
  const mpcSigner = getMPCSigner({
926
1144
  chainName,
@@ -938,13 +1156,14 @@ class DynamicWalletClient {
938
1156
  return signature;
939
1157
  } catch (error) {
940
1158
  logError({
941
- message: '[DynamicWaasWalletClient] Error in clientSign',
1159
+ message: 'Error in clientSign',
942
1160
  error: error,
943
1161
  context: {
944
1162
  chainName,
945
1163
  roomId,
946
1164
  derivationPath,
947
- isFormatted
1165
+ isFormatted,
1166
+ dynamicRequestId
948
1167
  }
949
1168
  });
950
1169
  throw error;
@@ -952,6 +1171,7 @@ class DynamicWalletClient {
952
1171
  }
953
1172
  //todo: need to modify with imported flag
954
1173
  async sign({ accountAddress, message, chainName, password = undefined, isFormatted = false, signedSessionId, mfaToken, context, onError }) {
1174
+ const dynamicRequestId = uuid.v4();
955
1175
  try {
956
1176
  await this.verifyPassword({
957
1177
  accountAddress,
@@ -972,13 +1192,15 @@ class DynamicWalletClient {
972
1192
  isFormatted,
973
1193
  mfaToken,
974
1194
  context,
975
- onError
1195
+ onError,
1196
+ dynamicRequestId
976
1197
  });
977
1198
  this.logger.debug('[DynamicWaasWalletClient] Server sign completed', {
978
1199
  message,
979
1200
  accountAddress,
980
1201
  walletId: wallet.walletId,
981
- roomId: data.roomId
1202
+ roomId: data.roomId,
1203
+ dynamicRequestId
982
1204
  });
983
1205
  const derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
984
1206
  // Perform the client sign and return the signature
@@ -991,7 +1213,8 @@ class DynamicWalletClient {
991
1213
  roomId: data.roomId,
992
1214
  keyShare: clientKeyShares[0],
993
1215
  derivationPath,
994
- isFormatted
1216
+ isFormatted,
1217
+ dynamicRequestId
995
1218
  });
996
1219
  this.logger.debug('[DynamicWaasWalletClient] Client sign completed', {
997
1220
  chainName,
@@ -1003,12 +1226,13 @@ class DynamicWalletClient {
1003
1226
  return signature;
1004
1227
  } catch (error) {
1005
1228
  logError({
1006
- message: '[DynamicWaasWalletClient] Error in sign',
1229
+ message: 'Error in sign',
1007
1230
  error: error,
1008
1231
  context: {
1009
1232
  accountAddress,
1010
1233
  chainName,
1011
- isFormatted: isFormatted ? 'true' : 'false'
1234
+ isFormatted: isFormatted ? 'true' : 'false',
1235
+ dynamicRequestId
1012
1236
  }
1013
1237
  });
1014
1238
  throw error;
@@ -1056,7 +1280,7 @@ class DynamicWalletClient {
1056
1280
  });
1057
1281
  } catch (error) {
1058
1282
  logError({
1059
- message: '[DynamicWaasWalletClient] Error in refreshWalletAccountShares',
1283
+ message: 'Error in refreshWalletAccountShares',
1060
1284
  error: error,
1061
1285
  context: {
1062
1286
  accountAddress,
@@ -1121,6 +1345,7 @@ class DynamicWalletClient {
1121
1345
  async reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined, signedSessionId, backupToGoogleDrive = false, delegateToProjectEnvironment = false, mfaToken }) {
1122
1346
  const dynamicRequestId = uuid.v4();
1123
1347
  try {
1348
+ var _publicKey_key, _publicKey_key1;
1124
1349
  await this.verifyPassword({
1125
1350
  accountAddress,
1126
1351
  password,
@@ -1172,35 +1397,54 @@ class DynamicWalletClient {
1172
1397
  chainName,
1173
1398
  baseRelayUrl: this.baseMPCRelayApiUrl
1174
1399
  });
1175
- const reshareResults = await Promise.all([
1176
- ...newClientInitKeygenResults.map((keygenResult)=>mpcSigner.reshareNewParty(roomId, oldMpcConfig.threshold, newMpcConfig.threshold, keygenResult, allPartyKeygenIds)),
1177
- ...existingClientKeyShares.map((keyShare)=>mpcSigner.reshareRemainingParty(roomId, newMpcConfig.threshold, keyShare, allPartyKeygenIds))
1400
+ const existingResharePromises = existingClientKeyShares.map((keyShare)=>mpcSigner.reshareRemainingParty(roomId, newMpcConfig.threshold, keyShare, allPartyKeygenIds));
1401
+ const newResharePromises = newClientInitKeygenResults.map((keygenResult)=>mpcSigner.reshareNewParty(roomId, oldMpcConfig.threshold, newMpcConfig.threshold, keygenResult, allPartyKeygenIds));
1402
+ // Run both share parties in parallel by group
1403
+ const [existingReshareResults, newReshareResults] = await Promise.all([
1404
+ Promise.all(existingResharePromises),
1405
+ Promise.all(newResharePromises)
1178
1406
  ]);
1407
+ const clientKeyshares = delegateToProjectEnvironment ? [
1408
+ ...existingReshareResults
1409
+ ] : [
1410
+ ...existingReshareResults,
1411
+ ...newReshareResults
1412
+ ];
1179
1413
  this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
1180
1414
  thresholdSignatureScheme: newThresholdSignatureScheme
1181
1415
  });
1182
1416
  await this.setClientKeySharesToLocalStorage({
1183
1417
  accountAddress,
1184
- clientKeyShares: reshareResults,
1418
+ clientKeyShares: clientKeyshares,
1185
1419
  overwriteOrMerge: 'overwrite'
1186
1420
  });
1187
- if (delegateToProjectEnvironment) {
1188
- await this.storeEncryptedBackupByDelegatedWallet({
1189
- accountAddress,
1190
- password,
1191
- signedSessionId
1192
- });
1193
- } else {
1194
- await this.storeEncryptedBackupByWallet({
1195
- accountAddress,
1196
- password,
1197
- signedSessionId,
1198
- backupToGoogleDrive
1199
- });
1421
+ await this.storeEncryptedBackupByWallet({
1422
+ accountAddress,
1423
+ password,
1424
+ signedSessionId,
1425
+ backupToGoogleDrive,
1426
+ delegatedLocations: newReshareResults.map(()=>({
1427
+ location: core.BackupLocation.DELEGATED
1428
+ }))
1429
+ });
1430
+ const publicKey = await this.apiClient.getDelegatedEncryptionKey({
1431
+ environmentId: this.environmentId
1432
+ });
1433
+ if (!(publicKey == null ? void 0 : (_publicKey_key = publicKey.key) == null ? void 0 : _publicKey_key.publicKeyPemB64)) {
1434
+ throw new Error('Public key not found');
1200
1435
  }
1436
+ const encryptedDelegatedKeyShareEnvelope = await encryptDelegatedKeyShare(JSON.stringify(clientKeyshares[0]), publicKey == null ? void 0 : (_publicKey_key1 = publicKey.key) == null ? void 0 : _publicKey_key1.publicKeyPemB64);
1437
+ await this.apiClient.publishDelegatedKeyShare({
1438
+ walletId: this.walletMap[accountAddress].walletId,
1439
+ encryptedKeyShare: encryptedDelegatedKeyShareEnvelope == null ? void 0 : encryptedDelegatedKeyShareEnvelope.encodedEnvelopeBytes,
1440
+ encryptionVersion: ENCRYPTION_VERSION_CURRENT,
1441
+ signedSessionId,
1442
+ requiresSignedSessionId: this.requiresSignedSessionId(),
1443
+ dynamicRequestId
1444
+ });
1201
1445
  } catch (error) {
1202
1446
  logError({
1203
- message: '[DynamicWaasWalletClient] Error in reshare',
1447
+ message: 'Error in reshare, resetting wallet to previous state',
1204
1448
  error: error,
1205
1449
  context: {
1206
1450
  accountAddress,
@@ -1211,36 +1455,14 @@ class DynamicWalletClient {
1211
1455
  dynamicRequestId
1212
1456
  }
1213
1457
  });
1214
- throw error;
1215
- }
1216
- }
1217
- async sendKeySharesToDelegatedAccess({ accountAddress, chainName, delegatedKeyShares, environmentId, userId, walletId }) {
1218
- try {
1219
- if (!this.delegatedAccessEndpoint) {
1220
- throw new Error('Cannot send key shares to delegated access because delegated access endpoint is not set');
1221
- }
1222
- const delegatedAccessEndpoint = this.delegatedAccessEndpoint;
1223
- const response = await fetch(delegatedAccessEndpoint, {
1224
- method: 'POST',
1225
- body: JSON.stringify({
1226
- chainName,
1227
- accountAddress,
1228
- delegatedKeyShares,
1229
- environmentId,
1230
- userId,
1231
- walletId
1232
- })
1458
+ // reset user wallet when reshare fails, this would allow the client to recover wallets from an active state
1459
+ this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
1460
+ thresholdSignatureScheme: oldThresholdSignatureScheme
1233
1461
  });
1234
- const data = await response.json();
1235
- return data;
1236
- } catch (error) {
1237
- logError({
1238
- message: '[DynamicWaasWalletClient] Error in sendKeySharesToDelegatedAccess',
1239
- error: error,
1240
- context: {
1241
- accountAddress,
1242
- chainName
1243
- }
1462
+ await this.setClientKeySharesToLocalStorage({
1463
+ accountAddress,
1464
+ clientKeyShares: [],
1465
+ overwriteOrMerge: 'overwrite'
1244
1466
  });
1245
1467
  throw error;
1246
1468
  }
@@ -1251,15 +1473,9 @@ class DynamicWalletClient {
1251
1473
  if (!delegateToProjectEnvironment) {
1252
1474
  throw new Error('Delegation is not allowed for this project environment');
1253
1475
  }
1254
- const environmentSettings = await this.apiClient.getEnvironmentSettings();
1255
- const delegatedAccessEndpoint = environmentSettings.sdk.waas.delegatedAccessEndpoint;
1256
- if (!delegatedAccessEndpoint) {
1257
- throw new Error('Cannot delegate key shares because verified access endpoint is not set in the environment settings');
1258
- }
1259
- this.delegatedAccessEndpoint = delegatedAccessEndpoint;
1260
1476
  const wallet = await this.getWallet({
1261
1477
  accountAddress,
1262
- walletOperation: core.WalletOperation.REACH_ALL_PARTIES,
1478
+ walletOperation: core.WalletOperation.RESHARE,
1263
1479
  password,
1264
1480
  signedSessionId
1265
1481
  });
@@ -1267,28 +1483,23 @@ class DynamicWalletClient {
1267
1483
  throw new Error('Delegation is not allowed for SUI');
1268
1484
  }
1269
1485
  const currentThresholdSignatureScheme = this.walletMap[accountAddress].thresholdSignatureScheme;
1270
- if (currentThresholdSignatureScheme === core.ThresholdSignatureScheme.TWO_OF_TWO) {
1271
- // Reshare to 2-of-3, which will automatically handle the backup distribution
1272
- await this.reshare({
1273
- chainName: this.walletMap[accountAddress].chainName,
1274
- accountAddress,
1275
- oldThresholdSignatureScheme: currentThresholdSignatureScheme,
1276
- newThresholdSignatureScheme: core.ThresholdSignatureScheme.TWO_OF_THREE,
1277
- password,
1278
- signedSessionId,
1279
- backupToGoogleDrive: false,
1280
- delegateToProjectEnvironment: true,
1281
- mfaToken
1282
- });
1283
- const backupInfo = this.walletMap[accountAddress].clientKeySharesBackupInfo;
1284
- const delegatedKeyShares = backupInfo.backups[core.BackupLocation.EXTERNAL] || [];
1285
- return delegatedKeyShares;
1286
- } else {
1287
- throw new Error('Delegation is not allowed for this threshold signature scheme');
1288
- }
1486
+ await this.reshare({
1487
+ chainName: this.walletMap[accountAddress].chainName,
1488
+ accountAddress,
1489
+ oldThresholdSignatureScheme: currentThresholdSignatureScheme,
1490
+ newThresholdSignatureScheme: core.ThresholdSignatureScheme.TWO_OF_THREE,
1491
+ password,
1492
+ signedSessionId,
1493
+ backupToGoogleDrive: false,
1494
+ delegateToProjectEnvironment: true,
1495
+ mfaToken
1496
+ });
1497
+ const backupInfo = this.walletMap[accountAddress].clientKeySharesBackupInfo;
1498
+ const delegatedKeyShares = backupInfo.backups[core.BackupLocation.DELEGATED] || [];
1499
+ return delegatedKeyShares;
1289
1500
  } catch (error) {
1290
1501
  logError({
1291
- message: '[DynamicWaasWalletClient] Error in delegateKeyShares',
1502
+ message: 'Error in delegateKeyShares',
1292
1503
  error: error,
1293
1504
  context: {
1294
1505
  accountAddress
@@ -1355,7 +1566,7 @@ class DynamicWalletClient {
1355
1566
  };
1356
1567
  } catch (error) {
1357
1568
  logError({
1358
- message: '[DynamicWaasWalletClient] Error in exportKey',
1569
+ message: 'Error in exportKey',
1359
1570
  error: error,
1360
1571
  context: {
1361
1572
  accountAddress,
@@ -1403,7 +1614,7 @@ class DynamicWalletClient {
1403
1614
  };
1404
1615
  } catch (error) {
1405
1616
  logError({
1406
- message: '[DynamicWaasWalletClient] Error in offlineExportKey',
1617
+ message: 'Error in offlineExportKey',
1407
1618
  error: error,
1408
1619
  context: {
1409
1620
  chainName
@@ -1441,7 +1652,7 @@ class DynamicWalletClient {
1441
1652
  return (parsedWalletObject == null ? void 0 : parsedWalletObject.clientKeyShares) || [];
1442
1653
  } catch (error) {
1443
1654
  logError({
1444
- message: `[DynamicWaasWalletClient] Error parsing clientKeyShares: ${error} for accountAddress: ${accountAddress}`,
1655
+ message: `Error parsing clientKeyShares: Error for accountAddress:`,
1445
1656
  error: error,
1446
1657
  context: {
1447
1658
  accountAddress
@@ -1487,7 +1698,8 @@ class DynamicWalletClient {
1487
1698
  * @param params.signedSessionId - Optional signed session ID for authentication
1488
1699
  * @param params.backupToGoogleDrive - Whether to backup to Google Drive (defaults to false)
1489
1700
  * @returns Promise with backup metadata including share locations and IDs
1490
- */ async storeEncryptedBackupByWallet({ accountAddress, clientKeyShares = undefined, password = undefined, signedSessionId, backupToGoogleDrive = false }) {
1701
+ */ async storeEncryptedBackupByWallet({ accountAddress, clientKeyShares = undefined, password = undefined, signedSessionId, backupToGoogleDrive = false, delegatedLocations = [] }) {
1702
+ const dynamicRequestId = uuid.v4();
1491
1703
  try {
1492
1704
  var _this_walletMap_accountAddress, _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups_BackupLocation_GOOGLE_DRIVE, _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups, _this_walletMap_accountAddress_clientKeySharesBackupInfo, _this_walletMap_accountAddress1;
1493
1705
  const keySharesToBackup = clientKeyShares != null ? clientKeyShares : await this.getClientKeySharesFromLocalStorage({
@@ -1496,7 +1708,7 @@ class DynamicWalletClient {
1496
1708
  if (!((_this_walletMap_accountAddress = this.walletMap[accountAddress]) == null ? void 0 : _this_walletMap_accountAddress.walletId)) {
1497
1709
  const error = new Error(`WalletId not found for accountAddress ${accountAddress}`);
1498
1710
  logError({
1499
- message: '[DynamicWaasWalletClient] Error in storeEncryptedBackupByWallet, wallet or walletId not found from the wallet map',
1711
+ message: 'Error in storeEncryptedBackupByWallet, wallet or walletId not found from the wallet map',
1500
1712
  error,
1501
1713
  context: {
1502
1714
  accountAddress,
@@ -1533,7 +1745,8 @@ class DynamicWalletClient {
1533
1745
  encryptionVersion: ENCRYPTION_VERSION_CURRENT,
1534
1746
  signedSessionId,
1535
1747
  authMode: this.authMode,
1536
- requiresSignedSessionId: this.requiresSignedSessionId()
1748
+ requiresSignedSessionId: this.requiresSignedSessionId(),
1749
+ dynamicRequestId
1537
1750
  });
1538
1751
  if (data.keyShareIds.length === 0) {
1539
1752
  throw new Error('No key shares were backed up');
@@ -1553,9 +1766,13 @@ class DynamicWalletClient {
1553
1766
  location: core.BackupLocation.GOOGLE_DRIVE
1554
1767
  });
1555
1768
  }
1769
+ if ((delegatedLocations == null ? void 0 : delegatedLocations.length) > 0) {
1770
+ locations.push(...delegatedLocations);
1771
+ }
1556
1772
  const backupData = await this.apiClient.markKeySharesAsBackedUp({
1557
1773
  walletId: this.walletMap[accountAddress].walletId,
1558
- locations
1774
+ locations,
1775
+ dynamicRequestId
1559
1776
  });
1560
1777
  const updatedBackupInfo = getClientKeyShareBackupInfo({
1561
1778
  walletProperties: {
@@ -1576,109 +1793,11 @@ class DynamicWalletClient {
1576
1793
  return data;
1577
1794
  } catch (error) {
1578
1795
  logError({
1579
- message: '[DynamicWaasWalletClient] Error in storeEncryptedBackupByWallet',
1796
+ message: 'Error in storeEncryptedBackupByWallet',
1580
1797
  error: error,
1581
1798
  context: {
1582
- accountAddress
1583
- }
1584
- });
1585
- throw error;
1586
- }
1587
- }
1588
- async storeEncryptedBackupByDelegatedWallet({ accountAddress, clientKeyShares = undefined, password = undefined, signedSessionId }) {
1589
- try {
1590
- var _this_walletMap_accountAddress, _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups_BackupLocation_EXTERNAL, _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups, _this_walletMap_accountAddress_clientKeySharesBackupInfo, _this_walletMap_accountAddress1;
1591
- const keySharesToBackup = clientKeyShares != null ? clientKeyShares : await this.getClientKeySharesFromLocalStorage({
1592
- accountAddress
1593
- });
1594
- if (!((_this_walletMap_accountAddress = this.walletMap[accountAddress]) == null ? void 0 : _this_walletMap_accountAddress.walletId)) {
1595
- const error = new Error(`WalletId not found for accountAddress ${accountAddress}`);
1596
- logError({
1597
- message: '[DynamicWaasWalletClient] Error in storeEncryptedBackupByWallet, wallet or walletId not found from the wallet map',
1598
- error,
1599
- context: {
1600
- accountAddress,
1601
- walletMap: this.walletMap
1602
- }
1603
- });
1604
- throw error;
1605
- }
1606
- let dynamicClientKeyShares = [];
1607
- let delegatedKeyShares = [];
1608
- const encryptedKeyShares = await Promise.all(keySharesToBackup.map((keyShare)=>this.encryptKeyShare({
1609
- keyShare,
1610
- password
1611
- })));
1612
- const hasExistingDelegatedBackup = ((_this_walletMap_accountAddress1 = this.walletMap[accountAddress]) == null ? void 0 : (_this_walletMap_accountAddress_clientKeySharesBackupInfo = _this_walletMap_accountAddress1.clientKeySharesBackupInfo) == null ? void 0 : (_this_walletMap_accountAddress_clientKeySharesBackupInfo_backups = _this_walletMap_accountAddress_clientKeySharesBackupInfo.backups) == null ? void 0 : (_this_walletMap_accountAddress_clientKeySharesBackupInfo_backups_BackupLocation_EXTERNAL = _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups[core.BackupLocation.EXTERNAL]) == null ? void 0 : _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups_BackupLocation_EXTERNAL.length) > 0;
1613
- const shouldBackupToDelegated = hasExistingDelegatedBackup || keySharesToBackup.length >= 2;
1614
- if (shouldBackupToDelegated) {
1615
- // For 2 shares: 1 to backend, 1 to delegated
1616
- // For 3+ shares: N-1 to backend, 1 to delegated
1617
- dynamicClientKeyShares = encryptedKeyShares.slice(0, -core.DELEGATED_SHARE_COUNT);
1618
- delegatedKeyShares = encryptedKeyShares.slice(-core.DELEGATED_SHARE_COUNT);
1619
- } else {
1620
- dynamicClientKeyShares = encryptedKeyShares;
1621
- }
1622
- const data = await this.apiClient.storeEncryptedBackupByWallet({
1623
- walletId: this.walletMap[accountAddress].walletId,
1624
- encryptedKeyShares: dynamicClientKeyShares,
1625
- passwordEncrypted: Boolean(password) && password !== this.environmentId,
1626
- encryptionVersion: ENCRYPTION_VERSION_CURRENT,
1627
- signedSessionId,
1628
- authMode: this.authMode,
1629
- requiresSignedSessionId: this.requiresSignedSessionId()
1630
- });
1631
- await this.apiClient.markKeySharesAsBackedUp({
1632
- walletId: this.walletMap[accountAddress].walletId,
1633
- locations: [
1634
- {
1635
- location: core.BackupLocation.DYNAMIC
1636
- }
1637
- ]
1638
- });
1639
- if (delegatedKeyShares.length > 0) {
1640
- const wallet = this.walletMap[accountAddress];
1641
- var _this_userId;
1642
- const delegatedKeyShareIds = await this.sendKeySharesToDelegatedAccess({
1643
1799
  accountAddress,
1644
- chainName: wallet.chainName,
1645
- environmentId: this.environmentId,
1646
- walletId: wallet.walletId,
1647
- userId: (_this_userId = this.userId) != null ? _this_userId : '',
1648
- delegatedKeyShares: delegatedKeyShares
1649
- });
1650
- data.keyShares.push({
1651
- backupLocation: core.BackupLocation.EXTERNAL,
1652
- id: delegatedKeyShareIds
1653
- });
1654
- //todo: combine with user share service backup once other branch is merged
1655
- await this.apiClient.markKeySharesAsBackedUp({
1656
- walletId: this.walletMap[accountAddress].walletId,
1657
- locations: [
1658
- {
1659
- location: core.BackupLocation.EXTERNAL
1660
- }
1661
- ]
1662
- });
1663
- }
1664
- const updatedBackupInfo = getClientKeyShareBackupInfo({
1665
- walletProperties: {
1666
- derivationPath: this.walletMap[accountAddress].derivationPath,
1667
- keyShares: data.keyShares,
1668
- thresholdSignatureScheme: this.walletMap[accountAddress].thresholdSignatureScheme
1669
- }
1670
- });
1671
- this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
1672
- clientKeySharesBackupInfo: updatedBackupInfo
1673
- });
1674
- await this.storage.setItem(this.storageKey, JSON.stringify(this.walletMap));
1675
- return data;
1676
- } catch (error) {
1677
- logError({
1678
- message: '[DynamicWaasWalletClient] Error in storeEncryptedBackupByDelegatedWallet',
1679
- error: error,
1680
- context: {
1681
- accountAddress
1800
+ dynamicRequestId
1682
1801
  }
1683
1802
  });
1684
1803
  throw error;
@@ -1725,8 +1844,9 @@ class DynamicWalletClient {
1725
1844
  * @returns The Google OAuth Account ID
1726
1845
  * @throws Error if no Google OAuth account ID is found
1727
1846
  */ async getGoogleOauthAccountIdOrThrow(accountAddress) {
1847
+ const dynamicRequestId = uuid.v4();
1728
1848
  try {
1729
- const user = await this.apiClient.getUser();
1849
+ const user = await this.apiClient.getUser(dynamicRequestId);
1730
1850
  const oauthAccountId = getGoogleOAuthAccountId(user == null ? void 0 : user.verifiedCredentials);
1731
1851
  if (!oauthAccountId) {
1732
1852
  const error = new Error('No Google OAuth account ID found');
@@ -1743,10 +1863,11 @@ class DynamicWalletClient {
1743
1863
  return oauthAccountId;
1744
1864
  } catch (error) {
1745
1865
  logError({
1746
- message: '[DynamicWaasWalletClient] Error in getGoogleOauthAccountIdOrThrow',
1866
+ message: 'Error in getGoogleOauthAccountIdOrThrow',
1747
1867
  error: error,
1748
1868
  context: {
1749
- accountAddress
1869
+ accountAddress,
1870
+ dynamicRequestId
1750
1871
  }
1751
1872
  });
1752
1873
  throw error;
@@ -1816,7 +1937,7 @@ class DynamicWalletClient {
1816
1937
  return decryptedKeyShares;
1817
1938
  } catch (error) {
1818
1939
  logError({
1819
- message: '[DynamicWaasWalletClient] Error in recoverEncryptedBackupByWallet',
1940
+ message: 'Error in recoverEncryptedBackupByWallet',
1820
1941
  error: error,
1821
1942
  context: {
1822
1943
  accountAddress,
@@ -1882,7 +2003,7 @@ class DynamicWalletClient {
1882
2003
  }
1883
2004
  } catch (error) {
1884
2005
  logError({
1885
- message: '[DynamicWaasWalletClient] Error in backupKeySharesToGoogleDrive',
2006
+ message: 'Error in backupKeySharesToGoogleDrive',
1886
2007
  error: error,
1887
2008
  context: {
1888
2009
  accountAddress
@@ -1930,7 +2051,7 @@ class DynamicWalletClient {
1930
2051
  return;
1931
2052
  } catch (error) {
1932
2053
  logError({
1933
- message: '[DynamicWaasWalletClient] Error in backupKeySharesToGoogleDrive',
2054
+ message: 'Error in backupKeySharesToGoogleDrive',
1934
2055
  error: error,
1935
2056
  context: {
1936
2057
  accountAddress
@@ -1962,7 +2083,7 @@ class DynamicWalletClient {
1962
2083
  }));
1963
2084
  } catch (error) {
1964
2085
  logError({
1965
- message: '[DynamicWaasWalletClient] Failed to download backup from Google Drive',
2086
+ message: 'Failed to download backup from Google Drive',
1966
2087
  error: error,
1967
2088
  context: {
1968
2089
  accountAddress,
@@ -1974,7 +2095,7 @@ class DynamicWalletClient {
1974
2095
  if (!backupData) {
1975
2096
  const error = new Error('No backup file found');
1976
2097
  logError({
1977
- message: '[DynamicWaasWalletClient] No backup file found',
2098
+ message: 'No backup file found',
1978
2099
  error: new Error('No backup file found'),
1979
2100
  context: {
1980
2101
  accountAddress,
@@ -1987,7 +2108,7 @@ class DynamicWalletClient {
1987
2108
  if (!backupData.keyShares || !backupData.metadata) {
1988
2109
  const error = new Error('Invalid backup format: missing keyShares or metadata');
1989
2110
  logError({
1990
- message: '[DynamicWaasWalletClient] Invalid backup format: missing keyShares or metadata',
2111
+ message: 'Invalid backup format: missing keyShares or metadata',
1991
2112
  error,
1992
2113
  context: {
1993
2114
  accountAddress,
@@ -2009,7 +2130,7 @@ class DynamicWalletClient {
2009
2130
  return decryptedKeyShares;
2010
2131
  } catch (error) {
2011
2132
  logError({
2012
- message: '[DynamicWaasWalletClient] Error in restoreBackupFromGoogleDrive',
2133
+ message: 'Error in restoreBackupFromGoogleDrive',
2013
2134
  error: error,
2014
2135
  context: {
2015
2136
  accountAddress
@@ -2141,7 +2262,7 @@ class DynamicWalletClient {
2141
2262
  });
2142
2263
  } catch (error) {
2143
2264
  logError({
2144
- message: '[DynamicWaasWalletClient] Error in verifyPassword',
2265
+ message: 'Error in verifyPassword',
2145
2266
  error: error,
2146
2267
  context: {
2147
2268
  accountAddress
@@ -2193,6 +2314,7 @@ class DynamicWalletClient {
2193
2314
  return true;
2194
2315
  }
2195
2316
  async getWalletClientKeyShareBackupInfo({ accountAddress }) {
2317
+ const dynamicRequestId = uuid.v4();
2196
2318
  try {
2197
2319
  var _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups_BackupLocation_DYNAMIC, _this_walletMap_accountAddress_clientKeySharesBackupInfo_backups, _this_walletMap_accountAddress_clientKeySharesBackupInfo, _this_walletMap_accountAddress, _user_verifiedCredentials;
2198
2320
  // Return existing backup info if it exists
@@ -2200,23 +2322,25 @@ class DynamicWalletClient {
2200
2322
  return this.walletMap[accountAddress].clientKeySharesBackupInfo;
2201
2323
  }
2202
2324
  // Get backup info from server
2203
- const user = await this.apiClient.getUser();
2325
+ const user = await this.apiClient.getUser(dynamicRequestId);
2204
2326
  const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
2205
2327
  return getClientKeyShareBackupInfo({
2206
2328
  walletProperties: wallet == null ? void 0 : wallet.walletProperties
2207
2329
  });
2208
2330
  } catch (error) {
2209
2331
  logError({
2210
- message: '[DynamicWaasWalletClient] Error in getWalletClientKeyShareBackupInfo',
2332
+ message: 'Error in getWalletClientKeyShareBackupInfo',
2211
2333
  error: error,
2212
2334
  context: {
2213
- accountAddress
2335
+ accountAddress,
2336
+ dynamicRequestId
2214
2337
  }
2215
2338
  });
2216
2339
  throw error;
2217
2340
  }
2218
2341
  }
2219
2342
  async getWallet({ accountAddress, walletOperation = core.WalletOperation.NO_OPERATION, shareCount = undefined, password = undefined, signedSessionId }) {
2343
+ const dynamicRequestId = uuid.v4();
2220
2344
  try {
2221
2345
  var _user_verifiedCredentials;
2222
2346
  const existingWalletCheck = await this.checkWalletFields({
@@ -2229,7 +2353,7 @@ class DynamicWalletClient {
2229
2353
  return this.walletMap[accountAddress];
2230
2354
  }
2231
2355
  // Fetch and restore wallet from server
2232
- const user = await this.apiClient.getUser();
2356
+ const user = await this.apiClient.getUser(dynamicRequestId);
2233
2357
  const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
2234
2358
  this.logger.debug('[DynamicWaasWalletClient] Restoring wallet', wallet);
2235
2359
  const walletProperties = wallet.walletProperties;
@@ -2275,21 +2399,23 @@ class DynamicWalletClient {
2275
2399
  return this.walletMap[accountAddress];
2276
2400
  } catch (error) {
2277
2401
  logError({
2278
- message: '[DynamicWaasWalletClient] Error in getWallet',
2402
+ message: 'Error in getWallet',
2279
2403
  error: error,
2280
2404
  context: {
2281
2405
  accountAddress,
2282
2406
  walletOperation,
2283
- shareCount
2407
+ shareCount,
2408
+ dynamicRequestId
2284
2409
  }
2285
2410
  });
2286
2411
  throw error;
2287
2412
  }
2288
2413
  }
2289
2414
  async getWallets() {
2415
+ const dynamicRequestId = uuid.v4();
2290
2416
  try {
2291
2417
  var _user_verifiedCredentials;
2292
- const user = await this.apiClient.getUser();
2418
+ const user = await this.apiClient.getUser(dynamicRequestId);
2293
2419
  this.userId = user.id;
2294
2420
  const waasWallets = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.filter((vc)=>vc.walletName === 'dynamicwaas');
2295
2421
  const wallets = waasWallets.map((vc)=>{
@@ -2322,9 +2448,11 @@ class DynamicWalletClient {
2322
2448
  return wallets;
2323
2449
  } catch (error) {
2324
2450
  logError({
2325
- message: '[DynamicWaasWalletClient] Error in getWallets',
2451
+ message: 'Error in getWallets',
2326
2452
  error: error,
2327
- context: {}
2453
+ context: {
2454
+ dynamicRequestId
2455
+ }
2328
2456
  });
2329
2457
  throw error;
2330
2458
  }
@@ -2342,7 +2470,6 @@ class DynamicWalletClient {
2342
2470
  sdkVersion }){
2343
2471
  this.userId = undefined;
2344
2472
  this.sessionId = undefined;
2345
- this.delegatedAccessEndpoint = undefined;
2346
2473
  this.initializePromise = null;
2347
2474
  this.logger = logger;
2348
2475
  this.walletMap = {} // todo: store in session storage
@@ -2455,10 +2582,7 @@ exports.ERROR_SIGN_MESSAGE = ERROR_SIGN_MESSAGE;
2455
2582
  exports.ERROR_SIGN_TYPED_DATA = ERROR_SIGN_TYPED_DATA;
2456
2583
  exports.ERROR_VERIFY_MESSAGE_SIGNATURE = ERROR_VERIFY_MESSAGE_SIGNATURE;
2457
2584
  exports.ERROR_VERIFY_TRANSACTION_SIGNATURE = ERROR_VERIFY_TRANSACTION_SIGNATURE;
2458
- exports.base64ToBytes = base64ToBytes;
2459
- exports.bytesToBase64 = bytesToBase64;
2460
2585
  exports.createBackupData = createBackupData;
2461
- exports.ensureBase64Padding = ensureBase64Padding;
2462
2586
  exports.formatEvmMessage = formatEvmMessage;
2463
2587
  exports.formatMessage = formatMessage;
2464
2588
  exports.getClientKeyShareBackupInfo = getClientKeyShareBackupInfo;
@@ -2470,7 +2594,6 @@ exports.isBrowser = isBrowser;
2470
2594
  exports.isHexString = isHexString;
2471
2595
  exports.mergeUniqueKeyShares = mergeUniqueKeyShares;
2472
2596
  exports.retryPromise = retryPromise;
2473
- exports.stringToBytes = stringToBytes;
2474
2597
  exports.timeoutPromise = timeoutPromise;
2475
2598
  Object.keys(core).forEach(function (k) {
2476
2599
  if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {