@0xsequence/dapp-client 0.0.0-20250910142613

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 (43) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/CHANGELOG.md +11 -0
  3. package/LICENSE +202 -0
  4. package/README.md +238 -0
  5. package/dist/ChainSessionManager.d.ts +203 -0
  6. package/dist/ChainSessionManager.d.ts.map +1 -0
  7. package/dist/ChainSessionManager.js +742 -0
  8. package/dist/DappClient.d.ts +409 -0
  9. package/dist/DappClient.d.ts.map +1 -0
  10. package/dist/DappClient.js +667 -0
  11. package/dist/DappTransport.d.ts +47 -0
  12. package/dist/DappTransport.d.ts.map +1 -0
  13. package/dist/DappTransport.js +443 -0
  14. package/dist/index.d.ts +11 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +7 -0
  17. package/dist/types/index.d.ts +168 -0
  18. package/dist/types/index.d.ts.map +1 -0
  19. package/dist/types/index.js +25 -0
  20. package/dist/utils/constants.d.ts +6 -0
  21. package/dist/utils/constants.d.ts.map +1 -0
  22. package/dist/utils/constants.js +5 -0
  23. package/dist/utils/errors.d.ts +28 -0
  24. package/dist/utils/errors.d.ts.map +1 -0
  25. package/dist/utils/errors.js +54 -0
  26. package/dist/utils/index.d.ts +11 -0
  27. package/dist/utils/index.d.ts.map +1 -0
  28. package/dist/utils/index.js +135 -0
  29. package/dist/utils/storage.d.ts +64 -0
  30. package/dist/utils/storage.d.ts.map +1 -0
  31. package/dist/utils/storage.js +196 -0
  32. package/eslint.config.mjs +4 -0
  33. package/package.json +38 -0
  34. package/src/ChainSessionManager.ts +978 -0
  35. package/src/DappClient.ts +801 -0
  36. package/src/DappTransport.ts +518 -0
  37. package/src/index.ts +47 -0
  38. package/src/types/index.ts +218 -0
  39. package/src/utils/constants.ts +5 -0
  40. package/src/utils/errors.ts +62 -0
  41. package/src/utils/index.ts +158 -0
  42. package/src/utils/storage.ts +272 -0
  43. package/tsconfig.json +10 -0
