@etherplay/connect 0.0.35 → 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 +96 -35
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +118 -68
- package/dist/index.js.map +1 -1
- package/package.json +31 -4
- package/src/index.ts +346 -152
package/src/index.ts
CHANGED
|
@@ -68,6 +68,8 @@ export type Mechanism = AlchemyMechanism | WalletMechanism<string | undefined, `
|
|
|
68
68
|
|
|
69
69
|
export type FullfilledMechanism = AlchemyMechanism | WalletMechanism<string, `0x${string}`>;
|
|
70
70
|
|
|
71
|
+
export type TargetStep = 'WalletConnected' | 'SignedIn';
|
|
72
|
+
|
|
71
73
|
export type WalletState<WalletProviderType> = {
|
|
72
74
|
provider: WalletProvider<WalletProviderType>;
|
|
73
75
|
accounts: `0x${string}`[];
|
|
@@ -77,12 +79,18 @@ export type WalletState<WalletProviderType> = {
|
|
|
77
79
|
switchingChain: 'addingChain' | 'switchingChain' | false;
|
|
78
80
|
} & ({status: 'connected'} | {status: 'locked'; unlocking: boolean} | {status: 'disconnected'; connecting: boolean});
|
|
79
81
|
|
|
80
|
-
type
|
|
82
|
+
type WaitingForSignature<WalletProviderType> = {
|
|
81
83
|
step: 'WaitingForSignature';
|
|
82
84
|
mechanism: WalletMechanism<string, `0x${string}`>;
|
|
83
85
|
wallet: WalletState<WalletProviderType>;
|
|
84
86
|
};
|
|
85
87
|
|
|
88
|
+
type WalletConnected<WalletProviderType> = {
|
|
89
|
+
step: 'WalletConnected';
|
|
90
|
+
mechanism: WalletMechanism<string, `0x${string}`>;
|
|
91
|
+
wallet: WalletState<WalletProviderType>;
|
|
92
|
+
};
|
|
93
|
+
|
|
86
94
|
type SignedIn<WalletProviderType> =
|
|
87
95
|
| {
|
|
88
96
|
step: 'SignedIn';
|
|
@@ -144,13 +152,9 @@ export type Connection<WalletProviderType> = {
|
|
|
144
152
|
}
|
|
145
153
|
// Once the wallet is connected, the system will need a signature
|
|
146
154
|
// this state represent the fact and require another user interaction to request the signature
|
|
147
|
-
| {
|
|
148
|
-
step: 'WalletConnected';
|
|
149
|
-
mechanism: WalletMechanism<string, `0x${string}`>;
|
|
150
|
-
wallet: WalletState<WalletProviderType>;
|
|
151
|
-
}
|
|
152
|
-
// This state is triggered once the signature is requested, the user will have to confirm with its wallet
|
|
153
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>
|
|
154
158
|
// Finally the user is fully signed in
|
|
155
159
|
// wallet?.accountChanged if set, represent the fact that the user has changed its web3-wallet accounnt.
|
|
156
160
|
// wallet?.invalidChainId if set, represent the fact that the wallet is connected to a different chain.
|
|
@@ -159,6 +163,56 @@ export type Connection<WalletProviderType> = {
|
|
|
159
163
|
| SignedIn<WalletProviderType>
|
|
160
164
|
);
|
|
161
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
|
+
|
|
162
216
|
function viemChainInfoToSwitchChainInfo(chainInfo: BasicChainInfo): {
|
|
163
217
|
chainId: `0x${string}`;
|
|
164
218
|
readonly rpcUrls?: readonly string[];
|
|
@@ -183,15 +237,25 @@ function viemChainInfoToSwitchChainInfo(chainInfo: BasicChainInfo): {
|
|
|
183
237
|
const storageKeyAccount = '__origin_account';
|
|
184
238
|
const storageKeyLastWallet = '__last_wallet';
|
|
185
239
|
|
|
186
|
-
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
|
+
> = {
|
|
187
251
|
subscribe: (run: (value: Connection<WalletProviderType>) => void) => () => void;
|
|
188
252
|
connect: (
|
|
189
|
-
mechanism?:
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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,
|
|
195
259
|
) => Promise<void>;
|
|
196
260
|
cancel: () => void;
|
|
197
261
|
back: (step: 'MechanismToChoose' | 'Idle' | 'WalletToChoose') => void;
|
|
@@ -204,78 +268,161 @@ export type ConnectionStore<WalletProviderType> = {
|
|
|
204
268
|
getSignatureForPublicKeyPublication: () => Promise<`0x${string}`>;
|
|
205
269
|
switchWalletChain: (chainInfo?: BasicChainInfo) => Promise<void>;
|
|
206
270
|
unlock: () => Promise<void>;
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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
|
|
235
321
|
provider: WalletProviderType;
|
|
236
322
|
chainId: string;
|
|
237
323
|
chainInfo: ChainInfo<WalletProviderType>;
|
|
238
324
|
};
|
|
239
325
|
|
|
240
326
|
// Function overloads for proper typing
|
|
327
|
+
|
|
328
|
+
// WalletConnected target with custom wallet connector - walletHost optional
|
|
241
329
|
export function createConnection<WalletProviderType>(settings: {
|
|
242
|
-
|
|
243
|
-
walletHost
|
|
330
|
+
targetStep: 'WalletConnected';
|
|
331
|
+
walletHost?: string;
|
|
332
|
+
chainInfo: ChainInfo<WalletProviderType>;
|
|
333
|
+
walletConnector: WalletConnector<WalletProviderType>;
|
|
244
334
|
autoConnect?: boolean;
|
|
245
|
-
|
|
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;
|
|
346
|
+
autoConnect?: boolean;
|
|
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>;
|
|
246
358
|
walletConnector: WalletConnector<WalletProviderType>;
|
|
359
|
+
signingOrigin?: string;
|
|
360
|
+
autoConnect?: boolean;
|
|
247
361
|
requestSignatureAutomaticallyIfPossible?: boolean;
|
|
248
362
|
alwaysUseCurrentAccount?: boolean;
|
|
249
|
-
chainInfo: ChainInfo<WalletProviderType>;
|
|
250
363
|
prioritizeWalletProvider?: boolean;
|
|
251
364
|
requestsPerSecond?: number;
|
|
252
|
-
}): ConnectionStore<WalletProviderType>;
|
|
365
|
+
}): ConnectionStore<WalletProviderType, 'SignedIn', true>;
|
|
253
366
|
|
|
367
|
+
// SignedIn target with walletOnly: true (default Ethereum connector) - walletHost optional
|
|
254
368
|
export function createConnection(settings: {
|
|
369
|
+
targetStep?: 'SignedIn';
|
|
370
|
+
walletOnly: true;
|
|
371
|
+
walletHost?: string;
|
|
372
|
+
chainInfo: ChainInfo<UnderlyingEthereumProvider>;
|
|
373
|
+
walletConnector?: undefined;
|
|
255
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;
|
|
256
386
|
walletHost: string;
|
|
387
|
+
chainInfo: ChainInfo<WalletProviderType>;
|
|
388
|
+
walletConnector: WalletConnector<WalletProviderType>;
|
|
389
|
+
signingOrigin?: string;
|
|
257
390
|
autoConnect?: boolean;
|
|
258
|
-
autoConnectWallet?: boolean;
|
|
259
|
-
walletConnector?: undefined;
|
|
260
391
|
requestSignatureAutomaticallyIfPossible?: boolean;
|
|
261
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;
|
|
262
402
|
chainInfo: ChainInfo<UnderlyingEthereumProvider>;
|
|
403
|
+
walletConnector?: undefined;
|
|
404
|
+
signingOrigin?: string;
|
|
405
|
+
autoConnect?: boolean;
|
|
406
|
+
requestSignatureAutomaticallyIfPossible?: boolean;
|
|
407
|
+
alwaysUseCurrentAccount?: boolean;
|
|
263
408
|
prioritizeWalletProvider?: boolean;
|
|
264
409
|
requestsPerSecond?: number;
|
|
265
|
-
}): ConnectionStore<UnderlyingEthereumProvider>;
|
|
410
|
+
}): ConnectionStore<UnderlyingEthereumProvider, 'SignedIn', false>;
|
|
266
411
|
|
|
412
|
+
// Implementation signature
|
|
267
413
|
export function createConnection<WalletProviderType = UnderlyingEthereumProvider>(settings: {
|
|
414
|
+
targetStep?: TargetStep;
|
|
415
|
+
walletOnly?: boolean;
|
|
268
416
|
signingOrigin?: string;
|
|
269
|
-
walletHost
|
|
417
|
+
walletHost?: string;
|
|
270
418
|
autoConnect?: boolean;
|
|
271
|
-
autoConnectWallet?: boolean;
|
|
272
419
|
walletConnector?: WalletConnector<WalletProviderType>;
|
|
273
420
|
requestSignatureAutomaticallyIfPossible?: boolean;
|
|
274
421
|
alwaysUseCurrentAccount?: boolean;
|
|
275
422
|
chainInfo: ChainInfo<WalletProviderType>;
|
|
276
423
|
prioritizeWalletProvider?: boolean;
|
|
277
424
|
requestsPerSecond?: number;
|
|
278
|
-
}) {
|
|
425
|
+
}): ConnectionStore<WalletProviderType, TargetStep, boolean> {
|
|
279
426
|
function originToSignWith() {
|
|
280
427
|
return settings.signingOrigin || origin;
|
|
281
428
|
}
|
|
@@ -290,15 +437,18 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
290
437
|
prioritizeWalletProvider: settings.prioritizeWalletProvider,
|
|
291
438
|
requestsPerSecond: settings.requestsPerSecond,
|
|
292
439
|
});
|
|
440
|
+
// Determine target step (defaults to 'SignedIn')
|
|
441
|
+
const targetStep: TargetStep = settings.targetStep || 'SignedIn';
|
|
442
|
+
|
|
293
443
|
let autoConnect = true;
|
|
294
444
|
if (typeof settings.autoConnect !== 'undefined') {
|
|
295
445
|
autoConnect = settings.autoConnect;
|
|
296
446
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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;
|
|
302
452
|
|
|
303
453
|
let $connection: Connection<WalletProviderType> = {step: 'Idle', loading: true, wallet: undefined, wallets: []};
|
|
304
454
|
const _store = writable<Connection<WalletProviderType>>($connection);
|
|
@@ -351,13 +501,18 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
351
501
|
});
|
|
352
502
|
}
|
|
353
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;
|
|
354
508
|
if (autoConnect) {
|
|
355
509
|
if (typeof window !== 'undefined') {
|
|
356
|
-
// set({step: 'Idle', loading: true, wallets: $connection.wallets});
|
|
357
510
|
try {
|
|
358
|
-
|
|
359
|
-
if (
|
|
360
|
-
|
|
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;
|
|
361
516
|
const mechanismUsed = existingAccount.mechanismUsed as
|
|
362
517
|
| AlchemyMechanism
|
|
363
518
|
| WalletMechanism<string, `0x${string}`>;
|
|
@@ -369,15 +524,11 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
369
524
|
const chainIdAsHex = await withTimeout(walletProvider.getChainId());
|
|
370
525
|
const chainId = Number(chainIdAsHex).toString();
|
|
371
526
|
_wallet = {provider: walletProvider, chainId};
|
|
372
|
-
// TODO
|
|
373
527
|
alwaysOnProviderWrapper.setWalletProvider(walletProvider.underlyingProvider);
|
|
374
528
|
watchForChainIdChange(_wallet.provider);
|
|
375
529
|
let accounts: `0x${string}`[] = [];
|
|
376
|
-
// try {
|
|
377
530
|
accounts = await withTimeout(walletProvider.getAccounts());
|
|
378
531
|
accounts = accounts.map((v) => v.toLowerCase() as `0x${string}`);
|
|
379
|
-
// } catch {}
|
|
380
|
-
// // TODO try catch ? and use logic of onAccountChanged
|
|
381
532
|
set({
|
|
382
533
|
step: 'SignedIn',
|
|
383
534
|
account: existingAccount,
|
|
@@ -394,7 +545,6 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
394
545
|
},
|
|
395
546
|
});
|
|
396
547
|
alwaysOnProviderWrapper.setWalletStatus('connected');
|
|
397
|
-
// TODO use the same logic before hand
|
|
398
548
|
onAccountChanged(accounts);
|
|
399
549
|
watchForAccountChange(walletProvider);
|
|
400
550
|
})
|
|
@@ -410,54 +560,46 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
410
560
|
wallet: undefined,
|
|
411
561
|
});
|
|
412
562
|
}
|
|
413
|
-
} else {
|
|
414
|
-
set({step: 'Idle', loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
415
563
|
}
|
|
416
|
-
}
|
|
417
|
-
if (autoConnectWallet) {
|
|
418
|
-
const lastWallet = getLastWallet();
|
|
419
|
-
if (lastWallet) {
|
|
420
|
-
waitForWallet(lastWallet.name)
|
|
421
|
-
.then(async (walletDetails: WalletHandle<WalletProviderType>) => {
|
|
422
|
-
const walletProvider = walletDetails.walletProvider;
|
|
423
|
-
const chainIdAsHex = await withTimeout(walletProvider.getChainId());
|
|
424
|
-
const chainId = Number(chainIdAsHex).toString();
|
|
425
|
-
_wallet = {provider: walletProvider, chainId};
|
|
426
|
-
// TODO
|
|
427
|
-
alwaysOnProviderWrapper.setWalletProvider(walletProvider.underlyingProvider);
|
|
428
|
-
watchForChainIdChange(_wallet.provider);
|
|
564
|
+
}
|
|
429
565
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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
|
+
},
|
|
457
595
|
});
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
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
|
+
});
|
|
461
603
|
} else {
|
|
462
604
|
set({step: 'Idle', loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
463
605
|
}
|
|
@@ -984,6 +1126,10 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
984
1126
|
});
|
|
985
1127
|
}
|
|
986
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
|
+
}
|
|
987
1133
|
popup = connectViaPopup({
|
|
988
1134
|
mechanism,
|
|
989
1135
|
walletHost: settings.walletHost,
|
|
@@ -1035,6 +1181,10 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1035
1181
|
}
|
|
1036
1182
|
}
|
|
1037
1183
|
|
|
1184
|
+
// ensureConnected overloads - the default step depends on targetStep
|
|
1185
|
+
function ensureConnected(
|
|
1186
|
+
options?: ConnectionOptions,
|
|
1187
|
+
): Promise<WalletConnected<WalletProviderType> | SignedIn<WalletProviderType>>;
|
|
1038
1188
|
function ensureConnected(
|
|
1039
1189
|
step: 'WalletConnected',
|
|
1040
1190
|
mechanism?: WalletMechanism<string | undefined, `0x${string}` | undefined>,
|
|
@@ -1045,51 +1195,70 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1045
1195
|
mechanism?: Mechanism,
|
|
1046
1196
|
options?: ConnectionOptions,
|
|
1047
1197
|
): Promise<SignedIn<WalletProviderType>>;
|
|
1048
|
-
function ensureConnected
|
|
1049
|
-
|
|
1050
|
-
stepOrMechanism?: Step | Mechanism,
|
|
1198
|
+
async function ensureConnected<Step extends 'WalletConnected' | 'SignedIn'>(
|
|
1199
|
+
stepOrMechanismOrOptions?: Step | Mechanism | ConnectionOptions,
|
|
1051
1200
|
mechanismOrOptions?: Mechanism | ConnectionOptions,
|
|
1052
1201
|
options?: ConnectionOptions,
|
|
1053
|
-
) {
|
|
1054
|
-
|
|
1055
|
-
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
|
|
1056
1226
|
if (!mechanism && step === 'WalletConnected') {
|
|
1057
1227
|
mechanism = {type: 'wallet'};
|
|
1058
1228
|
}
|
|
1059
|
-
|
|
1060
|
-
const promise = new Promise<
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
resolve($connection as any);
|
|
1073
|
-
return;
|
|
1074
|
-
}
|
|
1075
|
-
let idlePassed = $connection.step != 'Idle';
|
|
1076
|
-
if (!idlePassed || forceConnect) {
|
|
1077
|
-
connect(mechanism, options);
|
|
1078
|
-
}
|
|
1079
|
-
const unsubscribe = _store.subscribe((connection) => {
|
|
1080
|
-
if (connection.step === 'Idle' && idlePassed) {
|
|
1081
|
-
unsubscribe();
|
|
1082
|
-
reject();
|
|
1083
|
-
}
|
|
1084
|
-
if (!idlePassed && connection.step !== 'Idle') {
|
|
1085
|
-
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;
|
|
1086
1242
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1243
|
+
let idlePassed = $connection.step != 'Idle';
|
|
1244
|
+
if (!idlePassed || forceConnect) {
|
|
1245
|
+
connect(mechanism, opts);
|
|
1090
1246
|
}
|
|
1091
|
-
|
|
1092
|
-
|
|
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
|
+
);
|
|
1093
1262
|
|
|
1094
1263
|
return promise;
|
|
1095
1264
|
}
|
|
@@ -1393,7 +1562,27 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1393
1562
|
}
|
|
1394
1563
|
}
|
|
1395
1564
|
|
|
1396
|
-
|
|
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 = {
|
|
1397
1586
|
subscribe: _store.subscribe,
|
|
1398
1587
|
connect,
|
|
1399
1588
|
cancel,
|
|
@@ -1404,9 +1593,14 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1404
1593
|
getSignatureForPublicKeyPublication,
|
|
1405
1594
|
switchWalletChain,
|
|
1406
1595
|
unlock,
|
|
1407
|
-
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,
|
|
1408
1600
|
provider: alwaysOnProviderWrapper.provider,
|
|
1409
1601
|
chainId: '' + settings.chainInfo.id,
|
|
1410
1602
|
chainInfo: settings.chainInfo,
|
|
1411
1603
|
};
|
|
1604
|
+
|
|
1605
|
+
return store as ConnectionStore<WalletProviderType, TargetStep, boolean>;
|
|
1412
1606
|
}
|