@dynamic-labs-wallet/core 0.0.0-preview.112

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.esm.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./src/index";
package/index.esm.js ADDED
@@ -0,0 +1,686 @@
1
+ import axios from 'axios';
2
+
3
+ const DYNAMIC_AUTH_PROD_BASE_API_URL = 'https://app.dynamicauth.com';
4
+ const DYNAMIC_AUTH_PREPROD_BASE_API_URL = 'https://app.dynamic-preprod.xyz';
5
+ const DYNAMIC_CLIENT_RELAY_PROD_BASE_API_URL = 'https://app-dynamicauth-com-app-6e12fc400995.relay.evervault.app';
6
+ const DYNAMIC_CLIENT_RELAY_PREPROD_BASE_API_URL = 'https://app-dynamic-preprod-xyz-app-32d15525a875.relay.evervault.app';
7
+ const MPC_RELAY_PROD_API_URL = 'relay.dynamicauth.com';
8
+ const MPC_RELAY_PREPROD_API_URL = 'relay.dynamic-preprod.xyz';
9
+ const SOLANA_RPC_URL = 'https://api.devnet.solana.com';
10
+ const chain = {
11
+ EVM: 'EVM',
12
+ SOL: 'SOL',
13
+ COSMOS: 'COSMOS',
14
+ BTC: 'BTC',
15
+ FLOW: 'FLOW',
16
+ SUI: 'SUI'
17
+ };
18
+ var WalletOperation = /*#__PURE__*/ function(WalletOperation) {
19
+ WalletOperation["REACH_THRESHOLD"] = "REACH_THRESHOLD";
20
+ WalletOperation["REACH_ALL_PARTIES"] = "REACH_ALL_PARTIES";
21
+ WalletOperation["SIGN_MESSAGE"] = "SIGN_MESSAGE";
22
+ WalletOperation["SIGN_TRANSACTION"] = "SIGN_TRANSACTION";
23
+ WalletOperation["REFRESH"] = "REFRESH";
24
+ WalletOperation["RESHARE"] = "RESHARE";
25
+ WalletOperation["EXPORT_PRIVATE_KEY"] = "EXPORT_PRIVATE_KEY";
26
+ WalletOperation["NO_OPERATION"] = "NO_OPERATION";
27
+ return WalletOperation;
28
+ }({});
29
+ var BackupLocation = /*#__PURE__*/ function(BackupLocation) {
30
+ BackupLocation["DYNAMIC"] = "dynamic";
31
+ BackupLocation["GOOGLE_DRIVE"] = "googleDrive";
32
+ BackupLocation["ICLOUD"] = "iCloud";
33
+ BackupLocation["USER"] = "user";
34
+ BackupLocation["EXTERNAL"] = "external";
35
+ return BackupLocation;
36
+ }({});
37
+ // TODO: replace with apiClient proxy and move this to apiClient when ready
38
+ const IFRAME_DOMAIN_PREPROD = 'https://waas.dynamic-preprod.xyz';
39
+ const IFRAME_DOMAIN_PROD = 'https://waas.dynamicauth.com';
40
+ const ChainEnumToVerifiedCredentialName = {
41
+ BTC: 'bip122',
42
+ EVM: 'eip155',
43
+ FLOW: 'flow',
44
+ SOL: 'solana'
45
+ };
46
+ const VerifiedCredentialNameToChainEnum = {
47
+ bip122: 'BTC',
48
+ eip155: 'EVM',
49
+ solana: 'SOL'
50
+ };
51
+
52
+ var SigningAlgorithm = /*#__PURE__*/ function(SigningAlgorithm) {
53
+ SigningAlgorithm["ECDSA"] = "ECDSA";
54
+ SigningAlgorithm["ED25519"] = "ED25519";
55
+ SigningAlgorithm["BIP340"] = "BIP340";
56
+ return SigningAlgorithm;
57
+ }({});
58
+ const BITCOIN_DERIVATION_PATHS = {
59
+ LEGACY: [
60
+ 44,
61
+ 0,
62
+ 0,
63
+ 0,
64
+ 0
65
+ ],
66
+ // m/49'/0'/0'/0/0 - SegWit (P2SH-P2WPKH)
67
+ NATIVE_SEGWIT: [
68
+ 84,
69
+ 0,
70
+ 0,
71
+ 0,
72
+ 0
73
+ ],
74
+ // m/44'/0'/0'/0/0 - Legacy (P2PKH)
75
+ SEGWIT: [
76
+ 49,
77
+ 0,
78
+ 0,
79
+ 0,
80
+ 0
81
+ ]
82
+ };
83
+ const MPC_CHAIN_CONFIG = {
84
+ EVM: {
85
+ // Uses secp256k1 ECDSA
86
+ derivationPath: [
87
+ 44,
88
+ 60,
89
+ 0,
90
+ 0,
91
+ 0
92
+ ],
93
+ signingAlgorithm: "ECDSA"
94
+ },
95
+ SOL: {
96
+ // Uses Ed25519
97
+ derivationPath: [
98
+ 44,
99
+ 501,
100
+ 0,
101
+ 0,
102
+ 0
103
+ ],
104
+ signingAlgorithm: "ED25519"
105
+ },
106
+ BTC: {
107
+ // Uses secp256k1 BIP340
108
+ derivationPath: BITCOIN_DERIVATION_PATHS.NATIVE_SEGWIT,
109
+ signingAlgorithm: "BIP340"
110
+ },
111
+ COSMOS: {
112
+ // Uses Ed25519
113
+ derivationPath: [
114
+ 44,
115
+ 118,
116
+ 0,
117
+ 0,
118
+ 0
119
+ ],
120
+ signingAlgorithm: "ED25519"
121
+ },
122
+ FLOW: {
123
+ // Uses Ed25519
124
+ derivationPath: [
125
+ 44,
126
+ 539,
127
+ 0,
128
+ 0,
129
+ 0
130
+ ],
131
+ signingAlgorithm: "ED25519"
132
+ }
133
+ };
134
+ var ThresholdSignatureScheme = /*#__PURE__*/ function(ThresholdSignatureScheme) {
135
+ ThresholdSignatureScheme["TWO_OF_TWO"] = "TWO_OF_TWO";
136
+ ThresholdSignatureScheme["TWO_OF_THREE"] = "TWO_OF_THREE";
137
+ ThresholdSignatureScheme["THREE_OF_FIVE"] = "THREE_OF_FIVE";
138
+ return ThresholdSignatureScheme;
139
+ }({});
140
+ const MPC_CONFIG = {
141
+ ["TWO_OF_TWO"]: {
142
+ numberOfParties: 2,
143
+ threshold: 2,
144
+ clientThreshold: 1,
145
+ dynamicServerThreshold: 1
146
+ },
147
+ ["TWO_OF_THREE"]: {
148
+ numberOfParties: 3,
149
+ threshold: 2,
150
+ clientThreshold: 2,
151
+ dynamicServerThreshold: 1
152
+ },
153
+ ["THREE_OF_FIVE"]: {
154
+ numberOfParties: 5,
155
+ threshold: 3,
156
+ clientThreshold: 3,
157
+ dynamicServerThreshold: 2
158
+ }
159
+ };
160
+ var CreateRoomPartiesOptions = /*#__PURE__*/ function(CreateRoomPartiesOptions) {
161
+ CreateRoomPartiesOptions["THRESHOLD"] = "threshold";
162
+ CreateRoomPartiesOptions["FULL"] = "full";
163
+ return CreateRoomPartiesOptions;
164
+ }({});
165
+
166
+ const getMPCChainConfig = (chainName)=>{
167
+ const chainConfig = MPC_CHAIN_CONFIG[chainName];
168
+ if (!chainConfig) {
169
+ throw new Error(`Chain ${chainName} not supported`);
170
+ }
171
+ return chainConfig;
172
+ };
173
+ const getTSSConfig = (thresholdSignatureScheme)=>{
174
+ const { threshold, numberOfParties } = MPC_CONFIG[thresholdSignatureScheme];
175
+ return {
176
+ threshold,
177
+ numberOfParties
178
+ };
179
+ };
180
+ const getClientThreshold = (thresholdSignatureScheme)=>{
181
+ return MPC_CONFIG[thresholdSignatureScheme].clientThreshold;
182
+ };
183
+ const getDynamicServerThreshold = (thresholdSignatureScheme)=>{
184
+ return MPC_CONFIG[thresholdSignatureScheme].dynamicServerThreshold;
185
+ };
186
+ /**
187
+ * Helper function to get the reshare config for client and server shares
188
+ * @param {ThresholdSignatureScheme} oldThresholdSignatureScheme - The current threshold signature scheme
189
+ * @param {ThresholdSignatureScheme} newThresholdSignatureScheme - The target threshold signature scheme
190
+ * @returns {{
191
+ * existingClientShareCount: number,
192
+ * newClientShareCount: number,
193
+ * existingServerShareCount: number,
194
+ * newServerShareCount: number
195
+ * }} The number of existing and new client and server shares needed
196
+ */ const getReshareConfig = ({ oldThresholdSignatureScheme, newThresholdSignatureScheme })=>{
197
+ switch(true){
198
+ // 2-of-2 -> 2-of-2:
199
+ // -- dynamic server shares: 1 existing, 0 new
200
+ // -- client shares: 1 existing, 0 new
201
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_TWO && newThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_TWO:
202
+ return {
203
+ existingClientShareCount: 1,
204
+ newClientShareCount: 0,
205
+ existingServerShareCount: 1,
206
+ newServerShareCount: 0
207
+ };
208
+ // 2-of-3 -> 2-of-3:
209
+ // -- dynamic server shares: 1 existing, 0 new
210
+ // -- client shares: 1 existing, 1 new
211
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE && newThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE:
212
+ return {
213
+ existingClientShareCount: 1,
214
+ newClientShareCount: 1,
215
+ existingServerShareCount: 1,
216
+ newServerShareCount: 0
217
+ };
218
+ // 3-of-5 -> 3-of-5:
219
+ // -- dynamic server shares: 2 existing, 0 new
220
+ // -- client shares: 1 existing, 2 new
221
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.THREE_OF_FIVE && newThresholdSignatureScheme === ThresholdSignatureScheme.THREE_OF_FIVE:
222
+ return {
223
+ existingClientShareCount: 1,
224
+ newClientShareCount: 2,
225
+ existingServerShareCount: 2,
226
+ newServerShareCount: 0
227
+ };
228
+ // 2-of-2 -> 2-of-3:
229
+ // -- dynamic server shares: 1 existing, 0 new
230
+ // -- client shares: 1 existing, 1 new
231
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_TWO && newThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE:
232
+ return {
233
+ existingClientShareCount: 1,
234
+ newClientShareCount: 1,
235
+ existingServerShareCount: 1,
236
+ newServerShareCount: 0
237
+ };
238
+ // 2-of-2 -> 3-of-5:
239
+ // -- dynamic server shares: 1 existing, 1 new
240
+ // -- client shares: 1 existing, 2 new
241
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_TWO && newThresholdSignatureScheme === ThresholdSignatureScheme.THREE_OF_FIVE:
242
+ return {
243
+ existingClientShareCount: 1,
244
+ newClientShareCount: 2,
245
+ existingServerShareCount: 1,
246
+ newServerShareCount: 1
247
+ };
248
+ // 2-of-3 -> 3-of-5:
249
+ // -- dynamic server shares: 1 existing, 1 new
250
+ // -- client shares: 1 existing, 2 new
251
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE && newThresholdSignatureScheme === ThresholdSignatureScheme.THREE_OF_FIVE:
252
+ return {
253
+ existingClientShareCount: 1,
254
+ newClientShareCount: 2,
255
+ existingServerShareCount: 1,
256
+ newServerShareCount: 1
257
+ };
258
+ // 2-of-3 -> 2-of-2:
259
+ // -- dynamic server shares: 1 existing, 0 new
260
+ // -- client shares: 1 existing, 0 new
261
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE && newThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_TWO:
262
+ return {
263
+ existingClientShareCount: 1,
264
+ newClientShareCount: 0,
265
+ existingServerShareCount: 1,
266
+ newServerShareCount: 0
267
+ };
268
+ // 3-of-5 -> 2-of-3:
269
+ // -- dynamic server shares: 1 existing, 0 new
270
+ // -- client shares: 2 existing, 0 new
271
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.THREE_OF_FIVE && newThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE:
272
+ return {
273
+ existingClientShareCount: 2,
274
+ newClientShareCount: 0,
275
+ existingServerShareCount: 1,
276
+ newServerShareCount: 0
277
+ };
278
+ default:
279
+ throw new Error(`Unsupported reshare from ${oldThresholdSignatureScheme} to ${newThresholdSignatureScheme}`);
280
+ }
281
+ };
282
+ /**
283
+ * Helper function to get the reshare config for client and server shares
284
+ * @param {ThresholdSignatureScheme} oldThresholdSignatureScheme - The current threshold signature scheme
285
+ * @param {ThresholdSignatureScheme} newThresholdSignatureScheme - The target threshold signature scheme
286
+ * @returns {{
287
+ * existingServerShareCount: number,
288
+ * newServerhareCount: number,
289
+ * existingDynamicServerShareCount: number,
290
+ * newDynamicServerShareCount: number
291
+ * }} The number of existing and new client and server shares needed
292
+ */ const getServerWalletReshareConfig = ({ oldThresholdSignatureScheme, newThresholdSignatureScheme })=>{
293
+ switch(true){
294
+ // 2-of-2 -> 2-of-2:
295
+ // -- dyanmic server shares: 1 existing, 0 new
296
+ // -- external server shares: 1 existing, 0 new
297
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_TWO && newThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_TWO:
298
+ return {
299
+ existingExternalServerShareCount: 1,
300
+ newExternalServerShareCount: 0,
301
+ existingDynamicServerShareCount: 1,
302
+ newDynamicServerShareCount: 0
303
+ };
304
+ // 2-of-3 -> 2-of-3:
305
+ // -- dyanmic server shares: 1 existing, 0 new
306
+ // -- external server shares: 1 existing, 1 new
307
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE && newThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE:
308
+ return {
309
+ existingExternalServerShareCount: 1,
310
+ newExternalServerShareCount: 1,
311
+ existingDynamicServerShareCount: 1,
312
+ newDynamicServerShareCount: 0
313
+ };
314
+ // 3-of-5 -> 3-of-5:
315
+ // -- dyanmic server shares: 2 existing, 0 new
316
+ // -- external server shares: 1 existing, 2 new
317
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.THREE_OF_FIVE && newThresholdSignatureScheme === ThresholdSignatureScheme.THREE_OF_FIVE:
318
+ return {
319
+ existingExternalServerShareCount: 1,
320
+ newExternalServerShareCount: 2,
321
+ existingDynamicServerShareCount: 2,
322
+ newDynamicServerShareCount: 0
323
+ };
324
+ // 2-of-2 -> 2-of-3:
325
+ // -- dyanmic server shares: 1 existing, 0 new
326
+ // -- external server shares: 1 existing, 1 new
327
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_TWO && newThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE:
328
+ return {
329
+ existingExternalServerShareCount: 1,
330
+ newExternalServerShareCount: 1,
331
+ existingDynamicServerShareCount: 1,
332
+ newDynamicServerShareCount: 0
333
+ };
334
+ // 2-of-2 -> 3-of-5:
335
+ // -- dyanmic server shares: 1 existing, 1 new
336
+ // -- external server shares: 1 existing, 2 new
337
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_TWO && newThresholdSignatureScheme === ThresholdSignatureScheme.THREE_OF_FIVE:
338
+ return {
339
+ existingExternalServerShareCount: 1,
340
+ newExternalServerShareCount: 2,
341
+ existingDynamicServerShareCount: 1,
342
+ newDynamicServerShareCount: 1
343
+ };
344
+ // 2-of-3 -> 3-of-5:
345
+ // -- dyanmic server shares: 1 existing, 1 new
346
+ // -- external server shares: 1 existing, 2 new
347
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE && newThresholdSignatureScheme === ThresholdSignatureScheme.THREE_OF_FIVE:
348
+ return {
349
+ existingExternalServerShareCount: 1,
350
+ newExternalServerShareCount: 2,
351
+ existingDynamicServerShareCount: 1,
352
+ newDynamicServerShareCount: 1
353
+ };
354
+ // 2-of-3 -> 2-of-2:
355
+ // -- dyanmic server shares: 1 existing, 0 new
356
+ // -- external server shares: 1 existing, 0 new
357
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE && newThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_TWO:
358
+ return {
359
+ existingExternalServerShareCount: 1,
360
+ newExternalServerShareCount: 0,
361
+ existingDynamicServerShareCount: 1,
362
+ newDynamicServerShareCount: 0
363
+ };
364
+ // 3-of-5 -> 2-of-3:
365
+ // -- dyanmic server shares: 1 existing, 0 new
366
+ // -- external server shares: 2 existing, 0 new
367
+ case oldThresholdSignatureScheme === ThresholdSignatureScheme.THREE_OF_FIVE && newThresholdSignatureScheme === ThresholdSignatureScheme.TWO_OF_THREE:
368
+ return {
369
+ existingExternalServerShareCount: 2,
370
+ newExternalServerShareCount: 0,
371
+ existingDynamicServerShareCount: 1,
372
+ newDynamicServerShareCount: 0
373
+ };
374
+ default:
375
+ throw new Error(`Unsupported reshare from ${oldThresholdSignatureScheme} to ${newThresholdSignatureScheme}`);
376
+ }
377
+ };
378
+
379
+ class BaseClient {
380
+ constructor({ environmentId, baseApiUrl, authToken, baseClientRelayApiUrl }){
381
+ const headers = {};
382
+ headers['Authorization'] = authToken ? `Bearer ${authToken}` : undefined;
383
+ this.environmentId = environmentId;
384
+ const isProd = typeof baseApiUrl === 'undefined' || DYNAMIC_AUTH_PROD_BASE_API_URL === baseApiUrl;
385
+ this.baseApiUrl = isProd ? DYNAMIC_AUTH_PROD_BASE_API_URL : baseApiUrl || DYNAMIC_AUTH_PREPROD_BASE_API_URL;
386
+ this.apiClient = axios.create({
387
+ baseURL: this.baseApiUrl,
388
+ headers
389
+ });
390
+ this.clientRelayBaseApiUrl = isProd ? DYNAMIC_CLIENT_RELAY_PROD_BASE_API_URL : baseClientRelayApiUrl || DYNAMIC_CLIENT_RELAY_PREPROD_BASE_API_URL;
391
+ this.clientRelayApiClient = axios.create({
392
+ baseURL: this.clientRelayBaseApiUrl,
393
+ headers
394
+ });
395
+ }
396
+ }
397
+
398
+ var SuccessEventType = /*#__PURE__*/ function(SuccessEventType) {
399
+ SuccessEventType["KeygenComplete"] = "keygen_complete";
400
+ SuccessEventType["RoomCreated"] = "room_created";
401
+ SuccessEventType["CeremonyComplete"] = "ceremony_complete";
402
+ return SuccessEventType;
403
+ }({});
404
+
405
+ /**
406
+ * Creates a promise that resolves when a specific event is received from an event stream.
407
+ * Adds a timeout to prevent hanging and races the two promises.
408
+ *
409
+ * @template T The expected type of the response data
410
+ * @param apiClient The axios instance to use for API calls
411
+ * @param options The configuration options
412
+ * @returns A promise that resolves with the event data or rejects on timeout
413
+ */ const createEventStreamPromise = ({ apiClient, endpoint, body, successEventType, timeoutMs = 30000, timeoutMessage, onError, onCeremonyComplete })=>{
414
+ // Create a promise that will resolve when the success event is received
415
+ const eventPromise = new Promise((resolve, reject)=>{
416
+ apiClient.post(endpoint, body, {
417
+ responseType: 'stream',
418
+ headers: {
419
+ Accept: 'text/event-stream',
420
+ 'Cache-Control': 'no-cache',
421
+ Connection: 'keep-alive'
422
+ },
423
+ adapter: 'fetch'
424
+ }).then(createSuccessErrorEventStreamHandler({
425
+ onError,
426
+ reject,
427
+ resolve,
428
+ successEventType,
429
+ onCeremonyComplete
430
+ })).catch(reject);
431
+ });
432
+ // Add a timeout to prevent hanging
433
+ const timeoutPromise = new Promise((_, reject)=>{
434
+ setTimeout(()=>reject(new Error(timeoutMessage)), timeoutMs);
435
+ });
436
+ // Return the event data as soon as it's available
437
+ return Promise.race([
438
+ eventPromise,
439
+ timeoutPromise
440
+ ]);
441
+ };
442
+ /**
443
+ * Creates a handler function for processing server-sent events (SSE) streams.
444
+ * This utility manages asynchronous event-based communication with the server,
445
+ * particularly for long-running operations like wallet creation or key generation.
446
+ *
447
+ * @template T - The expected type of the successful response data
448
+ * @param {function} resolve - Promise resolution function to call when the success event is received
449
+ * @param {function} reject - Promise rejection function to call when an error occurs
450
+ * @param {string} successEventType - The event type string that indicates a successful operation
451
+ * @param {function} [onError] - Optional callback for error handling, allowing custom error processing
452
+ * @returns {function} A response handler function that processes the event stream
453
+ */ const createSuccessErrorEventStreamHandler = ({ resolve, reject, successEventType, onError, onCeremonyComplete })=>{
454
+ return (response)=>{
455
+ const reader = response.data.getReader();
456
+ const decoder = new TextDecoder();
457
+ let buffer = '';
458
+ const processStream = async ()=>{
459
+ try {
460
+ const { value, done } = await reader.read();
461
+ if (done) return;
462
+ buffer += decoder.decode(value, {
463
+ stream: true
464
+ });
465
+ const events = parseEventStream(buffer);
466
+ for (const event of events){
467
+ if (event.type === successEventType) {
468
+ resolve(event.data);
469
+ }
470
+ if (event.type === SuccessEventType.CeremonyComplete) {
471
+ const { accountAddress, walletId } = event.data;
472
+ onCeremonyComplete == null ? void 0 : onCeremonyComplete(accountAddress, walletId);
473
+ }
474
+ if (event.type === 'error') {
475
+ reject(createErrorFromEventData(event.data));
476
+ onError == null ? void 0 : onError(createErrorFromEventData(event.data));
477
+ }
478
+ }
479
+ processStream();
480
+ } catch (err) {
481
+ reject(err instanceof Error ? err : new Error(String(err)));
482
+ }
483
+ };
484
+ processStream();
485
+ };
486
+ };
487
+ /**
488
+ * Creates an error object from event stream error data.
489
+ *
490
+ * @param data - The error data received from the event stream
491
+ * @returns A standardized Error object with properties from the error data
492
+ */ const createErrorFromEventData = (data)=>{
493
+ const error = new Error(typeof data === 'object' && data !== null && 'error' in data ? String(data.error) : 'Unknown error');
494
+ if (typeof data === 'object' && data !== null) {
495
+ Object.assign(error, data);
496
+ }
497
+ return error;
498
+ };
499
+ /**
500
+ * Parses a Server-Sent Events (SSE) stream into structured event objects.
501
+ *
502
+ * @param input - Raw string data from an event stream
503
+ * @returns Array of parsed events with type and data properties
504
+ */ const parseEventStream = (input)=>{
505
+ const lines = input.split('\n');
506
+ const events = [];
507
+ let currentEvent = {};
508
+ let inEvent = false;
509
+ for (const line of lines){
510
+ // Empty line marks the end of an event
511
+ if (line === '') {
512
+ if (currentEvent.type && currentEvent.data) {
513
+ events.push({
514
+ type: currentEvent.type,
515
+ data: JSON.parse(currentEvent.data)
516
+ });
517
+ currentEvent = {};
518
+ inEvent = false;
519
+ }
520
+ continue;
521
+ }
522
+ // Process event fields
523
+ if (line.startsWith('event:')) {
524
+ currentEvent.type = line.substring(6).trim();
525
+ inEvent = true;
526
+ } else if (line.startsWith('data:')) {
527
+ currentEvent.data = line.substring(5).trim();
528
+ inEvent = true;
529
+ } else if (inEvent && currentEvent.data) {
530
+ currentEvent.data += line;
531
+ }
532
+ }
533
+ return events;
534
+ };
535
+
536
+ class DynamicApiClient extends BaseClient {
537
+ async authenticateApiToken({ environmentId }) {
538
+ return this.apiClient.post(`/api/v0/environments/${environmentId}/waas/authenticate`);
539
+ }
540
+ async createWalletAccount({ chainName, clientKeygenIds, thresholdSignatureScheme, onError, onCeremonyComplete }) {
541
+ return createEventStreamPromise({
542
+ apiClient: this.apiClient,
543
+ endpoint: `/api/v0/sdk/${this.environmentId}/waas/create`,
544
+ body: {
545
+ chain: chainName,
546
+ clientKeygenIds,
547
+ thresholdSignatureScheme
548
+ },
549
+ successEventType: SuccessEventType.KeygenComplete,
550
+ timeoutMessage: 'Wallet creation timed out',
551
+ onError,
552
+ onCeremonyComplete
553
+ });
554
+ }
555
+ async signMessage({ walletId, message, onError }) {
556
+ return createEventStreamPromise({
557
+ apiClient: this.apiClient,
558
+ endpoint: `/api/v0/sdk/${this.environmentId}/waas/${walletId}/signMessage`,
559
+ body: {
560
+ message
561
+ },
562
+ successEventType: SuccessEventType.RoomCreated,
563
+ timeoutMessage: 'Message signing timed out',
564
+ onError
565
+ });
566
+ }
567
+ async refreshWalletAccountShares({ walletId, onError }) {
568
+ return createEventStreamPromise({
569
+ apiClient: this.apiClient,
570
+ endpoint: `/api/v0/sdk/${this.environmentId}/waas/${walletId}/refresh`,
571
+ body: undefined,
572
+ successEventType: SuccessEventType.RoomCreated,
573
+ timeoutMessage: 'Refresh timed out',
574
+ onError
575
+ });
576
+ }
577
+ async reshare({ walletId, clientKeygenIds, oldThresholdSignatureScheme, newThresholdSignatureScheme, onError }) {
578
+ return createEventStreamPromise({
579
+ apiClient: this.apiClient,
580
+ endpoint: `/api/v0/sdk/${this.environmentId}/waas/${walletId}/reshare`,
581
+ body: {
582
+ clientKeygenIds,
583
+ oldThresholdSignatureScheme,
584
+ newThresholdSignatureScheme
585
+ },
586
+ successEventType: SuccessEventType.RoomCreated,
587
+ timeoutMessage: 'Reshare timed out',
588
+ onError
589
+ });
590
+ }
591
+ async exportKey({ walletId, exportId, onError }) {
592
+ return createEventStreamPromise({
593
+ apiClient: this.apiClient,
594
+ endpoint: `/api/v0/sdk/${this.environmentId}/waas/${walletId}/privateKey/export`,
595
+ body: {
596
+ exportId
597
+ },
598
+ successEventType: SuccessEventType.RoomCreated,
599
+ timeoutMessage: 'Key export timed out',
600
+ onError
601
+ });
602
+ }
603
+ async storeEncryptedBackupByWallet({ walletId, encryptedKeyShares, passwordEncrypted }) {
604
+ const { data } = await this.clientRelayApiClient.post(`/api/v0/sdk/${this.environmentId}/waas/${walletId}/keyShares/backup`, {
605
+ // TODO: decide on whether to store encryptedAccountCredentials or encryptedKeyShares as backup
606
+ encryptedAccountCredentials: encryptedKeyShares,
607
+ passwordEncrypted
608
+ });
609
+ return data;
610
+ }
611
+ async markKeySharesAsBackedUpGoogleDrive({ walletId }) {
612
+ const { data } = await this.clientRelayApiClient.post(`/api/v0/sdk/${this.environmentId}/waas/${walletId}/keyShares/backup/googleDrive`, {});
613
+ return data;
614
+ }
615
+ async recoverEncryptedBackupByWallet({ walletId, keyShareIds }) {
616
+ const { data } = await this.clientRelayApiClient.post(`/api/v0/sdk/${this.environmentId}/waas/${walletId}/keyShares/recover`, keyShareIds ? {
617
+ keyShareIds
618
+ } : undefined);
619
+ return data;
620
+ }
621
+ async getAccessToken({ oauthAccountId }) {
622
+ const { data } = await this.apiClient.get(`/api/v0/sdk/${this.environmentId}/oauthAccounts/${oauthAccountId}/accessToken`);
623
+ return data.accessToken;
624
+ }
625
+ // TODO: return array instead considering cases where server has multiple parties
626
+ async importPrivateKey({ chainName, clientKeygenIds, thresholdSignatureScheme, onError, onCeremonyComplete }) {
627
+ return createEventStreamPromise({
628
+ apiClient: this.apiClient,
629
+ endpoint: `/api/v0/sdk/${this.environmentId}/waas/privateKey/import`,
630
+ body: {
631
+ chain: chainName,
632
+ clientKeygenIds,
633
+ thresholdSignatureScheme
634
+ },
635
+ successEventType: SuccessEventType.KeygenComplete,
636
+ timeoutMessage: 'Key import timed out',
637
+ onError,
638
+ onCeremonyComplete
639
+ });
640
+ }
641
+ // TODO: consider removing the retry logics if we switch to server-sent events
642
+ async getUser() {
643
+ let attempts = 0;
644
+ const maxAttempts = 5;
645
+ const retryInterval = 1000; // 1 second interval for each retry
646
+ while(attempts < maxAttempts){
647
+ try {
648
+ const { data } = await this.apiClient.get(`/api/v0/sdk/${this.environmentId}/users`);
649
+ return data;
650
+ } catch (error) {
651
+ attempts++;
652
+ if (attempts === maxAttempts) {
653
+ throw error;
654
+ }
655
+ await new Promise((resolve)=>setTimeout(resolve, retryInterval));
656
+ }
657
+ }
658
+ }
659
+ // TODO: consider removing the retry logics if we switch to server-sent events
660
+ async refreshUser() {
661
+ let attempts = 0;
662
+ const maxAttempts = 5;
663
+ const retryInterval = 1000; // 1 second interval for each retry
664
+ while(attempts < maxAttempts){
665
+ try {
666
+ const { data } = await this.apiClient.post(`/api/v0/sdk/${this.environmentId}/refresh`, undefined);
667
+ return data;
668
+ } catch (error) {
669
+ attempts++;
670
+ if (attempts === maxAttempts) {
671
+ throw error;
672
+ }
673
+ await new Promise((resolve)=>setTimeout(resolve, retryInterval));
674
+ }
675
+ }
676
+ }
677
+ constructor({ environmentId, authToken, baseApiUrl }){
678
+ super({
679
+ environmentId,
680
+ authToken,
681
+ baseApiUrl
682
+ });
683
+ }
684
+ }
685
+
686
+ export { BITCOIN_DERIVATION_PATHS, BackupLocation, ChainEnumToVerifiedCredentialName, CreateRoomPartiesOptions, DYNAMIC_AUTH_PREPROD_BASE_API_URL, DYNAMIC_AUTH_PROD_BASE_API_URL, DYNAMIC_CLIENT_RELAY_PREPROD_BASE_API_URL, DYNAMIC_CLIENT_RELAY_PROD_BASE_API_URL, DynamicApiClient, IFRAME_DOMAIN_PREPROD, IFRAME_DOMAIN_PROD, MPC_CHAIN_CONFIG, MPC_CONFIG, MPC_RELAY_PREPROD_API_URL, MPC_RELAY_PROD_API_URL, SOLANA_RPC_URL, SigningAlgorithm, SuccessEventType, ThresholdSignatureScheme, VerifiedCredentialNameToChainEnum, WalletOperation, chain, getClientThreshold, getDynamicServerThreshold, getMPCChainConfig, getReshareConfig, getServerWalletReshareConfig, getTSSConfig };