@0xsequence/dapp-client 3.0.0-beta.9 → 3.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.
- package/.turbo/turbo-build.log +2 -2
- package/.turbo/turbo-lint.log +4 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +170 -0
- package/dist/ChainSessionManager.d.ts +6 -1
- package/dist/ChainSessionManager.d.ts.map +1 -1
- package/dist/ChainSessionManager.js +62 -18
- package/dist/DappClient.d.ts +8 -2
- package/dist/DappClient.d.ts.map +1 -1
- package/dist/DappClient.js +7 -3
- package/dist/DappTransport.d.ts.map +1 -1
- package/dist/DappTransport.js +1 -2
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/types/index.d.ts +16 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/index.d.ts +20 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +23 -1
- package/dist/utils/storage.d.ts +7 -1
- package/dist/utils/storage.d.ts.map +1 -1
- package/dist/utils/storage.js +29 -0
- package/package.json +14 -12
- package/src/ChainSessionManager.ts +77 -18
- package/src/DappClient.ts +16 -6
- package/src/DappTransport.ts +1 -4
- package/src/index.ts +22 -2
- package/src/types/index.ts +21 -0
- package/src/utils/index.ts +48 -2
- package/src/utils/storage.ts +34 -0
- package/test/ethauth-proof.test.ts +207 -0
- /package/{eslint.config.mjs → eslint.config.js} +0 -0
package/src/utils/storage.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
SignMessagePayload,
|
|
6
6
|
SignTypedDataPayload,
|
|
7
7
|
GuardConfig,
|
|
8
|
+
ETHAuthProof,
|
|
8
9
|
SendWalletTransactionPayload,
|
|
9
10
|
ModifyExplicitSessionPayload,
|
|
10
11
|
CreateNewSessionPayload,
|
|
@@ -81,6 +82,10 @@ export interface SequenceStorage {
|
|
|
81
82
|
getSessionlessConnection(): Promise<SessionlessConnectionData | null>
|
|
82
83
|
clearSessionlessConnection(): Promise<void>
|
|
83
84
|
|
|
85
|
+
saveEthAuthProof(proof: ETHAuthProof): Promise<void>
|
|
86
|
+
getEthAuthProof(): Promise<ETHAuthProof | null>
|
|
87
|
+
clearEthAuthProof(): Promise<void>
|
|
88
|
+
|
|
84
89
|
saveSessionlessConnectionSnapshot?(sessionData: SessionlessConnectionData): Promise<void>
|
|
85
90
|
getSessionlessConnectionSnapshot?(): Promise<SessionlessConnectionData | null>
|
|
86
91
|
clearSessionlessConnectionSnapshot?(): Promise<void>
|
|
@@ -94,6 +99,7 @@ const STORE_NAME = 'userKeys'
|
|
|
94
99
|
const IMPLICIT_SESSIONS_IDB_KEY = 'SequenceImplicitSession'
|
|
95
100
|
const EXPLICIT_SESSIONS_IDB_KEY = 'SequenceExplicitSession'
|
|
96
101
|
const SESSIONLESS_CONNECTION_IDB_KEY = 'SequenceSessionlessConnection'
|
|
102
|
+
const ETH_AUTH_PROOF_IDB_KEY = 'SequenceEthAuthProof'
|
|
97
103
|
const SESSIONLESS_CONNECTION_SNAPSHOT_IDB_KEY = 'SequenceSessionlessConnectionSnapshot'
|
|
98
104
|
|
|
99
105
|
const PENDING_REDIRECT_REQUEST_KEY = 'SequencePendingRedirect'
|
|
@@ -305,6 +311,15 @@ export class WebStorage implements SequenceStorage {
|
|
|
305
311
|
}
|
|
306
312
|
}
|
|
307
313
|
|
|
314
|
+
async saveEthAuthProof(proof: ETHAuthProof): Promise<void> {
|
|
315
|
+
try {
|
|
316
|
+
await this.setIDBItem(ETH_AUTH_PROOF_IDB_KEY, proof)
|
|
317
|
+
} catch (error) {
|
|
318
|
+
console.error('Failed to save ETHAuth proof:', error)
|
|
319
|
+
throw error
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
308
323
|
async getSessionlessConnection(): Promise<SessionlessConnectionData | null> {
|
|
309
324
|
try {
|
|
310
325
|
return (await this.getIDBItem<SessionlessConnectionData>(SESSIONLESS_CONNECTION_IDB_KEY)) ?? null
|
|
@@ -314,6 +329,15 @@ export class WebStorage implements SequenceStorage {
|
|
|
314
329
|
}
|
|
315
330
|
}
|
|
316
331
|
|
|
332
|
+
async getEthAuthProof(): Promise<ETHAuthProof | null> {
|
|
333
|
+
try {
|
|
334
|
+
return (await this.getIDBItem<ETHAuthProof>(ETH_AUTH_PROOF_IDB_KEY)) ?? null
|
|
335
|
+
} catch (error) {
|
|
336
|
+
console.error('Failed to retrieve ETHAuth proof:', error)
|
|
337
|
+
return null
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
317
341
|
async clearSessionlessConnection(): Promise<void> {
|
|
318
342
|
try {
|
|
319
343
|
await this.deleteIDBItem(SESSIONLESS_CONNECTION_IDB_KEY)
|
|
@@ -323,6 +347,15 @@ export class WebStorage implements SequenceStorage {
|
|
|
323
347
|
}
|
|
324
348
|
}
|
|
325
349
|
|
|
350
|
+
async clearEthAuthProof(): Promise<void> {
|
|
351
|
+
try {
|
|
352
|
+
await this.deleteIDBItem(ETH_AUTH_PROOF_IDB_KEY)
|
|
353
|
+
} catch (error) {
|
|
354
|
+
console.error('Failed to clear ETHAuth proof:', error)
|
|
355
|
+
throw error
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
326
359
|
async saveSessionlessConnectionSnapshot(sessionData: SessionlessConnectionData): Promise<void> {
|
|
327
360
|
try {
|
|
328
361
|
await this.setIDBItem(SESSIONLESS_CONNECTION_SNAPSHOT_IDB_KEY, sessionData)
|
|
@@ -363,6 +396,7 @@ export class WebStorage implements SequenceStorage {
|
|
|
363
396
|
await this.clearExplicitSessions()
|
|
364
397
|
await this.clearImplicitSession()
|
|
365
398
|
await this.clearSessionlessConnection()
|
|
399
|
+
await this.clearEthAuthProof()
|
|
366
400
|
await this.clearSessionlessConnectionSnapshot()
|
|
367
401
|
} catch (error) {
|
|
368
402
|
console.error('Failed to clear all data:', error)
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { DappClient } from '../src/DappClient.js'
|
|
4
|
+
import { DappTransport } from '../src/DappTransport.js'
|
|
5
|
+
import { RequestActionType, TransportMode } from '../src/types/index.js'
|
|
6
|
+
import { WebStorage } from '../src/utils/storage.js'
|
|
7
|
+
|
|
8
|
+
describe('ETHAuth proof persistence', () => {
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
vi.restoreAllMocks()
|
|
11
|
+
vi.unstubAllGlobals()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const createSequenceStorageMock = () => ({
|
|
15
|
+
setPendingRedirectRequest: vi.fn().mockResolvedValue(undefined),
|
|
16
|
+
isRedirectRequestPending: vi.fn().mockResolvedValue(false),
|
|
17
|
+
saveTempSessionPk: vi.fn().mockResolvedValue(undefined),
|
|
18
|
+
getAndClearTempSessionPk: vi.fn().mockResolvedValue(null),
|
|
19
|
+
savePendingRequest: vi.fn().mockResolvedValue(undefined),
|
|
20
|
+
getAndClearPendingRequest: vi.fn().mockResolvedValue(null),
|
|
21
|
+
peekPendingRequest: vi.fn().mockResolvedValue(null),
|
|
22
|
+
saveExplicitSession: vi.fn().mockResolvedValue(undefined),
|
|
23
|
+
getExplicitSessions: vi.fn().mockResolvedValue([]),
|
|
24
|
+
clearExplicitSessions: vi.fn().mockResolvedValue(undefined),
|
|
25
|
+
saveImplicitSession: vi.fn().mockResolvedValue(undefined),
|
|
26
|
+
getImplicitSession: vi.fn().mockResolvedValue(null),
|
|
27
|
+
clearImplicitSession: vi.fn().mockResolvedValue(undefined),
|
|
28
|
+
saveSessionlessConnection: vi.fn().mockResolvedValue(undefined),
|
|
29
|
+
getSessionlessConnection: vi.fn().mockResolvedValue(null),
|
|
30
|
+
clearSessionlessConnection: vi.fn().mockResolvedValue(undefined),
|
|
31
|
+
saveEthAuthProof: vi.fn().mockResolvedValue(undefined),
|
|
32
|
+
getEthAuthProof: vi.fn().mockResolvedValue(null),
|
|
33
|
+
clearEthAuthProof: vi.fn().mockResolvedValue(undefined),
|
|
34
|
+
clearAllData: vi.fn().mockResolvedValue(undefined),
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('persists ETHAuth proof when connect requests ethAuth in redirect mode', async () => {
|
|
38
|
+
const fetchMock = vi.fn()
|
|
39
|
+
vi.stubGlobal('fetch', fetchMock)
|
|
40
|
+
vi.stubGlobal('window', { fetch: fetchMock })
|
|
41
|
+
|
|
42
|
+
const ethAuthProof = {
|
|
43
|
+
typedData: {
|
|
44
|
+
domain: {},
|
|
45
|
+
types: {},
|
|
46
|
+
message: {},
|
|
47
|
+
},
|
|
48
|
+
ewtString: 'proof-string',
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const sequenceStorage = createSequenceStorageMock()
|
|
52
|
+
const sendRequestMock = vi.spyOn(DappTransport.prototype, 'sendRequest').mockResolvedValue({
|
|
53
|
+
walletAddress: '0x1111111111111111111111111111111111111111',
|
|
54
|
+
ethAuthProof,
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const client = new DappClient('https://wallet.example', 'https://dapp.example', 'test-project-access-key', {
|
|
58
|
+
sequenceStorage,
|
|
59
|
+
transportMode: TransportMode.REDIRECT,
|
|
60
|
+
canUseIndexedDb: false,
|
|
61
|
+
redirectActionHandler: vi.fn(),
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
await client.connect(1, undefined, {
|
|
65
|
+
ethAuth: {
|
|
66
|
+
app: 'app-name',
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
expect(sendRequestMock).toHaveBeenCalledWith(
|
|
71
|
+
RequestActionType.CREATE_NEW_SESSION,
|
|
72
|
+
'https://dapp.example',
|
|
73
|
+
expect.objectContaining({
|
|
74
|
+
ethAuth: {
|
|
75
|
+
app: 'app-name',
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
expect.any(Object),
|
|
79
|
+
)
|
|
80
|
+
expect(sequenceStorage.saveEthAuthProof).toHaveBeenCalledWith(ethAuthProof)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('persists ETHAuth proof when connect requests ethAuth in popup mode', async () => {
|
|
84
|
+
const fetchMock = vi.fn()
|
|
85
|
+
vi.stubGlobal('fetch', fetchMock)
|
|
86
|
+
vi.stubGlobal('window', { fetch: fetchMock })
|
|
87
|
+
vi.stubGlobal('document', {})
|
|
88
|
+
|
|
89
|
+
const ethAuthProof = {
|
|
90
|
+
typedData: {
|
|
91
|
+
domain: {},
|
|
92
|
+
types: {},
|
|
93
|
+
message: {},
|
|
94
|
+
},
|
|
95
|
+
ewtString: 'proof-string',
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const sequenceStorage = createSequenceStorageMock()
|
|
99
|
+
const sendRequestMock = vi.spyOn(DappTransport.prototype, 'sendRequest').mockResolvedValue({
|
|
100
|
+
walletAddress: '0x1111111111111111111111111111111111111111',
|
|
101
|
+
ethAuthProof,
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const client = new DappClient('https://wallet.example', 'https://dapp.example', 'test-project-access-key', {
|
|
105
|
+
sequenceStorage,
|
|
106
|
+
transportMode: TransportMode.POPUP,
|
|
107
|
+
canUseIndexedDb: false,
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
await client.connect(1, undefined, {
|
|
111
|
+
ethAuth: {
|
|
112
|
+
app: 'app-name',
|
|
113
|
+
},
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
expect(sendRequestMock).toHaveBeenCalledWith(
|
|
117
|
+
RequestActionType.CREATE_NEW_SESSION,
|
|
118
|
+
'https://dapp.example',
|
|
119
|
+
expect.objectContaining({
|
|
120
|
+
ethAuth: {
|
|
121
|
+
app: 'app-name',
|
|
122
|
+
},
|
|
123
|
+
}),
|
|
124
|
+
expect.any(Object),
|
|
125
|
+
)
|
|
126
|
+
expect(sequenceStorage.saveEthAuthProof).toHaveBeenCalledWith(ethAuthProof)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('does not persist ETHAuth proof when connect does not request ethAuth', async () => {
|
|
130
|
+
const fetchMock = vi.fn()
|
|
131
|
+
vi.stubGlobal('fetch', fetchMock)
|
|
132
|
+
vi.stubGlobal('window', { fetch: fetchMock })
|
|
133
|
+
|
|
134
|
+
const ethAuthProof = {
|
|
135
|
+
typedData: {
|
|
136
|
+
domain: {},
|
|
137
|
+
types: {},
|
|
138
|
+
message: {},
|
|
139
|
+
},
|
|
140
|
+
ewtString: 'proof-string',
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const sequenceStorage = createSequenceStorageMock()
|
|
144
|
+
const sendRequestMock = vi.spyOn(DappTransport.prototype, 'sendRequest').mockResolvedValue({
|
|
145
|
+
walletAddress: '0x1111111111111111111111111111111111111111',
|
|
146
|
+
ethAuthProof,
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
const client = new DappClient('https://wallet.example', 'https://dapp.example', 'test-project-access-key', {
|
|
150
|
+
sequenceStorage,
|
|
151
|
+
transportMode: TransportMode.REDIRECT,
|
|
152
|
+
canUseIndexedDb: false,
|
|
153
|
+
redirectActionHandler: vi.fn(),
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
await client.connect(1)
|
|
157
|
+
|
|
158
|
+
expect(sendRequestMock).toHaveBeenCalledWith(
|
|
159
|
+
RequestActionType.CREATE_NEW_SESSION,
|
|
160
|
+
'https://dapp.example',
|
|
161
|
+
expect.not.objectContaining({
|
|
162
|
+
ethAuth: expect.anything(),
|
|
163
|
+
}),
|
|
164
|
+
expect.any(Object),
|
|
165
|
+
)
|
|
166
|
+
expect(sequenceStorage.saveEthAuthProof).not.toHaveBeenCalled()
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
it('clears ETHAuth proof on disconnect', async () => {
|
|
170
|
+
const fetchMock = vi.fn()
|
|
171
|
+
vi.stubGlobal('fetch', fetchMock)
|
|
172
|
+
vi.stubGlobal('window', { fetch: fetchMock })
|
|
173
|
+
|
|
174
|
+
const ethAuthProof = {
|
|
175
|
+
typedData: {
|
|
176
|
+
domain: {},
|
|
177
|
+
types: {},
|
|
178
|
+
message: {},
|
|
179
|
+
},
|
|
180
|
+
ewtString: 'proof-string',
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
vi.spyOn(DappTransport.prototype, 'sendRequest').mockResolvedValue({
|
|
184
|
+
walletAddress: '0x1111111111111111111111111111111111111111',
|
|
185
|
+
ethAuthProof,
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
const client = new DappClient('https://wallet.example', 'https://dapp.example', 'test-project-access-key', {
|
|
189
|
+
sequenceStorage: new WebStorage(),
|
|
190
|
+
transportMode: TransportMode.REDIRECT,
|
|
191
|
+
canUseIndexedDb: false,
|
|
192
|
+
redirectActionHandler: vi.fn(),
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
await client.connect(1, undefined, {
|
|
196
|
+
ethAuth: {
|
|
197
|
+
app: 'app-name',
|
|
198
|
+
},
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
expect(await client.getEthAuthProof()).toEqual(ethAuthProof)
|
|
202
|
+
|
|
203
|
+
await client.disconnect()
|
|
204
|
+
|
|
205
|
+
expect(await client.getEthAuthProof()).toBeNull()
|
|
206
|
+
})
|
|
207
|
+
})
|
|
File without changes
|