@etherplay/connect 0.0.35 → 0.0.37
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 +121 -68
- package/dist/index.js.map +1 -1
- package/package.json +31 -4
- package/src/index.ts +349 -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>;
|
|
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;
|
|
244
346
|
autoConnect?: boolean;
|
|
245
|
-
|
|
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
|
}
|
|
@@ -761,6 +903,9 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
761
903
|
|
|
762
904
|
let remember: boolean = false;
|
|
763
905
|
async function connect(mechanism?: Mechanism, options?: ConnectionOptions) {
|
|
906
|
+
if (!mechanism && (targetStep === 'WalletConnected' || walletOnly)) {
|
|
907
|
+
mechanism = {type: 'wallet'};
|
|
908
|
+
}
|
|
764
909
|
remember = !(options?.doNotStoreLocally || false);
|
|
765
910
|
if (mechanism) {
|
|
766
911
|
if (mechanism.type === 'wallet') {
|
|
@@ -984,6 +1129,10 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
984
1129
|
});
|
|
985
1130
|
}
|
|
986
1131
|
} else {
|
|
1132
|
+
// Popup-based auth requires walletHost
|
|
1133
|
+
if (!settings.walletHost) {
|
|
1134
|
+
throw new Error('walletHost is required for popup-based authentication (email, oauth, mnemonic)');
|
|
1135
|
+
}
|
|
987
1136
|
popup = connectViaPopup({
|
|
988
1137
|
mechanism,
|
|
989
1138
|
walletHost: settings.walletHost,
|
|
@@ -1035,6 +1184,10 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1035
1184
|
}
|
|
1036
1185
|
}
|
|
1037
1186
|
|
|
1187
|
+
// ensureConnected overloads - the default step depends on targetStep
|
|
1188
|
+
function ensureConnected(
|
|
1189
|
+
options?: ConnectionOptions,
|
|
1190
|
+
): Promise<WalletConnected<WalletProviderType> | SignedIn<WalletProviderType>>;
|
|
1038
1191
|
function ensureConnected(
|
|
1039
1192
|
step: 'WalletConnected',
|
|
1040
1193
|
mechanism?: WalletMechanism<string | undefined, `0x${string}` | undefined>,
|
|
@@ -1045,51 +1198,70 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1045
1198
|
mechanism?: Mechanism,
|
|
1046
1199
|
options?: ConnectionOptions,
|
|
1047
1200
|
): Promise<SignedIn<WalletProviderType>>;
|
|
1048
|
-
function ensureConnected
|
|
1049
|
-
|
|
1050
|
-
stepOrMechanism?: Step | Mechanism,
|
|
1201
|
+
async function ensureConnected<Step extends 'WalletConnected' | 'SignedIn'>(
|
|
1202
|
+
stepOrMechanismOrOptions?: Step | Mechanism | ConnectionOptions,
|
|
1051
1203
|
mechanismOrOptions?: Mechanism | ConnectionOptions,
|
|
1052
1204
|
options?: ConnectionOptions,
|
|
1053
|
-
) {
|
|
1054
|
-
|
|
1055
|
-
let
|
|
1205
|
+
): Promise<WalletConnected<WalletProviderType> | SignedIn<WalletProviderType>> {
|
|
1206
|
+
// Determine if first arg is a step string, mechanism, or options
|
|
1207
|
+
let step: 'WalletConnected' | 'SignedIn';
|
|
1208
|
+
let mechanism: Mechanism | undefined;
|
|
1209
|
+
let opts: ConnectionOptions | undefined;
|
|
1210
|
+
|
|
1211
|
+
if (typeof stepOrMechanismOrOptions === 'string') {
|
|
1212
|
+
// First arg is a step
|
|
1213
|
+
step = stepOrMechanismOrOptions as 'WalletConnected' | 'SignedIn';
|
|
1214
|
+
mechanism = mechanismOrOptions as Mechanism | undefined;
|
|
1215
|
+
opts = options;
|
|
1216
|
+
} else if (stepOrMechanismOrOptions && 'type' in (stepOrMechanismOrOptions as any)) {
|
|
1217
|
+
// First arg is a mechanism
|
|
1218
|
+
step = targetStep; // Use configured target as default
|
|
1219
|
+
mechanism = stepOrMechanismOrOptions as Mechanism;
|
|
1220
|
+
opts = mechanismOrOptions as ConnectionOptions | undefined;
|
|
1221
|
+
} else {
|
|
1222
|
+
// First arg is options or undefined
|
|
1223
|
+
step = targetStep; // Use configured target as default
|
|
1224
|
+
mechanism = undefined;
|
|
1225
|
+
opts = stepOrMechanismOrOptions as ConnectionOptions | undefined;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
// For WalletConnected step, default to wallet mechanism
|
|
1056
1229
|
if (!mechanism && step === 'WalletConnected') {
|
|
1057
1230
|
mechanism = {type: 'wallet'};
|
|
1058
1231
|
}
|
|
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;
|
|
1232
|
+
|
|
1233
|
+
const promise = new Promise<WalletConnected<WalletProviderType> | SignedIn<WalletProviderType>>(
|
|
1234
|
+
(resolve, reject) => {
|
|
1235
|
+
let forceConnect = false;
|
|
1236
|
+
if (
|
|
1237
|
+
$connection.step == 'WalletConnected' &&
|
|
1238
|
+
($connection.wallet.status == 'locked' || $connection.wallet.status === 'disconnected')
|
|
1239
|
+
) {
|
|
1240
|
+
forceConnect = true;
|
|
1241
|
+
mechanism = $connection.mechanism; // we reuse existing mechanism as we just want to reconnect
|
|
1242
|
+
} else if ($connection.step == step) {
|
|
1243
|
+
resolve($connection as any);
|
|
1244
|
+
return;
|
|
1086
1245
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1246
|
+
let idlePassed = $connection.step != 'Idle';
|
|
1247
|
+
if (!idlePassed || forceConnect) {
|
|
1248
|
+
connect(mechanism, opts);
|
|
1090
1249
|
}
|
|
1091
|
-
|
|
1092
|
-
|
|
1250
|
+
const unsubscribe = _store.subscribe((connection) => {
|
|
1251
|
+
if (connection.step === 'Idle' && idlePassed) {
|
|
1252
|
+
unsubscribe();
|
|
1253
|
+
reject();
|
|
1254
|
+
}
|
|
1255
|
+
if (!idlePassed && connection.step !== 'Idle') {
|
|
1256
|
+
idlePassed = true;
|
|
1257
|
+
}
|
|
1258
|
+
if (connection.step === step) {
|
|
1259
|
+
unsubscribe();
|
|
1260
|
+
resolve(connection as any);
|
|
1261
|
+
}
|
|
1262
|
+
});
|
|
1263
|
+
},
|
|
1264
|
+
);
|
|
1093
1265
|
|
|
1094
1266
|
return promise;
|
|
1095
1267
|
}
|
|
@@ -1393,7 +1565,27 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1393
1565
|
}
|
|
1394
1566
|
}
|
|
1395
1567
|
|
|
1396
|
-
|
|
1568
|
+
// Determine walletOnly (defaults to false, but true implies WalletConnected target behavior for mechanism)
|
|
1569
|
+
const walletOnly = settings.walletOnly || targetStep === 'WalletConnected';
|
|
1570
|
+
|
|
1571
|
+
// Method on the store to check if target step is reached
|
|
1572
|
+
function storeIsTargetStepReached(connection: Connection<WalletProviderType>): boolean {
|
|
1573
|
+
if (targetStep === 'WalletConnected') {
|
|
1574
|
+
// For WalletConnected target, accept WalletConnected OR SignedIn-with-wallet
|
|
1575
|
+
return (
|
|
1576
|
+
connection.step === 'WalletConnected' || (connection.step === 'SignedIn' && connection.wallet !== undefined)
|
|
1577
|
+
);
|
|
1578
|
+
}
|
|
1579
|
+
// For SignedIn target
|
|
1580
|
+
if (walletOnly) {
|
|
1581
|
+
// With walletOnly, only accept SignedIn-with-wallet
|
|
1582
|
+
return connection.step === 'SignedIn' && connection.wallet !== undefined;
|
|
1583
|
+
}
|
|
1584
|
+
// Accept any SignedIn variant
|
|
1585
|
+
return connection.step === 'SignedIn';
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
const store = {
|
|
1397
1589
|
subscribe: _store.subscribe,
|
|
1398
1590
|
connect,
|
|
1399
1591
|
cancel,
|
|
@@ -1404,9 +1596,14 @@ export function createConnection<WalletProviderType = UnderlyingEthereumProvider
|
|
|
1404
1596
|
getSignatureForPublicKeyPublication,
|
|
1405
1597
|
switchWalletChain,
|
|
1406
1598
|
unlock,
|
|
1407
|
-
ensureConnected,
|
|
1599
|
+
ensureConnected: ensureConnected as any, // Cast to bypass complex conditional typing
|
|
1600
|
+
isTargetStepReached: storeIsTargetStepReached as any, // Cast for type guard
|
|
1601
|
+
targetStep,
|
|
1602
|
+
walletOnly,
|
|
1408
1603
|
provider: alwaysOnProviderWrapper.provider,
|
|
1409
1604
|
chainId: '' + settings.chainInfo.id,
|
|
1410
1605
|
chainInfo: settings.chainInfo,
|
|
1411
1606
|
};
|
|
1607
|
+
|
|
1608
|
+
return store as ConnectionStore<WalletProviderType, TargetStep, boolean>;
|
|
1412
1609
|
}
|