@dynamic-labs-wallet/browser-wallet-client 0.0.0-beta.3 → 0.0.1

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 (35) hide show
  1. package/index.cjs.js +504 -207
  2. package/index.esm.js +494 -185
  3. package/package.json +7 -6
  4. package/src/client/client.d.ts +37 -87
  5. package/src/client/client.d.ts.map +1 -1
  6. package/src/client/iframeManager/IframeManager.d.ts +90 -0
  7. package/src/client/iframeManager/IframeManager.d.ts.map +1 -0
  8. package/src/client/iframeManager/index.d.ts +2 -0
  9. package/src/client/iframeManager/index.d.ts.map +1 -0
  10. package/src/client/index.d.ts +1 -0
  11. package/src/client/index.d.ts.map +1 -1
  12. package/src/index.d.ts +0 -1
  13. package/src/index.d.ts.map +1 -1
  14. package/src/services/iframeMessageHandler.d.ts +9 -8
  15. package/src/services/iframeMessageHandler.d.ts.map +1 -1
  16. package/internal/core/bip340.d.ts +0 -22
  17. package/internal/core/bip340.js +0 -1
  18. package/internal/core/common.d.ts +0 -1
  19. package/internal/core/common.js +0 -1
  20. package/internal/core/ecdsa.d.ts +0 -23
  21. package/internal/core/ecdsa.js +0 -1
  22. package/internal/core/ed25519.d.ts +0 -22
  23. package/internal/core/ed25519.js +0 -1
  24. package/internal/core/index.d.ts +0 -6
  25. package/internal/core/index.js +0 -1
  26. package/internal/core/native.d.ts +0 -103
  27. package/internal/core/native.js +0 -1
  28. package/internal/core/types.d.ts +0 -58
  29. package/internal/core/types.js +0 -1
  30. package/internal/web/generated/libmpc_executor.d.ts +0 -130
  31. package/internal/web/generated/libmpc_executor.js +0 -2
  32. package/internal/web/generated/libmpc_executor_bg.wasm +0 -0
  33. package/internal/web/generated/libmpc_executor_bg.wasm.d.ts +0 -64
  34. package/internal/web/index.d.ts +0 -11
  35. package/internal/web/index.js +0 -1
package/index.cjs.js CHANGED
@@ -1,65 +1,30 @@
1
1
  'use strict';
2
2
 
3
+ var core = require('@dynamic-labs-wallet/core');
4
+ var uuid = require('uuid');
3
5
  var messageTransport = require('@dynamic-labs/message-transport');
4
6
  var logger$1 = require('@dynamic-labs/logger');
5
- var core = require('@dynamic-labs-wallet/core');
6
- var web = require('./internal/web');
7
7
 
