@etherplay/connect 0.0.34 → 0.0.36
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/dist/index.d.ts +102 -37
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +119 -70
- package/dist/index.js.map +1 -1
- package/package.json +32 -5
- package/src/index.ts +358 -157
- package/dist/provider.d.ts +0 -14
- package/dist/provider.d.ts.map +0 -1
- package/dist/provider.js +0 -77
- package/dist/provider.js.map +0 -1
package/src/index.ts
CHANGED
|
@@ -38,7 +38,8 @@ export type BasicChainInfo = {
|
|
|
38
38
|
|
|
39
39
|
chainType?: string;
|
|
40
40
|
};
|
|
41
|
-
|
|
41
|
+
|
|
42
|
+
type ChainInfoWithRPCUrl = BasicChainInfo & {
|
|
42
43
|
readonly rpcUrls: {
|
|
43
44
|
readonly default: {
|
|
44
45
|
http: readonly string[];
|
|
@@ -46,6 +47,12 @@ export type ChainInfo = BasicChainInfo & {
|
|
|
46
47
|
};
|
|
47
48
|
};
|
|
48
49
|
|
|
50
|
+
type ChainInfoWithProvider<WalletProviderType> = BasicChainInfo & {
|
|
51
|
+
provider: WalletProviderType;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type ChainInfo<WalletProviderType> = ChainInfoWithRPCUrl | ChainInfoWithProvider<WalletProviderType>;
|
|
55
|
+
|
|
49
56
|
export type PopupSettings = {
|
|
50
57
|
walletHost: string;
|
|
51
58
|
mechanism: AlchemyMechanism;
|
|
@@ -61,6 +68,8 @@ export type Mechanism = AlchemyMechanism | WalletMechanism<string | undefined, `
|
|
|
61
68
|
|
|
62
69
|
export type FullfilledMechanism = AlchemyMechanism | WalletMechanism<string, `0x${string}`>;
|
|
63
70
|
|
|
71
|
+
export type TargetStep = 'WalletConnected' | 'SignedIn';
|
|
72
|
+
|
|
64
73
|
export type WalletState<WalletProviderType> = {
|
|
65
74
|
provider: WalletProvider<WalletProviderType>;
|
|
66
75
|
accounts: `0x${string}`[];
|
|
@@ -70,12 +79,18 @@ export type WalletState<WalletProviderType> = {
|
|
|
70
79
|
switchingChain: 'addingChain' | 'switchingChain' | false;
|
|
71
80
|
} & ({status: 'connected'} | {status: 'locked'; unlocking: boolean} | {status: 'disconnected'; connecting: boolean});
|
|
72
81
|
|
|
73
|
-
type
|
|
82
|
+
type WaitingForSignature<WalletProviderType> = {
|
|
74
83
|
step: 'WaitingForSignature';
|
|
75
84
|
mechanism: WalletMechanism<string, `0x${string}`>;
|
|
76
85
|
wallet: WalletState<WalletProviderType>;
|
|
77
86
|
};
|
|
78
87
|
|
|
88
|
+
type WalletConnected<WalletProviderType> = {
|
|
89
|
+
step: 'WalletConnected';
|
|
90
|
+
mechanism: WalletMechanism<string, `0x${string}`>;
|
|
91
|
+
wallet: WalletState<WalletProviderType>;
|
|
92
|
+
};
|
|
93
|
+
|
|
79
94
|
type SignedIn<WalletProviderType> =
|
|
80
95
|
| {
|
|
81
96
|
step: 'SignedIn';
|
|
@@ -137,13 +152,9 @@ export type Connection<WalletProviderType> = {
|
|
|
137
152
|
}
|
|
138
153
|
// Once the wallet is connected, the system will need a signature
|
|
139
154
|
// this state represent the fact and require another user interaction to request the signature
|
|
140
|
-
| {
|
|
141
|
-
step: 'WalletConnected';
|
|
142
|
-
mechanism: WalletMechanism<string, `0x${string}`>;
|
|
143
|
-
wallet: WalletState<WalletProviderType>;
|
|
144
|
-
}
|
|
145
|
-
// This state is triggered once the signature is requested, the user will have to confirm with its wallet
|
|
146
155
|
| WalletConnected<WalletProviderType>
|
|
156
|
+
// This state is triggered once the signature is requested, the user will have to confirm with its wallet
|
|
157
|
+
| WaitingForSignature<WalletProviderType>
|
|
147
158
|
// Finally the user is fully signed in
|
|
148
159
|
// wallet?.accountChanged if set, represent the fact that the user has changed its web3-wallet accounnt.
|
|
149
160
|
// wallet?.invalidChainId if set, represent the fact that the wallet is connected to a different chain.
|
|
@@ -152,6 +163,56 @@ export type Connection<WalletProviderType> = {
|
|
|
152
163
|
| SignedIn<WalletProviderType>
|
|
153
164
|
);
|
|
154
165
|
|
|
166
|
+
// Type for SignedIn state that was reached via wallet authentication (not popup-based auth)
|
|
167
|
+
// This variant always has wallet and WalletMechanism
|
|
168
|
+
export type SignedInWithWallet<WalletProviderType> = Extract<
|
|
169
|
+
Connection<WalletProviderType>,
|
|
170
|
+
{step: 'SignedIn'; wallet: WalletState<WalletProviderType>}
|
|
171
|
+
>;
|
|
172
|
+
|
|
173
|
+
// Full WalletConnected type from Connection
|
|
174
|
+
export type WalletConnectedState<WalletProviderType> = Extract<
|
|
175
|
+
Connection<WalletProviderType>,
|
|
176
|
+
{step: 'WalletConnected'}
|
|
177
|
+
>;
|
|
178
|
+
|
|
179
|
+
// Type representing wallet-connected states (both WalletConnected and SignedIn-via-wallet)
|
|
180
|
+
// This is what you get when targetStep is 'WalletConnected' and target is reached
|
|
181
|
+
// Both variants have WalletMechanism and wallet
|
|
182
|
+
export type ConnectedWithWallet<WalletProviderType> =
|
|
183
|
+
| WalletConnectedState<WalletProviderType>
|
|
184
|
+
| SignedInWithWallet<WalletProviderType>;
|
|
185
|
+
|
|
186
|
+
// Full SignedIn type from Connection (includes both popup-based and wallet-based variants)
|
|
187
|
+
export type SignedInState<WalletProviderType> = Extract<Connection<WalletProviderType>, {step: 'SignedIn'}>;
|
|
188
|
+
|
|
189
|
+
// Type guard - narrows Connection based on targetStep and walletOnly
|
|
190
|
+
// For 'WalletConnected' target: narrows to ConnectedWithWallet (WalletConnected | SignedIn-with-wallet)
|
|
191
|
+
// For 'SignedIn' target with walletOnly: narrows to SignedInWithWallet
|
|
192
|
+
// For 'SignedIn' target (default): narrows to SignedIn
|
|
193
|
+
export function isTargetStepReached<WalletProviderType, Target extends TargetStep, WalletOnly extends boolean = false>(
|
|
194
|
+
connection: Connection<WalletProviderType>,
|
|
195
|
+
targetStep: Target,
|
|
196
|
+
walletOnly?: WalletOnly,
|
|
197
|
+
): connection is Target extends 'WalletConnected'
|
|
198
|
+
? ConnectedWithWallet<WalletProviderType>
|
|
199
|
+
: WalletOnly extends true
|
|
200
|
+
? SignedInWithWallet<WalletProviderType>
|
|
201
|
+
: SignedInState<WalletProviderType> {
|
|
202
|
+
if (targetStep === 'WalletConnected') {
|
|
203
|
+
// For WalletConnected target, accept WalletConnected OR SignedIn-with-wallet
|
|
204
|
+
return connection.step === 'WalletConnected' || (connection.step === 'SignedIn' && connection.wallet !== undefined);
|
|
205
|
+
}
|
|
206
|
+
// For SignedIn target (regardless of walletOnly), only accept SignedIn
|
|
207
|
+
// walletOnly affects the return type narrowing, not the step check
|
|
208
|
+
if (walletOnly) {
|
|
209
|
+
// For SignedIn + walletOnly, only accept SignedIn-with-wallet
|
|
210
|
+
return connection.step === 'SignedIn' && connection.wallet !== undefined;
|
|
211
|
+
}
|
|
212
|
+
// For SignedIn target, accept any SignedIn variant
|
|
213
|
+
return connection.step === 'SignedIn';
|
|
214
|
+
}
|
|
215
|
+
|
|
155
216
|
function viemChainInfoToSwitchChainInfo(chainInfo: BasicChainInfo): {
|
|
156
217
|
chainId: `0x${string}`;
|
|
157
218
|
readonly rpcUrls?: readonly string[];
|
|
@@ -176,15 +237,25 @@ function viemChainInfoToSwitchChainInfo(chainInfo: BasicChainInfo): {
|
|
|
176
237
|
const storageKeyAccount = '__origin_account';
|
|
177
238
|
const storageKeyLastWallet = '__last_wallet';
|
|
178
239
|
|
|
179
|
-
export type
|
|
240
|
+
export type ConnectionOptions = {
|
|
241
|
+
requireUserConfirmationBeforeSignatureRequest?: boolean;
|
|
242
|
+
doNotStoreLocally?: boolean;
|
|
243
|
+
requestSignatureRightAway?: boolean;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
export type ConnectionStore<
|
|
247
|
+
WalletProviderType,
|
|
248
|
+
Target extends TargetStep = 'SignedIn',
|
|
249
|
+
WalletOnly extends boolean = false,
|
|
250
|
+
> = {
|
|
180
251
|
subscribe: (run: (value: Connection<WalletProviderType>) => void) => () => void;
|
|
181
252
|
connect: (
|
|
182
|
-
mechanism?:
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
253
|
+
mechanism?: Target extends 'WalletConnected'
|
|
254
|
+
? WalletMechanism<string | undefined, `0x${string}` | undefined>
|
|
255
|
+
: WalletOnly extends true
|
|
256
|
+
? WalletMechanism<string | undefined, `0x${string}` | undefined>
|
|
257
|
+
: Mechanism,
|
|
258
|
+
options?: ConnectionOptions,
|
|
188
259
|
) => Promise<void>;
|
|
189
260
|
cancel: () => void;
|
|
190
261
|
back: (step: 'MechanismToChoose' | 'Idle' | 'WalletToChoose') => void;
|
|
@@ -197,101 +268,187 @@ export type ConnectionStore<WalletProviderType> = {
|
|
|
197
268
|
getSignatureForPublicKeyPublication: () => Promise<`0x${string}`>;
|
|
198
269
|
switchWalletChain: (chainInfo?: BasicChainInfo) => Promise<void>;
|
|
199
270
|
unlock: () => Promise<void>;
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
271
|
+
|
|
272
|
+
// ensureConnected signature depends on target and walletOnly
|
|
273
|
+
ensureConnected: Target extends 'WalletConnected'
|
|
274
|
+
? {
|
|
275
|
+
(options?: ConnectionOptions): Promise<WalletConnected<WalletProviderType>>;
|
|
276
|
+
(
|
|
277
|
+
step: 'WalletConnected',
|
|
278
|
+
mechanism?: WalletMechanism<string | undefined, `0x${string}` | undefined>,
|
|
279
|
+
options?: ConnectionOptions,
|
|
280
|
+
): Promise<WalletConnected<WalletProviderType>>;
|
|
281
|
+
}
|
|
282
|
+
: WalletOnly extends true
|
|
283
|
+
? {
|
|
284
|
+
// walletOnly: true for SignedIn - returns SignedInWithWallet (not full SignedIn union)
|
|
285
|
+
(options?: ConnectionOptions): Promise<SignedInWithWallet<WalletProviderType>>;
|
|
286
|
+
(
|
|
287
|
+
step: 'WalletConnected',
|
|
288
|
+
mechanism?: WalletMechanism<string | undefined, `0x${string}` | undefined>,
|
|
289
|
+
options?: ConnectionOptions,
|
|
290
|
+
): Promise<WalletConnected<WalletProviderType>>;
|
|
291
|
+
(
|
|
292
|
+
step: 'SignedIn',
|
|
293
|
+
mechanism?: WalletMechanism<string | undefined, `0x${string}` | undefined>,
|
|
294
|
+
options?: ConnectionOptions,
|
|
295
|
+
): Promise<SignedInWithWallet<WalletProviderType>>;
|
|
296
|
+
}
|
|
297
|
+
: {
|
|
298
|
+
(options?: ConnectionOptions): Promise<SignedIn<WalletProviderType>>;
|
|
299
|
+
(
|
|
300
|
+
step: 'WalletConnected',
|
|
301
|
+
mechanism?: WalletMechanism<string | undefined, `0x${string}` | undefined>,
|
|
302
|
+
options?: ConnectionOptions,
|
|
303
|
+
): Promise<WalletConnected<WalletProviderType>>;
|
|
304
|
+
(step: 'SignedIn', mechanism?: Mechanism, options?: ConnectionOptions): Promise<SignedIn<WalletProviderType>>;
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// Method to check if target step is reached with proper type narrowing
|
|
308
|
+
isTargetStepReached: (
|
|
309
|
+
connection: Connection<WalletProviderType>,
|
|
310
|
+
) => connection is Target extends 'WalletConnected'
|
|
311
|
+
? ConnectedWithWallet<WalletProviderType>
|
|
312
|
+
: WalletOnly extends true
|
|
313
|
+
? SignedInWithWallet<WalletProviderType>
|
|
314
|
+
: SignedInState<WalletProviderType>;
|
|
315
|
+
|
|
316
|
+
// New properties
|
|
317
|
+
targetStep: Target;
|
|
318
|
+
walletOnly: WalletOnly;
|
|
319
|
+
|
|
320
|
+
// Existing properties
|
|
228
321
|
provider: WalletProviderType;
|
|
229
322
|
chainId: string;
|
|
230
|
-
chainInfo: ChainInfo
|
|
323
|
+
chainInfo: ChainInfo<WalletProviderType>;
|
|
231
324
|
};
|
|
232
325
|
|
|
233
326
|
// Function overloads for proper typing
|
|
327
|
+
|
|
328
|
+
// WalletConnected target with custom wallet connector - walletHost optional
|
|
234
329
|
export function createConnection<WalletProviderType>(settings: {
|
|
235
|
-
|
|
236
|
-
walletHost
|
|
330
|
+
targetStep: 'WalletConnected';
|
|
331
|
+
walletHost?: string;
|
|
332
|
+
chainInfo: ChainInfo<WalletProviderType>;
|
|
333
|
+
walletConnector: WalletConnector<WalletProviderType>;
|
|
334
|
+
autoConnect?: boolean;
|
|
335
|
+
alwaysUseCurrentAccount?: boolean;
|
|
336
|
+
prioritizeWalletProvider?: boolean;
|
|
337
|
+
requestsPerSecond?: number;
|
|
338
|
+
}): ConnectionStore<WalletProviderType, 'WalletConnected'>;
|
|
339
|
+
|
|
340
|
+
// WalletConnected target with default Ethereum connector - walletHost optional
|
|
341
|
+
export function createConnection(settings: {
|
|
342
|
+
targetStep: 'WalletConnected';
|
|
343
|
+
walletHost?: string;
|
|
344
|
+
chainInfo: ChainInfo<UnderlyingEthereumProvider>;
|
|
345
|
+
walletConnector?: undefined;
|
|
237
346
|
autoConnect?: boolean;
|
|
238
|
-
|
|
347
|
+
alwaysUseCurrentAccount?: boolean;
|
|
348
|
+
prioritizeWalletProvider?: boolean;
|
|
349
|
+
requestsPerSecond?: number;
|
|
350
|
+
}): ConnectionStore<UnderlyingEthereumProvider, 'WalletConnected', true>;
|
|
351
|
+
|
|
352
|
+
// SignedIn target with walletOnly: true (custom wallet connector) - walletHost optional
|
|
353
|
+
export function createConnection<WalletProviderType>(settings: {
|
|
354
|
+
targetStep?: 'SignedIn';
|
|
355
|
+
walletOnly: true;
|
|
356
|
+
walletHost?: string;
|
|
357
|
+
chainInfo: ChainInfo<WalletProviderType>;
|
|
239
358
|
walletConnector: WalletConnector<WalletProviderType>;
|
|
359
|
+
signingOrigin?: string;
|
|
360
|
+
autoConnect?: boolean;
|
|
240
361
|
requestSignatureAutomaticallyIfPossible?: boolean;
|
|
241
362
|
alwaysUseCurrentAccount?: boolean;
|
|
242
|
-
chainInfo: ChainInfo;
|
|
243
363
|
prioritizeWalletProvider?: boolean;
|
|
244
364
|
requestsPerSecond?: number;
|
|
245
|
-
}): ConnectionStore<WalletProviderType>;
|
|
365
|
+
}): ConnectionStore<WalletProviderType, 'SignedIn', true>;
|
|
246
366
|
|
|
367
|
+
// SignedIn target with walletOnly: true (default Ethereum connector) - walletHost optional
|
|
247
368
|
export function createConnection(settings: {
|
|
369
|
+
targetStep?: 'SignedIn';
|
|
370
|
+
walletOnly: true;
|
|
371
|
+
walletHost?: string;
|
|
372
|
+
chainInfo: ChainInfo<UnderlyingEthereumProvider>;
|
|
373
|
+
walletConnector?: undefined;
|
|
248
374
|
signingOrigin?: string;
|
|
375
|
+
autoConnect?: boolean;
|
|
376
|
+
requestSignatureAutomaticallyIfPossible?: boolean;
|
|
377
|
+
alwaysUseCurrentAccount?: boolean;
|
|
378
|
+
prioritizeWalletProvider?: boolean;
|
|
379
|
+
requestsPerSecond?: number;
|
|
380
|
+
}): ConnectionStore<UnderlyingEthereumProvider, 'SignedIn', true>;
|
|
381
|
+
|
|
382
|
+
// SignedIn target (explicit) with custom wallet connector - walletHost required
|
|
383
|
+
export function createConnection<WalletProviderType>(settings: {
|
|
384
|
+
targetStep?: 'SignedIn';
|
|
385
|
+
walletOnly?: false;
|
|
249
386
|
walletHost: string;
|
|
387
|
+
chainInfo: ChainInfo<WalletProviderType>;
|
|
388
|
+
walletConnector: WalletConnector<WalletProviderType>;
|
|
389
|
+
signingOrigin?: string;
|
|
250
390
|
autoConnect?: boolean;
|
|
251
|
-
|
|
391
|
+
requestSignatureAutomaticallyIfPossible?: boolean;
|
|
392
|
+
alwaysUseCurrentAccount?: boolean;
|
|
393
|
+
prioritizeWalletProvider?: boolean;
|
|
394
|
+
requestsPerSecond?: number;
|
|
395
|
+
}): ConnectionStore<WalletProviderType, 'SignedIn', false>;
|
|
396
|
+
|
|
397
|
+
// SignedIn target (default) with default Ethereum connector - walletHost required
|
|
398
|
+
export function createConnection(settings: {
|
|
399
|
+
targetStep?: 'SignedIn';
|
|
400
|
+
walletOnly?: false;
|
|
401
|
+
walletHost: string;
|
|
402
|
+
chainInfo: ChainInfo<UnderlyingEthereumProvider>;
|
|
252
403
|
walletConnector?: undefined;
|
|
404
|
+
signingOrigin?: string;
|
|
405
|
+
autoConnect?: boolean;
|
|
253
406
|
requestSignatureAutomaticallyIfPossible?: boolean;
|
|
254
407
|
alwaysUseCurrentAccount?: boolean;
|
|
255
|
-
chainInfo: ChainInfo;
|
|
256
408
|
prioritizeWalletProvider?: boolean;
|
|
257
409
|
requestsPerSecond?: number;
|
|
258
|
-
}): ConnectionStore<UnderlyingEthereumProvider>;
|
|
410
|
+
}): ConnectionStore<UnderlyingEthereumProvider, 'SignedIn', false>;
|
|
259
411
|
|
|
412
|
+
// Implementation signature
|
|
260
413
|
export function createConnection<WalletProviderType = UnderlyingEthereumProvider>(settings: {
|
|
414
|
+
targetStep?: TargetStep;
|
|
415
|
+
walletOnly?: boolean;
|
|
261
416
|
signingOrigin?: string;
|
|
262
|
-
walletHost
|
|
417
|
+
walletHost?: string;
|
|
263
418
|
autoConnect?: boolean;
|
|
264
|
-
autoConnectWallet?: boolean;
|
|
265
419
|
walletConnector?: WalletConnector<WalletProviderType>;
|
|
266
420
|
requestSignatureAutomaticallyIfPossible?: boolean;
|
|
267
421
|
alwaysUseCurrentAccount?: boolean;
|
|
268
|
-
chainInfo: ChainInfo
|
|
422
|
+
chainInfo: ChainInfo<WalletProviderType>;
|
|
269
423
|
prioritizeWalletProvider?: boolean;
|
|
270
424
|
requestsPerSecond?: number;
|
|
271
|
-
}) {
|
|
425
|
+
}): ConnectionStore<WalletProviderType, TargetStep, boolean> {
|
|
272
426
|
function originToSignWith() {
|
|
273
427
|
return settings.signingOrigin || origin;
|
|
274
428
|
}
|
|
275
429
|
|
|
276
|
-
const endpoint = settings.chainInfo.rpcUrls.default.http[0];
|
|
277
430
|
const walletConnector =
|
|
278
431
|
settings.walletConnector || (new EthereumWalletConnector() as unknown as WalletConnector<WalletProviderType>);
|
|
279
432
|
const alwaysOnChainId = '' + settings.chainInfo.id;
|
|
280
433
|
const alwaysOnProviderWrapper = walletConnector.createAlwaysOnProvider({
|
|
281
|
-
endpoint
|
|
434
|
+
endpoint:
|
|
435
|
+
'provider' in settings.chainInfo ? settings.chainInfo.provider : settings.chainInfo.rpcUrls.default.http[0],
|
|
282
436
|
chainId: '' + settings.chainInfo.id,
|
|
283
437
|
prioritizeWalletProvider: settings.prioritizeWalletProvider,
|
|
284
438
|
requestsPerSecond: settings.requestsPerSecond,
|
|
285
439
|
});
|
|
440
|
+
// Determine target step (defaults to 'SignedIn')
|
|
441
|
+
const targetStep: TargetStep = settings.targetStep || 'SignedIn';
|
|
442
|
+
|
|
286
443
|
let autoConnect = true;
|
|
287
444
|
if (typeof settings.autoConnect !== 'undefined') {
|
|
288
445
|
autoConnect = settings.autoConnect;
|
|
289
446
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
447
|
+
|
|
448
|
+
// For SignedIn target, we can auto-request signature if configured
|
|
449
|
+
// For WalletConnected target, this is always false (we never auto-request signature)
|
|
450
|
+
const requestSignatureAutomaticallyIfPossible =
|
|
451
|
+
targetStep === 'SignedIn' ? settings.requestSignatureAutomaticallyIfPossible || false : false;
|
|
295
452
|
|
|
296
453
|
let $connection: Connection<WalletProviderType> = {step: 'Idle', loading: true, wallet: undefined, wallets: []};
|
|
297
454
|
const _store = writable<Connection<WalletProviderType>>($connection);
|
|
@@ -344,13 +501,18 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
344
501
|
});
|
|
345
502
|
}
|
|
346
503
|
|
|
504
|
+
// Auto-connect logic based on targetStep
|
|
505
|
+
// When targetStep: 'WalletConnected' - only check lastWallet
|
|
506
|
+
// When targetStep: 'SignedIn' - check originAccount first, then fallback to lastWallet
|
|
507
|
+
let autoConnectHandled = false;
|
|
347
508
|
if (autoConnect) {
|
|
348
509
|
if (typeof window !== 'undefined') {
|
|
349
|
-
// set({step: 'Idle', loading: true, wallets: $connection.wallets});
|
|
350
510
|
try {
|
|
351
|
-
|
|
352
|
-
if (
|
|
353
|
-
|
|
511
|
+
// For SignedIn target, check for existing account first
|
|
512
|
+
if (targetStep === 'SignedIn') {
|
|
513
|
+
const existingAccount = getOriginAccount();
|
|
514
|
+
if (existingAccount && existingAccount.signer) {
|
|
515
|
+
autoConnectHandled = true;
|
|
354
516
|
const mechanismUsed = existingAccount.mechanismUsed as
|
|
355
517
|
| AlchemyMechanism
|
|
356
518
|
| WalletMechanism<string, `0x${string}`>;
|
|
@@ -362,15 +524,11 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
362
524
|
const chainIdAsHex = await withTimeout(walletProvider.getChainId());
|
|
363
525
|
const chainId = Number(chainIdAsHex).toString();
|
|
364
526
|
_wallet = {provider: walletProvider, chainId};
|
|
365
|
-
// TODO
|
|
366
527
|
alwaysOnProviderWrapper.setWalletProvider(walletProvider.underlyingProvider);
|
|
367
528
|
watchForChainIdChange(_wallet.provider);
|
|
368
529
|
let accounts: `0x${string}`[] = [];
|
|
369
|
-
// try {
|
|
370
530
|
accounts = await withTimeout(walletProvider.getAccounts());
|
|
371
531
|
accounts = accounts.map((v) => v.toLowerCase() as `0x${string}`);
|
|
372
|
-
// } catch {}
|
|
373
|
-
// // TODO try catch ? and use logic of onAccountChanged
|
|
374
532
|
set({
|
|
375
533
|
step: 'SignedIn',
|
|
376
534
|
account: existingAccount,
|
|
@@ -387,7 +545,6 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
387
545
|
},
|
|
388
546
|
});
|
|
389
547
|
alwaysOnProviderWrapper.setWalletStatus('connected');
|
|
390
|
-
// TODO use the same logic before hand
|
|
391
548
|
onAccountChanged(accounts);
|
|
392
549
|
watchForAccountChange(walletProvider);
|
|
393
550
|
})
|
|
@@ -403,54 +560,46 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
403
560
|
wallet: undefined,
|
|
404
561
|
});
|
|
405
562
|
}
|
|
406
|
-
} else {
|
|
407
|
-
set({step: 'Idle', loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
408
563
|
}
|
|
409
|
-
}
|
|
410
|
-
if (autoConnectWallet) {
|
|
411
|
-
const lastWallet = getLastWallet();
|
|
412
|
-
if (lastWallet) {
|
|
413
|
-
waitForWallet(lastWallet.name)
|
|
414
|
-
.then(async (walletDetails: WalletHandle<WalletProviderType>) => {
|
|
415
|
-
const walletProvider = walletDetails.walletProvider;
|
|
416
|
-
const chainIdAsHex = await withTimeout(walletProvider.getChainId());
|
|
417
|
-
const chainId = Number(chainIdAsHex).toString();
|
|
418
|
-
_wallet = {provider: walletProvider, chainId};
|
|
419
|
-
// TODO
|
|
420
|
-
alwaysOnProviderWrapper.setWalletProvider(walletProvider.underlyingProvider);
|
|
421
|
-
watchForChainIdChange(_wallet.provider);
|
|
564
|
+
}
|
|
422
565
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
566
|
+
// For both targets, fallback to lastWallet if no account found (or WalletConnected target)
|
|
567
|
+
if (!autoConnectHandled) {
|
|
568
|
+
const lastWallet = getLastWallet();
|
|
569
|
+
if (lastWallet) {
|
|
570
|
+
waitForWallet(lastWallet.name)
|
|
571
|
+
.then(async (walletDetails: WalletHandle<WalletProviderType>) => {
|
|
572
|
+
const walletProvider = walletDetails.walletProvider;
|
|
573
|
+
const chainIdAsHex = await withTimeout(walletProvider.getChainId());
|
|
574
|
+
const chainId = Number(chainIdAsHex).toString();
|
|
575
|
+
_wallet = {provider: walletProvider, chainId};
|
|
576
|
+
alwaysOnProviderWrapper.setWalletProvider(walletProvider.underlyingProvider);
|
|
577
|
+
watchForChainIdChange(_wallet.provider);
|
|
578
|
+
|
|
579
|
+
let accounts: `0x${string}`[] = [];
|
|
580
|
+
accounts = await withTimeout(walletProvider.getAccounts());
|
|
581
|
+
accounts = accounts.map((v) => v.toLowerCase() as `0x${string}`);
|
|
582
|
+
set({
|
|
583
|
+
step: 'WalletConnected',
|
|
584
|
+
mechanism: lastWallet,
|
|
585
|
+
wallets: $connection.wallets,
|
|
586
|
+
wallet: {
|
|
587
|
+
provider: walletProvider,
|
|
588
|
+
accounts,
|
|
589
|
+
status: 'connected',
|
|
590
|
+
accountChanged: undefined,
|
|
591
|
+
chainId,
|
|
592
|
+
invalidChainId: alwaysOnChainId != chainId,
|
|
593
|
+
switchingChain: false,
|
|
594
|
+
},
|
|
450
595
|
});
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
596
|
+
alwaysOnProviderWrapper.setWalletStatus('connected');
|
|
597
|
+
onAccountChanged(accounts);
|
|
598
|
+
watchForAccountChange(walletProvider);
|
|
599
|
+
})
|
|
600
|
+
.catch((err) => {
|
|
601
|
+
set({step: 'Idle', loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
602
|
+
});
|
|
454
603
|
} else {
|
|
455
604
|
set({step: 'Idle', loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
456
605
|
}
|
|
@@ -977,6 +1126,10 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
977
1126
|
});
|
|
978
1127
|
}
|
|
979
1128
|
} else {
|
|
1129
|
+
// Popup-based auth requires walletHost
|
|
1130
|
+
if (!settings.walletHost) {
|
|
1131
|
+
throw new Error('walletHost is required for popup-based authentication (email, oauth, mnemonic)');
|
|
1132
|
+
}
|
|
980
1133
|
popup = connectViaPopup({
|
|
981
1134
|
mechanism,
|
|
982
1135
|
walletHost: settings.walletHost,
|
|
@@ -1028,6 +1181,10 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1028
1181
|
}
|
|
1029
1182
|
}
|
|
1030
1183
|
|
|
1184
|
+
// ensureConnected overloads - the default step depends on targetStep
|
|
1185
|
+
function ensureConnected(
|
|
1186
|
+
options?: ConnectionOptions,
|
|
1187
|
+
): Promise<WalletConnected<WalletProviderType> | SignedIn<WalletProviderType>>;
|
|
1031
1188
|
function ensureConnected(
|
|
1032
1189
|
step: 'WalletConnected',
|
|
1033
1190
|
mechanism?: WalletMechanism<string | undefined, `0x${string}` | undefined>,
|
|
@@ -1038,51 +1195,70 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1038
1195
|
mechanism?: Mechanism,
|
|
1039
1196
|
options?: ConnectionOptions,
|
|
1040
1197
|
): Promise<SignedIn<WalletProviderType>>;
|
|
1041
|
-
function ensureConnected
|
|
1042
|
-
|
|
1043
|
-
stepOrMechanism?: Step | Mechanism,
|
|
1198
|
+
async function ensureConnected<Step extends 'WalletConnected' | 'SignedIn'>(
|
|
1199
|
+
stepOrMechanismOrOptions?: Step | Mechanism | ConnectionOptions,
|
|
1044
1200
|
mechanismOrOptions?: Mechanism | ConnectionOptions,
|
|
1045
1201
|
options?: ConnectionOptions,
|
|
1046
|
-
) {
|
|
1047
|
-
|
|
1048
|
-
let
|
|
1202
|
+
): Promise<WalletConnected<WalletProviderType> | SignedIn<WalletProviderType>> {
|
|
1203
|
+
// Determine if first arg is a step string, mechanism, or options
|
|
1204
|
+
let step: 'WalletConnected' | 'SignedIn';
|
|
1205
|
+
let mechanism: Mechanism | undefined;
|
|
1206
|
+
let opts: ConnectionOptions | undefined;
|
|
1207
|
+
|
|
1208
|
+
if (typeof stepOrMechanismOrOptions === 'string') {
|
|
1209
|
+
// First arg is a step
|
|
1210
|
+
step = stepOrMechanismOrOptions as 'WalletConnected' | 'SignedIn';
|
|
1211
|
+
mechanism = mechanismOrOptions as Mechanism | undefined;
|
|
1212
|
+
opts = options;
|
|
1213
|
+
} else if (stepOrMechanismOrOptions && 'type' in (stepOrMechanismOrOptions as any)) {
|
|
1214
|
+
// First arg is a mechanism
|
|
1215
|
+
step = targetStep; // Use configured target as default
|
|
1216
|
+
mechanism = stepOrMechanismOrOptions as Mechanism;
|
|
1217
|
+
opts = mechanismOrOptions as ConnectionOptions | undefined;
|
|
1218
|
+
} else {
|
|
1219
|
+
// First arg is options or undefined
|
|
1220
|
+
step = targetStep; // Use configured target as default
|
|
1221
|
+
mechanism = undefined;
|
|
1222
|
+
opts = stepOrMechanismOrOptions as ConnectionOptions | undefined;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
// For WalletConnected step, default to wallet mechanism
|
|
1049
1226
|
if (!mechanism && step === 'WalletConnected') {
|
|
1050
1227
|
mechanism = {type: 'wallet'};
|
|
1051
1228
|
}
|
|
1052
|
-
|
|
1053
|
-
const promise = new Promise<
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
resolve($connection as any);
|
|
1066
|
-
return;
|
|
1067
|
-
}
|
|
1068
|
-
let idlePassed = $connection.step != 'Idle';
|
|
1069
|
-
if (!idlePassed || forceConnect) {
|
|
1070
|
-
connect(mechanism, options);
|
|
1071
|
-
}
|
|
1072
|
-
const unsubscribe = _store.subscribe((connection) => {
|
|
1073
|
-
if (connection.step === 'Idle' && idlePassed) {
|
|
1074
|
-
unsubscribe();
|
|
1075
|
-
reject();
|
|
1076
|
-
}
|
|
1077
|
-
if (!idlePassed && connection.step !== 'Idle') {
|
|
1078
|
-
idlePassed = true;
|
|
1229
|
+
|
|
1230
|
+
const promise = new Promise<WalletConnected<WalletProviderType> | SignedIn<WalletProviderType>>(
|
|
1231
|
+
(resolve, reject) => {
|
|
1232
|
+
let forceConnect = false;
|
|
1233
|
+
if (
|
|
1234
|
+
$connection.step == 'WalletConnected' &&
|
|
1235
|
+
($connection.wallet.status == 'locked' || $connection.wallet.status === 'disconnected')
|
|
1236
|
+
) {
|
|
1237
|
+
forceConnect = true;
|
|
1238
|
+
mechanism = $connection.mechanism; // we reuse existing mechanism as we just want to reconnect
|
|
1239
|
+
} else if ($connection.step == step) {
|
|
1240
|
+
resolve($connection as any);
|
|
1241
|
+
return;
|
|
1079
1242
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1243
|
+
let idlePassed = $connection.step != 'Idle';
|
|
1244
|
+
if (!idlePassed || forceConnect) {
|
|
1245
|
+
connect(mechanism, opts);
|
|
1083
1246
|
}
|
|
1084
|
-
|
|
1085
|
-
|
|
1247
|
+
const unsubscribe = _store.subscribe((connection) => {
|
|
1248
|
+
if (connection.step === 'Idle' && idlePassed) {
|
|
1249
|
+
unsubscribe();
|
|
1250
|
+
reject();
|
|
1251
|
+
}
|
|
1252
|
+
if (!idlePassed && connection.step !== 'Idle') {
|
|
1253
|
+
idlePassed = true;
|
|
1254
|
+
}
|
|
1255
|
+
if (connection.step === step) {
|
|
1256
|
+
unsubscribe();
|
|
1257
|
+
resolve(connection as any);
|
|
1258
|
+
}
|
|
1259
|
+
});
|
|
1260
|
+
},
|
|
1261
|
+
);
|
|
1086
1262
|
|
|
1087
1263
|
return promise;
|
|
1088
1264
|
}
|
|
@@ -1386,7 +1562,27 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1386
1562
|
}
|
|
1387
1563
|
}
|
|
1388
1564
|
|
|
1389
|
-
|
|
1565
|
+
// Determine walletOnly (defaults to false, but true implies WalletConnected target behavior for mechanism)
|
|
1566
|
+
const walletOnly = settings.walletOnly || targetStep === 'WalletConnected';
|
|
1567
|
+
|
|
1568
|
+
// Method on the store to check if target step is reached
|
|
1569
|
+
function storeIsTargetStepReached(connection: Connection<WalletProviderType>): boolean {
|
|
1570
|
+
if (targetStep === 'WalletConnected') {
|
|
1571
|
+
// For WalletConnected target, accept WalletConnected OR SignedIn-with-wallet
|
|
1572
|
+
return (
|
|
1573
|
+
connection.step === 'WalletConnected' || (connection.step === 'SignedIn' && connection.wallet !== undefined)
|
|
1574
|
+
);
|
|
1575
|
+
}
|
|
1576
|
+
// For SignedIn target
|
|
1577
|
+
if (walletOnly) {
|
|
1578
|
+
// With walletOnly, only accept SignedIn-with-wallet
|
|
1579
|
+
return connection.step === 'SignedIn' && connection.wallet !== undefined;
|
|
1580
|
+
}
|
|
1581
|
+
// Accept any SignedIn variant
|
|
1582
|
+
return connection.step === 'SignedIn';
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
const store = {
|
|
1390
1586
|
subscribe: _store.subscribe,
|
|
1391
1587
|
connect,
|
|
1392
1588
|
cancel,
|
|
@@ -1397,9 +1593,14 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1397
1593
|
getSignatureForPublicKeyPublication,
|
|
1398
1594
|
switchWalletChain,
|
|
1399
1595
|
unlock,
|
|
1400
|
-
ensureConnected,
|
|
1596
|
+
ensureConnected: ensureConnected as any, // Cast to bypass complex conditional typing
|
|
1597
|
+
isTargetStepReached: storeIsTargetStepReached as any, // Cast for type guard
|
|
1598
|
+
targetStep,
|
|
1599
|
+
walletOnly,
|
|
1401
1600
|
provider: alwaysOnProviderWrapper.provider,
|
|
1402
1601
|
chainId: '' + settings.chainInfo.id,
|
|
1403
1602
|
chainInfo: settings.chainInfo,
|
|
1404
1603
|
};
|
|
1604
|
+
|
|
1605
|
+
return store as ConnectionStore<WalletProviderType, TargetStep, boolean>;
|
|
1405
1606
|
}
|