@etherplay/connect 0.0.9 → 0.0.11
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 +3176 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +272 -26
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts +13 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +49 -0
- package/dist/provider.js.map +1 -0
- package/package.json +5 -4
- package/src/index.ts +339 -34
- package/src/provider.ts +70 -0
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {AlchemyMechanism, OriginAccount} from '@etherplay/alchemy';
|
|
2
2
|
import {writable} from 'svelte/store';
|
|
3
3
|
import {createPopupLauncher, type PopupPromise} from './popup.js';
|
|
4
|
-
import type {EIP1193WindowWalletProvider} from 'eip-1193';
|
|
4
|
+
import type {EIP1193ChainId, EIP1193WindowWalletProvider} from 'eip-1193';
|
|
5
5
|
import {
|
|
6
6
|
fromEntropyKeyToMnemonic,
|
|
7
7
|
fromMnemonicToFirstAccount,
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
originPublicKeyPublicationMessage,
|
|
11
11
|
} from '@etherplay/alchemy';
|
|
12
12
|
import {hashMessage} from './utils.js';
|
|
13
|
+
import {createProvider} from './provider.js';
|
|
13
14
|
|
|
14
15
|
export {fromEntropyKeyToMnemonic, originPublicKeyPublicationMessage, originKeyMessage};
|
|
15
16
|
export type {OriginAccount};
|
|
@@ -40,50 +41,82 @@ export type Connection = {
|
|
|
40
41
|
| {
|
|
41
42
|
step: 'Idle';
|
|
42
43
|
loading: boolean;
|
|
44
|
+
wallet: undefined;
|
|
43
45
|
}
|
|
44
46
|
// It can then end up in MechanismToChoose if no specific connection mechanism was chosen upon clicking "connect"
|
|
45
47
|
| {
|
|
46
48
|
step: 'MechanismToChoose';
|
|
49
|
+
wallet: undefined;
|
|
47
50
|
}
|
|
48
|
-
// if a social/email login mechanism was
|
|
51
|
+
// if a social/email login mechanism was chosen, a popup will be launched
|
|
49
52
|
// popupClosed can be true and this means the popup has been closed and the user has to cancel the process to continue further
|
|
50
53
|
| {
|
|
51
54
|
step: 'PopupLaunched';
|
|
55
|
+
wallet: undefined;
|
|
52
56
|
popupClosed: boolean;
|
|
53
57
|
mechanism: AlchemyMechanism;
|
|
54
58
|
}
|
|
55
59
|
// If the user has chosen to use web3-wallet there might be multi-choice for it
|
|
56
60
|
| {
|
|
57
61
|
step: 'WalletToChoose';
|
|
62
|
+
wallet: undefined;
|
|
58
63
|
mechanism: WalletMechanism<undefined, undefined>;
|
|
59
64
|
}
|
|
60
65
|
// Once a user has chosen a wallet, the system will try to connect to it
|
|
61
66
|
| {
|
|
62
67
|
step: 'WaitingForWalletConnection';
|
|
68
|
+
wallet: undefined;
|
|
63
69
|
mechanism: WalletMechanism<string, undefined>;
|
|
64
70
|
}
|
|
65
71
|
// Once the wallet is connected, the system will need a signature
|
|
66
72
|
// this state represent the fact and require another user interaction to request the signature
|
|
67
73
|
| {
|
|
68
|
-
step: '
|
|
74
|
+
step: 'WalletConnected';
|
|
69
75
|
mechanism: WalletMechanism<string, `0x${string}`>;
|
|
76
|
+
wallet: {
|
|
77
|
+
provider: EIP1193WindowWalletProvider;
|
|
78
|
+
locked: boolean;
|
|
79
|
+
accountChanged?: `0x${string}`;
|
|
80
|
+
chainId: string;
|
|
81
|
+
invalidChainId: boolean;
|
|
82
|
+
switchingChain: 'addingChain' | 'switchingChain' | false;
|
|
83
|
+
};
|
|
70
84
|
}
|
|
71
85
|
// This state is triggered once the signature is requested, the user will have to confirm with its wallet
|
|
72
86
|
| {
|
|
73
87
|
step: 'WaitingForSignature';
|
|
74
88
|
mechanism: WalletMechanism<string, `0x${string}`>;
|
|
89
|
+
wallet: {
|
|
90
|
+
provider: EIP1193WindowWalletProvider;
|
|
91
|
+
locked: boolean;
|
|
92
|
+
accountChanged?: `0x${string}`;
|
|
93
|
+
chainId: string;
|
|
94
|
+
invalidChainId: boolean;
|
|
95
|
+
switchingChain: 'addingChain' | 'switchingChain' | false;
|
|
96
|
+
};
|
|
75
97
|
}
|
|
76
98
|
// Finally the user is fully signed in
|
|
77
|
-
//
|
|
99
|
+
// wallet?.accountChanged if set, represent the fact that the user has changed its web3-wallet accounnt.
|
|
100
|
+
// wallet?.invalidChainId if set, represent the fact that the wallet is connected to a different chain.
|
|
101
|
+
// wallet?.switchingChain if set, represent the fact that the user is currently switching chain.
|
|
78
102
|
// a notification could be shown to the user so that he can switch the app to use that other account.
|
|
79
103
|
| {
|
|
80
104
|
step: 'SignedIn';
|
|
81
|
-
mechanism:
|
|
105
|
+
mechanism: AlchemyMechanism;
|
|
82
106
|
account: OriginAccount;
|
|
83
|
-
wallet
|
|
107
|
+
wallet: undefined;
|
|
108
|
+
}
|
|
109
|
+
| {
|
|
110
|
+
step: 'SignedIn';
|
|
111
|
+
mechanism: WalletMechanism<string, `0x${string}`>;
|
|
112
|
+
account: OriginAccount;
|
|
113
|
+
wallet: {
|
|
84
114
|
provider: EIP1193WindowWalletProvider;
|
|
115
|
+
locked: boolean;
|
|
85
116
|
accountChanged?: `0x${string}`;
|
|
86
117
|
chainId: string;
|
|
118
|
+
invalidChainId: boolean;
|
|
119
|
+
switchingChain: 'addingChain' | 'switchingChain' | false;
|
|
87
120
|
};
|
|
88
121
|
}
|
|
89
122
|
);
|
|
@@ -106,13 +139,26 @@ export interface EIP6963AnnounceProviderEvent extends CustomEvent {
|
|
|
106
139
|
}
|
|
107
140
|
|
|
108
141
|
const storageAccountKey = '__origin_account';
|
|
109
|
-
export function createConnection(settings: {
|
|
142
|
+
export function createConnection(settings: {
|
|
143
|
+
walletHost: string;
|
|
144
|
+
autoConnect?: boolean;
|
|
145
|
+
requestSignatureAutomaticallyIfPossible?: boolean;
|
|
146
|
+
node: {url: string; chainId: string; prioritizeWalletProvider?: boolean; requestsPerSecond?: number};
|
|
147
|
+
}) {
|
|
148
|
+
const alwaysOnChainId = settings.node.chainId;
|
|
149
|
+
const alwaysOnProvider = createProvider({
|
|
150
|
+
endpoint: settings.node.url,
|
|
151
|
+
chainId: settings.node.chainId,
|
|
152
|
+
prioritizeWalletProvider: settings.node.prioritizeWalletProvider,
|
|
153
|
+
requestsPerSecond: settings.node.requestsPerSecond,
|
|
154
|
+
});
|
|
110
155
|
let autoConnect = true;
|
|
111
156
|
if (typeof settings.autoConnect !== 'undefined') {
|
|
112
157
|
autoConnect = settings.autoConnect;
|
|
113
158
|
}
|
|
159
|
+
const requestSignatureAutomaticallyIfPossible = settings.requestSignatureAutomaticallyIfPossible || false;
|
|
114
160
|
|
|
115
|
-
let $connection: Connection = {step: 'Idle', loading: true, wallets: []};
|
|
161
|
+
let $connection: Connection = {step: 'Idle', loading: true, wallet: undefined, wallets: []};
|
|
116
162
|
const _store = writable<Connection>($connection);
|
|
117
163
|
function set(connection: Connection) {
|
|
118
164
|
$connection = connection;
|
|
@@ -182,53 +228,60 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
182
228
|
const existingAccount = getOriginAccount();
|
|
183
229
|
if (existingAccount) {
|
|
184
230
|
if (existingAccount.signer) {
|
|
185
|
-
|
|
186
|
-
|
|
231
|
+
const mechanismUsed = existingAccount.mechanismUsed as
|
|
232
|
+
| AlchemyMechanism
|
|
233
|
+
| WalletMechanism<string, `0x${string}`>;
|
|
234
|
+
if (mechanismUsed.type == 'wallet') {
|
|
235
|
+
const walletMechanism = mechanismUsed as WalletMechanism<string, `0x${string}`>;
|
|
187
236
|
waitForWallet(walletMechanism.name)
|
|
188
237
|
.then(async (walletDetails: EIP6963ProviderDetail) => {
|
|
189
238
|
const walletProvider = walletDetails.provider;
|
|
190
239
|
const chainIdAsHex = await walletProvider.request({method: 'eth_chainId'});
|
|
191
240
|
const chainId = Number(chainIdAsHex).toString();
|
|
192
241
|
_wallet = {provider: walletProvider, chainId};
|
|
242
|
+
alwaysOnProvider.setWalletProvider(walletProvider);
|
|
193
243
|
watchForChainIdChange(_wallet.provider);
|
|
194
244
|
set({
|
|
195
245
|
step: 'SignedIn',
|
|
196
246
|
account: existingAccount,
|
|
197
|
-
mechanism:
|
|
247
|
+
mechanism: walletMechanism,
|
|
198
248
|
wallets: $connection.wallets,
|
|
199
249
|
wallet: {
|
|
200
250
|
provider: walletProvider,
|
|
251
|
+
locked: false, // TODO should fetch eth_account first
|
|
201
252
|
accountChanged: undefined,
|
|
202
253
|
chainId,
|
|
254
|
+
invalidChainId: alwaysOnChainId != chainId,
|
|
255
|
+
switchingChain: false,
|
|
203
256
|
},
|
|
204
257
|
});
|
|
205
258
|
walletProvider.request({method: 'eth_accounts'}).then(onAccountChanged);
|
|
206
259
|
watchForAccountChange(walletProvider);
|
|
207
260
|
})
|
|
208
261
|
.catch((err) => {
|
|
209
|
-
set({step: 'Idle', loading: false, wallets: $connection.wallets});
|
|
262
|
+
set({step: 'Idle', loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
210
263
|
});
|
|
211
264
|
} else {
|
|
212
265
|
set({
|
|
213
266
|
step: 'SignedIn',
|
|
214
267
|
account: existingAccount,
|
|
215
|
-
mechanism:
|
|
268
|
+
mechanism: mechanismUsed,
|
|
216
269
|
wallets: $connection.wallets,
|
|
217
270
|
wallet: undefined,
|
|
218
271
|
});
|
|
219
272
|
}
|
|
220
273
|
} else {
|
|
221
|
-
set({step: 'Idle', loading: false, wallets: $connection.wallets});
|
|
274
|
+
set({step: 'Idle', loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
222
275
|
}
|
|
223
276
|
} else {
|
|
224
|
-
set({step: 'Idle', loading: false, wallets: $connection.wallets});
|
|
277
|
+
set({step: 'Idle', loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
225
278
|
}
|
|
226
279
|
} catch {
|
|
227
|
-
set({step: 'Idle', loading: false, wallets: $connection.wallets});
|
|
280
|
+
set({step: 'Idle', loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
228
281
|
}
|
|
229
282
|
}
|
|
230
283
|
} else {
|
|
231
|
-
set({step: 'Idle', loading: false, wallets: $connection.wallets});
|
|
284
|
+
set({step: 'Idle', loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
232
285
|
}
|
|
233
286
|
fetchWallets();
|
|
234
287
|
|
|
@@ -249,8 +302,8 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
249
302
|
}
|
|
250
303
|
|
|
251
304
|
async function requestSignature() {
|
|
252
|
-
if ($connection.step !== '
|
|
253
|
-
throw new Error(`invalid step: ${$connection.step}, needs to be
|
|
305
|
+
if ($connection.step !== 'WalletConnected') {
|
|
306
|
+
throw new Error(`invalid step: ${$connection.step}, needs to be WalletConnected`);
|
|
254
307
|
}
|
|
255
308
|
|
|
256
309
|
if (!_wallet) {
|
|
@@ -278,7 +331,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
278
331
|
// TODO handle rejection (code: 4001 ?)
|
|
279
332
|
set({
|
|
280
333
|
...$connection,
|
|
281
|
-
step: '
|
|
334
|
+
step: 'WalletConnected',
|
|
282
335
|
mechanism: {
|
|
283
336
|
type: 'wallet',
|
|
284
337
|
name: $connection.mechanism.name,
|
|
@@ -318,7 +371,10 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
318
371
|
wallet: {
|
|
319
372
|
chainId,
|
|
320
373
|
provider: provider,
|
|
374
|
+
locked: false,
|
|
321
375
|
accountChanged: undefined, // TODO check account list
|
|
376
|
+
invalidChainId: alwaysOnChainId != chainId,
|
|
377
|
+
switchingChain: false,
|
|
322
378
|
},
|
|
323
379
|
});
|
|
324
380
|
if (remember) {
|
|
@@ -343,12 +399,18 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
343
399
|
if (_wallet) {
|
|
344
400
|
_wallet.chainId = chainId;
|
|
345
401
|
}
|
|
346
|
-
if (
|
|
402
|
+
if (
|
|
403
|
+
$connection.step === 'SignedIn' &&
|
|
404
|
+
$connection.mechanism.type === 'wallet' &&
|
|
405
|
+
$connection.wallet &&
|
|
406
|
+
$connection.wallet.chainId != chainId
|
|
407
|
+
) {
|
|
347
408
|
set({
|
|
348
409
|
...$connection,
|
|
349
410
|
wallet: {
|
|
350
411
|
...$connection.wallet,
|
|
351
412
|
chainId,
|
|
413
|
+
invalidChainId: alwaysOnChainId != chainId,
|
|
352
414
|
},
|
|
353
415
|
});
|
|
354
416
|
}
|
|
@@ -356,6 +418,25 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
356
418
|
|
|
357
419
|
function onAccountChanged(accounts: `0x${string}`[]) {
|
|
358
420
|
const accountsFormated = accounts.map((a) => a.toLowerCase()) as `0x${string}`[];
|
|
421
|
+
|
|
422
|
+
if (accountsFormated.length === 0 && $connection.wallet) {
|
|
423
|
+
set({
|
|
424
|
+
...$connection,
|
|
425
|
+
wallet: {
|
|
426
|
+
...$connection.wallet,
|
|
427
|
+
locked: true,
|
|
428
|
+
},
|
|
429
|
+
});
|
|
430
|
+
} else if (accountsFormated.length > 0 && $connection.wallet?.locked) {
|
|
431
|
+
set({
|
|
432
|
+
...$connection,
|
|
433
|
+
wallet: {
|
|
434
|
+
...$connection.wallet,
|
|
435
|
+
locked: false,
|
|
436
|
+
},
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
|
|
359
440
|
if ($connection.step === 'SignedIn' && $connection.mechanism.type === 'wallet') {
|
|
360
441
|
// TODO if auto-connect and saved-signature ?
|
|
361
442
|
// connect(
|
|
@@ -364,7 +445,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
364
445
|
// address: accounts[0],
|
|
365
446
|
// name: $connection.mechanism.name
|
|
366
447
|
// },
|
|
367
|
-
// {
|
|
448
|
+
// { requireUserConfirmationBeforeSignatureRequest: true }
|
|
368
449
|
// );
|
|
369
450
|
|
|
370
451
|
if ($connection.wallet && accountsFormated.length > 0 && accountsFormated[0] != $connection.account.address) {
|
|
@@ -407,7 +488,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
407
488
|
async function connect(
|
|
408
489
|
mechanism?: Mechanism,
|
|
409
490
|
options?: {
|
|
410
|
-
|
|
491
|
+
requireUserConfirmationBeforeSignatureRequest?: boolean;
|
|
411
492
|
doNotStoreLocally?: boolean;
|
|
412
493
|
requestSignatureRightAway?: boolean;
|
|
413
494
|
},
|
|
@@ -420,6 +501,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
420
501
|
const wallet = $connection.wallets.find((v) => v.info.name == walletName || v.info.uuid == walletName);
|
|
421
502
|
if (wallet) {
|
|
422
503
|
if (_wallet) {
|
|
504
|
+
alwaysOnProvider.setWalletProvider(undefined);
|
|
423
505
|
stopatchingForAccountChange(_wallet.provider);
|
|
424
506
|
stopatchingForChainIdChange(_wallet.provider);
|
|
425
507
|
}
|
|
@@ -433,6 +515,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
433
515
|
step: 'WaitingForWalletConnection', // TODO FetchingAccounts
|
|
434
516
|
mechanism,
|
|
435
517
|
wallets: $connection.wallets,
|
|
518
|
+
wallet: undefined,
|
|
436
519
|
});
|
|
437
520
|
const provider = wallet.provider;
|
|
438
521
|
const chainIdAsHex = await provider.request({method: 'eth_chainId'});
|
|
@@ -441,14 +524,16 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
441
524
|
chainId,
|
|
442
525
|
provider,
|
|
443
526
|
};
|
|
527
|
+
alwaysOnProvider.setWalletProvider(_wallet.provider);
|
|
444
528
|
watchForChainIdChange(_wallet.provider);
|
|
445
529
|
let accounts = await provider.request({method: 'eth_accounts'});
|
|
446
530
|
accounts = accounts.map((v) => v.toLowerCase()) as `0x${string}`[];
|
|
447
531
|
if (accounts.length === 0) {
|
|
448
532
|
set({
|
|
449
|
-
step: 'WaitingForWalletConnection',
|
|
533
|
+
step: 'WaitingForWalletConnection', // TODO add another step to unlock ?
|
|
450
534
|
mechanism,
|
|
451
535
|
wallets: $connection.wallets,
|
|
536
|
+
wallet: undefined,
|
|
452
537
|
});
|
|
453
538
|
accounts = await provider.request({method: 'eth_requestAccounts'});
|
|
454
539
|
accounts = accounts.map((v) => v.toLowerCase()) as `0x${string}`[];
|
|
@@ -456,22 +541,38 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
456
541
|
if (options?.requestSignatureRightAway) {
|
|
457
542
|
watchForAccountChange(_wallet.provider);
|
|
458
543
|
set({
|
|
459
|
-
step: '
|
|
544
|
+
step: 'WalletConnected',
|
|
460
545
|
mechanism: {
|
|
461
546
|
...mechanism,
|
|
462
547
|
address: accounts[0],
|
|
463
548
|
},
|
|
464
549
|
wallets: $connection.wallets,
|
|
550
|
+
wallet: {
|
|
551
|
+
provider: _wallet.provider,
|
|
552
|
+
locked: false,
|
|
553
|
+
accountChanged: undefined,
|
|
554
|
+
chainId,
|
|
555
|
+
invalidChainId: alwaysOnChainId != chainId,
|
|
556
|
+
switchingChain: false,
|
|
557
|
+
},
|
|
465
558
|
});
|
|
466
559
|
await requestSignature();
|
|
467
560
|
} else {
|
|
468
561
|
set({
|
|
469
|
-
step: '
|
|
562
|
+
step: 'WalletConnected',
|
|
470
563
|
mechanism: {
|
|
471
564
|
...mechanism,
|
|
472
565
|
address: accounts[0],
|
|
473
566
|
},
|
|
474
567
|
wallets: $connection.wallets,
|
|
568
|
+
wallet: {
|
|
569
|
+
provider: _wallet.provider,
|
|
570
|
+
locked: false,
|
|
571
|
+
accountChanged: undefined,
|
|
572
|
+
chainId,
|
|
573
|
+
invalidChainId: alwaysOnChainId != chainId,
|
|
574
|
+
switchingChain: false,
|
|
575
|
+
},
|
|
475
576
|
});
|
|
476
577
|
watchForAccountChange(_wallet.provider);
|
|
477
578
|
}
|
|
@@ -479,29 +580,46 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
479
580
|
set({
|
|
480
581
|
step: 'MechanismToChoose',
|
|
481
582
|
wallets: $connection.wallets,
|
|
583
|
+
wallet: undefined,
|
|
482
584
|
error: {message: 'could not get any accounts'},
|
|
483
585
|
});
|
|
484
586
|
}
|
|
485
587
|
} else {
|
|
486
|
-
if (options?.
|
|
588
|
+
if (!requestSignatureAutomaticallyIfPossible || options?.requireUserConfirmationBeforeSignatureRequest) {
|
|
487
589
|
set({
|
|
488
|
-
step: '
|
|
590
|
+
step: 'WalletConnected',
|
|
489
591
|
mechanism: {
|
|
490
592
|
...mechanism,
|
|
491
593
|
address: accounts[0],
|
|
492
594
|
},
|
|
493
595
|
wallets: $connection.wallets,
|
|
596
|
+
wallet: {
|
|
597
|
+
provider: _wallet.provider,
|
|
598
|
+
locked: false,
|
|
599
|
+
accountChanged: undefined,
|
|
600
|
+
chainId,
|
|
601
|
+
invalidChainId: alwaysOnChainId != chainId,
|
|
602
|
+
switchingChain: false,
|
|
603
|
+
},
|
|
494
604
|
});
|
|
495
605
|
watchForAccountChange(_wallet.provider);
|
|
496
606
|
} else {
|
|
497
607
|
watchForAccountChange(_wallet.provider);
|
|
498
608
|
set({
|
|
499
|
-
step: '
|
|
609
|
+
step: 'WalletConnected',
|
|
500
610
|
mechanism: {
|
|
501
611
|
...mechanism,
|
|
502
612
|
address: accounts[0],
|
|
503
613
|
},
|
|
504
614
|
wallets: $connection.wallets,
|
|
615
|
+
wallet: {
|
|
616
|
+
provider: _wallet.provider,
|
|
617
|
+
locked: false,
|
|
618
|
+
accountChanged: undefined,
|
|
619
|
+
chainId,
|
|
620
|
+
invalidChainId: alwaysOnChainId != chainId,
|
|
621
|
+
switchingChain: false,
|
|
622
|
+
},
|
|
505
623
|
});
|
|
506
624
|
await requestSignature();
|
|
507
625
|
}
|
|
@@ -511,6 +629,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
511
629
|
set({
|
|
512
630
|
step: 'MechanismToChoose',
|
|
513
631
|
wallets: $connection.wallets,
|
|
632
|
+
wallet: undefined,
|
|
514
633
|
error: {message: `failed to get wallet ${walletName}`},
|
|
515
634
|
});
|
|
516
635
|
}
|
|
@@ -524,6 +643,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
524
643
|
set({
|
|
525
644
|
step: 'WalletToChoose',
|
|
526
645
|
mechanism: {type: 'wallet'},
|
|
646
|
+
wallet: undefined,
|
|
527
647
|
wallets: $connection.wallets,
|
|
528
648
|
});
|
|
529
649
|
}
|
|
@@ -537,6 +657,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
537
657
|
popupClosed: false,
|
|
538
658
|
mechanism,
|
|
539
659
|
wallets: $connection.wallets,
|
|
660
|
+
wallet: undefined,
|
|
540
661
|
});
|
|
541
662
|
|
|
542
663
|
const unsubscribe = popup.subscribe(($popup) => {
|
|
@@ -564,7 +685,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
564
685
|
}
|
|
565
686
|
} catch (err) {
|
|
566
687
|
console.log({error: err});
|
|
567
|
-
set({step: 'Idle', loading: false, wallets: $connection.wallets});
|
|
688
|
+
set({step: 'Idle', loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
568
689
|
} finally {
|
|
569
690
|
unsubscribe();
|
|
570
691
|
}
|
|
@@ -573,6 +694,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
573
694
|
set({
|
|
574
695
|
step: 'MechanismToChoose',
|
|
575
696
|
wallets: $connection.wallets,
|
|
697
|
+
wallet: undefined,
|
|
576
698
|
});
|
|
577
699
|
}
|
|
578
700
|
}
|
|
@@ -580,6 +702,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
580
702
|
function disconnect() {
|
|
581
703
|
deleteOriginAccount();
|
|
582
704
|
if (_wallet) {
|
|
705
|
+
alwaysOnProvider.setWalletProvider(undefined);
|
|
583
706
|
stopatchingForAccountChange(_wallet.provider);
|
|
584
707
|
stopatchingForChainIdChange(_wallet.provider);
|
|
585
708
|
}
|
|
@@ -587,6 +710,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
587
710
|
set({
|
|
588
711
|
step: 'Idle',
|
|
589
712
|
loading: false,
|
|
713
|
+
wallet: undefined,
|
|
590
714
|
wallets: $connection.wallets,
|
|
591
715
|
});
|
|
592
716
|
}
|
|
@@ -594,11 +718,11 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
594
718
|
function back(step: 'MechanismToChoose' | 'Idle' | 'WalletToChoose') {
|
|
595
719
|
popup?.cancel();
|
|
596
720
|
if (step === 'MechanismToChoose') {
|
|
597
|
-
set({step, wallets: $connection.wallets});
|
|
721
|
+
set({step, wallets: $connection.wallets, wallet: undefined});
|
|
598
722
|
} else if (step === 'Idle') {
|
|
599
|
-
set({step, loading: false, wallets: $connection.wallets});
|
|
723
|
+
set({step, loading: false, wallet: undefined, wallets: $connection.wallets});
|
|
600
724
|
} else if (step === 'WalletToChoose') {
|
|
601
|
-
set({step, wallets: $connection.wallets, mechanism: {type: 'wallet'}});
|
|
725
|
+
set({step, wallet: undefined, wallets: $connection.wallets, mechanism: {type: 'wallet'}});
|
|
602
726
|
}
|
|
603
727
|
}
|
|
604
728
|
|
|
@@ -664,7 +788,7 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
664
788
|
|
|
665
789
|
function cancel() {
|
|
666
790
|
popup?.cancel();
|
|
667
|
-
set({step: 'Idle', loading: false, wallets: $connection.wallets});
|
|
791
|
+
set({step: 'Idle', wallet: undefined, loading: false, wallets: $connection.wallets});
|
|
668
792
|
}
|
|
669
793
|
|
|
670
794
|
function getSignatureForPublicKeyPublication(): Promise<`0x${string}`> {
|
|
@@ -693,6 +817,182 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
693
817
|
throw new Error(`no saved public key publication signature for ${account.address}`);
|
|
694
818
|
}
|
|
695
819
|
|
|
820
|
+
async function unlock() {
|
|
821
|
+
if (!$connection.wallet) {
|
|
822
|
+
throw new Error(`invali state`);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
const wallet = $connection.wallet;
|
|
826
|
+
|
|
827
|
+
// TODO unlocking state
|
|
828
|
+
await wallet.provider.request({method: 'eth_requestAccounts'}).then(onAccountChanged);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
async function switchWalletChain(
|
|
832
|
+
chainId: string,
|
|
833
|
+
config?: {
|
|
834
|
+
readonly rpcUrls?: readonly string[];
|
|
835
|
+
readonly blockExplorerUrls?: readonly string[];
|
|
836
|
+
readonly chainName?: string;
|
|
837
|
+
readonly iconUrls?: readonly string[];
|
|
838
|
+
readonly nativeCurrency?: {
|
|
839
|
+
name: string;
|
|
840
|
+
symbol: string;
|
|
841
|
+
decimals: number;
|
|
842
|
+
};
|
|
843
|
+
},
|
|
844
|
+
) {
|
|
845
|
+
if (!$connection.wallet) {
|
|
846
|
+
throw new Error(`invali state`);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
const wallet = $connection.wallet;
|
|
850
|
+
// if (!wallet) {
|
|
851
|
+
// throw new Error(`no wallet`);
|
|
852
|
+
// }
|
|
853
|
+
|
|
854
|
+
try {
|
|
855
|
+
// attempt to switch...
|
|
856
|
+
set({
|
|
857
|
+
...$connection,
|
|
858
|
+
wallet: {...$connection.wallet, switchingChain: 'switchingChain'},
|
|
859
|
+
});
|
|
860
|
+
const result = await wallet.provider.request({
|
|
861
|
+
method: 'wallet_switchEthereumChain',
|
|
862
|
+
params: [
|
|
863
|
+
{
|
|
864
|
+
chainId: ('0x' + parseInt(chainId).toString(16)) as EIP1193ChainId,
|
|
865
|
+
},
|
|
866
|
+
],
|
|
867
|
+
});
|
|
868
|
+
if (!result) {
|
|
869
|
+
if ($connection.wallet) {
|
|
870
|
+
set({
|
|
871
|
+
...$connection,
|
|
872
|
+
wallet: {...$connection.wallet, switchingChain: false},
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// logger.info(`wallet_switchEthereumChain: complete`);
|
|
877
|
+
// this will be taken care with `chainChanged` (but maybe it should be done there ?)
|
|
878
|
+
// handleNetwork(chainId);
|
|
879
|
+
} else {
|
|
880
|
+
if ($connection.wallet) {
|
|
881
|
+
set({
|
|
882
|
+
...$connection,
|
|
883
|
+
wallet: {...$connection.wallet, switchingChain: false},
|
|
884
|
+
error: {
|
|
885
|
+
message: `Failed to switch to ${config?.chainName || `chain with id = ${chainId}`}`,
|
|
886
|
+
cause: result,
|
|
887
|
+
},
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
throw result;
|
|
891
|
+
}
|
|
892
|
+
} catch (err) {
|
|
893
|
+
if ((err as any).code === 4001) {
|
|
894
|
+
// logger.info(`wallet_addEthereumChain: failed but error code === 4001, we ignore as user rejected it`, err);
|
|
895
|
+
if ($connection.wallet) {
|
|
896
|
+
set({
|
|
897
|
+
...$connection,
|
|
898
|
+
wallet: {...$connection.wallet, switchingChain: false},
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
// if ((err as any).code === 4902) {
|
|
904
|
+
else if (config && config.rpcUrls && config.rpcUrls.length > 0) {
|
|
905
|
+
if ($connection.wallet) {
|
|
906
|
+
set({
|
|
907
|
+
...$connection,
|
|
908
|
+
wallet: {...$connection.wallet, switchingChain: 'addingChain'},
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
// logger.info(`wallet_switchEthereumChain: could not switch, try adding the chain via "wallet_addEthereumChain"`);
|
|
912
|
+
try {
|
|
913
|
+
const result = await wallet.provider.request({
|
|
914
|
+
method: 'wallet_addEthereumChain',
|
|
915
|
+
params: [
|
|
916
|
+
{
|
|
917
|
+
chainId: ('0x' + parseInt(chainId).toString(16)) as EIP1193ChainId,
|
|
918
|
+
rpcUrls: config.rpcUrls,
|
|
919
|
+
chainName: config.chainName,
|
|
920
|
+
blockExplorerUrls: config.blockExplorerUrls,
|
|
921
|
+
iconUrls: config.iconUrls,
|
|
922
|
+
nativeCurrency: config.nativeCurrency,
|
|
923
|
+
},
|
|
924
|
+
],
|
|
925
|
+
});
|
|
926
|
+
if (!result) {
|
|
927
|
+
if ($connection.wallet) {
|
|
928
|
+
set({
|
|
929
|
+
...$connection,
|
|
930
|
+
wallet: {...$connection.wallet, switchingChain: false},
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
// this will be taken care with `chainChanged` (but maybe it should be done there ?)
|
|
934
|
+
// handleNetwork(chainId);
|
|
935
|
+
} else {
|
|
936
|
+
if ($connection.wallet) {
|
|
937
|
+
set({
|
|
938
|
+
...$connection,
|
|
939
|
+
wallet: {...$connection.wallet, switchingChain: false},
|
|
940
|
+
error: {
|
|
941
|
+
message: `Failed to add new chain: ${config?.chainName || `chain with id = ${chainId}`}`,
|
|
942
|
+
cause: result,
|
|
943
|
+
},
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
// logger.info(`wallet_addEthereumChain: a non-undefinded result means an error`, result);
|
|
947
|
+
throw result;
|
|
948
|
+
}
|
|
949
|
+
} catch (err) {
|
|
950
|
+
if ((err as any).code !== 4001) {
|
|
951
|
+
if ($connection.wallet) {
|
|
952
|
+
set({
|
|
953
|
+
...$connection,
|
|
954
|
+
wallet: {...$connection.wallet, switchingChain: false},
|
|
955
|
+
error: {
|
|
956
|
+
message: `Failed to add new chain: ${config?.chainName || `chain with id = ${chainId}`}`,
|
|
957
|
+
cause: err,
|
|
958
|
+
},
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
// logger.info(`wallet_addEthereumChain: failed`, err);
|
|
962
|
+
// TODO ?
|
|
963
|
+
// set({
|
|
964
|
+
// error: {message: `Failed to add new chain`, cause: err},
|
|
965
|
+
// });
|
|
966
|
+
// for now:
|
|
967
|
+
throw err;
|
|
968
|
+
} else {
|
|
969
|
+
if ($connection.wallet) {
|
|
970
|
+
set({
|
|
971
|
+
...$connection,
|
|
972
|
+
wallet: {...$connection.wallet, switchingChain: false},
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
// logger.info(`wallet_addEthereumChain: failed but error code === 4001, we ignore as user rejected it`, err);
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
} else {
|
|
980
|
+
const errorMessage = `Chain "${config?.chainName || `with chainId = ${chainId}`} " is not available on your wallet`;
|
|
981
|
+
if ($connection.wallet) {
|
|
982
|
+
set({
|
|
983
|
+
...$connection,
|
|
984
|
+
wallet: {...$connection.wallet, switchingChain: false},
|
|
985
|
+
error: {
|
|
986
|
+
message: errorMessage,
|
|
987
|
+
},
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
throw new Error(errorMessage);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
|
|
696
996
|
return {
|
|
697
997
|
subscribe: _store.subscribe,
|
|
698
998
|
connect,
|
|
@@ -702,5 +1002,10 @@ export function createConnection(settings: {walletHost: string; autoConnect?: bo
|
|
|
702
1002
|
connectOnCurrentWalletAccount,
|
|
703
1003
|
disconnect,
|
|
704
1004
|
getSignatureForPublicKeyPublication,
|
|
1005
|
+
switchWalletChain,
|
|
1006
|
+
unlock,
|
|
1007
|
+
provider: alwaysOnProvider,
|
|
705
1008
|
};
|
|
706
1009
|
}
|
|
1010
|
+
|
|
1011
|
+
export type ConnectionStore = ReturnType<typeof createConnection>;
|