8
- const setupMessageTransportBridge = (messageTransport$1, iframe, iframeOrigin)=>{
9
- if (!(iframe == null ? void 0 : iframe.contentWindow)) {
10
- throw new Error('Iframe or contentWindow not available');
11
- }
12
- const logger = new logger$1.Logger('debug');
13
- messageTransport$1.on((message)=>{
14
- // Forward the message to webview via postMessage
15
- if (message.origin === 'host') {
16
- var _iframe_contentWindow;
17
- iframe == null ? void 0 : (_iframe_contentWindow = iframe.contentWindow) == null ? void 0 : _iframe_contentWindow.postMessage(message, iframeOrigin);
18
- }
19
- });
20
- const handleIncomingMessage = (message)=>{
21
- const { data } = message;
22
- if (!data) return;
23
- if ((data == null ? void 0 : data.origin) !== 'webview') {
24
- return;
25
- }
26
- if (typeof data !== 'object') {
27
- return;
28
- }
29
- try {
30
- const message = messageTransport.parseMessageTransportData(data);
31
- messageTransport$1.emit(message);
32
- } catch (error) {
33
- if (!(error instanceof SyntaxError)) {
34
- logger.error('Error handling incoming message:', error);
35
- }
8
+ function _extends() {
9
+ _extends = Object.assign || function assign(target) {
10
+ for(var i = 1; i < arguments.length; i++){
11
+ var source = arguments[i];
12
+ for(var key in source)if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
36
13
  }
14
+ return target;
37
15
  };
38
- /**
39
- * Handle incoming message from android client
40
- */ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
41
- // @ts-ignore
42
- document.addEventListener('message', handleIncomingMessage);
43
- /**
44
- * Handle incoming message from iOS client
45
- */ window.addEventListener('message', handleIncomingMessage);
46
- };
16
+ return _extends.apply(this, arguments);
17
+ }
47
18
 
48
19
  class iframeMessageHandler {
49
- async getWallets() {
50
- return this.requestChannel.request('getWallets');
20
+ async getWallets(request) {
21
+ return this.requestChannel.request('getWallets', request);
51
22
  }
52
- async getWallet({ accountAddress, walletOperation }) {
53
- return this.requestChannel.request('getWallet', {
54
- accountAddress,
55
- walletOperation
56
- });
23
+ async getWallet(request) {
24
+ return this.requestChannel.request('getWallet', request);
57
25
  }
58
- async createWalletAccount(thresholdSignatureScheme, password) {
59
- return this.requestChannel.request('createWalletAccount', {
60
- thresholdSignatureScheme,
61
- password
62
- });
26
+ async createWalletAccount(request) {
27
+ return this.requestChannel.request('createWalletAccount', request);
63
28
  }
64
29
  async requiresPasswordForOperation(request) {
65
30
  return this.requestChannel.request('requiresPasswordForOperation', request);
@@ -67,6 +32,9 @@ class iframeMessageHandler {
67
32
  async signMessage(request) {
68
33
  return this.requestChannel.request('signMessage', request);
69
34
  }
35
+ async signRawMessage(request) {
36
+ return this.requestChannel.request('signRawMessage', request);
37
+ }
70
38
  async signTransaction(request) {
71
39
  return this.requestChannel.request('signTransaction', request);
72
40
  }
@@ -76,6 +44,9 @@ class iframeMessageHandler {
76
44
  async backupKeySharesToGoogleDrive(request) {
77
45
  await this.requestChannel.request('backupKeySharesToGoogleDrive', request);
78
46
  }
47
+ async delegateKeyShares(request) {
48
+ return this.requestChannel.request('delegateKeyShares', request);
49
+ }
79
50
  async restoreBackupFromGoogleDrive(request) {
80
51
  return this.requestChannel.request('restoreBackupFromGoogleDrive', request);
81
52
  }
@@ -97,8 +68,8 @@ class iframeMessageHandler {
97
68
  async importPrivateKey(request) {
98
69
  return this.requestChannel.request('importPrivateKey', request);
99
70
  }
100
- async sendAuthToken(token) {
101
- return this.requestChannel.request('sendAuthToken', token);
71
+ async sendAuthToken(token, authMode) {
72
+ return this.requestChannel.request('sendAuthToken', token, authMode);
102
73
  }
103
74
  async exportClientKeyshares(request) {
104
75
  return this.requestChannel.request('exportClientKeyshares', request);
@@ -106,6 +77,12 @@ class iframeMessageHandler {
106
77
  async offlineExportPrivateKey(request) {
107
78
  return this.requestChannel.request('offlineExportPrivateKey', request);
108
79
  }
80
+ async signTypedData(request) {
81
+ return this.requestChannel.request('signTypedData', request);
82
+ }
83
+ async cleanup() {
84
+ return this.requestChannel.request('cleanup');
85
+ }
109
86
  constructor(messageTransport$1){
110
87
  this.requestChannel = messageTransport.createRequestChannel(messageTransport$1);
111
88
  }
@@ -113,7 +90,47 @@ class iframeMessageHandler {
113
90
 
114
91
  const logger = new logger$1.Logger('DynamicWaasWalletClient');
115
92
 
116
- class DynamicWalletClient {
93
+ const setupMessageTransportBridge = (messageTransport$1, iframe, iframeOrigin)=>{
94
+ if (!(iframe == null ? void 0 : iframe.contentWindow)) {
95
+ throw new Error('Iframe or contentWindow not available');
96
+ }
97
+ const logger = new logger$1.Logger('debug');
98
+ messageTransport$1.on((message)=>{
99
+ // Forward the message to webview via postMessage
100
+ if (message.origin === 'host') {
101
+ var _iframe_contentWindow;
102
+ iframe == null ? void 0 : (_iframe_contentWindow = iframe.contentWindow) == null ? void 0 : _iframe_contentWindow.postMessage(message, iframeOrigin);
103
+ }
104
+ });
105
+ const handleIncomingMessage = (message)=>{
106
+ const { data } = message;
107
+ if (!data) return;
108
+ if ((data == null ? void 0 : data.origin) !== 'webview') {
109
+ return;
110
+ }
111
+ if (typeof data !== 'object') {
112
+ return;
113
+ }
114
+ try {
115
+ const message = messageTransport.parseMessageTransportData(data);
116
+ messageTransport$1.emit(message);
117
+ } catch (error) {
118
+ if (!(error instanceof SyntaxError)) {
119
+ logger.error('Error handling incoming message:', error);
120
+ }
121
+ }
122
+ };
123
+ /**
124
+ * Handle incoming message from android client
125
+ */ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
126
+ // @ts-ignore
127
+ document.addEventListener('message', handleIncomingMessage);
128
+ /**
129
+ * Handle incoming message from iOS client
130
+ */ window.addEventListener('message', handleIncomingMessage);
131
+ };
132
+
133
+ class IframeManager {
117
134
  // Simply load the iframe from localhost
118
135
  async initialize() {
119
136
  await this.doInitializeIframeCommunication();
@@ -122,10 +139,10 @@ class DynamicWalletClient {
122
139
  * this is called on class construction time
123
140
  * @returns {Promise<void>} that resolves when the iframe is loaded and the message transport and iframe storage are initialized
124
141
  */ initializeIframeCommunication() {
125
- if (!this.iframeLoadPromise) {
126
- this.iframeLoadPromise = this.doInitializeIframeCommunication();
127
- }
128
- return this.iframeLoadPromise;
142
+ var _IframeManager;
143
+ var _iframeLoadPromise;
144
+ (_iframeLoadPromise = (_IframeManager = IframeManager).iframeLoadPromise) != null ? _iframeLoadPromise : _IframeManager.iframeLoadPromise = this.doInitializeIframeCommunication();
145
+ return IframeManager.iframeLoadPromise;
129
146
  }
130
147
  /**
131
148
  * initialize the iframe communication by awaiting the iframe load promise
@@ -133,8 +150,6 @@ class DynamicWalletClient {
133
150
  */ async doInitializeIframeCommunication() {
134
151
  try {
135
152
  await this.loadIframe();
136
- this.initializeMessageTransport();
137
- await this.initAuthToken();
138
153
  } catch (error) {
139
154
  this.logger.error('Error initializing iframe:', error);
140
155
  throw error;
@@ -142,7 +157,12 @@ class DynamicWalletClient {
142
157
  }
143
158
  /**
144
159
  * initialize the message transport after iframe is successfully loaded
145
- */ initializeMessageTransport() {
160
+ */ async initializeMessageTransport() {
161
+ if (this.messageTransport && this.iframeMessageHandler) {
162
+ this.logger.debug('Skipping initializeMessageTransport: transport and message handler already initialized');
163
+ return;
164
+ }
165
+ await this.initializeIframeCommunication();
146
166
  const transport = messageTransport.applyDefaultMessageOrigin({
147
167
  defaultOrigin: 'host',
148
168
  messageTransport: messageTransport.createMessageTransport()
@@ -153,6 +173,7 @@ class DynamicWalletClient {
153
173
  }
154
174
  setupMessageTransportBridge(this.messageTransport, this.iframe, this.iframeDomain);
155
175
  this.iframeMessageHandler = new iframeMessageHandler(this.messageTransport);
176
+ await this.initAuthToken();
156
177
  }
157
178
  /**
158
179
  * securely exchange the auth token with iframe securely
@@ -162,52 +183,150 @@ class DynamicWalletClient {
162
183
  }
163
184
  try {
164
185
  // Send auth token to iframe
165
- await this.iframeMessageHandler.sendAuthToken(this.authToken);
186
+ await this.iframeMessageHandler.sendAuthToken(this.authToken, this.authMode);
166
187
  } catch (error) {
167
188
  throw new Error('Failed to establish secure token exchange: ' + error);
168
189
  }
169
190
  }
170
- loadIframe() {
171
- return new Promise((resolve, reject)=>{
172
- const iframe = document.createElement('iframe');
173
- const iframeTimeoutId = setTimeout(()=>{
174
- reject(new Error('Iframe load timeout'));
175
- }, 10000);
176
- iframe.style.display = 'none';
177
- iframe.setAttribute('title', 'Dynamic Wallet Iframe');
178
- iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-downloads');
179
- iframe.setAttribute('referrerpolicy', 'origin');
180
- iframe.style.position = 'fixed';
181
- iframe.style.top = '0';
182
- iframe.style.left = '0';
183
- iframe.style.width = '0';
184
- iframe.style.height = '0';
185
- iframe.style.border = 'none';
186
- iframe.style.pointerEvents = 'none';
187
- var _this_instanceId;
188
- const params = new URLSearchParams({
189
- instanceId: (_this_instanceId = this.instanceId) != null ? _this_instanceId : '',
190
- hostOrigin: window.location.origin,
191
- environmentId: this.environmentId,
192
- authToken: this.authToken,
193
- baseApiUrl: this.baseApiUrl,
194
- baseMPCRelayApiUrl: this.baseMPCRelayApiUrl,
195
- chain: this.chainName
191
+ /**
192
+ * Reset the shared iframe and iframe load promise, and iframe instance count
193
+ */ async resetSharedIframe() {
194
+ IframeManager.sharedIframe = null;
195
+ IframeManager.iframeInstanceCount = 0;
196
+ IframeManager.iframeLoadPromise = null;
197
+ this.iframe = null;
198
+ this.iframeMessageHandler = null;
199
+ this.messageTransport = null;
200
+ // Double the timeout and cap at 60 seconds to give more time for slow networks
201
+ IframeManager.iframeLoadTimeout = Math.min(IframeManager.iframeLoadTimeout * 2, 60000);
202
+ }
203
+ async loadIframe() {
204
+ // If the iframe is already loaded, just assign and resolve
205
+ if (IframeManager.sharedIframe) {
206
+ this.assignExistingIframe();
207
+ return Promise.resolve();
208
+ }
209
+ // If a load is in progress, wait for it, then assign
210
+ if (IframeManager.iframeLoadPromise) {
211
+ return IframeManager.iframeLoadPromise.then(()=>{
212
+ this.assignExistingIframe();
196
213
  });
197
- iframe.src = `${this.iframeDomain}/waas/${this.environmentId}?${params.toString()}`;
198
- this.logger.debug('Creating iframe with src:', iframe.src);
199
- document.body.appendChild(iframe);
200
- iframe.onload = ()=>{
214
+ }
215
+ IframeManager.iframeLoadPromise = this.createIframeLoadPromise();
216
+ return IframeManager.iframeLoadPromise;
217
+ }
218
+ assignExistingIframe() {
219
+ this.iframe = IframeManager.sharedIframe;
220
+ IframeManager.iframeInstanceCount++;
221
+ }
222
+ createIframeLoadPromise() {
223
+ return new Promise((resolve, reject)=>{
224
+ const attemptLoad = ()=>{
225
+ IframeManager.iframeLoadAttempts++;
226
+ this.logger.info(`Loading iframe for waas wallet client... (attempt ${IframeManager.iframeLoadAttempts}/${IframeManager.maxRetryAttempts + 1})`, this.getIframeContext());
227
+ const iframe = document.createElement('iframe');
228
+ let messageListener = null;
229
+ const context = _extends({}, this.getIframeContext(), {
230
+ attempt: IframeManager.iframeLoadAttempts
231
+ });
232
+ // Set up timeout that will trigger iframe error, a retry will be triggered on this iframe error
233
+ const iframeTimeoutId = setTimeout(()=>{
234
+ if (iframe.onerror) {
235
+ iframe.onerror('Iframe load timeout');
236
+ }
237
+ }, IframeManager.iframeLoadTimeout);
238
+ messageListener = this.createMessageListener(iframe, iframeTimeoutId, resolve);
239
+ window.addEventListener('message', messageListener);
240
+ this.configureIframe(iframe);
241
+ this.setIframeSource(iframe);
242
+ this.logger.debug('Creating iframe with src:', iframe.src);
243
+ document.body.appendChild(iframe);
244
+ this.setupIframeEventHandlersWithRetry(iframe, messageListener, iframeTimeoutId, reject, attemptLoad, context);
245
+ };
246
+ // Start the first attempt
247
+ attemptLoad();
248
+ });
249
+ }
250
+ setupIframeEventHandlersWithRetry(iframe, messageListener, iframeTimeoutId, reject, attemptLoad, context) {
251
+ iframe.onload = ()=>{
252
+ this.logger.debug('Iframe onload fired, waiting for ready message...');
253
+ };
254
+ iframe.onerror = (error)=>{
255
+ if (messageListener) {
256
+ window.removeEventListener('message', messageListener);
257
+ }
258
+ clearTimeout(iframeTimeoutId);
259
+ // Check if we should retry
260
+ if (IframeManager.iframeLoadAttempts <= IframeManager.maxRetryAttempts) {
261
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error occurred.';
262
+ this.logger.warn(`(loadIframe) Iframe failed to load on attempt ${IframeManager.iframeLoadAttempts}, retrying... context: ${JSON.stringify(context)}, error: ${errorMsg}`);
263
+ // Clean up current attempt
264
+ if (iframe.parentNode) {
265
+ iframe.parentNode.removeChild(iframe);
266
+ }
267
+ // Retry after a short delay
268
+ setTimeout(()=>{
269
+ attemptLoad();
270
+ }, 1000); // 1 second delay between retries
271
+ } else {
272
+ // Max retries reached, give up
273
+ this.logger.error('Iframe failed to load after all retry attempts: ', error);
274
+ this.resetSharedIframe();
275
+ IframeManager.iframeLoadAttempts = 0;
276
+ reject(new Error(`Failed to load iframe after all retry attempts... context: ${JSON.stringify(context)}`));
277
+ }
278
+ };
279
+ }
280
+ getIframeContext() {
281
+ var _this_sdkVersion;
282
+ return {
283
+ iframeDomain: this.iframeDomain,
284
+ environmentId: this.environmentId,
285
+ sdkVersion: (_this_sdkVersion = this.sdkVersion) != null ? _this_sdkVersion : '',
286
+ instanceId: this.instanceId,
287
+ chainName: this.chainName,
288
+ iframeLoadTimeout: IframeManager.iframeLoadTimeout
289
+ };
290
+ }
291
+ createMessageListener(iframe, iframeTimeoutId, resolve) {
292
+ const messageListener = (event)=>{
293
+ if (event.source === iframe.contentWindow && event.data === `iframe-ready-${this.instanceId}`) {
294
+ window.removeEventListener('message', messageListener);
201
295
  clearTimeout(iframeTimeoutId);
296
+ IframeManager.sharedIframe = iframe;
202
297
  this.iframe = iframe;
298
+ IframeManager.iframeInstanceCount++;
299
+ IframeManager.iframeLoadAttempts = 0; // Reset retry counter on success
203
300
  resolve();
204
- };
205
- iframe.onerror = (error)=>{
206
- clearTimeout(iframeTimeoutId);
207
- this.logger.error('Iframe failed to load:', error);
208
- reject(new Error('Failed to load iframe'));
209
- };
301
+ this.logger.info('Iframe loaded successfully...', this.getIframeContext());
302
+ }
303
+ };
304
+ return messageListener;
305
+ }
306
+ configureIframe(iframe) {
307
+ iframe.style.display = 'none';
308
+ iframe.setAttribute('title', 'Dynamic Wallet Iframe');
309
+ iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-downloads');
310
+ iframe.setAttribute('referrerpolicy', 'origin');
311
+ iframe.style.position = 'fixed';
312
+ iframe.style.top = '0';
313
+ iframe.style.left = '0';
314
+ iframe.style.width = '0';
315
+ iframe.style.height = '0';
316
+ iframe.style.border = 'none';
317
+ iframe.style.pointerEvents = 'none';
318
+ }
319
+ setIframeSource(iframe) {
320
+ var _this_instanceId, _this_sdkVersion;
321
+ const params = new URLSearchParams({
322
+ instanceId: (_this_instanceId = this.instanceId) != null ? _this_instanceId : '',
323
+ hostOrigin: window.location.origin,
324
+ environmentId: this.environmentId,
325
+ baseApiUrl: this.baseApiUrl,
326
+ baseMPCRelayApiUrl: this.baseMPCRelayApiUrl,
327
+ sdkVersion: (_this_sdkVersion = this.sdkVersion) != null ? _this_sdkVersion : ''
210
328
  });
329
+ iframe.src = `${this.iframeDomain}/waas-v1/${this.environmentId}?${params.toString()}`;
211
330
  }
212
331
  /**
213
332
  * Load an iframe for a specific container
@@ -215,41 +334,78 @@ class DynamicWalletClient {
215
334
  * @returns {Promise<HTMLIFrameElement>} that resolves when the iframe is loaded
216
335
  */ loadIframeForContainer(container) {
217
336
  return new Promise((resolve, reject)=>{
337
+ var _this_sdkVersion;
338
+ const context = {
339
+ iframeDomain: this.iframeDomain,
340
+ environmentId: this.environmentId,
341
+ sdkVersion: (_this_sdkVersion = this.sdkVersion) != null ? _this_sdkVersion : '',
342
+ instanceId: this.instanceId,
343
+ chainName: this.chainName,
344
+ iframeLoadTimeout: IframeManager.iframeLoadTimeout
345
+ };
346
+ this.logger.info(`Loading iframe for container...`, context);
218
347
  const iframe = document.createElement('iframe');
348
+ let messageListener = null;
219
349
  const iframeTimeoutId = setTimeout(()=>{
220
- reject(new Error('Iframe load timeout'));
221
- }, 10000);
350
+ if (messageListener) {
351
+ window.removeEventListener('message', messageListener);
352
+ }
353
+ this.logger.error(`(loadIframeForContainer) Iframe load timeout due to no handshake message from iframe, this could be network issues, incorrect iframe domain, or CORS errors that prevents iframe from being loaded or sending handshake message, context: ${JSON.stringify(context)}`);
354
+ reject(new Error(`(loadIframeForContainer) Iframe load timeout due to no handshake message from iframe, this could be network issues, incorrect iframe domain, or CORS errors that prevents iframe from being loaded or sending handshake message, context: ${JSON.stringify(context)}`));
355
+ }, IframeManager.iframeLoadTimeout);
222
356
  iframe.style.display = 'block';
223
357
  iframe.style.width = '100%';
224
358
  iframe.style.height = '100%';
225
359
  iframe.setAttribute('title', 'Dynamic Wallet Storage');
226
360
  iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
227
361
  iframe.setAttribute('referrerpolicy', 'origin');
228
- var _this_instanceId;
362
+ var _this_instanceId, _this_sdkVersion1;
229
363
  const params = new URLSearchParams({
230
364
  instanceId: (_this_instanceId = this.instanceId) != null ? _this_instanceId : '',
231
365
  hostOrigin: window.location.origin,
232
366
  environmentId: this.environmentId,
233
- authToken: this.authToken,
234
367
  baseApiUrl: this.baseApiUrl,
235
368
  baseMPCRelayApiUrl: this.baseMPCRelayApiUrl,
236
- chain: this.chainName
369
+ sdkVersion: (_this_sdkVersion1 = this.sdkVersion) != null ? _this_sdkVersion1 : ''
237
370
  });
238
- iframe.src = `${this.iframeDomain}/waas/${this.environmentId}?${params.toString()}`;
371
+ iframe.src = `${this.iframeDomain}/waas-v1/${this.environmentId}?${params.toString()}`;
239
372
  this.logger.debug('Creating iframe with src:', iframe.src);
240
373
  // Add iframe to the provided container
241
374
  container.appendChild(iframe);
242
375
  iframe.onload = ()=>{
243
- clearTimeout(iframeTimeoutId);
244
- this.logger.debug('Iframe loaded successfully');
245
- this.iframe = iframe;
246
- resolve(iframe);
376
+ // The message listener is already set up, so iframe can send ready message
377
+ this.logger.debug('Iframe onload fired, waiting for ready message...');
247
378
  };
248
379
  iframe.onerror = (error)=>{
380
+ if (messageListener) {
381
+ window.removeEventListener('message', messageListener);
382
+ }
249
383
  clearTimeout(iframeTimeoutId);
250
- this.logger.error('Iframe failed to load:', error);
251
- reject(new Error('Failed to load iframe'));
384
+ this.logger.error('Iframe failed to load due to errors: ', error);
385
+ reject(new Error('Failed to load iframe due to unknown load errors, this is likely a browser or network issue.'));
386
+ };
387
+ // Set up message listener BEFORE creating iframe
388
+ messageListener = (event)=>{
389
+ if (event.source === iframe.contentWindow && event.data === `iframe-ready-${this.instanceId}`) {
390
+ if (messageListener) {
391
+ window.removeEventListener('message', messageListener);
392
+ }
393
+ clearTimeout(iframeTimeoutId);
394
+ IframeManager.sharedIframe = iframe;
395
+ this.iframe = iframe;
396
+ IframeManager.iframeInstanceCount++;
397
+ resolve(iframe);
398
+ var _this_sdkVersion;
399
+ this.logger.info('Iframe loaded successfully...', {
400
+ iframeDomain: this.iframeDomain,
401
+ environmentId: this.environmentId,
402
+ sdkVersion: (_this_sdkVersion = this.sdkVersion) != null ? _this_sdkVersion : '',
403
+ instanceId: this.instanceId,
404
+ chainName: this.chainName
405
+ });
406
+ }
252
407
  };
408
+ window.addEventListener('message', messageListener);
253
409
  });
254
410
  }
255
411
  /**
@@ -269,8 +425,10 @@ class DynamicWalletClient {
269
425
  });
270
426
  setupMessageTransportBridge(transport, iframe, this.iframeDomain);
271
427
  const iframeDisplay = new iframeMessageHandler(transport);
272
- // Send auth token to iframe
273
- await iframeDisplay.sendAuthToken(this.authToken);
428
+ var _this_authMode;
429
+ // if authMode is header: inform iframe the authMode with auth token
430
+ // if authMode is cookie: inform iframe the authMode with empty authToken
431
+ await iframeDisplay.sendAuthToken(this.authToken, (_this_authMode = this.authMode) != null ? _this_authMode : core.AuthMode.HEADER);
274
432
  return {
275
433
  iframe,
276
434
  iframeDisplay,
@@ -283,58 +441,144 @@ class DynamicWalletClient {
283
441
  throw error;
284
442
  }
285
443
  }
444
+ async cleanup() {
445
+ await this.initializeMessageTransport();
446
+ if (!this.iframeMessageHandler) {
447
+ throw new Error('Iframe message handler not initialized');
448
+ }
449
+ await this.iframeMessageHandler.cleanup();
450
+ if (this.iframe) {
451
+ IframeManager.iframeInstanceCount--;
452
+ if (IframeManager.sharedIframe && IframeManager.iframeInstanceCount === 0) {
453
+ document.body.removeChild(IframeManager.sharedIframe);
454
+ IframeManager.sharedIframe = null;
455
+ IframeManager.iframeLoadPromise = null;
456
+ }
457
+ this.iframe = null;
458
+ }
459
+ }
460
+ constructor({ environmentId, baseApiUrl, baseMPCRelayApiUrl, chainName, sdkVersion, authMode = core.AuthMode.HEADER, authToken, debug }){
461
+ this.logger = logger;
462
+ this.instanceId = null;
463
+ this.iframeDomain = null;
464
+ this.messageTransport = null;
465
+ this.iframeMessageHandler = null;
466
+ this.iframe = null;
467
+ this.environmentId = environmentId;
468
+ this.authToken = authToken;
469
+ this.authMode = authMode;
470
+ this.baseApiUrl = baseApiUrl;
471
+ this.baseMPCRelayApiUrl = baseMPCRelayApiUrl;
472
+ this.chainName = chainName;
473
+ this.sdkVersion = sdkVersion;
474
+ const environment = core.getEnvironmentFromUrl(baseApiUrl);
475
+ this.iframeDomain = core.IFRAME_DOMAIN_MAP[environment];
476
+ if (this.authMode === core.AuthMode.COOKIE) {
477
+ this.iframeDomain = this.baseApiUrl;
478
+ }
479
+ // Generate unique instanceId when client is created
480
+ this.instanceId = uuid.v4();
481
+ this.debug = Boolean(debug);
482
+ this.logger.setLogLevel(this.debug ? 'DEBUG' : 'INFO');
483
+ }
484
+ }
485
+ IframeManager.iframeLoadPromise = null;
486
+ IframeManager.iframeLoadTimeout = 10000;
487
+ IframeManager.iframeLoadAttempts = 0;
488
+ IframeManager.maxRetryAttempts = 1;
489
+ IframeManager.sharedIframe = null;
490
+ IframeManager.iframeInstanceCount = 0;
491
+
492
+ class DynamicWalletClient extends IframeManager {
286
493
  async getWallets() {
287
- await this.initializeIframeCommunication();
494
+ await this.initializeMessageTransport();
288
495
  if (!this.iframeMessageHandler) {
289
496
  throw new Error('Iframe message handler not initialized');
290
497
  }
291
- return this.iframeMessageHandler.getWallets();
498
+ return this.iframeMessageHandler.getWallets({
499
+ chainName: this.chainName
500
+ });
292
501
  }
293
- async getWallet({ accountAddress, walletOperation }) {
294
- await this.initializeIframeCommunication();
502
+ async getWallet({ accountAddress, walletOperation = core.WalletOperation.NO_OPERATION, signedSessionId, authToken }) {
503
+ await this.initializeMessageTransport();
295
504
  if (!this.iframeMessageHandler) {
296
505
  throw new Error('Iframe message handler not initialized');
297
506
  }
298
507
  return this.iframeMessageHandler.getWallet({
508
+ chainName: this.chainName,
299
509
  accountAddress,
300
- walletOperation
510
+ walletOperation,
511
+ signedSessionId,
512
+ authToken
301
513
  });
302
514
  }
303
- async createWalletAccount({ thresholdSignatureScheme, password = undefined }) {
304
- await this.initializeIframeCommunication();
515
+ async createWalletAccount({ thresholdSignatureScheme, password = undefined, signedSessionId, authToken }) {
516
+ await this.initializeMessageTransport();
305
517
  if (!this.iframeMessageHandler) {
306
518
  throw new Error('Iframe message handler not initialized');
307
519
  }
308
- return this.iframeMessageHandler.createWalletAccount(thresholdSignatureScheme, password);
520
+ return this.iframeMessageHandler.createWalletAccount({
521
+ chainName: this.chainName,
522
+ thresholdSignatureScheme,
523
+ password,
524
+ signedSessionId,
525
+ authToken
526
+ });
309
527
  }
310
- async requiresPasswordForOperation({ accountAddress, walletOperation }) {
311
- await this.initializeIframeCommunication();
528
+ async requiresPasswordForOperation({ accountAddress, walletOperation = core.WalletOperation.REACH_THRESHOLD, authToken }) {
529
+ await this.initializeMessageTransport();
312
530
  if (!this.iframeMessageHandler) {
313
531
  throw new Error('Iframe message handler not initialized');
314
532
  }
315
533
  return this.iframeMessageHandler.requiresPasswordForOperation({
534
+ chainName: this.chainName,
316
535
  accountAddress,
317
- walletOperation
536
+ walletOperation,
537
+ authToken
318
538
  });
319
539
  }
320
- async isPasswordEncrypted({ accountAddress }) {
321
- await this.initializeIframeCommunication();
540
+ async isPasswordEncrypted({ accountAddress, authToken }) {
541
+ await this.initializeMessageTransport();
322
542
  if (!this.iframeMessageHandler) {
323
543
  throw new Error('Iframe message handler not initialized');
324
544
  }
325
545
  return this.iframeMessageHandler.isPasswordEncrypted({
326
- accountAddress
546
+ chainName: this.chainName,
547
+ accountAddress,
548
+ authToken
327
549
  });
328
550
  }
329
- async signMessage({ message, accountAddress, password = undefined }) {
330
- await this.initializeIframeCommunication();
551
+ async signMessage({ message, accountAddress, password = undefined, signedSessionId, authToken, mfaToken, context }) {
552
+ await this.initializeMessageTransport();
331
553
  if (!this.iframeMessageHandler) {
332
554
  throw new Error('Iframe message handler not initialized');
333
555
  }
556
+ const contextString = JSON.stringify(context, (_key, value)=>typeof value === 'bigint' ? value.toString() : value);
334
557
  return this.iframeMessageHandler.signMessage({
558
+ chainName: this.chainName,
335
559
  message,
336
560
  accountAddress,
337
- password
561
+ password,
562
+ signedSessionId,
563
+ authToken,
564
+ mfaToken,
565
+ context: contextString
566
+ });
567
+ }
568
+ async signRawMessage({ message, accountAddress, password = undefined, signedSessionId, authToken, mfaToken, context }) {
569
+ await this.initializeMessageTransport();
570
+ if (!this.iframeMessageHandler) {
571
+ throw new Error('Iframe message handler not initialized');
572
+ }
573
+ return this.iframeMessageHandler.signRawMessage({
574
+ chainName: this.chainName,
575
+ message,
576
+ accountAddress,
577
+ password,
578
+ signedSessionId,
579
+ authToken,
580
+ mfaToken,
581
+ context
338
582
  });
339
583
  }
340
584
  /**
@@ -347,25 +591,65 @@ class DynamicWalletClient {
347
591
  * SUI:
348
592
  * const txBytes = await txb.build({ client });
349
593
  * const txString = Buffer.from(txBytes).toString("hex");
350
- */ async signTransaction({ senderAddress, transaction, password = undefined }) {
351
- await this.initializeIframeCommunication();
594
+ */ async signTransaction({ senderAddress, transaction, password = undefined, signedSessionId, authToken, mfaToken, chainId }) {
595
+ await this.initializeMessageTransport();
352
596
  if (!this.iframeMessageHandler) {
353
597
  throw new Error('Iframe message handler not initialized');
354
598
  }
355
599
  return this.iframeMessageHandler.signTransaction({
600
+ chainName: this.chainName,
356
601
  senderAddress,
357
602
  transaction,
358
- password
603
+ password,
604
+ signedSessionId,
605
+ authToken,
606
+ mfaToken,
607
+ chainId
359
608
  });
360
609
  }
361
- async backupKeySharesToGoogleDrive(request) {
362
- await this.initializeIframeCommunication();
610
+ async signTypedData({ accountAddress, typedData, password = undefined, signedSessionId, authToken, mfaToken }) {
611
+ await this.initializeMessageTransport();
612
+ if (!this.iframeMessageHandler) {
613
+ throw new Error('Iframe message handler not initialized');
614
+ }
615
+ return this.iframeMessageHandler.signTypedData({
616
+ chainName: this.chainName,
617
+ accountAddress,
618
+ typedData: JSON.stringify(typedData),
619
+ password,
620
+ signedSessionId,
621
+ authToken,
622
+ mfaToken
623
+ });
624
+ }
625
+ async backupKeySharesToGoogleDrive({ accountAddress, password = undefined, signedSessionId, authToken }) {
626
+ await this.initializeMessageTransport();
363
627
  if (!this.iframeMessageHandler) {
364
628
  throw new Error('Iframe message handler not initialized');
365
629
  }
366
- return this.iframeMessageHandler.backupKeySharesToGoogleDrive(request);
630
+ return this.iframeMessageHandler.backupKeySharesToGoogleDrive({
631
+ chainName: this.chainName,
632
+ accountAddress,
633
+ password,
634
+ signedSessionId,
635
+ authToken
636
+ });
367
637
  }
368
- async restoreBackupFromGoogleDrive({ accountAddress, oauthAccountId, displayContainer, name, password }) {
638
+ async delegateKeyShares({ accountAddress, password, signedSessionId, authToken, mfaToken }) {
639
+ await this.initializeMessageTransport();
640
+ if (!this.iframeMessageHandler) {
641
+ throw new Error('Iframe message handler not initialized');
642
+ }
643
+ return this.iframeMessageHandler.delegateKeyShares({
644
+ chainName: this.chainName,
645
+ accountAddress,
646
+ password,
647
+ signedSessionId,
648
+ authToken,
649
+ mfaToken
650
+ });
651
+ }
652
+ async restoreBackupFromGoogleDrive({ accountAddress, displayContainer, password, signedSessionId, authToken }) {
369
653
  const { iframeDisplay } = await this.initializeIframeDisplayForContainer({
370
654
  container: displayContainer
371
655
  });
@@ -373,27 +657,44 @@ class DynamicWalletClient {
373
657
  throw new Error('Failed to initialize iframe handler with display functionality');
374
658
  }
375
659
  return iframeDisplay.restoreBackupFromGoogleDrive({
660
+ chainName: this.chainName,
376
661
  accountAddress,
377
- oauthAccountId,
378
- name,
379
- password
662
+ password,
663
+ signedSessionId,
664
+ authToken
380
665
  });
381
666
  }
382
- async refreshWalletAccountShares(request) {
383
- await this.initializeIframeCommunication();
667
+ async refreshWalletAccountShares({ accountAddress, password, signedSessionId, authToken, mfaToken }) {
668
+ await this.initializeMessageTransport();
384
669
  if (!this.iframeMessageHandler) {
385
670
  throw new Error('Iframe message handler not initialized');
386
671
  }
387
- return this.iframeMessageHandler.refreshWalletAccountShares(request);
672
+ return this.iframeMessageHandler.refreshWalletAccountShares({
673
+ chainName: this.chainName,
674
+ accountAddress: accountAddress,
675
+ password: password,
676
+ signedSessionId,
677
+ authToken,
678
+ mfaToken
679
+ });
388
680
  }
389
- async reshare(request) {
390
- await this.initializeIframeCommunication();
681
+ async reshare({ accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password, signedSessionId, authToken, mfaToken }) {
682
+ await this.initializeMessageTransport();
391
683
  if (!this.iframeMessageHandler) {
392
684
  throw new Error('Iframe message handler not initialized');
393
685
  }
394
- return this.iframeMessageHandler.reshare(request);
686
+ return this.iframeMessageHandler.reshare({
687
+ chainName: this.chainName,
688
+ accountAddress,
689
+ oldThresholdSignatureScheme,
690
+ newThresholdSignatureScheme,
691
+ password,
692
+ signedSessionId,
693
+ authToken,
694
+ mfaToken
695
+ });
395
696
  }
396
- async exportPrivateKey({ accountAddress, displayContainer, password }) {
697
+ async exportPrivateKey({ accountAddress, displayContainer, password, signedSessionId, authToken, mfaToken }) {
397
698
  const { iframeDisplay } = await this.initializeIframeDisplayForContainer({
398
699
  container: displayContainer
399
700
  });
@@ -401,55 +702,72 @@ class DynamicWalletClient {
401
702
  throw new Error('Failed to initialize iframe handler with display functionality');
402
703
  }
403
704
  return iframeDisplay.exportPrivateKey({
705
+ chainName: this.chainName,
404
706
  accountAddress,
405
- password
707
+ password,
708
+ signedSessionId,
709
+ authToken,
710
+ mfaToken
406
711
  });
407
712
  }
408
- async verifyPassword({ accountAddress, password, walletOperation }) {
409
- await this.initializeIframeCommunication();
713
+ async verifyPassword({ accountAddress, password, walletOperation = core.WalletOperation.NO_OPERATION, signedSessionId, authToken }) {
714
+ await this.initializeMessageTransport();
410
715
  if (!this.iframeMessageHandler) {
411
716
  throw new Error('Iframe message handler not initialized');
412
717
  }
413
718
  return this.iframeMessageHandler.verifyPassword({
719
+ chainName: this.chainName,
414
720
  accountAddress,
415
721
  password,
416
- walletOperation
722
+ walletOperation,
723
+ signedSessionId,
724
+ authToken
417
725
  });
418
726
  }
419
- async updatePassword({ accountAddress, existingPassword, newPassword }) {
420
- await this.initializeIframeCommunication();
727
+ async updatePassword({ accountAddress, existingPassword, newPassword, signedSessionId, authToken }) {
728
+ await this.initializeMessageTransport();
421
729
  if (!this.iframeMessageHandler) {
422
730
  throw new Error('Iframe message handler not initialized');
423
731
  }
424
732
  return this.iframeMessageHandler.updatePassword({
733
+ chainName: this.chainName,
425
734
  accountAddress,
426
735
  existingPassword,
427
- newPassword
736
+ newPassword,
737
+ signedSessionId,
738
+ authToken
428
739
  });
429
740
  }
430
- async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme }) {
431
- await this.initializeIframeCommunication();
741
+ async importPrivateKey({ privateKey, thresholdSignatureScheme, signedSessionId, authToken }) {
742
+ await this.initializeMessageTransport();
432
743
  if (!this.iframeMessageHandler) {
433
744
  throw new Error('Iframe message handler not initialized');
434
745
  }
435
746
  return this.iframeMessageHandler.importPrivateKey({
747
+ chainName: this.chainName,
436
748
  privateKey,
437
- chainName,
438
- thresholdSignatureScheme
749
+ thresholdSignatureScheme,
750
+ signedSessionId,
751
+ authToken
439
752
  });
440
753
  }
441
- async exportClientKeyshares({ accountAddress, password }) {
442
- await this.initializeIframeCommunication();
754
+ async exportClientKeyshares({ accountAddress, password, signedSessionId, authToken }) {
755
+ await this.initializeMessageTransport();
443
756
  if (!this.iframeMessageHandler) {
444
757
  throw new Error('Iframe message handler not initialized');
445
758
  }
446
759
  return this.iframeMessageHandler.exportClientKeyshares({
760
+ chainName: this.chainName,
447
761
  accountAddress,
448
- password
762
+ password,
763
+ signedSessionId,
764
+ authToken
449
765
  });
450
766
  }
451
- async offlineExportPrivateKey({ keyShares, derivationPath }) {
452
- await this.initializeIframeCommunication();
767
+ /**
768
+ * keyShares is stringified list of EcdsaKeygenResult[] and Ed25519KeygenResult[]
769
+ */ async offlineExportPrivateKey({ keyShares, derivationPath }) {
770
+ await this.initializeMessageTransport();
453
771
  if (!this.iframeMessageHandler) {
454
772
  throw new Error('Iframe message handler not initialized');
455
773
  }
@@ -462,63 +780,42 @@ class DynamicWalletClient {
462
780
  const argsBuffer = new TextEncoder().encode(serializedArgs);
463
781
  const base64Args = Buffer.from(argsBuffer).toString('base64');
464
782
  return this.iframeMessageHandler.offlineExportPrivateKey({
783
+ chainName: this.chainName,
465
784
  base64Args
466
785
  });
467
786
  }
468
- constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, chainName, debug }){
469
- this.logger = logger;
470
- this.instanceId = null;
471
- this.iframeDomain = null;
472
- this.messageTransport = null;
473
- this.iframeMessageHandler = null;
474
- this.iframeLoadPromise = null;
475
- this.iframe = null;
476
- this.environmentId = environmentId;
477
- this.authToken = authToken;
478
- this.baseApiUrl = baseApiUrl;
479
- this.baseMPCRelayApiUrl = baseMPCRelayApiUrl;
480
- this.chainName = chainName;
481
- const environment = core.getEnvironmentFromUrl(baseApiUrl);
482
- this.iframeDomain = core.IFRAME_DOMAIN_MAP[environment];
483
- // Generate unique instanceId when client is created
484
- this.instanceId = crypto.randomUUID();
485
- this.debug = Boolean(debug);
486
- this.logger.setLogLevel(this.debug ? 'DEBUG' : 'INFO');
487
- // initialize the client
488
- this.initialize();
787
+ constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, chainName, sdkVersion, debug, authMode = core.AuthMode.HEADER }){
788
+ super({
789
+ environmentId,
790
+ authToken,
791
+ baseApiUrl,
792
+ baseMPCRelayApiUrl,
793
+ chainName,
794
+ sdkVersion,
795
+ debug,
796
+ authMode
797
+ });
489
798
  }
490
799
  }
491
800
 
801
+ Object.defineProperty(exports, "AuthMode", {
802
+ enumerable: true,
803
+ get: function () { return core.AuthMode; }
804
+ });
492
805
  Object.defineProperty(exports, "MPC_RELAY_PREPROD_API_URL", {
493
- enumerable: true,
494
- get: function () { return core.MPC_RELAY_PREPROD_API_URL; }
806
+ enumerable: true,
807
+ get: function () { return core.MPC_RELAY_PREPROD_API_URL; }
495
808
  });
496
809
  Object.defineProperty(exports, "MPC_RELAY_PROD_API_URL", {
497
- enumerable: true,
498
- get: function () { return core.MPC_RELAY_PROD_API_URL; }
810
+ enumerable: true,
811
+ get: function () { return core.MPC_RELAY_PROD_API_URL; }
499
812
  });
500
813
  Object.defineProperty(exports, "ThresholdSignatureScheme", {
501
- enumerable: true,
502
- get: function () { return core.ThresholdSignatureScheme; }
814
+ enumerable: true,
815
+ get: function () { return core.ThresholdSignatureScheme; }
503
816
  });
504
817
  Object.defineProperty(exports, "WalletOperation", {
505
- enumerable: true,
506
- get: function () { return core.WalletOperation; }
507
- });
508
- Object.defineProperty(exports, "BIP340KeygenResult", {
509
- enumerable: true,
510
- get: function () { return web.BIP340KeygenResult; }
511
- });
512
- Object.defineProperty(exports, "EcdsaKeygenResult", {
513
- enumerable: true,
514
- get: function () { return web.EcdsaKeygenResult; }
515
- });
516
- Object.defineProperty(exports, "EcdsaSignature", {
517
- enumerable: true,
518
- get: function () { return web.EcdsaSignature; }
519
- });
520
- Object.defineProperty(exports, "Ed25519KeygenResult", {
521
- enumerable: true,
522
- get: function () { return web.Ed25519KeygenResult; }
818
+ enumerable: true,
819
+ get: function () { return core.WalletOperation; }
523
820
  });
524
821
  exports.DynamicWalletClient = DynamicWalletClient;