@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/dist/utils/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
1
|
import { Network } from '@0xsequence/wallet-primitives';
|
|
3
2
|
import { Bytes, Hex } from 'ox';
|
|
3
|
+
export { VALUE_FORWARDER_ADDRESS } from './constants.js';
|
|
4
4
|
/**
|
|
5
5
|
* Creates a single JSON replacer by chaining multiple replacers.
|
|
6
6
|
* The first replacer to transform a value wins.
|
|
@@ -114,6 +114,28 @@ const uint8ArrayReviver = (key, value) => {
|
|
|
114
114
|
};
|
|
115
115
|
export const jsonRevivers = chainRevivers([mapReviver, bigIntReviver, uint8ArrayReviver]);
|
|
116
116
|
export const jsonReplacers = chainReplacers([mapReplacer, bigIntReplacer, uint8ArrayReplacer]);
|
|
117
|
+
export const createExplicitSessionConfig = (params) => {
|
|
118
|
+
const nowInSeconds = BigInt(Math.floor(Date.now() / 1000));
|
|
119
|
+
const { days = 0, hours = 0, minutes = 0 } = params.expiresIn;
|
|
120
|
+
const sessionLifetimeSeconds = days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60;
|
|
121
|
+
const deadline = nowInSeconds + BigInt(sessionLifetimeSeconds);
|
|
122
|
+
if (params.permissions.length === 0) {
|
|
123
|
+
throw new Error('createExplicitSessionConfig: At least one permission is required.');
|
|
124
|
+
}
|
|
125
|
+
const nativeTokenSpending = params.nativeTokenSpending;
|
|
126
|
+
const valueLimit = nativeTokenSpending?.valueLimit ?? 0n;
|
|
127
|
+
const nativeTokenReceivers = [...(nativeTokenSpending?.allowedRecipients || [])];
|
|
128
|
+
const nativeTokenSpendingPermissions = nativeTokenReceivers.map((receiver) => ({
|
|
129
|
+
target: receiver,
|
|
130
|
+
rules: [],
|
|
131
|
+
}));
|
|
132
|
+
return {
|
|
133
|
+
chainId: params.chainId,
|
|
134
|
+
valueLimit,
|
|
135
|
+
deadline,
|
|
136
|
+
permissions: [...params.permissions, ...nativeTokenSpendingPermissions],
|
|
137
|
+
};
|
|
138
|
+
};
|
|
117
139
|
/**
|
|
118
140
|
* Apply a template to a string.
|
|
119
141
|
*
|
package/dist/utils/storage.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Address, Hex } from 'ox';
|
|
2
|
-
import { LoginMethod, SignMessagePayload, SignTypedDataPayload, GuardConfig, SendWalletTransactionPayload, ModifyExplicitSessionPayload, CreateNewSessionPayload, AddExplicitSessionPayload } from '../types/index.js';
|
|
2
|
+
import { LoginMethod, SignMessagePayload, SignTypedDataPayload, GuardConfig, ETHAuthProof, SendWalletTransactionPayload, ModifyExplicitSessionPayload, CreateNewSessionPayload, AddExplicitSessionPayload } from '../types/index.js';
|
|
3
3
|
import { Attestation } from '../index.js';
|
|
4
4
|
export interface ExplicitSessionData {
|
|
5
5
|
pk: Hex.Hex;
|
|
@@ -48,6 +48,9 @@ export interface SequenceStorage {
|
|
|
48
48
|
saveSessionlessConnection(sessionData: SessionlessConnectionData): Promise<void>;
|
|
49
49
|
getSessionlessConnection(): Promise<SessionlessConnectionData | null>;
|
|
50
50
|
clearSessionlessConnection(): Promise<void>;
|
|
51
|
+
saveEthAuthProof(proof: ETHAuthProof): Promise<void>;
|
|
52
|
+
getEthAuthProof(): Promise<ETHAuthProof | null>;
|
|
53
|
+
clearEthAuthProof(): Promise<void>;
|
|
51
54
|
saveSessionlessConnectionSnapshot?(sessionData: SessionlessConnectionData): Promise<void>;
|
|
52
55
|
getSessionlessConnectionSnapshot?(): Promise<SessionlessConnectionData | null>;
|
|
53
56
|
clearSessionlessConnectionSnapshot?(): Promise<void>;
|
|
@@ -73,8 +76,11 @@ export declare class WebStorage implements SequenceStorage {
|
|
|
73
76
|
getImplicitSession(): Promise<ImplicitSessionData | null>;
|
|
74
77
|
clearImplicitSession(): Promise<void>;
|
|
75
78
|
saveSessionlessConnection(sessionData: SessionlessConnectionData): Promise<void>;
|
|
79
|
+
saveEthAuthProof(proof: ETHAuthProof): Promise<void>;
|
|
76
80
|
getSessionlessConnection(): Promise<SessionlessConnectionData | null>;
|
|
81
|
+
getEthAuthProof(): Promise<ETHAuthProof | null>;
|
|
77
82
|
clearSessionlessConnection(): Promise<void>;
|
|
83
|
+
clearEthAuthProof(): Promise<void>;
|
|
78
84
|
saveSessionlessConnectionSnapshot(sessionData: SessionlessConnectionData): Promise<void>;
|
|
79
85
|
getSessionlessConnectionSnapshot(): Promise<SessionlessConnectionData | null>;
|
|
80
86
|
clearSessionlessConnectionSnapshot(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/storage.js
CHANGED
|
@@ -9,6 +9,7 @@ const STORE_NAME = 'userKeys';
|
|
|
9
9
|
const IMPLICIT_SESSIONS_IDB_KEY = 'SequenceImplicitSession';
|
|
10
10
|
const EXPLICIT_SESSIONS_IDB_KEY = 'SequenceExplicitSession';
|
|
11
11
|
const SESSIONLESS_CONNECTION_IDB_KEY = 'SequenceSessionlessConnection';
|
|
12
|
+
const ETH_AUTH_PROOF_IDB_KEY = 'SequenceEthAuthProof';
|
|
12
13
|
const SESSIONLESS_CONNECTION_SNAPSHOT_IDB_KEY = 'SequenceSessionlessConnectionSnapshot';
|
|
13
14
|
const PENDING_REDIRECT_REQUEST_KEY = 'SequencePendingRedirect';
|
|
14
15
|
const TEMP_SESSION_PK_KEY = 'SequencePendingTempSessionPk';
|
|
@@ -219,6 +220,15 @@ export class WebStorage {
|
|
|
219
220
|
throw error;
|
|
220
221
|
}
|
|
221
222
|
}
|
|
223
|
+
async saveEthAuthProof(proof) {
|
|
224
|
+
try {
|
|
225
|
+
await this.setIDBItem(ETH_AUTH_PROOF_IDB_KEY, proof);
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
console.error('Failed to save ETHAuth proof:', error);
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
222
232
|
async getSessionlessConnection() {
|
|
223
233
|
try {
|
|
224
234
|
return (await this.getIDBItem(SESSIONLESS_CONNECTION_IDB_KEY)) ?? null;
|
|
@@ -228,6 +238,15 @@ export class WebStorage {
|
|
|
228
238
|
return null;
|
|
229
239
|
}
|
|
230
240
|
}
|
|
241
|
+
async getEthAuthProof() {
|
|
242
|
+
try {
|
|
243
|
+
return (await this.getIDBItem(ETH_AUTH_PROOF_IDB_KEY)) ?? null;
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
console.error('Failed to retrieve ETHAuth proof:', error);
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
231
250
|
async clearSessionlessConnection() {
|
|
232
251
|
try {
|
|
233
252
|
await this.deleteIDBItem(SESSIONLESS_CONNECTION_IDB_KEY);
|
|
@@ -237,6 +256,15 @@ export class WebStorage {
|
|
|
237
256
|
throw error;
|
|
238
257
|
}
|
|
239
258
|
}
|
|
259
|
+
async clearEthAuthProof() {
|
|
260
|
+
try {
|
|
261
|
+
await this.deleteIDBItem(ETH_AUTH_PROOF_IDB_KEY);
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
console.error('Failed to clear ETHAuth proof:', error);
|
|
265
|
+
throw error;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
240
268
|
async saveSessionlessConnectionSnapshot(sessionData) {
|
|
241
269
|
try {
|
|
242
270
|
await this.setIDBItem(SESSIONLESS_CONNECTION_SNAPSHOT_IDB_KEY, sessionData);
|
|
@@ -276,6 +304,7 @@ export class WebStorage {
|
|
|
276
304
|
await this.clearExplicitSessions();
|
|
277
305
|
await this.clearImplicitSession();
|
|
278
306
|
await this.clearSessionlessConnection();
|
|
307
|
+
await this.clearEthAuthProof();
|
|
279
308
|
await this.clearSessionlessConnectionSnapshot();
|
|
280
309
|
}
|
|
281
310
|
catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xsequence/dapp-client",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -14,26 +14,28 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@types/node": "^25.0
|
|
18
|
-
"@vitest/coverage-v8": "^4.0.
|
|
19
|
-
"dotenv": "^17.
|
|
17
|
+
"@types/node": "^25.3.0",
|
|
18
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
19
|
+
"dotenv": "^17.3.1",
|
|
20
20
|
"fake-indexeddb": "^6.2.5",
|
|
21
|
-
"happy-dom": "^20.0
|
|
21
|
+
"happy-dom": "^20.7.0",
|
|
22
22
|
"typescript": "^5.9.3",
|
|
23
|
-
"vitest": "^4.0.
|
|
24
|
-
"@repo/
|
|
23
|
+
"vitest": "^4.0.18",
|
|
24
|
+
"@repo/eslint-config": "^0.0.1",
|
|
25
|
+
"@repo/typescript-config": "^0.0.1"
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
27
28
|
"ox": "^0.9.17",
|
|
28
|
-
"@0xsequence/guard": "^3.0.
|
|
29
|
-
"@0xsequence/wallet-core": "^3.0.
|
|
30
|
-
"@0xsequence/wallet-primitives": "^3.0.
|
|
31
|
-
"@0xsequence/relayer": "^3.0.
|
|
29
|
+
"@0xsequence/guard": "^3.0.1",
|
|
30
|
+
"@0xsequence/wallet-core": "^3.0.1",
|
|
31
|
+
"@0xsequence/wallet-primitives": "^3.0.1",
|
|
32
|
+
"@0xsequence/relayer": "^3.0.1"
|
|
32
33
|
},
|
|
33
34
|
"scripts": {
|
|
34
35
|
"build": "tsc",
|
|
35
36
|
"dev": "tsc --watch",
|
|
36
37
|
"typecheck": "tsc --noEmit",
|
|
37
|
-
"clean": "rimraf dist"
|
|
38
|
+
"clean": "rimraf dist",
|
|
39
|
+
"lint": "eslint . --max-warnings 0"
|
|
38
40
|
}
|
|
39
41
|
}
|
|
@@ -37,12 +37,14 @@ import {
|
|
|
37
37
|
TransportMode,
|
|
38
38
|
GuardConfig,
|
|
39
39
|
CreateNewSessionPayload,
|
|
40
|
+
EthAuthSettings,
|
|
40
41
|
ModifyExplicitSessionPayload,
|
|
41
42
|
SessionResponse,
|
|
42
43
|
AddExplicitSessionPayload,
|
|
43
44
|
FeeOption,
|
|
44
45
|
OperationFailedStatus,
|
|
45
46
|
OperationStatus,
|
|
47
|
+
ETHAuthProof,
|
|
46
48
|
} from './types/index.js'
|
|
47
49
|
import { CACHE_DB_NAME, VALUE_FORWARDER_ADDRESS } from './utils/constants.js'
|
|
48
50
|
import { ExplicitSession, ImplicitSession, ExplicitSessionConfig } from './index.js'
|
|
@@ -84,6 +86,11 @@ export class ChainSessionManager {
|
|
|
84
86
|
public loginMethod: LoginMethod | null = null
|
|
85
87
|
public userEmail: string | null = null
|
|
86
88
|
private guard?: GuardConfig
|
|
89
|
+
private lastSignedCallCache?: {
|
|
90
|
+
fingerprint: string
|
|
91
|
+
signedCall: { to: Address.Address; data: Hex.Hex }
|
|
92
|
+
createdAtMs: number
|
|
93
|
+
}
|
|
87
94
|
|
|
88
95
|
/**
|
|
89
96
|
* @param chainId The ID of the chain this manager is responsible for.
|
|
@@ -151,11 +158,11 @@ export class ChainSessionManager {
|
|
|
151
158
|
listener: ChainSessionManagerEventMap[K],
|
|
152
159
|
): () => void {
|
|
153
160
|
if (!this.eventListeners[event]) {
|
|
154
|
-
this.eventListeners[event] = new Set()
|
|
161
|
+
this.eventListeners[event] = new Set<ChainSessionManagerEventMap[K]>()
|
|
155
162
|
}
|
|
156
|
-
|
|
163
|
+
this.eventListeners[event].add(listener)
|
|
157
164
|
return () => {
|
|
158
|
-
|
|
165
|
+
this.eventListeners[event]?.delete(listener)
|
|
159
166
|
}
|
|
160
167
|
}
|
|
161
168
|
|
|
@@ -280,6 +287,7 @@ export class ChainSessionManager {
|
|
|
280
287
|
preferredLoginMethod?: LoginMethod
|
|
281
288
|
email?: string
|
|
282
289
|
includeImplicitSession?: boolean
|
|
290
|
+
ethAuth?: EthAuthSettings
|
|
283
291
|
} = {},
|
|
284
292
|
): Promise<void> {
|
|
285
293
|
if (this.isInitialized) {
|
|
@@ -306,6 +314,7 @@ export class ChainSessionManager {
|
|
|
306
314
|
origin,
|
|
307
315
|
session: completeSession as ExplicitSession | undefined,
|
|
308
316
|
includeImplicitSession: options.includeImplicitSession ?? false,
|
|
317
|
+
ethAuth: options.ethAuth,
|
|
309
318
|
preferredLoginMethod: options.preferredLoginMethod,
|
|
310
319
|
email: options.preferredLoginMethod === 'email' ? options.email : undefined,
|
|
311
320
|
}
|
|
@@ -372,6 +381,10 @@ export class ChainSessionManager {
|
|
|
372
381
|
this.guard = guard
|
|
373
382
|
}
|
|
374
383
|
|
|
384
|
+
if (payload.ethAuth) {
|
|
385
|
+
await this._saveEthAuthProofIfProvided(connectResponse.ethAuthProof)
|
|
386
|
+
}
|
|
387
|
+
|
|
375
388
|
if (this.transport.mode === TransportMode.POPUP) {
|
|
376
389
|
this.transport.closeWallet()
|
|
377
390
|
}
|
|
@@ -591,6 +604,10 @@ export class ChainSessionManager {
|
|
|
591
604
|
this.userEmail = userEmail ?? null
|
|
592
605
|
this.guard = guard
|
|
593
606
|
}
|
|
607
|
+
|
|
608
|
+
if (savedPayload?.ethAuth) {
|
|
609
|
+
await this._saveEthAuthProofIfProvided(connectResponse.ethAuthProof)
|
|
610
|
+
}
|
|
594
611
|
} else if (response.action === RequestActionType.ADD_EXPLICIT_SESSION) {
|
|
595
612
|
if (!this.walletAddress || !Address.isEqual(receivedAddress, this.walletAddress)) {
|
|
596
613
|
throw new InitializationError('Received an explicit session for a wallet that is not active.')
|
|
@@ -811,19 +828,6 @@ export class ChainSessionManager {
|
|
|
811
828
|
await this.sessionManager.findSignersForCalls(this.wallet.address, this.chainId, calls)
|
|
812
829
|
return true
|
|
813
830
|
} catch (error) {
|
|
814
|
-
if (error instanceof Error && error.message.includes('Signer supporting call is expired')) {
|
|
815
|
-
// Extract the expired signer address from the message with address regex
|
|
816
|
-
const expiredSignerAddress = error.message.match(/(0x[0-9a-fA-F]{40})/)?.[1]
|
|
817
|
-
if (expiredSignerAddress) {
|
|
818
|
-
// Refresh the session
|
|
819
|
-
await this._refreshExplicitSession(Address.from(expiredSignerAddress))
|
|
820
|
-
// Retry the permission check
|
|
821
|
-
return this.hasPermission(transactions)
|
|
822
|
-
} else {
|
|
823
|
-
// Could not parse error message. Rethrow as this shouldn't happen.
|
|
824
|
-
throw error
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
831
|
// An error from findSignersForCalls indicates a permission failure.
|
|
828
832
|
console.warn(
|
|
829
833
|
`Permission check failed for chain ${this.chainId}:`,
|
|
@@ -851,7 +855,17 @@ export class ChainSessionManager {
|
|
|
851
855
|
}))
|
|
852
856
|
try {
|
|
853
857
|
const signedCall = await this._buildAndSignCalls(callsToSend)
|
|
854
|
-
const
|
|
858
|
+
const fingerprint = this._fingerprintCalls(callsToSend)
|
|
859
|
+
if (fingerprint) {
|
|
860
|
+
this.lastSignedCallCache = {
|
|
861
|
+
fingerprint,
|
|
862
|
+
signedCall,
|
|
863
|
+
createdAtMs: Date.now(),
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
const walletAddress = this.walletAddress
|
|
867
|
+
if (!walletAddress) throw new InitializationError('Wallet is not initialized.')
|
|
868
|
+
const feeOptions = await this.relayer.feeOptions(walletAddress, this.chainId, signedCall.to, callsToSend)
|
|
855
869
|
return feeOptions.options
|
|
856
870
|
} catch (err) {
|
|
857
871
|
throw new FeeOptionError(`Failed to get fee options: ${err instanceof Error ? err.message : String(err)}`)
|
|
@@ -907,7 +921,7 @@ export class ChainSessionManager {
|
|
|
907
921
|
callsToSend.unshift(transferCall)
|
|
908
922
|
}
|
|
909
923
|
}
|
|
910
|
-
const signedCalls = await this._buildAndSignCalls(callsToSend)
|
|
924
|
+
const signedCalls = this._getCachedSignedCall(callsToSend) ?? (await this._buildAndSignCalls(callsToSend))
|
|
911
925
|
const hash = await this.relayer.relay(signedCalls.to, signedCalls.data, this.chainId)
|
|
912
926
|
const status = await this._waitForTransactionReceipt(hash.opHash, this.chainId)
|
|
913
927
|
if (status.status === 'confirmed') {
|
|
@@ -1101,4 +1115,49 @@ export class ChainSessionManager {
|
|
|
1101
1115
|
await this.sequenceStorage.clearExplicitSessions()
|
|
1102
1116
|
await this.sequenceStorage.clearSessionlessConnection()
|
|
1103
1117
|
}
|
|
1118
|
+
|
|
1119
|
+
private async _saveEthAuthProofIfProvided(ethAuthProof?: ETHAuthProof): Promise<void> {
|
|
1120
|
+
if (!ethAuthProof) {
|
|
1121
|
+
return
|
|
1122
|
+
}
|
|
1123
|
+
await this.sequenceStorage.saveEthAuthProof(ethAuthProof)
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
private _getCachedSignedCall(calls: Payload.Call[]): { to: Address.Address; data: Hex.Hex } | null {
|
|
1127
|
+
if (!this.lastSignedCallCache) {
|
|
1128
|
+
return null
|
|
1129
|
+
}
|
|
1130
|
+
const ttlMs = 30_000
|
|
1131
|
+
if (Date.now() - this.lastSignedCallCache.createdAtMs > ttlMs) {
|
|
1132
|
+
this.lastSignedCallCache = undefined
|
|
1133
|
+
return null
|
|
1134
|
+
}
|
|
1135
|
+
const fingerprint = this._fingerprintCalls(calls)
|
|
1136
|
+
if (!fingerprint) {
|
|
1137
|
+
return null
|
|
1138
|
+
}
|
|
1139
|
+
if (fingerprint !== this.lastSignedCallCache.fingerprint) {
|
|
1140
|
+
return null
|
|
1141
|
+
}
|
|
1142
|
+
return this.lastSignedCallCache.signedCall
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
private _fingerprintCalls(calls: Payload.Call[]): string | null {
|
|
1146
|
+
try {
|
|
1147
|
+
return JSON.stringify(
|
|
1148
|
+
calls.map((call) => ({
|
|
1149
|
+
to: call.to,
|
|
1150
|
+
value: call.value?.toString() ?? '0',
|
|
1151
|
+
data: call.data ?? '0x',
|
|
1152
|
+
gasLimit: call.gasLimit?.toString() ?? '0',
|
|
1153
|
+
delegateCall: call.delegateCall ?? false,
|
|
1154
|
+
onlyFallback: call.onlyFallback ?? false,
|
|
1155
|
+
behaviorOnError: call.behaviorOnError ?? 'revert',
|
|
1156
|
+
})),
|
|
1157
|
+
)
|
|
1158
|
+
} catch (error) {
|
|
1159
|
+
console.warn('ChainSessionManager._fingerprintCalls failed:', error)
|
|
1160
|
+
return null
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1104
1163
|
}
|
package/src/DappClient.ts
CHANGED
|
@@ -14,8 +14,10 @@ import {
|
|
|
14
14
|
GetFeeTokensResponse,
|
|
15
15
|
GuardConfig,
|
|
16
16
|
LoginMethod,
|
|
17
|
+
EthAuthSettings,
|
|
17
18
|
RandomPrivateKeyFn,
|
|
18
19
|
RequestActionType,
|
|
20
|
+
ETHAuthProof,
|
|
19
21
|
SendWalletTransactionPayload,
|
|
20
22
|
SequenceSessionStorage,
|
|
21
23
|
SignMessagePayload,
|
|
@@ -30,7 +32,7 @@ import { KEYMACHINE_URL, NODES_URL, RELAYER_URL } from './utils/constants.js'
|
|
|
30
32
|
import { getRelayerUrl, getRpcUrl } from './utils/index.js'
|
|
31
33
|
import { Relayer } from '@0xsequence/relayer'
|
|
32
34
|
|
|
33
|
-
export type DappClientEventListener = (data?:
|
|
35
|
+
export type DappClientEventListener = (data?: unknown) => void
|
|
34
36
|
|
|
35
37
|
interface DappClientEventMap {
|
|
36
38
|
sessionsUpdated: () => void
|
|
@@ -180,11 +182,12 @@ export class DappClient {
|
|
|
180
182
|
*/
|
|
181
183
|
public on<K extends keyof DappClientEventMap>(event: K, listener: DappClientEventMap[K]): () => void {
|
|
182
184
|
if (!this.eventListeners[event]) {
|
|
183
|
-
|
|
185
|
+
// @ts-expect-error - indexing into evenListeners will improperly create a union of all the possible types
|
|
186
|
+
this.eventListeners[event] = new Set<DappClientEventMap[K]>()
|
|
184
187
|
}
|
|
185
|
-
|
|
188
|
+
this.eventListeners[event].add(listener)
|
|
186
189
|
return () => {
|
|
187
|
-
|
|
190
|
+
this.eventListeners[event]?.delete(listener)
|
|
188
191
|
}
|
|
189
192
|
}
|
|
190
193
|
|
|
@@ -407,6 +410,13 @@ export class DappClient {
|
|
|
407
410
|
}
|
|
408
411
|
}
|
|
409
412
|
|
|
413
|
+
/**
|
|
414
|
+
* Returns the latest persisted ETHAuth proof, if one has been received from the wallet.
|
|
415
|
+
*/
|
|
416
|
+
public async getEthAuthProof(): Promise<ETHAuthProof | null> {
|
|
417
|
+
return this.sequenceStorage.getEthAuthProof()
|
|
418
|
+
}
|
|
419
|
+
|
|
410
420
|
/**
|
|
411
421
|
* Restores a sessionless connection that was previously persisted via {@link disconnect} or a connect flow.
|
|
412
422
|
* @returns A promise that resolves to true if a sessionless connection was applied.
|
|
@@ -559,6 +569,7 @@ export class DappClient {
|
|
|
559
569
|
preferredLoginMethod?: LoginMethod
|
|
560
570
|
email?: string
|
|
561
571
|
includeImplicitSession?: boolean
|
|
572
|
+
ethAuth?: EthAuthSettings
|
|
562
573
|
} = {},
|
|
563
574
|
): Promise<void> {
|
|
564
575
|
if (this.isInitialized) {
|
|
@@ -614,6 +625,7 @@ export class DappClient {
|
|
|
614
625
|
preferredLoginMethod?: LoginMethod
|
|
615
626
|
email?: string
|
|
616
627
|
includeImplicitSession?: boolean
|
|
628
|
+
ethAuth?: EthAuthSettings
|
|
617
629
|
} = {},
|
|
618
630
|
): Promise<void> {
|
|
619
631
|
if (!this.isInitialized || !this.hasSessionlessConnection || !this.walletAddress) {
|
|
@@ -965,8 +977,6 @@ export class DappClient {
|
|
|
965
977
|
async disconnect(options?: { keepSessionlessConnection?: boolean }): Promise<void> {
|
|
966
978
|
const keepSessionlessConnection = options?.keepSessionlessConnection ?? true
|
|
967
979
|
|
|
968
|
-
const transportMode = this.transportMode
|
|
969
|
-
|
|
970
980
|
if (this.transport) {
|
|
971
981
|
this.transport.destroy()
|
|
972
982
|
}
|
package/src/DappTransport.ts
CHANGED
|
@@ -378,10 +378,7 @@ export class DappTransport {
|
|
|
378
378
|
return
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
-
|
|
382
|
-
this.walletWindow && (event.source === this.walletWindow || !this.walletWindow.closed)
|
|
383
|
-
|
|
384
|
-
if (!isPotentiallyValidSource && event.data?.type !== MessageType.WALLET_OPENED) {
|
|
381
|
+
if (!this.walletWindow || event.source !== this.walletWindow) {
|
|
385
382
|
return
|
|
386
383
|
}
|
|
387
384
|
|
package/src/index.ts
CHANGED
|
@@ -24,6 +24,8 @@ export type {
|
|
|
24
24
|
FeeToken,
|
|
25
25
|
FeeOption,
|
|
26
26
|
TransportMessage,
|
|
27
|
+
EthAuthSettings,
|
|
28
|
+
ETHAuthProof,
|
|
27
29
|
} from './types/index.js'
|
|
28
30
|
export { RequestActionType, TransportMode, MessageType } from './types/index.js'
|
|
29
31
|
export {
|
|
@@ -35,7 +37,17 @@ export {
|
|
|
35
37
|
SigningError,
|
|
36
38
|
ModifyExplicitSessionError,
|
|
37
39
|
} from './utils/errors.js'
|
|
38
|
-
export {
|
|
40
|
+
export {
|
|
41
|
+
createExplicitSessionConfig,
|
|
42
|
+
getExplorerUrl,
|
|
43
|
+
getNetwork,
|
|
44
|
+
getRelayerUrl,
|
|
45
|
+
getRpcUrl,
|
|
46
|
+
jsonReplacers,
|
|
47
|
+
jsonRevivers,
|
|
48
|
+
VALUE_FORWARDER_ADDRESS,
|
|
49
|
+
} from './utils/index.js'
|
|
50
|
+
export type { ExplicitSessionParams, NativeTokenSpending, SessionDuration } from './utils/index.js'
|
|
39
51
|
export type {
|
|
40
52
|
SequenceStorage,
|
|
41
53
|
ExplicitSessionData,
|
|
@@ -46,6 +58,14 @@ export type {
|
|
|
46
58
|
} from './utils/storage.js'
|
|
47
59
|
export { WebStorage } from './utils/storage.js'
|
|
48
60
|
|
|
49
|
-
export {
|
|
61
|
+
export {
|
|
62
|
+
Attestation,
|
|
63
|
+
Permission,
|
|
64
|
+
Extensions,
|
|
65
|
+
SessionConfig,
|
|
66
|
+
Constants,
|
|
67
|
+
Payload,
|
|
68
|
+
Network,
|
|
69
|
+
} from '@0xsequence/wallet-primitives'
|
|
50
70
|
export type { ExplicitSessionConfig, ExplicitSession, ImplicitSession, Session } from '@0xsequence/wallet-core'
|
|
51
71
|
export { Signers, Wallet, Utils, Envelope, State } from '@0xsequence/wallet-core'
|
package/src/types/index.ts
CHANGED
|
@@ -28,12 +28,32 @@ export interface GuardConfig {
|
|
|
28
28
|
moduleAddresses: Map<Address.Address, Address.Address>
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
export interface EthAuthSettings {
|
|
32
|
+
app?: string
|
|
33
|
+
/** expiry number (in seconds) that is used for ETHAuth proof. Default is 1 week in seconds. */
|
|
34
|
+
expiry?: number
|
|
35
|
+
/** origin hint of the dapp's host opening the wallet. This value will automatically
|
|
36
|
+
* be determined and verified for integrity, and can be omitted. */
|
|
37
|
+
origin?: string
|
|
38
|
+
/** authorizeNonce is an optional number to be passed as ETHAuth's nonce claim for replay protection. **/
|
|
39
|
+
nonce?: number
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface ETHAuthProof {
|
|
43
|
+
// eip712 typed-data payload for ETHAuth domain as input
|
|
44
|
+
typedData: Payload.TypedDataToSign
|
|
45
|
+
|
|
46
|
+
// signature encoded in an ETHAuth proof string
|
|
47
|
+
ewtString: string
|
|
48
|
+
}
|
|
49
|
+
|
|
31
50
|
// --- Payloads for Transport ---
|
|
32
51
|
|
|
33
52
|
export interface CreateNewSessionPayload {
|
|
34
53
|
origin?: string
|
|
35
54
|
session?: ExplicitSession
|
|
36
55
|
includeImplicitSession?: boolean
|
|
56
|
+
ethAuth?: EthAuthSettings
|
|
37
57
|
preferredLoginMethod?: LoginMethod
|
|
38
58
|
email?: string
|
|
39
59
|
}
|
|
@@ -81,6 +101,7 @@ export interface CreateNewSessionResponse {
|
|
|
81
101
|
userEmail?: string
|
|
82
102
|
loginMethod?: LoginMethod
|
|
83
103
|
guard?: GuardConfig
|
|
104
|
+
ethAuthProof?: ETHAuthProof
|
|
84
105
|
}
|
|
85
106
|
|
|
86
107
|
export interface SignatureResponse {
|
package/src/utils/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import type { ExplicitSessionConfig } from '@0xsequence/wallet-core'
|
|
3
|
+
import { Network, Permission } from '@0xsequence/wallet-primitives'
|
|
4
|
+
import { Bytes, Hex, type Address } from 'ox'
|
|
5
|
+
export { VALUE_FORWARDER_ADDRESS } from './constants.js'
|
|
4
6
|
|
|
5
7
|
type JsonReplacer = (key: string, value: any) => any
|
|
6
8
|
type JsonReviver = (key: string, value: any) => any
|
|
@@ -124,6 +126,50 @@ const uint8ArrayReviver: JsonReviver = (key, value) => {
|
|
|
124
126
|
export const jsonRevivers = chainRevivers([mapReviver, bigIntReviver, uint8ArrayReviver])
|
|
125
127
|
export const jsonReplacers = chainReplacers([mapReplacer, bigIntReplacer, uint8ArrayReplacer])
|
|
126
128
|
|
|
129
|
+
export type SessionDuration = {
|
|
130
|
+
days?: number
|
|
131
|
+
hours?: number
|
|
132
|
+
minutes?: number
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export type NativeTokenSpending = {
|
|
136
|
+
valueLimit: bigint
|
|
137
|
+
allowedRecipients?: Address.Address[]
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export type ExplicitSessionParams = {
|
|
141
|
+
chainId: number
|
|
142
|
+
expiresIn: SessionDuration
|
|
143
|
+
permissions: Permission.Permission[]
|
|
144
|
+
nativeTokenSpending?: NativeTokenSpending
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const createExplicitSessionConfig = (params: ExplicitSessionParams): ExplicitSessionConfig => {
|
|
148
|
+
const nowInSeconds = BigInt(Math.floor(Date.now() / 1000))
|
|
149
|
+
const { days = 0, hours = 0, minutes = 0 } = params.expiresIn
|
|
150
|
+
const sessionLifetimeSeconds = days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60
|
|
151
|
+
const deadline = nowInSeconds + BigInt(sessionLifetimeSeconds)
|
|
152
|
+
|
|
153
|
+
if (params.permissions.length === 0) {
|
|
154
|
+
throw new Error('createExplicitSessionConfig: At least one permission is required.')
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const nativeTokenSpending = params.nativeTokenSpending
|
|
158
|
+
const valueLimit = nativeTokenSpending?.valueLimit ?? 0n
|
|
159
|
+
const nativeTokenReceivers = [...(nativeTokenSpending?.allowedRecipients || [])]
|
|
160
|
+
const nativeTokenSpendingPermissions = nativeTokenReceivers.map((receiver) => ({
|
|
161
|
+
target: receiver,
|
|
162
|
+
rules: [],
|
|
163
|
+
}))
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
chainId: params.chainId,
|
|
167
|
+
valueLimit,
|
|
168
|
+
deadline,
|
|
169
|
+
permissions: [...params.permissions, ...nativeTokenSpendingPermissions],
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
127
173
|
/**
|
|
128
174
|
* Apply a template to a string.
|
|
129
175
|
*
|