@@ -0,0 +1,518 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
3
+ import { jsonReplacers, jsonRevivers } from './utils/index.js'
4
+ import {
5
+ MessageType,
6
+ PendingRequest,
7
+ PopupModeOptions,
8
+ SendRequestOptions,
9
+ SequenceSessionStorage,
10
+ TransportMessage,
11
+ TransportMode,
12
+ WalletSize,
13
+ } from './types/index.js'
14
+
15
+ enum ConnectionState {
16
+ DISCONNECTED = 'DISCONNECTED',
17
+ CONNECTING = 'CONNECTING',
18
+ CONNECTED = 'CONNECTED',
19
+ }
20
+
21
+ const REDIRECT_REQUEST_KEY = 'dapp-redirect-request'
22
+
23
+ export class DappTransport {
24
+ private walletWindow: Window | undefined = undefined
25
+ private connectionState: ConnectionState = ConnectionState.DISCONNECTED
26
+ private readyPromise: Promise<void> | undefined = undefined
27
+ private readyPromiseResolve: (() => void) | undefined = undefined
28
+ private readyPromiseReject: ((reason?: any) => void) | undefined = undefined
29
+ private initId: string | undefined = undefined
30
+ private handshakeTimeoutId: number | undefined = undefined
31
+ private closeCheckIntervalId: number | undefined = undefined
32
+ private sessionId: string | undefined = undefined
33
+ private pendingRequests = new Map<string, PendingRequest>()
34
+ private messageQueue: TransportMessage[] = []
35
+ private readonly requestTimeoutMs: number
36
+ private readonly handshakeTimeoutMs: number
37
+ private readonly sequenceSessionStorage: SequenceSessionStorage
38
+ private readonly redirectActionHandler?: (url: string) => void
39
+
40
+ public readonly walletOrigin: string
41
+
42
+ constructor(
43
+ public readonly walletUrl: string,
44
+ readonly mode: TransportMode = TransportMode.POPUP,
45
+ popupModeOptions: PopupModeOptions = {},
46
+ sequenceSessionStorage?: SequenceSessionStorage,
47
+ redirectActionHandler?: (url: string) => void,
48
+ ) {
49
+ try {
50
+ this.walletOrigin = new URL(walletUrl).origin
51
+ } catch (e) {
52
+ console.error('[DApp] Invalid walletUrl provided:', walletUrl, e)
53
+ throw new Error(`Invalid walletUrl: ${walletUrl}`)
54
+ }
55
+ if (!this.walletOrigin || this.walletOrigin === 'null' || this.walletOrigin === '*') {
56
+ console.error('[DApp] Could not determine a valid wallet origin from the URL:', walletUrl)
57
+ throw new Error('Invalid wallet origin derived from walletUrl.')
58
+ }
59
+
60
+ if (sequenceSessionStorage) {
61
+ this.sequenceSessionStorage = sequenceSessionStorage
62
+ } else if (typeof window !== 'undefined' && window.sessionStorage) {
63
+ this.sequenceSessionStorage = window.sessionStorage
64
+ } else {
65
+ throw new Error('A storage implementation must be provided for non-browser environments.')
66
+ }
67
+
68
+ this.requestTimeoutMs = popupModeOptions.requestTimeoutMs ?? 300000
69
+ this.handshakeTimeoutMs = popupModeOptions.handshakeTimeoutMs ?? 15000
70
+
71
+ if (this.mode === TransportMode.POPUP) {
72
+ window.addEventListener('message', this.handleMessage)
73
+ }
74
+
75
+ this.redirectActionHandler = redirectActionHandler
76
+ }
77
+
78
+ get isWalletOpen(): boolean {
79
+ if (this.mode === TransportMode.REDIRECT) return false
80
+ return !!this.walletWindow && !this.walletWindow.closed
81
+ }
82
+
83
+ get isReady(): boolean {
84
+ if (this.mode === TransportMode.REDIRECT) return false
85
+ return this.connectionState === ConnectionState.CONNECTED
86
+ }
87
+
88
+ async sendRequest<TResponse = any, TRequest = any>(
89
+ action: string,
90
+ redirectUrl: string,
91
+ payload?: TRequest,
92
+ options: SendRequestOptions = {},
93
+ ): Promise<TResponse> {
94
+ if (this.mode === TransportMode.REDIRECT) {
95
+ const url = await this.getRequestRedirectUrl(action, payload, redirectUrl, options.path)
96
+ if (this.redirectActionHandler) {
97
+ this.redirectActionHandler(url)
98
+ } else {
99
+ console.info('[DappTransport] No redirectActionHandler provided. Using window.location.href to navigate.')
100
+ window.location.href = url
101
+ }
102
+ return new Promise<TResponse>(() => {})
103
+ }
104
+
105
+ if (this.connectionState !== ConnectionState.CONNECTED) {
106
+ await this.openWallet(options.path)
107
+ }
108
+
109
+ if (!this.isWalletOpen || this.connectionState !== ConnectionState.CONNECTED) {
110
+ throw new Error('Wallet connection is not available or failed to establish.')
111
+ }
112
+
113
+ const id = this.generateId()
114
+ const message: TransportMessage<TRequest> = {
115
+ id,
116
+ type: MessageType.REQUEST,
117
+ action,
118
+ payload,
119
+ }
120
+
121
+ return new Promise((resolve, reject) => {
122
+ const timeout = options.timeout ?? this.requestTimeoutMs
123
+ const timer = window.setTimeout(() => {
124
+ if (this.pendingRequests.has(id)) {
125
+ this.pendingRequests.delete(id)
126
+ reject(new Error(`Request '${action}' (ID: ${id}) timed out after ${timeout}ms.`))
127
+ }
128
+ }, timeout)
129
+
130
+ this.pendingRequests.set(id, { resolve, reject, timer, action })
131
+ this.postMessageToWallet(message)
132
+ })
133
+ }
134
+
135
+ public async getRequestRedirectUrl(
136
+ action: string,
137
+ payload: any,
138
+ redirectUrl: string,
139
+ path?: string,
140
+ ): Promise<string> {
141
+ const id = this.generateId()
142
+ const request = { id, action, timestamp: Date.now() }
143
+
144
+ try {
145
+ await this.sequenceSessionStorage.setItem(REDIRECT_REQUEST_KEY, JSON.stringify(request, jsonReplacers))
146
+ } catch (e) {
147
+ console.error('Failed to set redirect request in storage', e)
148
+ throw new Error('Could not save redirect state to storage. Redirect flow is unavailable.')
149
+ }
150
+
151
+ const serializedPayload = btoa(JSON.stringify(payload || {}, jsonReplacers))
152
+ const fullWalletUrl = path ? `${this.walletUrl}${path}` : this.walletUrl
153
+ const url = new URL(fullWalletUrl)
154
+ url.searchParams.set('action', action)
155
+ url.searchParams.set('payload', serializedPayload)
156
+ url.searchParams.set('id', id)
157
+ url.searchParams.set('redirectUrl', redirectUrl)
158
+ url.searchParams.set('mode', 'redirect')
159
+
160
+ return url.toString()
161
+ }
162
+
163
+ public async getRedirectResponse<TResponse = any>(
164
+ cleanState: boolean = true,
165
+ url?: string,
166
+ ): Promise<{ payload: TResponse; action: string } | { error: any; action: string } | null> {
167
+ const params = new URLSearchParams(url ? new URL(url).search : window.location.search)
168
+ const responseId = params.get('id')
169
+ if (!responseId) return null
170
+
171
+ let originalRequest: { id: string; action: string; timestamp: number }
172
+ try {
173
+ const storedRequest = await this.sequenceSessionStorage.getItem(REDIRECT_REQUEST_KEY)
174
+ if (!storedRequest) {
175
+ return null
176
+ }
177
+ originalRequest = JSON.parse(storedRequest, jsonRevivers)
178
+ } catch (e) {
179
+ console.error('Failed to parse redirect request from storage', e)
180
+ return null
181
+ }
182
+
183
+ if (originalRequest.id !== responseId) {
184
+ console.error(`Mismatched ID in redirect response. Expected ${originalRequest.id}, got ${responseId}.`)
185
+ if (cleanState) {
186
+ await this.sequenceSessionStorage.removeItem(REDIRECT_REQUEST_KEY)
187
+ }
188
+ return null
189
+ }
190
+
191
+ const responsePayloadB64 = params.get('payload')
192
+ const responseErrorB64 = params.get('error')
193
+
194
+ const isBrowser = typeof window !== 'undefined' && window.history
195
+
196
+ if (cleanState) {
197
+ await this.sequenceSessionStorage.removeItem(REDIRECT_REQUEST_KEY)
198
+ if (isBrowser && !url) {
199
+ const cleanUrl = new URL(window.location.href)
200
+ ;['id', 'payload', 'error', 'mode'].forEach((p) => cleanUrl.searchParams.delete(p))
201
+ history.replaceState({}, document.title, cleanUrl.toString())
202
+ }
203
+ }
204
+
205
+ if (responseErrorB64) {
206
+ try {
207
+ return {
208
+ error: JSON.parse(atob(responseErrorB64), jsonRevivers),
209
+ action: originalRequest.action,
210
+ }
211
+ } catch (e) {
212
+ console.error('Failed to parse error from redirect response', e)
213
+ return {
214
+ error: 'Failed to parse error from redirect',
215
+ action: originalRequest.action,
216
+ }
217
+ }
218
+ }
219
+ if (responsePayloadB64) {
220
+ try {
221
+ return {
222
+ payload: JSON.parse(atob(responsePayloadB64), jsonRevivers),
223
+ action: originalRequest.action,
224
+ }
225
+ } catch (e) {
226
+ console.error('Failed to parse payload from redirect response', e)
227
+ return {
228
+ error: 'Failed to parse payload from redirect',
229
+ action: originalRequest.action,
230
+ }
231
+ }
232
+ }
233
+ return {
234
+ error: "Redirect response missing 'payload' or 'error'",
235
+ action: originalRequest.action,
236
+ }
237
+ }
238
+
239
+ public openWallet(path?: string): Promise<void> {
240
+ if (this.mode === TransportMode.REDIRECT) {
241
+ throw new Error("`openWallet` is not available in 'redirect' mode.")
242
+ }
243
+ if (this.connectionState !== ConnectionState.DISCONNECTED) {
244
+ if (this.isWalletOpen) this.walletWindow?.focus()
245
+ return this.readyPromise || Promise.resolve()
246
+ }
247
+ this.connectionState = ConnectionState.CONNECTING
248
+ this.clearPendingRequests(new Error('Wallet connection reset during open.'))
249
+ this.messageQueue = []
250
+ this.clearTimeouts()
251
+ this.readyPromise = new Promise<void>((resolve, reject) => {
252
+ this.readyPromiseResolve = resolve
253
+ this.readyPromiseReject = reject
254
+ })
255
+ this.readyPromise.catch(() => {})
256
+ this.initId = this.generateId()
257
+ const fullWalletUrl = path ? `${this.walletUrl}${path}` : this.walletUrl
258
+ this.sessionId = this.generateId()
259
+ const urlWithParams = new URL(fullWalletUrl)
260
+ urlWithParams.searchParams.set('dappOrigin', window.location.origin)
261
+ urlWithParams.searchParams.set('sessionId', this.sessionId)
262
+
263
+ try {
264
+ const openedWindow = window.open(
265
+ urlWithParams.toString(),
266
+ 'Wallet',
267
+ `width=${WalletSize.width},height=${WalletSize.height},scrollbars=yes,resizable=yes`,
268
+ )
269
+ this.walletWindow = openedWindow || undefined
270
+ } catch (error) {
271
+ const openError = new Error(
272
+ `Failed to open wallet window: ${error instanceof Error ? error.message : String(error)}`,
273
+ )
274
+ this._handlePreConnectionFailure(openError)
275
+ return Promise.reject(openError)
276
+ }
277
+ if (!this.walletWindow) {
278
+ const error = new Error('Failed to open wallet window. Please check your pop-up blocker settings.')
279
+ this._handlePreConnectionFailure(error)
280
+ return Promise.reject(error)
281
+ }
282
+
283
+ this.handshakeTimeoutId = window.setTimeout(() => {
284
+ if (this.connectionState === ConnectionState.CONNECTING) {
285
+ const timeoutError = new Error(`Wallet handshake timed out after ${this.handshakeTimeoutMs}ms.`)
286
+ this._handlePreConnectionFailure(timeoutError)
287
+ }
288
+ }, this.handshakeTimeoutMs)
289
+
290
+ this.closeCheckIntervalId = window.setInterval(() => {
291
+ if (!this.isWalletOpen) {
292
+ if (this.connectionState === ConnectionState.CONNECTING)
293
+ this._handlePreConnectionFailure(new Error('Wallet window was closed before becoming ready.'))
294
+ else if (this.connectionState === ConnectionState.CONNECTED) this._handleDetectedClosure()
295
+ }
296
+ }, 500)
297
+ return this.readyPromise
298
+ }
299
+
300
+ public closeWallet(): void {
301
+ if (this.mode === TransportMode.REDIRECT) {
302
+ console.warn(
303
+ "[DApp] `closeWallet` is not available in 'redirect' mode. Use window.location.href to navigate away.",
304
+ )
305
+ return
306
+ }
307
+ if (this.connectionState === ConnectionState.DISCONNECTED) return
308
+ if (this.isWalletOpen) this.walletWindow?.close()
309
+ this.connectionState = ConnectionState.DISCONNECTED
310
+ this.readyPromise = undefined
311
+ this.readyPromiseResolve = undefined
312
+ this.readyPromiseReject = undefined
313
+ this._resetConnection(new Error('Wallet closed intentionally by DApp.'), 'Wallet closed intentionally by DApp.')
314
+ }
315
+
316
+ destroy(): void {
317
+ if (this.mode === TransportMode.POPUP) {
318
+ window.removeEventListener('message', this.handleMessage)
319
+ if (this.isWalletOpen) {
320
+ this.walletWindow?.close()
321
+ }
322
+ this._resetConnection(new Error('Transport destroyed.'), 'Destroying transport...')
323
+ }
324
+ }
325
+
326
+ private handleMessage = (event: MessageEvent): void => {
327
+ if (event.origin !== this.walletOrigin) {
328
+ return
329
+ }
330
+
331
+ const isPotentiallyValidSource =
332
+ this.walletWindow && (event.source === this.walletWindow || !this.walletWindow.closed)
333
+
334
+ if (!isPotentiallyValidSource && event.data?.type !== MessageType.WALLET_OPENED) {
335
+ return
336
+ }
337
+
338
+ const message = event.data as TransportMessage
339
+ if (
340
+ !message ||
341
+ typeof message !== 'object' ||
342
+ !message.id ||
343
+ !message.type ||
344
+ (message.type === MessageType.WALLET_OPENED && !message.sessionId)
345
+ ) {
346
+ return
347
+ }
348
+
349
+ try {
350
+ switch (message.type) {
351
+ case MessageType.WALLET_OPENED:
352
+ this.handleWalletReadyMessage(message)
353
+ break
354
+ case MessageType.RESPONSE:
355
+ this.handleResponseMessage(message)
356
+ break
357
+ case MessageType.REQUEST:
358
+ case MessageType.INIT:
359
+ default:
360
+ break
361
+ }
362
+ } catch (error) {
363
+ console.error(`[DApp] Error processing received message (Type: ${message.type}, ID: ${message.id}):`, error)
364
+ }
365
+ }
366
+
367
+ private handleWalletReadyMessage(message: TransportMessage): void {
368
+ if (this.connectionState !== ConnectionState.CONNECTING) {
369
+ return
370
+ }
371
+
372
+ if (message.sessionId !== this.sessionId) {
373
+ return
374
+ }
375
+
376
+ if (this.handshakeTimeoutId !== undefined) {
377
+ window.clearTimeout(this.handshakeTimeoutId)
378
+ this.handshakeTimeoutId = undefined
379
+ }
380
+
381
+ const initMessage: TransportMessage = {
382
+ id: this.initId!,
383
+ type: MessageType.INIT,
384
+ sessionId: this.sessionId,
385
+ }
386
+ this.postMessageToWallet(initMessage)
387
+
388
+ this.connectionState = ConnectionState.CONNECTED
389
+
390
+ if (this.readyPromiseResolve) {
391
+ this.readyPromiseResolve()
392
+ }
393
+
394
+ this.messageQueue.forEach((queuedMsg) => {
395
+ this.postMessageToWallet(queuedMsg)
396
+ })
397
+ this.messageQueue = []
398
+ }
399
+
400
+ private handleResponseMessage(message: TransportMessage): void {
401
+ const pending = this.pendingRequests.get(message.id)
402
+ if (pending) {
403
+ window.clearTimeout(pending.timer)
404
+ this.pendingRequests.delete(message.id)
405
+ if (message.error) {
406
+ const error = new Error(`Wallet responded with error: ${JSON.stringify(message.error)}`)
407
+ pending.reject(error)
408
+ } else {
409
+ pending.resolve(message.payload)
410
+ }
411
+ }
412
+ }
413
+
414
+ private postMessageToWallet(message: TransportMessage): void {
415
+ if (!this.isWalletOpen) {
416
+ if (
417
+ message.type === MessageType.INIT &&
418
+ this.connectionState === ConnectionState.CONNECTING &&
419
+ message.id === this.initId
420
+ ) {
421
+ this._handlePreConnectionFailure(new Error('Failed to send INIT: Wallet window closed unexpectedly.'))
422
+ } else if (message.type === MessageType.REQUEST) {
423
+ const pendingReq = this.pendingRequests.get(message.id)
424
+ if (pendingReq) {
425
+ window.clearTimeout(pendingReq.timer)
426
+ this.pendingRequests.delete(message.id)
427
+ pendingReq.reject(new Error(`Failed to send request '${pendingReq.action}': Wallet window closed.`))
428
+ }
429
+ }
430
+ return
431
+ }
432
+
433
+ if (this.connectionState !== ConnectionState.CONNECTED && message.type !== MessageType.INIT) {
434
+ this.messageQueue.push(message)
435
+ return
436
+ }
437
+
438
+ try {
439
+ this.walletWindow?.postMessage(message, this.walletOrigin)
440
+ } catch (error) {
441
+ const rejectionError =
442
+ error instanceof Error ? error : new Error('Failed to send message to wallet due to unknown error')
443
+
444
+ if (
445
+ message.type === MessageType.INIT &&
446
+ this.connectionState === ConnectionState.CONNECTING &&
447
+ message.id === this.initId
448
+ ) {
449
+ this._handlePreConnectionFailure(rejectionError)
450
+ } else if (message.type === MessageType.REQUEST) {
451
+ const pendingReq = this.pendingRequests.get(message.id)
452
+ if (pendingReq) {
453
+ window.clearTimeout(pendingReq.timer)
454
+ this.pendingRequests.delete(message.id)
455
+ pendingReq.reject(rejectionError)
456
+ }
457
+ this._handleDetectedClosure()
458
+ } else {
459
+ this._handleDetectedClosure()
460
+ }
461
+ }
462
+ }
463
+
464
+ private _resetConnection(reason: Error, logMessage: string): void {
465
+ console.log(`[DApp] ${logMessage}`)
466
+ if (this.readyPromiseReject) {
467
+ this.readyPromiseReject(reason)
468
+ }
469
+ this.clearTimeouts()
470
+ this.clearPendingRequests(reason)
471
+ this.connectionState = ConnectionState.DISCONNECTED
472
+ this.walletWindow = undefined
473
+ this.readyPromise = undefined
474
+ this.readyPromiseResolve = undefined
475
+ this.readyPromiseReject = undefined
476
+ this.initId = undefined
477
+ this.sessionId = undefined
478
+ this.messageQueue = []
479
+ }
480
+
481
+ private _handlePreConnectionFailure(error: Error): void {
482
+ this._resetConnection(error, `Connection failure: ${error.message}`)
483
+ }
484
+
485
+ private _handleDetectedClosure(): void {
486
+ if (this.connectionState === ConnectionState.CONNECTED) {
487
+ const reason = new Error('Wallet connection terminated unexpectedly.')
488
+ this._resetConnection(reason, 'Wallet connection terminated unexpectedly after ready.')
489
+ }
490
+ }
491
+
492
+ private clearPendingRequests(reason: Error): void {
493
+ if (this.pendingRequests.size > 0) {
494
+ const requestsToClear = new Map(this.pendingRequests)
495
+ this.pendingRequests.clear()
496
+ requestsToClear.forEach((pending) => {
497
+ window.clearTimeout(pending.timer)
498
+ const errorToSend = reason instanceof Error ? reason : new Error(`Operation failed: ${reason}`)
499
+ pending.reject(errorToSend)
500
+ })
501
+ }
502
+ }
503
+
504
+ private clearTimeouts(): void {
505
+ if (this.handshakeTimeoutId !== undefined) {
506
+ window.clearTimeout(this.handshakeTimeoutId)
507
+ this.handshakeTimeoutId = undefined
508
+ }
509
+ if (this.closeCheckIntervalId !== undefined) {
510
+ window.clearInterval(this.closeCheckIntervalId)
511
+ this.closeCheckIntervalId = undefined
512
+ }
513
+ }
514
+
515
+ private generateId(): string {
516
+ return `${Date.now().toString(36)}-${Math.random().toString(36).substring(2, 9)}`
517
+ }
518
+ }
package/src/index.ts ADDED
@@ -0,0 +1,47 @@
1
+ export { DappClient } from './DappClient.js'
2
+ export type { DappClientEventListener } from './DappClient.js'
3
+ export type {
4
+ LoginMethod,
5
+ GuardConfig,
6
+ Transaction,
7
+ SignatureSuccessResponse,
8
+ ChainSessionManagerEvent,
9
+ SequenceSessionStorage,
10
+ RandomPrivateKeyFn,
11
+ Session,
12
+ SignMessagePayload,
13
+ AddExplicitSessionPayload,
14
+ CreateNewSessionPayload,
15
+ SignTypedDataPayload,
16
+ ConnectSuccessResponsePayload,
17
+ ModifySessionSuccessResponsePayload,
18
+ ModifySessionPayload,
19
+ DappClientWalletActionEventListener,
20
+ DappClientExplicitSessionEventListener,
21
+ TransactionRequest,
22
+ SendWalletTransactionPayload,
23
+ SendWalletTransactionSuccessResponse,
24
+ WalletActionResponse,
25
+ } from './types/index.js'
26
+ export { RequestActionType, TransportMode } from './types/index.js'
27
+ export {
28
+ FeeOptionError,
29
+ TransactionError,
30
+ AddExplicitSessionError,
31
+ ConnectionError,
32
+ InitializationError,
33
+ SigningError,
34
+ ModifyExplicitSessionError,
35
+ } from './utils/errors.js'
36
+ export { getExplorerUrl, jsonReplacers, jsonRevivers } from './utils/index.js'
37
+ export type {
38
+ SequenceStorage,
39
+ ExplicitSessionData,
40
+ ImplicitSessionData,
41
+ PendingRequestContext,
42
+ PendingPayload,
43
+ } from './utils/storage.js'
44
+ export { WebStorage } from './utils/storage.js'
45
+
46
+ export { Permission, Extensions, SessionConfig } from '@0xsequence/wallet-primitives'
47
+ export { Signers, Wallet, Utils, Relayer } from '@0xsequence/wallet-core'