@dynamic-labs-wallet/browser 0.0.155 → 0.0.157

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 CHANGED
@@ -2,12 +2,13 @@
2
2
 
3
3
  var core = require('@dynamic-labs-wallet/core');
4
4
  var web = require('./internal/web');
5
- var uuid = require('uuid');
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
@@ -341,20 +247,13 @@ const getKey = async ({ password, salt, encryptionConfig })=>{
341
247
  const saltBytes = base64ToBytes(paddedSalt);
342
248
  const ivBytes = base64ToBytes(paddedIv);
343
249
  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
- }
250
+ // Determine which encryption configuration to use
251
+ const encryptionConfig = getEncryptionConfig(version);
352
252
  try {
353
253
  const key = await getKey({
354
254
  password,
355
- salt: saltBytes,
356
- encryptionConfig
357
- });
255
+ salt: saltBytes
256
+ }, encryptionConfig);
358
257
  const decryptedData = await crypto.subtle.decrypt({
359
258
  name: AES_GCM_ALGORITHM,
360
259
  iv: ivBytes
@@ -368,17 +267,21 @@ const getKey = async ({ password, salt, encryptionConfig })=>{
368
267
  * Gets encryption metadata for a specific version.
369
268
  * Used when we need to include metadata in legacy systems or APIs that require it.
370
269
  */ const getEncryptionMetadataForVersion = (version)=>{
371
- const encryptionConfig = ENCRYPTION_VERSIONS[version];
372
- if (!encryptionConfig) {
373
- throw new Error(`Unsupported encryption version: ${version}`);
374
- }
375
- return {
270
+ const encryptionConfig = getEncryptionConfig(version);
271
+ const metadata = {
376
272
  algorithm: encryptionConfig.algorithm,
377
273
  keyDerivation: encryptionConfig.keyDerivation,
378
274
  iterations: encryptionConfig.iterations,
379
275
  hashAlgorithm: encryptionConfig.hashAlgorithm,
380
276
  algorithmLength: encryptionConfig.algorithmLength
381
277
  };
278
+ // Add Argon2-specific metadata if applicable
279
+ if (isArgon2Config(encryptionConfig)) {
280
+ metadata.memorySize = encryptionConfig.memorySize;
281
+ metadata.parallelism = encryptionConfig.parallelism;
282
+ metadata.hashLength = encryptionConfig.hashLength;
283
+ }
284
+ return metadata;
382
285
  };
383
286
 
384
287
  const GOOGLE_DRIVE_UPLOAD_API = 'https://www.googleapis.com';
@@ -477,6 +380,199 @@ const downloadFileFromGoogleDrive = async ({ accessToken, fileName })=>{
477
380
  }
478
381
  };
479
382
 
383
+ const handleAxiosError = (error, message, context)=>{
384
+ var _error_response, _error_response1;
385
+ logger.debug("[DynamicWaasWalletClient] Axios error: " + message, {
386
+ error: (_error_response = error.response) == null ? void 0 : _error_response.status,
387
+ message: error.message,
388
+ context
389
+ });
390
+ switch((_error_response1 = error.response) == null ? void 0 : _error_response1.status){
391
+ case 400:
392
+ throw createHttpError(400, 'Invalid request');
393
+ case 401:
394
+ throw createHttpError(401, 'Authorization header or cookie is required');
395
+ case 403:
396
+ throw createHttpError(403, 'Forbidden');
397
+ case 422:
398
+ throw createHttpError(422, 'Unprocessable content');
399
+ case 500:
400
+ throw createHttpError(500, 'Internal server error');
401
+ default:
402
+ throw createHttpError(500, 'Internal server error');
403
+ }
404
+ };
405
+
406
+ const logger = new logger$1.Logger('DynamicWaasWalletClient', logger$1.LogLevel.DEBUG);
407
+ const setLoggerContext = ({ environmentId, authMode = core.AuthMode.HEADER, sessionId = undefined, userId = undefined })=>{
408
+ try {
409
+ logger$1.Logger.setEnvironmentId(environmentId);
410
+ logger$1.Logger.globalMetaData.set('sid', sessionId);
411
+ logger$1.Logger.globalMetaData.set('user_id', userId);
412
+ logger$1.Logger.globalMetaData.set('auth_mode', authMode);
413
+ } catch (error) {
414
+ logError({
415
+ message: '[DynamicWaasWalletClient] Error setting logger context',
416
+ error: error,
417
+ context: {}
418
+ });
419
+ }
420
+ };
421
+ const logError = ({ message, error, context })=>{
422
+ if (error instanceof axios.AxiosError) {
423
+ handleAxiosError(error, message, context);
424
+ }
425
+ logger.error(message, {
426
+ error: error instanceof Error ? error.message : 'Unknown error',
427
+ context
428
+ });
429
+ };
430
+
431
+ const DEFAULT_LOG_LEVEL = logger$1.LogLevel.DEBUG; //todo: change back to info when done debugging
432
+ const STORAGE_KEY = 'dynamic-waas-wallet-client';
433
+ const CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX = 'dynamicWalletKeyShareBackup';
434
+ const SIGNED_SESSION_ID_MIN_VERSION = '4.25.4';
435
+ // Namespace-specific version requirements
436
+ const SIGNED_SESSION_ID_MIN_VERSION_BY_NAMESPACE = {
437
+ WalletKit: '4.25.4',
438
+ ClientSDK: '0.1.0-alpha.0'
439
+ };
440
+
441
+ const isBrowser = ()=>typeof window !== 'undefined';
442
+ const getClientKeyShareExportFileName = ({ thresholdSignatureScheme, accountAddress })=>{
443
+ return `${CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX}-${thresholdSignatureScheme}-${accountAddress}.json`;
444
+ };
445
+ const getClientKeyShareBackupInfo = (params)=>{
446
+ var _params_walletProperties, _params_walletProperties_keyShares_;
447
+ const backups = {
448
+ [core.BackupLocation.DYNAMIC]: [],
449
+ [core.BackupLocation.GOOGLE_DRIVE]: [],
450
+ [core.BackupLocation.ICLOUD]: [],
451
+ [core.BackupLocation.USER]: [],
452
+ [core.BackupLocation.EXTERNAL]: []
453
+ };
454
+ if (!(params == null ? void 0 : (_params_walletProperties = params.walletProperties) == null ? void 0 : _params_walletProperties.keyShares)) {
455
+ return {
456
+ backups,
457
+ passwordEncrypted: false
458
+ };
459
+ }
460
+ params.walletProperties.keyShares.forEach((keyShare)=>{
461
+ if (backups[keyShare.backupLocation]) {
462
+ backups[keyShare.backupLocation].push({
463
+ location: keyShare.backupLocation,
464
+ keyShareId: keyShare.id,
465
+ externalKeyShareId: keyShare == null ? void 0 : keyShare.externalKeyShareId
466
+ });
467
+ }
468
+ });
469
+ const passwordEncrypted = Boolean((_params_walletProperties_keyShares_ = params.walletProperties.keyShares[0]) == null ? void 0 : _params_walletProperties_keyShares_.passwordEncrypted);
470
+ return {
471
+ backups,
472
+ passwordEncrypted
473
+ };
474
+ };
475
+ /**
476
+ * Helper function to merge keyshares and remove duplicates based on pubkey and secretShare
477
+ * @param existingKeyShares - Array of existing keyshares
478
+ * @param newKeyShares - Array of new keyshares to merge
479
+ * @returns Array of merged unique keyshares
480
+ */ const mergeUniqueKeyShares = (existingKeyShares, newKeyShares)=>{
481
+ const uniqueKeyShares = newKeyShares.filter((newShare)=>!existingKeyShares.some((existingShare)=>{
482
+ if (!(newShare == null ? void 0 : newShare.pubkey) || !(existingShare == null ? void 0 : existingShare.pubkey)) return false;
483
+ return newShare.pubkey.toString() === existingShare.pubkey.toString() && newShare.secretShare === existingShare.secretShare;
484
+ }));
485
+ return [
486
+ ...existingKeyShares,
487
+ ...uniqueKeyShares
488
+ ];
489
+ };
490
+ const timeoutPromise = ({ timeInMs, activity = 'Ceremony' })=>{
491
+ return new Promise((_, reject)=>setTimeout(()=>reject(new Error(`${activity} did not complete in ${timeInMs}ms`)), timeInMs));
492
+ };
493
+ /**
494
+ * Generic helper function to retry a promise-based operations
495
+ *
496
+ * @param operation - The async operation to retry
497
+ * @param config - Configuration options for retry behavior
498
+ * @returns Promise with the operation result
499
+ * @throws Last error encountered after all retries are exhausted
500
+ */ async function retryPromise(operation, { maxAttempts = 5, retryInterval = 500, operationName = 'operation', logContext = {} } = {}) {
501
+ let attempts = 0;
502
+ while(attempts < maxAttempts){
503
+ try {
504
+ return await operation();
505
+ } catch (error) {
506
+ attempts++;
507
+ if (attempts === maxAttempts) {
508
+ logger.error(`Failed to execute ${operationName} after ${maxAttempts} attempts`, _extends({}, logContext, {
509
+ error: error instanceof Error ? error.message : 'Unknown error'
510
+ }));
511
+ throw error;
512
+ }
513
+ // Calculate exponential backoff delay
514
+ const exponentialDelay = retryInterval * 2 ** (attempts - 1);
515
+ await new Promise((resolve)=>setTimeout(resolve, exponentialDelay));
516
+ }
517
+ }
518
+ // TypeScript needs this even though it's unreachable
519
+ throw new Error('Unreachable code');
520
+ }
521
+ const formatEvmMessage = (message)=>{
522
+ if (typeof message === 'string' && message.startsWith('0x')) {
523
+ const serializedTxBytes = Uint8Array.from(Buffer.from(message.slice(2), 'hex'));
524
+ return web.MessageHash.keccak256(serializedTxBytes);
525
+ }
526
+ return web.MessageHash.keccak256(message);
527
+ };
528
+ const isHexString = (str)=>{
529
+ // Remove 0x prefix if present
530
+ const hex = str.startsWith('0x') ? str.slice(2) : str;
531
+ // Check if string contains only hex characters
532
+ return /^[0-9A-Fa-f]+$/.test(hex);
533
+ };
534
+ const formatSolanaMessage = (message)=>{
535
+ if (typeof message === 'string') {
536
+ if (!isHexString(message)) {
537
+ return Buffer.from(message).toString('hex');
538
+ } else {
539
+ return new Uint8Array(Buffer.from(message, 'hex'));
540
+ }
541
+ } else {
542
+ return message;
543
+ }
544
+ };
545
+ const formatMessage = (chainName, message)=>{
546
+ switch(chainName){
547
+ case 'EVM':
548
+ return formatEvmMessage(message);
549
+ case 'SVM':
550
+ return formatSolanaMessage(message);
551
+ case 'SUI':
552
+ return message;
553
+ default:
554
+ throw new Error('Unsupported chain name');
555
+ }
556
+ };
557
+ const getGoogleOAuthAccountId = (verifiedCredentials)=>{
558
+ const googleVerifiedCredential = verifiedCredentials == null ? void 0 : verifiedCredentials.find((credential)=>credential.oauthProvider === sdkApiCore.ProviderEnum.Google);
559
+ return googleVerifiedCredential == null ? void 0 : googleVerifiedCredential.id;
560
+ };
561
+ const createBackupData = ({ encryptedKeyShares, accountAddress, thresholdSignatureScheme, hasPassword = true })=>{
562
+ return {
563
+ keyShares: encryptedKeyShares,
564
+ metadata: {
565
+ createdAt: new Date().toISOString(),
566
+ accountAddress,
567
+ thresholdSignatureScheme,
568
+ hasPassword,
569
+ encryption: getEncryptionMetadataForVersion(ENCRYPTION_VERSION_CURRENT),
570
+ encryptionVersion: ENCRYPTION_VERSION_CURRENT,
571
+ shareCount: encryptedKeyShares.length
572
+ }
573
+ };
574
+ };
575
+
480
576
  /**
481
577
  * Uploads a backup to Google Drive App
482
578
  * @param accessToken - The access token for the Google Drive API
@@ -2455,10 +2551,7 @@ exports.ERROR_SIGN_MESSAGE = ERROR_SIGN_MESSAGE;
2455
2551
  exports.ERROR_SIGN_TYPED_DATA = ERROR_SIGN_TYPED_DATA;
2456
2552
  exports.ERROR_VERIFY_MESSAGE_SIGNATURE = ERROR_VERIFY_MESSAGE_SIGNATURE;
2457
2553
  exports.ERROR_VERIFY_TRANSACTION_SIGNATURE = ERROR_VERIFY_TRANSACTION_SIGNATURE;
2458
- exports.base64ToBytes = base64ToBytes;
2459
- exports.bytesToBase64 = bytesToBase64;
2460
2554
  exports.createBackupData = createBackupData;
2461
- exports.ensureBase64Padding = ensureBase64Padding;
2462
2555
  exports.formatEvmMessage = formatEvmMessage;
2463
2556
  exports.formatMessage = formatMessage;
2464
2557
  exports.getClientKeyShareBackupInfo = getClientKeyShareBackupInfo;
@@ -2470,7 +2563,6 @@ exports.isBrowser = isBrowser;
2470
2563
  exports.isHexString = isHexString;
2471
2564
  exports.mergeUniqueKeyShares = mergeUniqueKeyShares;
2472
2565
  exports.retryPromise = retryPromise;
2473
- exports.stringToBytes = stringToBytes;
2474
2566
  exports.timeoutPromise = timeoutPromise;
2475
2567
  Object.keys(core).forEach(function (k) {
2476
2568
  if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {