@reown/appkit-ethers-react-native 0.0.0-fix-approved-networks-20250822000414 → 0.0.0-fix-improvements-20250827190629

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.
Files changed (44) hide show
  1. package/lib/commonjs/adapter.js +81 -0
  2. package/lib/commonjs/adapter.js.map +1 -0
  3. package/lib/commonjs/helpers.js +33 -0
  4. package/lib/commonjs/helpers.js.map +1 -0
  5. package/lib/commonjs/index.js +3 -174
  6. package/lib/commonjs/index.js.map +1 -1
  7. package/lib/commonjs/package.json +1 -0
  8. package/lib/module/adapter.js +76 -0
  9. package/lib/module/adapter.js.map +1 -0
  10. package/lib/module/helpers.js +27 -0
  11. package/lib/module/helpers.js.map +1 -0
  12. package/lib/module/index.js +3 -132
  13. package/lib/module/index.js.map +1 -1
  14. package/lib/typescript/adapter.d.ts +11 -0
  15. package/lib/typescript/adapter.d.ts.map +1 -0
  16. package/lib/typescript/helpers.d.ts +3 -0
  17. package/lib/typescript/helpers.d.ts.map +1 -0
  18. package/lib/typescript/index.d.ts +2 -39
  19. package/lib/typescript/index.d.ts.map +1 -1
  20. package/package.json +7 -13
  21. package/src/adapter.ts +100 -0
  22. package/src/helpers.ts +25 -0
  23. package/src/index.tsx +2 -164
  24. package/lib/commonjs/client.js +0 -862
  25. package/lib/commonjs/client.js.map +0 -1
  26. package/lib/commonjs/utils/defaultConfig.js +0 -18
  27. package/lib/commonjs/utils/defaultConfig.js.map +0 -1
  28. package/lib/commonjs/utils/helpers.js +0 -27
  29. package/lib/commonjs/utils/helpers.js.map +0 -1
  30. package/lib/module/client.js +0 -854
  31. package/lib/module/client.js.map +0 -1
  32. package/lib/module/utils/defaultConfig.js +0 -12
  33. package/lib/module/utils/defaultConfig.js.map +0 -1
  34. package/lib/module/utils/helpers.js +0 -20
  35. package/lib/module/utils/helpers.js.map +0 -1
  36. package/lib/typescript/client.d.ts +0 -65
  37. package/lib/typescript/client.d.ts.map +0 -1
  38. package/lib/typescript/utils/defaultConfig.d.ts +0 -7
  39. package/lib/typescript/utils/defaultConfig.d.ts.map +0 -1
  40. package/lib/typescript/utils/helpers.d.ts +0 -10
  41. package/lib/typescript/utils/helpers.d.ts.map +0 -1
  42. package/src/client.ts +0 -1078
  43. package/src/utils/defaultConfig.ts +0 -19
  44. package/src/utils/helpers.ts +0 -27
package/src/client.ts DELETED
@@ -1,1078 +0,0 @@
1
- import {
2
- BrowserProvider,
3
- Contract,
4
- InfuraProvider,
5
- JsonRpcProvider,
6
- JsonRpcSigner,
7
- formatEther,
8
- formatUnits,
9
- getAddress,
10
- hexlify,
11
- isHexString,
12
- parseUnits,
13
- toUtf8Bytes
14
- } from 'ethers';
15
- import {
16
- type CaipAddress,
17
- type CaipNetwork,
18
- type CaipNetworkId,
19
- type ConnectionControllerClient,
20
- type Connector,
21
- type LibraryOptions,
22
- type NetworkControllerClient,
23
- type PublicStateControllerState,
24
- type SendTransactionArgs,
25
- type Token,
26
- AppKitScaffold,
27
- type WriteContractArgs,
28
- type AppKitFrameAccountType,
29
- type EstimateGasTransactionArgs
30
- } from '@reown/appkit-scaffold-react-native';
31
- import {
32
- erc20ABI,
33
- ErrorUtil,
34
- NamesUtil,
35
- NetworkUtil,
36
- PresetsUtil,
37
- ConstantsUtil
38
- } from '@reown/appkit-common-react-native';
39
- import {
40
- HelpersUtil,
41
- StorageUtil,
42
- EthersConstantsUtil,
43
- EthersHelpersUtil,
44
- EthersStoreUtil,
45
- type Address,
46
- type Metadata,
47
- type ProviderType,
48
- type Chain,
49
- type Provider,
50
- type EthersStoreUtilState,
51
- type CombinedProviderType,
52
- type AppKitFrameProvider
53
- } from '@reown/appkit-scaffold-utils-react-native';
54
- import {
55
- type AppKitSIWEClient,
56
- SIWEController,
57
- getDidChainId,
58
- getDidAddress
59
- } from '@reown/appkit-siwe-react-native';
60
- import EthereumProvider, {
61
- type EthereumProviderOptions,
62
- OPTIONAL_METHODS
63
- } from '@walletconnect/ethereum-provider';
64
- import { type JsonRpcError } from '@walletconnect/jsonrpc-types';
65
-
66
- import { getAuthCaipNetworks, getWalletConnectCaipNetworks } from './utils/helpers';
67
-
68
- // -- Types ---------------------------------------------------------------------
69
- export interface AppKitClientOptions extends Omit<LibraryOptions, 'defaultChain' | 'tokens'> {
70
- config: ProviderType;
71
- siweConfig?: AppKitSIWEClient;
72
- chains: Chain[];
73
- defaultChain?: Chain;
74
- chainImages?: Record<number, string>;
75
- connectorImages?: Record<string, string>;
76
- tokens?: Record<number, Token>;
77
- }
78
-
79
- export type AppKitOptions = Omit<AppKitClientOptions, '_sdkVersion'>;
80
-
81
- // @ts-expect-error: Overriden state type is correct
82
- interface AppKitState extends PublicStateControllerState {
83
- selectedNetworkId: number | undefined;
84
- }
85
-
86
- interface ExternalProvider extends EthereumProvider {
87
- address?: string;
88
- }
89
-
90
- // -- Client --------------------------------------------------------------------
91
- export class AppKit extends AppKitScaffold {
92
- private hasSyncedConnectedAccount = false;
93
-
94
- private walletConnectProvider?: EthereumProvider;
95
-
96
- private walletConnectProviderInitPromise?: Promise<void>;
97
-
98
- private projectId: string;
99
-
100
- private chains: Chain[];
101
-
102
- private metadata: Metadata;
103
-
104
- private options: AppKitClientOptions | undefined = undefined;
105
-
106
- private authProvider?: AppKitFrameProvider;
107
-
108
- public constructor(options: AppKitClientOptions) {
109
- const {
110
- config,
111
- siweConfig,
112
- chains,
113
- defaultChain,
114
- tokens,
115
- chainImages,
116
- _sdkVersion,
117
- ...appKitOptions
118
- } = options;
119
-
120
- if (!config) {
121
- throw new Error('appkit:constructor - config is undefined');
122
- }
123
-
124
- if (!appKitOptions.projectId) {
125
- throw new Error(ErrorUtil.ALERT_ERRORS.PROJECT_ID_NOT_CONFIGURED.shortMessage);
126
- }
127
-
128
- const networkControllerClient: NetworkControllerClient = {
129
- switchCaipNetwork: async caipNetwork => {
130
- const chainId = NetworkUtil.caipNetworkIdToNumber(caipNetwork?.id);
131
- if (chainId) {
132
- try {
133
- await this.switchNetwork(chainId);
134
- } catch (error) {
135
- EthersStoreUtil.setError(error);
136
- }
137
- }
138
- },
139
-
140
- getApprovedCaipNetworksData: async () =>
141
- new Promise(async resolve => {
142
- const walletId = (await StorageUtil.getItem(EthersConstantsUtil.WALLET_ID)) as string;
143
- const walletChoice = PresetsUtil.ConnectorTypesMap[walletId ?? ''];
144
- const walletConnectType =
145
- PresetsUtil.ConnectorTypesMap[ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID]!;
146
-
147
- const authType = PresetsUtil.ConnectorTypesMap[ConstantsUtil.AUTH_CONNECTOR_ID]!;
148
- if (walletChoice?.includes(walletConnectType)) {
149
- const provider = await this.getWalletConnectProvider();
150
- const result = getWalletConnectCaipNetworks(provider);
151
-
152
- resolve(result);
153
- } else if (walletChoice?.includes(authType)) {
154
- const result = getAuthCaipNetworks();
155
- resolve(result);
156
- } else {
157
- const result = {
158
- approvedCaipNetworkIds: undefined,
159
- supportsAllNetworks: true
160
- };
161
-
162
- resolve(result);
163
- }
164
- })
165
- };
166
-
167
- const connectionControllerClient: ConnectionControllerClient = {
168
- connectWalletConnect: async onUri => {
169
- const WalletConnectProvider = await this.getWalletConnectProvider();
170
- if (!WalletConnectProvider) {
171
- throw new Error('connectionControllerClient:getWalletConnectUri - provider is undefined');
172
- }
173
-
174
- WalletConnectProvider.on('display_uri', (uri: string) => {
175
- onUri(uri);
176
- });
177
-
178
- // When connecting through walletconnect, we need to set the clientId in the store
179
- const clientId = await WalletConnectProvider.signer?.client?.core?.crypto?.getClientId();
180
- if (clientId) {
181
- this.setClientId(clientId);
182
- }
183
-
184
- // SIWE
185
- const params = await siweConfig?.getMessageParams?.();
186
- if (siweConfig?.options?.enabled && params && Object.keys(params).length > 0) {
187
- const result = await WalletConnectProvider.authenticate({
188
- nonce: await siweConfig.getNonce(),
189
- methods: OPTIONAL_METHODS,
190
- ...params
191
- });
192
- // Auths is an array of signed CACAO objects https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-74.md
193
- const signedCacao = result?.auths?.[0];
194
- if (signedCacao) {
195
- const { p, s } = signedCacao;
196
- const chainId = getDidChainId(p.iss);
197
- const address = getDidAddress(p.iss);
198
-
199
- try {
200
- // Kicks off verifyMessage and populates external states
201
- const message = WalletConnectProvider.signer.client.formatAuthMessage({
202
- request: p,
203
- iss: p.iss
204
- });
205
-
206
- await SIWEController.verifyMessage({
207
- message,
208
- signature: s.s,
209
- cacao: signedCacao
210
- });
211
-
212
- if (address && chainId) {
213
- const session = {
214
- address,
215
- chainId: parseInt(chainId, 10)
216
- };
217
-
218
- SIWEController.setSession(session);
219
- SIWEController.onSignIn?.(session);
220
- }
221
- } catch (error) {
222
- // eslint-disable-next-line no-console
223
- console.error('Error verifying message', error);
224
- // eslint-disable-next-line no-console
225
- await WalletConnectProvider.disconnect().catch(console.error);
226
- // eslint-disable-next-line no-console
227
- await SIWEController.signOut().catch(console.error);
228
- throw error;
229
- }
230
- }
231
- } else {
232
- await WalletConnectProvider.connect({
233
- chains: [],
234
- optionalChains: [...this.chains.map(chain => chain.chainId)] as [number]
235
- });
236
- }
237
-
238
- await this.setWalletConnectProvider();
239
- },
240
-
241
- // @ts-expect-error TODO expected types in arguments are incomplete
242
- connectExternal: async ({ id }: { id: string; provider: Provider }) => {
243
- // If connecting with something else than walletconnect, we need to clear the clientId in the store
244
- this.setClientId(null);
245
-
246
- if (id === ConstantsUtil.COINBASE_CONNECTOR_ID) {
247
- const coinbaseProvider = config.extraConnectors?.find(connector => connector.id === id);
248
- if (!coinbaseProvider) {
249
- throw new Error('connectionControllerClient:connectCoinbase - connector is undefined');
250
- }
251
-
252
- try {
253
- await coinbaseProvider.request({ method: 'eth_requestAccounts' });
254
- await this.setCoinbaseProvider(coinbaseProvider as Provider);
255
- } catch (error) {
256
- EthersStoreUtil.setError(error);
257
- }
258
- } else if (id === ConstantsUtil.AUTH_CONNECTOR_ID) {
259
- await this.setAuthProvider();
260
- }
261
- },
262
-
263
- disconnect: async () => {
264
- const provider = EthersStoreUtil.state.provider;
265
- const providerType = EthersStoreUtil.state.providerType;
266
- const walletConnectType =
267
- PresetsUtil.ConnectorTypesMap[ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID];
268
-
269
- const authType = PresetsUtil.ConnectorTypesMap[ConstantsUtil.AUTH_CONNECTOR_ID];
270
-
271
- if (siweConfig?.options?.signOutOnDisconnect) {
272
- await SIWEController.signOut();
273
- }
274
-
275
- if (providerType === walletConnectType) {
276
- const WalletConnectProvider = provider;
277
- await (WalletConnectProvider as unknown as EthereumProvider).disconnect();
278
- } else if (providerType === authType) {
279
- await this.authProvider?.disconnect();
280
- } else if (provider) {
281
- provider.emit('disconnect');
282
- }
283
- StorageUtil.removeItem(EthersConstantsUtil.WALLET_ID);
284
- EthersStoreUtil.reset();
285
- this.setClientId(null);
286
- },
287
-
288
- signMessage: async (message: string) => {
289
- const provider = EthersStoreUtil.state.provider;
290
- if (!provider) {
291
- throw new Error('connectionControllerClient:signMessage - provider is undefined');
292
- }
293
- const hexMessage = isHexString(message) ? message : hexlify(toUtf8Bytes(message));
294
- const signature = await provider.request({
295
- method: 'personal_sign',
296
- params: [hexMessage, this.getAddress()]
297
- });
298
-
299
- return signature as `0x${string}`;
300
- },
301
-
302
- estimateGas: async ({
303
- address,
304
- to,
305
- data,
306
- chainNamespace
307
- }: EstimateGasTransactionArgs): Promise<bigint> => {
308
- const caipNetwork = this.getCaipNetwork();
309
- const provider = EthersStoreUtil.state.provider;
310
-
311
- if (!provider) {
312
- throw new Error('Provider is undefined');
313
- }
314
-
315
- try {
316
- if (!provider) {
317
- throw new Error('estimateGas - provider is undefined');
318
- }
319
- if (!address) {
320
- throw new Error('estimateGas - address is undefined');
321
- }
322
- if (chainNamespace && chainNamespace !== 'eip155') {
323
- throw new Error('estimateGas - chainNamespace is not eip155');
324
- }
325
-
326
- const txParams = {
327
- from: address,
328
- to,
329
- data,
330
- type: 0
331
- };
332
- const browserProvider = new BrowserProvider(provider, Number(caipNetwork?.id));
333
- const signer = new JsonRpcSigner(browserProvider, address);
334
-
335
- return await signer.estimateGas(txParams);
336
- } catch (error) {
337
- throw new Error('Ethers: estimateGas - Estimate gas failed');
338
- }
339
- },
340
-
341
- parseUnits: (value: string, decimals: number) => parseUnits(value, decimals),
342
-
343
- formatUnits: (value: bigint, decimals: number) => formatUnits(value, decimals),
344
-
345
- sendTransaction: async (data: SendTransactionArgs) => {
346
- const { chainId, provider, address } = EthersStoreUtil.state;
347
-
348
- if (!provider) {
349
- throw new Error('ethersClient:sendTransaction - provider is undefined');
350
- }
351
-
352
- if (!address) {
353
- throw new Error('ethersClient:sendTransaction - address is undefined');
354
- }
355
-
356
- const txParams = {
357
- to: data.to,
358
- value: data.value,
359
- gasLimit: data.gas,
360
- gasPrice: data.gasPrice,
361
- data: data.data,
362
- type: 0
363
- };
364
-
365
- const browserProvider = new BrowserProvider(provider, chainId);
366
- const signer = new JsonRpcSigner(browserProvider, address);
367
- const txResponse = await signer.sendTransaction(txParams);
368
- const txReceipt = await txResponse.wait();
369
-
370
- return (txReceipt?.hash as `0x${string}`) || null;
371
- },
372
-
373
- writeContract: async (data: WriteContractArgs) => {
374
- const { chainId, provider, address } = EthersStoreUtil.state;
375
-
376
- if (!provider) {
377
- throw new Error('ethersClient:writeContract - provider is undefined');
378
- }
379
-
380
- if (!address) {
381
- throw new Error('ethersClient:writeContract - address is undefined');
382
- }
383
-
384
- const browserProvider = new BrowserProvider(provider, chainId);
385
- const signer = new JsonRpcSigner(browserProvider, address);
386
- const contract = new Contract(data.tokenAddress, data.abi, signer);
387
-
388
- if (!contract || !data.method) {
389
- throw new Error('Contract method is undefined');
390
- }
391
-
392
- const method = contract[data.method];
393
- if (method) {
394
- const tx = await method(data.receiverAddress, data.tokenAmount);
395
-
396
- return tx;
397
- }
398
-
399
- throw new Error('Contract method is undefined');
400
- },
401
-
402
- getEnsAddress: async (value: string) => {
403
- try {
404
- const chainId = Number(this.getCaipNetwork()?.id);
405
- let ensName: string | null = null;
406
- let wcName: boolean | string = false;
407
-
408
- if (NamesUtil.isReownName(value)) {
409
- wcName = (await this?.resolveReownName(value)) || false;
410
- }
411
-
412
- // If on mainnet, fetch from ENS
413
- if (chainId === 1) {
414
- const ensProvider = new InfuraProvider('mainnet');
415
- ensName = await ensProvider.resolveName(value);
416
- }
417
-
418
- return ensName || wcName || false;
419
- } catch {
420
- return false;
421
- }
422
- },
423
-
424
- getEnsAvatar: async (value: string) => {
425
- const chainId = Number(NetworkUtil.caipNetworkIdToNumber(this.getCaipNetwork()?.id));
426
- if (chainId === 1) {
427
- const ensProvider = new InfuraProvider('mainnet');
428
- const avatar = await ensProvider.getAvatar(value);
429
-
430
- return avatar || false;
431
- }
432
-
433
- return false;
434
- }
435
- };
436
-
437
- super({
438
- networkControllerClient,
439
- connectionControllerClient,
440
- siweControllerClient: siweConfig,
441
- defaultChain: EthersHelpersUtil.getCaipDefaultChain(defaultChain),
442
- tokens: HelpersUtil.getCaipTokens(tokens),
443
- _sdkVersion: _sdkVersion ?? `react-native-ethers-${ConstantsUtil.VERSION}`,
444
- ...appKitOptions
445
- });
446
-
447
- this.options = options;
448
-
449
- this.metadata = config.metadata;
450
-
451
- this.projectId = appKitOptions.projectId;
452
- this.chains = chains;
453
-
454
- this.createProvider();
455
-
456
- EthersStoreUtil.subscribeKey('address', address => {
457
- this.syncAccount({ address });
458
- });
459
-
460
- EthersStoreUtil.subscribeKey('chainId', () => {
461
- this.syncNetwork(chainImages);
462
- });
463
-
464
- EthersStoreUtil.subscribeKey('provider', provider => {
465
- this.syncConnectedWalletInfo(provider);
466
- });
467
-
468
- this.syncRequestedNetworks(chains, chainImages);
469
- this.syncConnectors(config);
470
- this.syncAuthConnector(config);
471
- }
472
-
473
- // -- Public ------------------------------------------------------------------
474
-
475
- // @ts-expect-error: Overriden state type is correct
476
- public override getState() {
477
- const state = super.getState();
478
-
479
- return {
480
- ...state,
481
- selectedNetworkId: NetworkUtil.caipNetworkIdToNumber(state.selectedNetworkId)
482
- };
483
- }
484
-
485
- // @ts-expect-error: Overriden state type is correct
486
- public override subscribeState(callback: (state: AppKitState) => void) {
487
- return super.subscribeState(state =>
488
- callback({
489
- ...state,
490
- selectedNetworkId: NetworkUtil.caipNetworkIdToNumber(state.selectedNetworkId)
491
- })
492
- );
493
- }
494
-
495
- public setAddress(address?: string) {
496
- const originalAddress = address ? (getAddress(address) as Address) : undefined;
497
- EthersStoreUtil.setAddress(originalAddress);
498
- }
499
-
500
- public getAddress() {
501
- const { address } = EthersStoreUtil.state;
502
-
503
- return address ? getAddress(address) : address;
504
- }
505
-
506
- public getError() {
507
- return EthersStoreUtil.state.error;
508
- }
509
-
510
- public getChainId() {
511
- return EthersStoreUtil.state.chainId;
512
- }
513
-
514
- public getIsConnected() {
515
- return EthersStoreUtil.state.isConnected;
516
- }
517
-
518
- public getWalletProvider() {
519
- return EthersStoreUtil.state.provider;
520
- }
521
-
522
- public getWalletProviderType() {
523
- return EthersStoreUtil.state.providerType;
524
- }
525
-
526
- public subscribeProvider(callback: (newState: EthersStoreUtilState) => void) {
527
- return EthersStoreUtil.subscribe(callback);
528
- }
529
-
530
- public async disconnect() {
531
- const { provider } = EthersStoreUtil.state;
532
- StorageUtil.removeItem(EthersConstantsUtil.WALLET_ID);
533
- EthersStoreUtil.reset();
534
- this.setClientId(null);
535
-
536
- await (provider as unknown as EthereumProvider).disconnect();
537
- }
538
-
539
- // -- Private -----------------------------------------------------------------
540
- private createProvider() {
541
- if (!this.walletConnectProviderInitPromise) {
542
- this.walletConnectProviderInitPromise = this.initWalletConnectProvider();
543
- }
544
-
545
- return this.walletConnectProviderInitPromise;
546
- }
547
-
548
- private async initWalletConnectProvider() {
549
- const rpcMap = this.chains
550
- ? this.chains.reduce<Record<number, string>>((map, chain) => {
551
- map[chain.chainId] = chain.rpcUrl;
552
-
553
- return map;
554
- }, {})
555
- : ({} as Record<number, string>);
556
-
557
- const walletConnectProviderOptions: EthereumProviderOptions = {
558
- projectId: this.projectId,
559
- showQrModal: false,
560
- rpcMap,
561
- chains: [],
562
- optionalChains: [...this.chains.map(chain => chain.chainId)] as [number],
563
- metadata: this.metadata
564
- };
565
-
566
- this.walletConnectProvider = await EthereumProvider.init(walletConnectProviderOptions);
567
- this.addWalletConnectListeners(this.walletConnectProvider);
568
-
569
- await this.checkActiveWalletConnectProvider();
570
- }
571
-
572
- private async getWalletConnectProvider() {
573
- if (!this.walletConnectProvider) {
574
- try {
575
- await this.createProvider();
576
- } catch (error) {
577
- EthersStoreUtil.setError(error);
578
- }
579
- }
580
-
581
- return this.walletConnectProvider;
582
- }
583
-
584
- private syncRequestedNetworks(
585
- chains: AppKitClientOptions['chains'],
586
- chainImages?: AppKitClientOptions['chainImages']
587
- ) {
588
- const requestedCaipNetworks = chains?.map(
589
- chain =>
590
- ({
591
- id: `${ConstantsUtil.EIP155}:${chain.chainId}`,
592
- name: chain.name,
593
- imageId: PresetsUtil.EIP155NetworkImageIds[chain.chainId],
594
- imageUrl: chainImages?.[chain.chainId]
595
- }) as CaipNetwork
596
- );
597
- this.setRequestedCaipNetworks(requestedCaipNetworks ?? []);
598
- }
599
-
600
- private async checkActiveWalletConnectProvider() {
601
- const WalletConnectProvider = await this.getWalletConnectProvider();
602
- const walletId = await StorageUtil.getItem(EthersConstantsUtil.WALLET_ID);
603
-
604
- if (WalletConnectProvider) {
605
- if (walletId === ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID) {
606
- await this.setWalletConnectProvider();
607
- }
608
- }
609
- }
610
-
611
- private async checkActiveCoinbaseProvider(provider: Provider) {
612
- const CoinbaseProvider = provider as unknown as ExternalProvider;
613
- const walletId = await StorageUtil.getItem(EthersConstantsUtil.WALLET_ID);
614
-
615
- if (CoinbaseProvider) {
616
- if (walletId === ConstantsUtil.COINBASE_CONNECTOR_ID) {
617
- if (CoinbaseProvider.address) {
618
- await this.setCoinbaseProvider(provider);
619
- await this.watchCoinbase(provider);
620
- } else {
621
- await StorageUtil.removeItem(EthersConstantsUtil.WALLET_ID);
622
- EthersStoreUtil.reset();
623
- }
624
- }
625
- }
626
- }
627
-
628
- private async setWalletConnectProvider() {
629
- StorageUtil.setItem(EthersConstantsUtil.WALLET_ID, ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID);
630
- const WalletConnectProvider = await this.getWalletConnectProvider();
631
- if (WalletConnectProvider) {
632
- const providerType = PresetsUtil.ConnectorTypesMap[ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID];
633
- EthersStoreUtil.setChainId(WalletConnectProvider.chainId);
634
- EthersStoreUtil.setProviderType(providerType);
635
- EthersStoreUtil.setProvider(WalletConnectProvider as unknown as Provider);
636
- EthersStoreUtil.setIsConnected(true);
637
- this.setAddress(WalletConnectProvider.accounts?.[0]);
638
- await this.watchWalletConnect();
639
- }
640
- }
641
-
642
- private async setCoinbaseProvider(provider: Provider) {
643
- await StorageUtil.setItem(EthersConstantsUtil.WALLET_ID, ConstantsUtil.COINBASE_CONNECTOR_ID);
644
-
645
- if (provider) {
646
- const { address, chainId } = await EthersHelpersUtil.getUserInfo(provider);
647
- if (address && chainId) {
648
- const providerType = PresetsUtil.ConnectorTypesMap[ConstantsUtil.COINBASE_CONNECTOR_ID];
649
- EthersStoreUtil.setChainId(chainId);
650
- EthersStoreUtil.setProviderType(providerType);
651
- EthersStoreUtil.setProvider(provider);
652
- EthersStoreUtil.setIsConnected(true);
653
- this.setAddress(address);
654
- await this.watchCoinbase(provider);
655
- }
656
- }
657
- }
658
-
659
- private async setAuthProvider() {
660
- StorageUtil.setItem(EthersConstantsUtil.WALLET_ID, ConstantsUtil.AUTH_CONNECTOR_ID);
661
-
662
- if (this.authProvider) {
663
- const { address, chainId } = await this.authProvider.connect();
664
- super.setLoading(false);
665
- if (address && chainId) {
666
- EthersStoreUtil.setChainId(chainId);
667
- EthersStoreUtil.setProviderType(
668
- PresetsUtil.ConnectorTypesMap[ConstantsUtil.AUTH_CONNECTOR_ID]
669
- );
670
- EthersStoreUtil.setProvider(this.authProvider as CombinedProviderType);
671
- EthersStoreUtil.setIsConnected(true);
672
- EthersStoreUtil.setAddress(address as Address);
673
- }
674
- }
675
- }
676
-
677
- private async watchWalletConnect() {
678
- const WalletConnectProvider = await this.getWalletConnectProvider();
679
-
680
- function disconnectHandler() {
681
- StorageUtil.removeItem(EthersConstantsUtil.WALLET_ID);
682
- EthersStoreUtil.reset();
683
-
684
- WalletConnectProvider?.removeListener('disconnect', disconnectHandler);
685
- WalletConnectProvider?.removeListener('accountsChanged', accountsChangedHandler);
686
- WalletConnectProvider?.removeListener('chainChanged', chainChangedHandler);
687
- }
688
-
689
- function chainChangedHandler(chainId: string) {
690
- if (chainId) {
691
- const chain = EthersHelpersUtil.hexStringToNumber(chainId);
692
- EthersStoreUtil.setChainId(chain);
693
- }
694
- }
695
-
696
- const accountsChangedHandler = async (accounts: string[]) => {
697
- if (accounts.length > 0) {
698
- await this.setWalletConnectProvider();
699
- }
700
- };
701
-
702
- if (WalletConnectProvider) {
703
- WalletConnectProvider.on('disconnect', disconnectHandler);
704
- WalletConnectProvider.on('accountsChanged', accountsChangedHandler);
705
- WalletConnectProvider.on('chainChanged', chainChangedHandler);
706
- }
707
- }
708
-
709
- private async watchCoinbase(provider: Provider) {
710
- const walletId = await StorageUtil.getItem(EthersConstantsUtil.WALLET_ID);
711
-
712
- function disconnectHandler() {
713
- StorageUtil.removeItem(EthersConstantsUtil.WALLET_ID);
714
- EthersStoreUtil.reset();
715
-
716
- provider?.removeListener('disconnect', disconnectHandler);
717
- provider?.removeListener('accountsChanged', accountsChangedHandler);
718
- provider?.removeListener('chainChanged', chainChangedHandler);
719
- }
720
-
721
- function accountsChangedHandler(accounts: string[]) {
722
- if (accounts.length === 0) {
723
- StorageUtil.removeItem(EthersConstantsUtil.WALLET_ID);
724
- EthersStoreUtil.reset();
725
- } else {
726
- EthersStoreUtil.setAddress(accounts[0] as Address);
727
- }
728
- }
729
-
730
- function chainChangedHandler(chainId: string) {
731
- if (chainId && walletId === ConstantsUtil.COINBASE_CONNECTOR_ID) {
732
- const chain = Number(chainId);
733
- EthersStoreUtil.setChainId(chain);
734
- }
735
- }
736
-
737
- if (provider) {
738
- provider.on('disconnect', disconnectHandler);
739
- provider.on('accountsChanged', accountsChangedHandler);
740
- provider.on('chainChanged', chainChangedHandler);
741
- }
742
- }
743
-
744
- private async syncAccount({ address }: { address?: Address }) {
745
- const chainId = EthersStoreUtil.state.chainId;
746
- const isConnected = EthersStoreUtil.state.isConnected;
747
-
748
- if (isConnected && address && chainId) {
749
- const caipAddress: CaipAddress = `${ConstantsUtil.EIP155}:${chainId}:${address}`;
750
-
751
- this.setIsConnected(isConnected);
752
-
753
- this.setCaipAddress(caipAddress);
754
-
755
- await Promise.all([
756
- this.syncProfile(address),
757
- this.syncBalance(address),
758
- this.getApprovedCaipNetworksData()
759
- ]);
760
- this.hasSyncedConnectedAccount = true;
761
- } else if (!isConnected && this.hasSyncedConnectedAccount) {
762
- this.close();
763
- this.resetAccount();
764
- this.resetWcConnection();
765
- this.resetNetwork();
766
- }
767
- }
768
-
769
- private async syncNetwork(chainImages?: AppKitClientOptions['chainImages']) {
770
- const address = EthersStoreUtil.state.address;
771
- const chainId = EthersStoreUtil.state.chainId;
772
- const isConnected = EthersStoreUtil.state.isConnected;
773
- if (this.chains) {
774
- const chain = this.chains.find(c => c.chainId === chainId);
775
-
776
- if (chain) {
777
- const caipChainId: CaipNetworkId = `${ConstantsUtil.EIP155}:${chain.chainId}`;
778
-
779
- this.setCaipNetwork({
780
- id: caipChainId,
781
- name: chain.name,
782
- imageId: PresetsUtil.EIP155NetworkImageIds[chain.chainId],
783
- imageUrl: chainImages?.[chain.chainId]
784
- });
785
- if (isConnected && address) {
786
- const caipAddress: CaipAddress = `${ConstantsUtil.EIP155}:${chainId}:${address}`;
787
- this.setCaipAddress(caipAddress);
788
- if (chain.explorerUrl) {
789
- const url = `${chain.explorerUrl}/address/${address}`;
790
- this.setAddressExplorerUrl(url);
791
- } else {
792
- this.setAddressExplorerUrl(undefined);
793
- }
794
-
795
- if (this.hasSyncedConnectedAccount) {
796
- await this.syncBalance(address);
797
- }
798
- }
799
- }
800
- }
801
- }
802
-
803
- private async syncProfile(address: Address) {
804
- const chainId = EthersStoreUtil.state.chainId;
805
-
806
- try {
807
- const response = await this.fetchIdentity({ address });
808
-
809
- if (!response) {
810
- throw new Error('Couldnt fetch idendity');
811
- }
812
-
813
- this.setProfileName(response.name);
814
- this.setProfileImage(response.avatar);
815
- } catch {
816
- if (chainId === 1) {
817
- const ensProvider = new InfuraProvider('mainnet');
818
- const name = await ensProvider.lookupAddress(address);
819
- const avatar = await ensProvider.getAvatar(address);
820
-
821
- if (name) {
822
- this.setProfileName(name);
823
- }
824
- if (avatar) {
825
- this.setProfileImage(avatar);
826
- }
827
- } else {
828
- this.setProfileName(undefined);
829
- this.setProfileImage(undefined);
830
- }
831
- }
832
- }
833
-
834
- private async syncBalance(address: Address) {
835
- const chainId = EthersStoreUtil.state.chainId;
836
- if (chainId && this.chains) {
837
- const chain = this.chains.find(c => c.chainId === chainId);
838
- const token = this.options?.tokens?.[chainId];
839
-
840
- try {
841
- if (chain) {
842
- const jsonRpcProvider = new JsonRpcProvider(chain.rpcUrl, {
843
- chainId,
844
- name: chain.name
845
- });
846
-
847
- if (jsonRpcProvider) {
848
- if (token) {
849
- // Get balance from custom token address
850
- const erc20 = new Contract(token.address, erc20ABI, jsonRpcProvider);
851
- // @ts-expect-error
852
- const decimals = await erc20.decimals();
853
- // @ts-expect-error
854
- const symbol = await erc20.symbol();
855
- // @ts-expect-error
856
- const balanceOf = await erc20.balanceOf(address);
857
- this.setBalance(formatUnits(balanceOf, decimals), symbol);
858
- } else {
859
- const balance = await jsonRpcProvider.getBalance(address);
860
- const formattedBalance = formatEther(balance);
861
- this.setBalance(formattedBalance, chain.currency);
862
- }
863
- }
864
- }
865
- } catch {
866
- this.setBalance(undefined, undefined);
867
- }
868
- }
869
- }
870
-
871
- private async switchNetwork(chainId: number) {
872
- const provider = EthersStoreUtil.state.provider;
873
- const providerType = EthersStoreUtil.state.providerType;
874
- if (this.chains) {
875
- const chain = this.chains.find(c => c.chainId === chainId);
876
-
877
- const walletConnectType =
878
- PresetsUtil.ConnectorTypesMap[ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID];
879
-
880
- const coinbaseType = PresetsUtil.ConnectorTypesMap[ConstantsUtil.COINBASE_CONNECTOR_ID];
881
-
882
- const authType = PresetsUtil.ConnectorTypesMap[ConstantsUtil.AUTH_CONNECTOR_ID];
883
-
884
- if (providerType === walletConnectType && chain) {
885
- const WalletConnectProvider = provider as unknown as EthereumProvider;
886
-
887
- if (WalletConnectProvider) {
888
- try {
889
- await WalletConnectProvider.request({
890
- method: 'wallet_switchEthereumChain',
891
- params: [{ chainId: EthersHelpersUtil.numberToHexString(chain.chainId) }]
892
- });
893
-
894
- EthersStoreUtil.setChainId(chainId);
895
- } catch (switchError: any) {
896
- const message = switchError?.message as string;
897
- if (/(?<temp1>user rejected)/u.test(message?.toLowerCase())) {
898
- throw new Error('Chain is not supported');
899
- }
900
- await EthersHelpersUtil.addEthereumChain(
901
- WalletConnectProvider as unknown as Provider,
902
- chain
903
- );
904
- }
905
- }
906
- } else if (providerType === coinbaseType && chain) {
907
- const CoinbaseProvider = provider;
908
- if (CoinbaseProvider) {
909
- try {
910
- await CoinbaseProvider.request({
911
- method: 'wallet_switchEthereumChain',
912
- params: [{ chainId: EthersHelpersUtil.numberToHexString(chain.chainId) }]
913
- });
914
- EthersStoreUtil.setChainId(chain.chainId);
915
- } catch (switchError: any) {
916
- if (
917
- switchError.code === EthersConstantsUtil.ERROR_CODE_UNRECOGNIZED_CHAIN_ID ||
918
- switchError.code === EthersConstantsUtil.ERROR_CODE_DEFAULT ||
919
- switchError?.data?.originalError?.code ===
920
- EthersConstantsUtil.ERROR_CODE_UNRECOGNIZED_CHAIN_ID
921
- ) {
922
- await EthersHelpersUtil.addEthereumChain(CoinbaseProvider, chain);
923
- } else {
924
- throw new Error('Error switching network');
925
- }
926
- }
927
- }
928
- } else if (providerType === authType) {
929
- if (this.authProvider && chain?.chainId) {
930
- try {
931
- await this.authProvider?.switchNetwork(chain?.chainId);
932
- EthersStoreUtil.setChainId(chain.chainId);
933
- } catch {
934
- throw new Error('Switching chain failed');
935
- }
936
- }
937
- }
938
- }
939
- }
940
-
941
- private async handleAuthSetPreferredAccount(address: string, type: AppKitFrameAccountType) {
942
- if (!address) {
943
- return;
944
- }
945
-
946
- const chainId = this.getCaipNetwork()?.id;
947
- const caipAddress: CaipAddress = `${ConstantsUtil.EIP155}:${chainId}:${address}`;
948
- this.setCaipAddress(caipAddress);
949
- this.setPreferredAccountType(type);
950
-
951
- await this.syncAccount({ address: address as Address });
952
- this.setLoading(false);
953
- }
954
-
955
- private syncConnectors(config: ProviderType) {
956
- const _connectors: Connector[] = [];
957
- const EXCLUDED_CONNECTORS = [ConstantsUtil.AUTH_CONNECTOR_ID];
958
-
959
- _connectors.push({
960
- id: ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID,
961
- explorerId: PresetsUtil.ConnectorExplorerIds[ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID],
962
- imageId: PresetsUtil.ConnectorImageIds[ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID],
963
- imageUrl: this.options?.connectorImages?.[ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID],
964
- name: PresetsUtil.ConnectorNamesMap[ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID],
965
- type: PresetsUtil.ConnectorTypesMap[ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID]!
966
- });
967
-
968
- config.extraConnectors?.forEach(connector => {
969
- if (!EXCLUDED_CONNECTORS.includes(connector.id)) {
970
- if (connector.id === ConstantsUtil.COINBASE_CONNECTOR_ID) {
971
- _connectors.push({
972
- id: ConstantsUtil.COINBASE_CONNECTOR_ID,
973
- explorerId: PresetsUtil.ConnectorExplorerIds[ConstantsUtil.COINBASE_CONNECTOR_ID],
974
- imageId: PresetsUtil.ConnectorImageIds[ConstantsUtil.COINBASE_CONNECTOR_ID],
975
- imageUrl: this.options?.connectorImages?.[ConstantsUtil.COINBASE_CONNECTOR_ID],
976
- name:
977
- connector?.name ?? PresetsUtil.ConnectorNamesMap[ConstantsUtil.COINBASE_CONNECTOR_ID],
978
- type: PresetsUtil.ConnectorTypesMap[ConstantsUtil.COINBASE_CONNECTOR_ID]!
979
- });
980
- this.checkActiveCoinbaseProvider(connector as Provider);
981
- } else {
982
- _connectors.push({
983
- id: connector.id,
984
- name: connector.name ?? PresetsUtil.ConnectorNamesMap[connector.id],
985
- type: 'EXTERNAL'
986
- });
987
- }
988
- }
989
- });
990
-
991
- this.setConnectors(_connectors);
992
- }
993
-
994
- private async syncAuthConnector(config: ProviderType) {
995
- const authConnector = config.extraConnectors?.find(
996
- connector => connector.id === ConstantsUtil.AUTH_CONNECTOR_ID
997
- );
998
-
999
- if (!authConnector) {
1000
- return;
1001
- }
1002
-
1003
- this.authProvider = authConnector as AppKitFrameProvider;
1004
-
1005
- this.addConnector({
1006
- id: ConstantsUtil.AUTH_CONNECTOR_ID,
1007
- name: PresetsUtil.ConnectorNamesMap[ConstantsUtil.AUTH_CONNECTOR_ID],
1008
- type: PresetsUtil.ConnectorTypesMap[ConstantsUtil.AUTH_CONNECTOR_ID]!,
1009
- provider: authConnector
1010
- });
1011
-
1012
- const connectedConnector = await StorageUtil.getItem('@w3m/connected_connector');
1013
- if (connectedConnector === 'AUTH') {
1014
- // Set loader until it reconnects
1015
- this.setLoading(true);
1016
- }
1017
-
1018
- const { isConnected } = await this.authProvider.isConnected();
1019
- if (isConnected) {
1020
- this.setAuthProvider();
1021
- }
1022
-
1023
- this.addAuthListeners(this.authProvider);
1024
- }
1025
-
1026
- private async syncConnectedWalletInfo(provider?: Provider) {
1027
- if (!provider) {
1028
- this.setConnectedWalletInfo(undefined);
1029
-
1030
- return;
1031
- }
1032
-
1033
- if ((provider as any)?.session?.peer?.metadata) {
1034
- const metadata = (provider as unknown as EthereumProvider)?.session?.peer.metadata;
1035
- if (metadata) {
1036
- this.setConnectedWalletInfo({
1037
- ...metadata,
1038
- name: metadata.name,
1039
- icon: metadata.icons?.[0]
1040
- });
1041
- }
1042
- } else if (provider?.id) {
1043
- this.setConnectedWalletInfo({
1044
- id: provider.id,
1045
- name: provider?.name ?? PresetsUtil.ConnectorNamesMap[provider.id],
1046
- icon: this.options?.connectorImages?.[provider.id]
1047
- });
1048
- } else {
1049
- this.setConnectedWalletInfo(undefined);
1050
- }
1051
- }
1052
-
1053
- private async addAuthListeners(authProvider: AppKitFrameProvider) {
1054
- authProvider.onSetPreferredAccount(async ({ address, type }) => {
1055
- if (address) {
1056
- await this.handleAuthSetPreferredAccount(address, type);
1057
- }
1058
- this.setLoading(false);
1059
- });
1060
-
1061
- authProvider.setOnTimeout(async () => {
1062
- this.handleAlertError(ErrorUtil.ALERT_ERRORS.SOCIALS_TIMEOUT);
1063
- this.setLoading(false);
1064
- });
1065
- }
1066
-
1067
- private async addWalletConnectListeners(provider: EthereumProvider) {
1068
- if (provider) {
1069
- provider.signer.client.core.relayer.on('relayer_connect', () => {
1070
- provider.signer.client.core.relayer?.provider?.on('payload', (payload: JsonRpcError) => {
1071
- if (payload?.error) {
1072
- this.handleAlertError(payload?.error.message);
1073
- }
1074
- });
1075
- });
1076
- }
1077
- }
1078
- }