@reown/appkit 1.3.1 → 1.4.0

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 (34) hide show
  1. package/dist/esm/exports/adapters.js +2 -0
  2. package/dist/esm/exports/adapters.js.map +1 -0
  3. package/dist/esm/exports/constants.js +1 -1
  4. package/dist/esm/package.json +9 -1
  5. package/dist/esm/src/adapters/ChainAdapterBlueprint.js +138 -0
  6. package/dist/esm/src/adapters/ChainAdapterBlueprint.js.map +1 -0
  7. package/dist/esm/src/adapters/ChainAdapterConnector.js +2 -0
  8. package/dist/esm/src/adapters/ChainAdapterConnector.js.map +1 -0
  9. package/dist/esm/src/adapters/index.js +2 -0
  10. package/dist/esm/src/adapters/index.js.map +1 -0
  11. package/dist/esm/src/client.js +888 -40
  12. package/dist/esm/src/client.js.map +1 -1
  13. package/dist/esm/src/store/ProviderUtil.js.map +1 -1
  14. package/dist/esm/src/universal-adapter/client.js +98 -532
  15. package/dist/esm/src/universal-adapter/client.js.map +1 -1
  16. package/dist/esm/src/universal-adapter/index.js +1 -1
  17. package/dist/esm/src/universal-adapter/index.js.map +1 -1
  18. package/dist/esm/src/utils/HelpersUtil.js +6 -0
  19. package/dist/esm/src/utils/HelpersUtil.js.map +1 -1
  20. package/dist/esm/tsconfig.build.tsbuildinfo +1 -1
  21. package/dist/types/exports/adapters.d.ts +1 -0
  22. package/dist/types/exports/constants.d.ts +1 -1
  23. package/dist/types/src/adapters/ChainAdapterBlueprint.d.ts +324 -0
  24. package/dist/types/src/adapters/ChainAdapterConnector.d.ts +5 -0
  25. package/dist/types/src/adapters/index.d.ts +1 -0
  26. package/dist/types/src/client.d.ts +49 -10
  27. package/dist/types/src/library/react/index.d.ts +1 -1
  28. package/dist/types/src/library/vue/index.d.ts +1 -1
  29. package/dist/types/src/store/ProviderUtil.d.ts +5 -4
  30. package/dist/types/src/store/index.d.ts +1 -1
  31. package/dist/types/src/universal-adapter/client.d.ts +32 -44
  32. package/dist/types/src/universal-adapter/index.d.ts +1 -1
  33. package/dist/types/src/utils/HelpersUtil.d.ts +1 -0
  34. package/package.json +17 -9
@@ -1,16 +1,60 @@
1
- import { AccountController, BlockchainApiController, ConnectionController, ConnectorController, CoreHelperUtil, EventsController, ModalController, ChainController, PublicStateController, ThemeController, SnackController, RouterController, EnsController, OptionsController, AssetUtil, ApiController, AlertController } from '@reown/appkit-core';
1
+ /* eslint-disable max-depth */
2
+ import { ConstantsUtil as CoreConstantsUtil } from '@reown/appkit-core';
3
+ import { AccountController, BlockchainApiController, ConnectionController, ConnectorController, CoreHelperUtil, EventsController, ModalController, ChainController, PublicStateController, ThemeController, SnackController, RouterController, EnsController, OptionsController, AssetUtil, ApiController, AlertController, StorageUtil } from '@reown/appkit-core';
2
4
  import { setColorTheme, setThemeVariables } from '@reown/appkit-ui';
3
5
  import { ConstantsUtil, SafeLocalStorage, SafeLocalStorageKeys } from '@reown/appkit-common';
4
- import { UniversalAdapterClient } from './universal-adapter/client.js';
5
- import { CaipNetworksUtil, ErrorUtil } from '@reown/appkit-utils';
6
+ import { UniversalAdapter, UniversalAdapter as UniversalAdapterClient } from './universal-adapter/client.js';
7
+ import { CaipNetworksUtil, ErrorUtil, ConstantsUtil as UtilConstantsUtil } from '@reown/appkit-utils';
8
+ import { W3mFrameHelpers, W3mFrameRpcConstants } from '@reown/appkit-wallet';
6
9
  import { ProviderUtil } from './store/ProviderUtil.js';
10
+ import UniversalProvider from '@walletconnect/universal-provider';
11
+ import { W3mFrameProviderSingleton } from './auth-provider/W3MFrameProviderSingleton.js';
7
12
  // -- Export Controllers -------------------------------------------------------
8
13
  export { AccountController };
14
+ // -- Constants ----------------------------------------- //
15
+ const accountState = {
16
+ currentTab: 0,
17
+ tokenBalance: [],
18
+ smartAccountDeployed: false,
19
+ addressLabels: new Map(),
20
+ allAccounts: []
21
+ };
22
+ const networkState = {
23
+ supportsAllNetworks: true,
24
+ smartAccountEnabledNetworks: []
25
+ };
26
+ const OPTIONAL_METHODS = [
27
+ 'eth_accounts',
28
+ 'eth_requestAccounts',
29
+ 'eth_sendRawTransaction',
30
+ 'eth_sign',
31
+ 'eth_signTransaction',
32
+ 'eth_signTypedData',
33
+ 'eth_signTypedData_v3',
34
+ 'eth_signTypedData_v4',
35
+ 'eth_sendTransaction',
36
+ 'personal_sign',
37
+ 'wallet_switchEthereumChain',
38
+ 'wallet_addEthereumChain',
39
+ 'wallet_getPermissions',
40
+ 'wallet_requestPermissions',
41
+ 'wallet_registerOnboarding',
42
+ 'wallet_watchAsset',
43
+ 'wallet_scanQRCode',
44
+ // EIP-5792
45
+ 'wallet_getCallsStatus',
46
+ 'wallet_sendCalls',
47
+ 'wallet_getCapabilities',
48
+ // EIP-7715
49
+ 'wallet_grantPermissions',
50
+ 'wallet_revokePermissions'
51
+ ];
9
52
  // -- Helpers -------------------------------------------------------------------
10
53
  let isInitialized = false;
11
54
  // -- Client --------------------------------------------------------------------
12
55
  export class AppKit {
13
56
  constructor(options) {
57
+ this.chainNamespaces = [];
14
58
  this.initPromise = undefined;
15
59
  this.setStatus = (status, chain) => {
16
60
  AccountController.setStatus(status, chain);
@@ -32,6 +76,7 @@ export class AppKit {
32
76
  }
33
77
  return ChainController.getAccountProp('caipAddress', chainNamespace);
34
78
  };
79
+ this.getAddressByChainNamespace = (chainNamespace) => ChainController.getAccountProp('address', chainNamespace);
35
80
  this.getAddress = (chainNamespace) => {
36
81
  if (ChainController.state.activeChain === chainNamespace || !chainNamespace) {
37
82
  return AccountController.state.address;
@@ -112,11 +157,6 @@ export class AppKit {
112
157
  AccountController.setPreferredAccountType(preferredAccountType, chain);
113
158
  };
114
159
  this.getReownName = address => EnsController.getNamesForAddress(address);
115
- this.resolveReownName = async (name) => {
116
- const wcNameAddress = await EnsController.resolveName(name);
117
- const networkNameAddresses = Object.values(wcNameAddress?.addresses) || [];
118
- return networkNameAddresses[0]?.address || false;
119
- };
120
160
  this.setEIP6963Enabled = enabled => {
121
161
  OptionsController.setEIP6963Enabled(enabled);
122
162
  };
@@ -138,17 +178,27 @@ export class AppKit {
138
178
  this.open({ view: 'ApproveTransaction' });
139
179
  }
140
180
  };
141
- // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
142
- this.adapter = options.adapters?.[0];
143
- this.caipNetworks = this.extendCaipNetworks(options);
144
- this.defaultCaipNetwork = this.extendDefaultCaipNetwork(options);
145
- this.initControllers(options);
146
- this.initOrContinue();
147
- this.version = options.sdkVersion;
181
+ this.options = options;
182
+ this.initialize(options);
148
183
  }
149
184
  static getInstance() {
150
185
  return this.instance;
151
186
  }
187
+ async initialize(options) {
188
+ this.caipNetworks = this.extendCaipNetworks(options);
189
+ this.defaultCaipNetwork = this.extendDefaultCaipNetwork(options);
190
+ await this.initControllers(options);
191
+ this.createAuthProvider();
192
+ await this.createUniversalProvider();
193
+ this.createClients();
194
+ ChainController.initialize(options.adapters ?? []);
195
+ this.chainAdapters = await this.createAdapters(options.adapters);
196
+ await this.initChainAdapters();
197
+ this.syncRequestedNetworks();
198
+ await this.initOrContinue();
199
+ await this.syncExistingConnection();
200
+ this.version = options.sdkVersion;
201
+ }
152
202
  // -- Public -------------------------------------------------------------------
153
203
  async open(options) {
154
204
  await this.initOrContinue();
@@ -169,7 +219,7 @@ export class AppKit {
169
219
  return ChainController.state.activeCaipNetwork?.id;
170
220
  }
171
221
  switchNetwork(appKitNetwork) {
172
- const network = this.caipNetworks.find(n => n.id === appKitNetwork.id);
222
+ const network = this.caipNetworks?.find(n => n.id === appKitNetwork.id);
173
223
  if (!network) {
174
224
  AlertController.open(ErrorUtil.ALERT_ERRORS.SWITCH_NETWORK_NOT_FOUND, 'error');
175
225
  return;
@@ -289,8 +339,6 @@ export class AppKit {
289
339
  if (!options.metadata && defaultMetaData) {
290
340
  options.metadata = defaultMetaData;
291
341
  }
292
- this.initializeUniversalAdapter(options);
293
- this.initializeAdapters(options);
294
342
  this.setDefaultNetwork();
295
343
  OptionsController.setAllWallets(options.allWallets);
296
344
  OptionsController.setIncludeWalletIds(options.includeWalletIds);
@@ -321,7 +369,7 @@ export class AppKit {
321
369
  if (options.siwx) {
322
370
  OptionsController.setSIWX(options.siwx);
323
371
  }
324
- const evmAdapter = options.adapters?.find(adapter => adapter.chainNamespace === ConstantsUtil.CHAIN.EVM);
372
+ const evmAdapter = options.adapters?.find(adapter => adapter.namespace === ConstantsUtil.CHAIN.EVM);
325
373
  // Set the SIWE client for EVM chains
326
374
  if (evmAdapter) {
327
375
  if (options.siweConfig) {
@@ -358,35 +406,835 @@ export class AppKit {
358
406
  : undefined;
359
407
  return extendedNetwork;
360
408
  }
361
- initializeUniversalAdapter(options) {
362
- const extendedOptions = {
363
- ...options,
364
- networks: this.caipNetworks,
365
- defaultNetwork: this.defaultCaipNetwork
409
+ createClients() {
410
+ this.connectionControllerClient = {
411
+ connectWalletConnect: async (onUri) => {
412
+ const adapter = this.getAdapter(ChainController.state.activeChain);
413
+ this.universalProvider?.on('display_uri', (uri) => {
414
+ onUri(uri);
415
+ });
416
+ if (this.options.siweConfig) {
417
+ const siweParams = await this.options.siweConfig?.getMessageParams?.();
418
+ const isSiweEnabled = this.options.siweConfig?.options?.enabled;
419
+ const isProviderSupported = typeof this.universalProvider?.authenticate === 'function';
420
+ const isSiweParamsValid = siweParams && Object.keys(siweParams || {}).length > 0;
421
+ const clientId = await this.universalProvider?.client?.core?.crypto?.getClientId();
422
+ if (clientId) {
423
+ this.setClientId(clientId);
424
+ if (this.options.siweConfig &&
425
+ isSiweEnabled &&
426
+ siweParams &&
427
+ isProviderSupported &&
428
+ isSiweParamsValid &&
429
+ ChainController.state.activeChain === ConstantsUtil.CHAIN.EVM) {
430
+ const { SIWEController, getDidChainId, getDidAddress } = await import('@reown/appkit-siwe');
431
+ const chains = this.caipNetworks
432
+ ?.filter(network => network.chainNamespace === ConstantsUtil.CHAIN.EVM)
433
+ .map(chain => chain.caipNetworkId);
434
+ siweParams.chains = this.caipNetworks
435
+ ?.filter(network => network.chainNamespace === ConstantsUtil.CHAIN.EVM)
436
+ .map(chain => chain.id);
437
+ const result = await this.universalProvider?.authenticate({
438
+ nonce: await this.options.siweConfig?.getNonce?.(),
439
+ methods: [...OPTIONAL_METHODS],
440
+ ...siweParams,
441
+ chains
442
+ });
443
+ // Auths is an array of signed CACAO objects https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-74.md
444
+ const signedCacao = result?.auths?.[0];
445
+ if (signedCacao) {
446
+ const { p, s } = signedCacao;
447
+ const cacaoChainId = getDidChainId(p.iss);
448
+ const address = getDidAddress(p.iss);
449
+ if (address && cacaoChainId) {
450
+ SIWEController.setSession({
451
+ address,
452
+ chainId: parseInt(cacaoChainId, 10)
453
+ });
454
+ }
455
+ try {
456
+ // Kicks off verifyMessage and populates external states
457
+ const message = this.universalProvider?.client.formatAuthMessage({
458
+ request: p,
459
+ iss: p.iss
460
+ });
461
+ await SIWEController.verifyMessage({
462
+ message: message,
463
+ signature: s.s,
464
+ cacao: signedCacao
465
+ });
466
+ }
467
+ catch (error) {
468
+ // eslint-disable-next-line no-console
469
+ console.error('Error verifying message', error);
470
+ // eslint-disable-next-line no-console
471
+ await this.universalProvider?.disconnect().catch(console.error);
472
+ // eslint-disable-next-line no-console
473
+ await SIWEController.signOut().catch(console.error);
474
+ throw error;
475
+ }
476
+ }
477
+ }
478
+ }
479
+ }
480
+ else {
481
+ await adapter?.connectWalletConnect(onUri, this.getCaipNetwork()?.id);
482
+ }
483
+ await this.syncWalletConnectAccount();
484
+ },
485
+ connectExternal: async ({ id, info, type, provider, chain, caipNetwork }) => {
486
+ if (chain && chain !== ChainController.state.activeChain && !caipNetwork) {
487
+ const toConnectNetwork = this.caipNetworks?.find(network => network.chainNamespace === chain);
488
+ if (toConnectNetwork) {
489
+ this.setCaipNetwork(toConnectNetwork);
490
+ }
491
+ }
492
+ const adapter = chain
493
+ ? this.getAdapter(chain)
494
+ : this.getAdapter(ChainController.state.activeChain);
495
+ const res = await adapter?.connect({
496
+ id,
497
+ info,
498
+ type,
499
+ provider,
500
+ chainId: caipNetwork?.id || this.getCaipNetwork()?.id,
501
+ rpcUrl: caipNetwork?.rpcUrls?.default?.http?.[0] ||
502
+ this.getCaipNetwork()?.rpcUrls?.default?.http?.[0]
503
+ });
504
+ if (res) {
505
+ this.syncProvider({
506
+ ...res,
507
+ chainNamespace: chain || ChainController.state.activeChain
508
+ });
509
+ await this.syncAccount({
510
+ ...res,
511
+ chainNamespace: chain || ChainController.state.activeChain
512
+ });
513
+ }
514
+ },
515
+ reconnectExternal: async ({ id, info, type, provider }) => {
516
+ const adapter = this.getAdapter(ChainController.state.activeChain);
517
+ if (adapter?.reconnect) {
518
+ await adapter?.reconnect({ id, info, type, provider, chainId: this.getCaipNetwork()?.id });
519
+ }
520
+ },
521
+ disconnect: async () => {
522
+ const adapter = this.getAdapter(ChainController.state.activeChain);
523
+ const provider = ProviderUtil.getProvider(ChainController.state.activeChain);
524
+ if (this.options.siweConfig?.options?.signOutOnDisconnect) {
525
+ const { SIWEController } = await import('@reown/appkit-siwe');
526
+ await SIWEController.signOut();
527
+ }
528
+ const providerType = ProviderUtil.state.providerIds[ChainController.state.activeChain];
529
+ await adapter?.disconnect({ provider, providerType });
530
+ this.setStatus('disconnected', ChainController.state.activeChain);
531
+ localStorage.removeItem(SafeLocalStorageKeys.CONNECTED_CONNECTOR);
532
+ localStorage.removeItem(SafeLocalStorageKeys.ACTIVE_CAIP_NETWORK_ID);
533
+ ChainController.state.chains.forEach(chain => {
534
+ this.resetAccount(chain.namespace);
535
+ });
536
+ },
537
+ checkInstalled: (ids) => {
538
+ if (!ids) {
539
+ return Boolean(window.ethereum);
540
+ }
541
+ return ids.some(id => Boolean(window.ethereum?.[String(id)]));
542
+ },
543
+ signMessage: async (message) => {
544
+ const adapter = this.getAdapter(ChainController.state.activeChain);
545
+ const result = await adapter?.signMessage({
546
+ message,
547
+ address: AccountController.state.address,
548
+ provider: ProviderUtil.getProvider(ChainController.state.activeChain)
549
+ });
550
+ return result?.signature || '';
551
+ },
552
+ sendTransaction: async (args) => {
553
+ if (args.chainNamespace === 'eip155') {
554
+ const adapter = this.getAdapter(ChainController.state.activeChain);
555
+ const result = await adapter?.sendTransaction(args);
556
+ return result?.hash || '';
557
+ }
558
+ return '';
559
+ },
560
+ estimateGas: async (args) => {
561
+ if (args.chainNamespace === 'eip155') {
562
+ const adapter = this.getAdapter(ChainController.state.activeChain);
563
+ const provider = ProviderUtil.getProvider(ChainController.state.activeChain);
564
+ const caipNetwork = this.getCaipNetwork();
565
+ if (!caipNetwork) {
566
+ throw new Error('CaipNetwork is undefined');
567
+ }
568
+ const result = await adapter?.estimateGas({
569
+ ...args,
570
+ provider,
571
+ caipNetwork
572
+ });
573
+ return result?.gas || 0n;
574
+ }
575
+ return 0n;
576
+ },
577
+ getEnsAvatar: async () => {
578
+ const adapter = this.getAdapter(ChainController.state.activeChain);
579
+ const result = await adapter?.getProfile({
580
+ address: AccountController.state.address,
581
+ chainId: Number(this.getCaipNetwork()?.id)
582
+ });
583
+ return result?.profileImage || false;
584
+ },
585
+ getEnsAddress: async (name) => {
586
+ const adapter = this.getAdapter(ChainController.state.activeChain);
587
+ const caipNetwork = this.getCaipNetwork();
588
+ if (!caipNetwork) {
589
+ return false;
590
+ }
591
+ const result = await adapter?.getEnsAddress({
592
+ name,
593
+ caipNetwork
594
+ });
595
+ return result?.address || false;
596
+ },
597
+ writeContract: async (args) => {
598
+ const adapter = this.getAdapter(ChainController.state.activeChain);
599
+ const caipNetwork = this.getCaipNetwork();
600
+ const caipAddress = this.getCaipAddress();
601
+ const provider = ProviderUtil.getProvider(ChainController.state.activeChain);
602
+ if (!caipNetwork || !caipAddress) {
603
+ throw new Error('CaipNetwork or CaipAddress is undefined');
604
+ }
605
+ const result = await adapter?.writeContract({ ...args, caipNetwork, provider, caipAddress });
606
+ return result?.hash;
607
+ },
608
+ parseUnits: (value, decimals) => {
609
+ const adapter = this.getAdapter(ChainController.state.activeChain);
610
+ return adapter?.parseUnits({ value, decimals }) ?? 0n;
611
+ },
612
+ formatUnits: (value, decimals) => {
613
+ const adapter = this.getAdapter(ChainController.state.activeChain);
614
+ return adapter?.formatUnits({ value, decimals }) ?? '0';
615
+ },
616
+ getCapabilities: async (params) => {
617
+ const adapter = this.getAdapter(ChainController.state.activeChain);
618
+ await adapter?.getCapabilities(params);
619
+ },
620
+ grantPermissions: async (params) => {
621
+ const adapter = this.getAdapter(ChainController.state.activeChain);
622
+ return await adapter?.grantPermissions(params);
623
+ },
624
+ revokePermissions: async (params) => {
625
+ const adapter = this.getAdapter(ChainController.state.activeChain);
626
+ if (adapter?.revokePermissions) {
627
+ return await adapter.revokePermissions(params);
628
+ }
629
+ return '0x';
630
+ }
366
631
  };
367
- this.universalAdapter = new UniversalAdapterClient(extendedOptions);
368
- ChainController.initializeUniversalAdapter(this.universalAdapter, options.adapters || []);
369
- this.universalAdapter.construct?.(this, extendedOptions);
370
- }
371
- initializeAdapters(options) {
372
- const extendedOptions = {
373
- ...options,
374
- networks: this.caipNetworks,
375
- defaultNetwork: this.defaultCaipNetwork
632
+ this.networkControllerClient = {
633
+ switchCaipNetwork: async (caipNetwork) => {
634
+ if (!caipNetwork) {
635
+ return;
636
+ }
637
+ if (AccountController.state.address &&
638
+ caipNetwork.chainNamespace === ChainController.state.activeChain) {
639
+ const adapter = this.getAdapter(ChainController.state.activeChain);
640
+ const provider = ProviderUtil.getProvider(ChainController.state.activeChain);
641
+ const providerType = ProviderUtil.state.providerIds[ChainController.state.activeChain];
642
+ await adapter?.switchNetwork({ caipNetwork, provider, providerType });
643
+ this.setCaipNetwork(caipNetwork);
644
+ await this.syncAccount({
645
+ address: AccountController.state.address,
646
+ chainId: ChainController.state.activeCaipNetwork?.id,
647
+ chainNamespace: caipNetwork.chainNamespace
648
+ });
649
+ }
650
+ else if (AccountController.state.address) {
651
+ const providerType = ProviderUtil.state.providerIds[ChainController.state.activeChain];
652
+ if (providerType === 'AUTH') {
653
+ try {
654
+ ChainController.state.activeChain = caipNetwork.chainNamespace;
655
+ await this.connectionControllerClient?.connectExternal?.({
656
+ id: 'ID_AUTH',
657
+ provider: this.authProvider,
658
+ chain: caipNetwork.chainNamespace,
659
+ chainId: caipNetwork.id,
660
+ type: 'AUTH',
661
+ caipNetwork
662
+ });
663
+ }
664
+ catch (error) {
665
+ const adapter = this.getAdapter(caipNetwork.chainNamespace);
666
+ await adapter?.switchNetwork({
667
+ caipNetwork,
668
+ provider: this.authProvider,
669
+ providerType
670
+ });
671
+ }
672
+ }
673
+ else if (providerType === 'WALLET_CONNECT') {
674
+ this.setCaipNetwork(caipNetwork);
675
+ this.syncWalletConnectAccount();
676
+ }
677
+ else {
678
+ this.setCaipNetwork(caipNetwork);
679
+ const address = this.getAddressByChainNamespace(caipNetwork.chainNamespace);
680
+ if (address) {
681
+ this.syncAccount({
682
+ address,
683
+ chainId: caipNetwork.id,
684
+ chainNamespace: caipNetwork.chainNamespace
685
+ });
686
+ }
687
+ }
688
+ }
689
+ else {
690
+ this.setCaipNetwork(caipNetwork);
691
+ }
692
+ },
693
+ // eslint-disable-next-line @typescript-eslint/require-await
694
+ getApprovedCaipNetworksData: async () => {
695
+ const providerType = ProviderUtil.state.providerIds[ChainController.state.activeChain];
696
+ if (providerType === UtilConstantsUtil.CONNECTOR_TYPE_WALLET_CONNECT) {
697
+ const namespaces = this.universalProvider?.session?.namespaces;
698
+ return {
699
+ supportsAllNetworks: false,
700
+ approvedCaipNetworkIds: this.getChainsFromNamespaces(namespaces)
701
+ };
702
+ }
703
+ return { supportsAllNetworks: true, approvedCaipNetworkIds: [] };
704
+ }
376
705
  };
377
- ChainController.initialize(options.adapters || []);
378
- options.adapters?.forEach(adapter => {
379
- // @ts-expect-error will introduce construct later
380
- adapter.construct?.(this, extendedOptions);
706
+ if (this.networkControllerClient && this.connectionControllerClient) {
707
+ ConnectionController.setClient(this.connectionControllerClient);
708
+ }
709
+ }
710
+ async handleDisconnect() {
711
+ await this.connectionControllerClient?.disconnect();
712
+ }
713
+ async listenAuthConnector(provider) {
714
+ this.setLoading(true);
715
+ const isLoginEmailUsed = provider.getLoginEmailUsed();
716
+ this.setLoading(isLoginEmailUsed);
717
+ const { isConnected } = await provider.isConnected();
718
+ if (isConnected && this.connectionControllerClient?.connectExternal) {
719
+ this.connectionControllerClient?.connectExternal({
720
+ id: 'ID_AUTH',
721
+ info: {
722
+ name: 'ID_AUTH'
723
+ },
724
+ type: 'AUTH',
725
+ provider,
726
+ chainId: ChainController.state.activeCaipNetwork?.id
727
+ });
728
+ }
729
+ else {
730
+ this.setLoading(false);
731
+ }
732
+ provider.onRpcRequest((request) => {
733
+ if (W3mFrameHelpers.checkIfRequestExists(request)) {
734
+ if (!W3mFrameHelpers.checkIfRequestIsSafe(request)) {
735
+ this.handleUnsafeRPCRequest();
736
+ }
737
+ }
738
+ else {
739
+ this.open();
740
+ // eslint-disable-next-line no-console
741
+ console.error(W3mFrameRpcConstants.RPC_METHOD_NOT_ALLOWED_MESSAGE, {
742
+ method: request.method
743
+ });
744
+ setTimeout(() => {
745
+ this.showErrorMessage(W3mFrameRpcConstants.RPC_METHOD_NOT_ALLOWED_UI_MESSAGE);
746
+ }, 300);
747
+ provider.rejectRpcRequests();
748
+ }
749
+ });
750
+ provider.onRpcError(() => {
751
+ const isModalOpen = this.isOpen();
752
+ if (isModalOpen) {
753
+ if (this.isTransactionStackEmpty()) {
754
+ this.close();
755
+ }
756
+ else {
757
+ this.popTransactionStack(true);
758
+ }
759
+ }
760
+ });
761
+ provider.onRpcSuccess((_, request) => {
762
+ const isSafeRequest = W3mFrameHelpers.checkIfRequestIsSafe(request);
763
+ if (isSafeRequest) {
764
+ return;
765
+ }
766
+ if (this.isTransactionStackEmpty()) {
767
+ this.close();
768
+ }
769
+ else {
770
+ this.popTransactionStack();
771
+ }
772
+ });
773
+ provider.onNotConnected(() => {
774
+ const connectedConnector = SafeLocalStorage.getItem(SafeLocalStorageKeys.CONNECTED_CONNECTOR);
775
+ const isConnectedWithAuth = connectedConnector === 'ID_AUTH';
776
+ if (!isConnected && isConnectedWithAuth) {
777
+ this.setCaipAddress(undefined, ChainController.state.activeChain);
778
+ this.setLoading(false);
779
+ }
780
+ });
781
+ provider.onIsConnected(() => {
782
+ provider.connect();
783
+ });
784
+ provider.onConnect(async (user) => {
785
+ this.syncProvider({
786
+ type: 'AUTH',
787
+ provider,
788
+ id: 'ID_AUTH',
789
+ chainNamespace: ChainController.state.activeChain
790
+ });
791
+ const caipAddress = ChainController.state.activeChain === 'eip155'
792
+ ? `eip155:${user.chainId}:${user.address}`
793
+ : `${user.chainId}:${user.address}`;
794
+ this.setCaipAddress(caipAddress, ChainController.state.activeChain);
795
+ this.setSmartAccountDeployed(Boolean(user.smartAccountDeployed), ChainController.state.activeChain);
796
+ this.setPreferredAccountType(user.preferredAccountType, ChainController.state.activeChain);
797
+ this.setAllAccounts(user.accounts || [
798
+ {
799
+ address: user.address,
800
+ type: (user.preferredAccountType || 'eoa')
801
+ }
802
+ ], ChainController.state.activeChain);
803
+ await provider.getSmartAccountEnabledNetworks();
804
+ this.setLoading(false);
805
+ });
806
+ provider.onGetSmartAccountEnabledNetworks(networks => {
807
+ this.setSmartAccountEnabledNetworks(networks, ChainController.state.activeChain);
808
+ });
809
+ provider.onSetPreferredAccount(({ address, type }) => {
810
+ if (!address) {
811
+ return;
812
+ }
813
+ this.setPreferredAccountType(type, ChainController.state.activeChain);
381
814
  });
382
815
  }
816
+ listenWalletConnect() {
817
+ if (this.universalProvider) {
818
+ this.universalProvider.on('disconnect', () => {
819
+ this.chainNamespaces.forEach(namespace => {
820
+ this.resetAccount(namespace);
821
+ });
822
+ ConnectionController.resetWcConnection();
823
+ });
824
+ this.universalProvider.on('chainChanged', (chainId) => {
825
+ const caipNetwork = this.caipNetworks?.find(
826
+ // eslint-disable-next-line eqeqeq
827
+ c => c.chainNamespace === ChainController.state.activeChain && c.id == chainId);
828
+ const currentCaipNetwork = this.getCaipNetwork();
829
+ if (!caipNetwork) {
830
+ const namespace = this.getActiveChainNamespace() || ConstantsUtil.CHAIN.EVM;
831
+ ChainController.setActiveCaipNetwork({
832
+ id: chainId,
833
+ caipNetworkId: `${namespace}:${chainId}`,
834
+ name: 'Unknown Network',
835
+ chainNamespace: namespace,
836
+ nativeCurrency: {
837
+ name: '',
838
+ decimals: 0,
839
+ symbol: ''
840
+ },
841
+ rpcUrls: {
842
+ default: {
843
+ http: []
844
+ }
845
+ }
846
+ });
847
+ return;
848
+ }
849
+ if (!currentCaipNetwork || currentCaipNetwork?.id !== caipNetwork?.id) {
850
+ this.setCaipNetwork(caipNetwork);
851
+ }
852
+ });
853
+ }
854
+ }
855
+ listenAdapter(chainNamespace) {
856
+ const adapter = this.getAdapter(chainNamespace);
857
+ adapter?.on('switchNetwork', ({ address, chainId }) => {
858
+ if (chainId && this.caipNetworks?.find(n => n.id === chainId)) {
859
+ if (ChainController.state.activeChain === chainNamespace && address) {
860
+ this.syncAccount({ address, chainId, chainNamespace });
861
+ }
862
+ else if (ChainController.state.activeChain === chainNamespace &&
863
+ AccountController.state.address) {
864
+ this.syncAccount({
865
+ address: AccountController.state.address,
866
+ chainId,
867
+ chainNamespace
868
+ });
869
+ }
870
+ }
871
+ else {
872
+ ChainController.showUnsupportedChainUI();
873
+ }
874
+ });
875
+ adapter?.on('disconnect', () => {
876
+ if (ChainController.state.activeChain === chainNamespace) {
877
+ this.handleDisconnect();
878
+ }
879
+ });
880
+ adapter?.on('accountChanged', ({ address, chainId }) => {
881
+ if (ChainController.state.activeChain === chainNamespace && chainId) {
882
+ this.syncAccount({
883
+ address,
884
+ chainId,
885
+ chainNamespace
886
+ });
887
+ }
888
+ else if (ChainController.state.activeChain === chainNamespace &&
889
+ ChainController.state.activeCaipNetwork?.id) {
890
+ this.syncAccount({
891
+ address,
892
+ chainId: ChainController.state.activeCaipNetwork?.id,
893
+ chainNamespace
894
+ });
895
+ }
896
+ });
897
+ }
898
+ getChainsFromNamespaces(namespaces = {}) {
899
+ return Object.values(namespaces).flatMap(namespace => {
900
+ const chains = (namespace.chains || []);
901
+ const accountsChains = namespace.accounts.map(account => {
902
+ const [chainNamespace, chainId] = account.split(':');
903
+ return `${chainNamespace}:${chainId}`;
904
+ });
905
+ return Array.from(new Set([...chains, ...accountsChains]));
906
+ });
907
+ }
908
+ async syncWalletConnectAccount() {
909
+ const adapter = this.getAdapter(ChainController.state.activeChain);
910
+ StorageUtil.setConnectedNamespace(ChainController.state.activeChain);
911
+ this.chainNamespaces.forEach(async (chainNamespace) => {
912
+ const caipAddress = this.universalProvider?.session?.namespaces?.[chainNamespace]
913
+ ?.accounts[0];
914
+ if (caipAddress) {
915
+ ProviderUtil.setProviderId(chainNamespace, UtilConstantsUtil.CONNECTOR_TYPE_WALLET_CONNECT);
916
+ if (this.caipNetworks &&
917
+ ChainController.state.activeCaipNetwork &&
918
+ adapter?.adapterType === 'solana') {
919
+ const provider = adapter?.getWalletConnectProvider({
920
+ caipNetworks: this.caipNetworks,
921
+ provider: this.universalProvider,
922
+ activeCaipNetwork: ChainController.state.activeCaipNetwork
923
+ });
924
+ ProviderUtil.setProvider(chainNamespace, provider);
925
+ }
926
+ else {
927
+ ProviderUtil.setProvider(chainNamespace, this.universalProvider);
928
+ }
929
+ StorageUtil.setConnectedConnector(UtilConstantsUtil.CONNECTOR_TYPE_WALLET_CONNECT);
930
+ let address = '';
931
+ if (caipAddress.split(':').length === 3) {
932
+ address = caipAddress.split(':')[2];
933
+ }
934
+ else {
935
+ address = AccountController.state.address;
936
+ }
937
+ if (adapter?.adapterType === 'wagmi') {
938
+ try {
939
+ await adapter?.connect({
940
+ id: 'walletConnect',
941
+ type: 'WALLET_CONNECT',
942
+ chainId: ChainController.state.activeCaipNetwork?.id
943
+ });
944
+ }
945
+ catch (error) {
946
+ adapter?.switchNetwork({
947
+ provider: this.universalProvider,
948
+ caipNetwork: ChainController.state.activeCaipNetwork
949
+ });
950
+ }
951
+ }
952
+ this.syncWalletConnectAccounts(chainNamespace);
953
+ await this.syncAccount({
954
+ address,
955
+ chainId: ChainController.state.activeChain === chainNamespace
956
+ ? ChainController.state.activeCaipNetwork?.id
957
+ : this.caipNetworks?.find(n => n.chainNamespace === chainNamespace)?.id,
958
+ chainNamespace
959
+ });
960
+ }
961
+ });
962
+ await ChainController.setApprovedCaipNetworksData(ChainController.state.activeChain);
963
+ }
964
+ syncWalletConnectAccounts(chainNamespace) {
965
+ const addresses = this.universalProvider?.session?.namespaces?.[chainNamespace]?.accounts
966
+ ?.map(account => {
967
+ const [, , address] = account.split(':');
968
+ return address;
969
+ })
970
+ .filter((address, index, self) => self.indexOf(address) === index);
971
+ if (addresses) {
972
+ this.setAllAccounts(addresses.map(address => ({ address, type: 'eoa' })), chainNamespace);
973
+ }
974
+ }
975
+ syncProvider({ type, provider, id, chainNamespace }) {
976
+ ProviderUtil.setProviderId(chainNamespace, type);
977
+ ProviderUtil.setProvider(chainNamespace, provider);
978
+ StorageUtil.setConnectedConnector(id);
979
+ StorageUtil.setConnectedNamespace(ChainController.state.activeChain);
980
+ }
981
+ async syncAccount({ address, chainId, chainNamespace }) {
982
+ this.setPreferredAccountType(AccountController.state.preferredAccountType
983
+ ? AccountController.state.preferredAccountType
984
+ : 'eoa', ChainController.state.activeChain);
985
+ this.setCaipAddress(`${chainNamespace}:${chainId}:${address}`, chainNamespace);
986
+ this.setStatus('connected', chainNamespace);
987
+ if (chainNamespace === ChainController.state.activeChain) {
988
+ const caipNetwork = this.caipNetworks?.find(n => n.id === chainId && n.chainNamespace === chainNamespace);
989
+ if (caipNetwork) {
990
+ this.setCaipNetwork(caipNetwork);
991
+ }
992
+ else {
993
+ this.setCaipNetwork(this.caipNetworks?.find(n => n.chainNamespace === chainNamespace));
994
+ }
995
+ this.syncConnectedWalletInfo(chainNamespace);
996
+ const adapter = this.getAdapter(chainNamespace);
997
+ const balance = await adapter?.getBalance({
998
+ address,
999
+ chainId,
1000
+ caipNetwork: caipNetwork || this.getCaipNetwork(),
1001
+ tokens: this.options.tokens
1002
+ });
1003
+ if (balance) {
1004
+ this.setBalance(balance.balance, balance.symbol, chainNamespace);
1005
+ }
1006
+ await this.syncIdentity({ address, chainId: Number(chainId), chainNamespace });
1007
+ }
1008
+ }
1009
+ syncConnectedWalletInfo(chainNamespace) {
1010
+ const currentActiveWallet = SafeLocalStorage.getItem(SafeLocalStorageKeys.CONNECTED_CONNECTOR);
1011
+ const providerType = ProviderUtil.state.providerIds[chainNamespace];
1012
+ if (providerType === UtilConstantsUtil.CONNECTOR_TYPE_ANNOUNCED ||
1013
+ providerType === UtilConstantsUtil.CONNECTOR_TYPE_INJECTED) {
1014
+ if (currentActiveWallet) {
1015
+ const connector = this.getConnectors().find(c => c.id === currentActiveWallet);
1016
+ if (connector?.info) {
1017
+ this.setConnectedWalletInfo({ ...connector.info }, chainNamespace);
1018
+ }
1019
+ }
1020
+ }
1021
+ else if (providerType === UtilConstantsUtil.CONNECTOR_TYPE_WALLET_CONNECT) {
1022
+ const provider = ProviderUtil.getProvider(chainNamespace);
1023
+ if (provider?.session) {
1024
+ this.setConnectedWalletInfo({
1025
+ ...provider.session.peer.metadata,
1026
+ name: provider.session.peer.metadata.name,
1027
+ icon: provider.session.peer.metadata.icons?.[0]
1028
+ }, chainNamespace);
1029
+ }
1030
+ }
1031
+ else if (providerType === UtilConstantsUtil.COINBASE_CONNECTOR_ID) {
1032
+ const connector = this.getConnectors().find(c => c.id === UtilConstantsUtil.COINBASE_CONNECTOR_ID);
1033
+ this.setConnectedWalletInfo({ name: 'Coinbase Wallet', icon: this.getConnectorImage(connector) }, chainNamespace);
1034
+ }
1035
+ else if (currentActiveWallet) {
1036
+ this.setConnectedWalletInfo({ name: currentActiveWallet }, chainNamespace);
1037
+ }
1038
+ }
1039
+ async syncIdentity({ address, chainId, chainNamespace }) {
1040
+ try {
1041
+ const { name, avatar } = await this.fetchIdentity({
1042
+ address
1043
+ });
1044
+ this.setProfileName(name, chainNamespace);
1045
+ this.setProfileImage(avatar, chainNamespace);
1046
+ if (!name) {
1047
+ await this.syncReownName(address, chainNamespace);
1048
+ const adapter = this.getAdapter(chainNamespace);
1049
+ const result = await adapter?.getProfile({
1050
+ address,
1051
+ chainId: Number(chainId)
1052
+ });
1053
+ if (result?.profileName) {
1054
+ this.setProfileName(result.profileName, chainNamespace);
1055
+ if (result.profileImage) {
1056
+ this.setProfileImage(result.profileImage, chainNamespace);
1057
+ }
1058
+ }
1059
+ else {
1060
+ await this.syncReownName(address, chainNamespace);
1061
+ this.setProfileImage(null, chainNamespace);
1062
+ }
1063
+ }
1064
+ }
1065
+ catch {
1066
+ if (chainId === 1) {
1067
+ await this.syncReownName(address, chainNamespace);
1068
+ }
1069
+ else {
1070
+ await this.syncReownName(address, chainNamespace);
1071
+ this.setProfileImage(null, chainNamespace);
1072
+ }
1073
+ }
1074
+ }
1075
+ async syncReownName(address, chainNamespace) {
1076
+ try {
1077
+ const registeredWcNames = await this.getReownName(address);
1078
+ if (registeredWcNames[0]) {
1079
+ const wcName = registeredWcNames[0];
1080
+ this.setProfileName(wcName.name, chainNamespace);
1081
+ }
1082
+ else {
1083
+ this.setProfileName(null, chainNamespace);
1084
+ }
1085
+ }
1086
+ catch {
1087
+ this.setProfileName(null, chainNamespace);
1088
+ }
1089
+ }
1090
+ syncRequestedNetworks() {
1091
+ const uniqueChainNamespaces = [
1092
+ ...new Set(this.caipNetworks?.map(caipNetwork => caipNetwork.chainNamespace))
1093
+ ];
1094
+ this.chainNamespaces = uniqueChainNamespaces;
1095
+ uniqueChainNamespaces.forEach(chainNamespace => this.setRequestedCaipNetworks(this.caipNetworks?.filter(caipNetwork => caipNetwork.chainNamespace === chainNamespace) ??
1096
+ [], chainNamespace));
1097
+ }
1098
+ async syncExistingConnection() {
1099
+ const connectedConnector = SafeLocalStorage.getItem(SafeLocalStorageKeys.CONNECTED_CONNECTOR);
1100
+ const connectedNamespace = SafeLocalStorage.getItem(SafeLocalStorageKeys.CONNECTED_NAMESPACE);
1101
+ if (connectedConnector === UtilConstantsUtil.CONNECTOR_TYPE_WALLET_CONNECT &&
1102
+ connectedNamespace) {
1103
+ this.syncWalletConnectAccount();
1104
+ }
1105
+ else if (connectedConnector &&
1106
+ connectedConnector !== UtilConstantsUtil.CONNECTOR_TYPE_W3M_AUTH &&
1107
+ connectedNamespace) {
1108
+ const adapter = this.getAdapter(connectedNamespace);
1109
+ const res = await adapter?.syncConnection({
1110
+ id: connectedConnector,
1111
+ chainId: this.getCaipNetwork()?.id,
1112
+ namespace: connectedNamespace,
1113
+ rpcUrl: this.getCaipNetwork()?.rpcUrls?.default?.http?.[0]
1114
+ });
1115
+ if (res) {
1116
+ this.syncProvider({ ...res, chainNamespace: connectedNamespace });
1117
+ await this.syncAccount({ ...res, chainNamespace: connectedNamespace });
1118
+ }
1119
+ }
1120
+ }
1121
+ getAdapter(namespace) {
1122
+ return this.chainAdapters?.[namespace];
1123
+ }
1124
+ createUniversalProvider() {
1125
+ if (!this.universalProviderInitPromise &&
1126
+ typeof window !== 'undefined' &&
1127
+ this.options?.projectId) {
1128
+ this.universalProviderInitPromise = this.initializeUniversalAdapter();
1129
+ }
1130
+ return this.universalProviderInitPromise;
1131
+ }
1132
+ async initializeUniversalAdapter() {
1133
+ const universalProviderOptions = {
1134
+ projectId: this.options?.projectId,
1135
+ metadata: {
1136
+ name: this.options?.metadata ? this.options?.metadata.name : '',
1137
+ description: this.options?.metadata ? this.options?.metadata.description : '',
1138
+ url: this.options?.metadata ? this.options?.metadata.url : '',
1139
+ icons: this.options?.metadata ? this.options?.metadata.icons : ['']
1140
+ }
1141
+ };
1142
+ this.universalProvider = await UniversalProvider.init(universalProviderOptions);
1143
+ }
1144
+ async getUniversalProvider() {
1145
+ if (!this.universalProvider) {
1146
+ try {
1147
+ await this.createUniversalProvider();
1148
+ }
1149
+ catch (error) {
1150
+ throw new Error('AppKit:getUniversalProvider - Cannot create provider');
1151
+ }
1152
+ }
1153
+ return this.universalProvider;
1154
+ }
1155
+ createAuthProvider() {
1156
+ const emailEnabled = this.options?.features?.email === undefined
1157
+ ? CoreConstantsUtil.DEFAULT_FEATURES.email
1158
+ : this.options?.features?.email;
1159
+ const socialsEnabled = this.options?.features?.socials
1160
+ ? this.options?.features?.socials?.length > 0
1161
+ : CoreConstantsUtil.DEFAULT_FEATURES.socials;
1162
+ if (this.options?.projectId && (emailEnabled || socialsEnabled)) {
1163
+ this.authProvider = W3mFrameProviderSingleton.getInstance({
1164
+ projectId: this.options.projectId
1165
+ });
1166
+ this.listenAuthConnector(this.authProvider);
1167
+ }
1168
+ }
1169
+ async createAdapters(blueprints) {
1170
+ if (!this.universalProvider) {
1171
+ this.universalProvider = await this.getUniversalProvider();
1172
+ }
1173
+ this.syncRequestedNetworks();
1174
+ return this.chainNamespaces.reduce((adapters, namespace) => {
1175
+ const blueprint = blueprints?.find(b => b.namespace === namespace);
1176
+ if (blueprint) {
1177
+ adapters[namespace] = blueprint;
1178
+ adapters[namespace].namespace = namespace;
1179
+ adapters[namespace].construct({
1180
+ namespace,
1181
+ projectId: this.options?.projectId,
1182
+ networks: this.caipNetworks
1183
+ });
1184
+ if (this.universalProvider) {
1185
+ adapters[namespace].setUniversalProvider(this.universalProvider);
1186
+ }
1187
+ if (this.authProvider) {
1188
+ adapters[namespace].setAuthProvider(this.authProvider);
1189
+ }
1190
+ if (this.options?.features) {
1191
+ adapters[namespace].syncConnectors(this.options, this);
1192
+ }
1193
+ }
1194
+ else {
1195
+ adapters[namespace] = new UniversalAdapter({
1196
+ namespace,
1197
+ networks: this.caipNetworks
1198
+ });
1199
+ if (this.universalProvider) {
1200
+ adapters[namespace].setUniversalProvider(this.universalProvider);
1201
+ }
1202
+ if (this.authProvider) {
1203
+ adapters[namespace].setAuthProvider(this.authProvider);
1204
+ }
1205
+ }
1206
+ ChainController.state.chains.set(namespace, {
1207
+ namespace,
1208
+ connectionControllerClient: this.connectionControllerClient,
1209
+ networkControllerClient: this.networkControllerClient,
1210
+ networkState,
1211
+ accountState,
1212
+ caipNetworks: this.caipNetworks ?? []
1213
+ });
1214
+ return adapters;
1215
+ // eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter
1216
+ }, {});
1217
+ }
1218
+ async initChainAdapters() {
1219
+ await Promise.all(
1220
+ // eslint-disable-next-line @typescript-eslint/require-await
1221
+ this.chainNamespaces.map(async (namespace) => {
1222
+ if (this.options) {
1223
+ this.listenAdapter(namespace);
1224
+ this.setConnectors(this.chainAdapters?.[namespace]?.connectors || []);
1225
+ }
1226
+ }));
1227
+ this.listenWalletConnect();
1228
+ }
383
1229
  setDefaultNetwork() {
384
1230
  const previousNetwork = SafeLocalStorage.getItem(SafeLocalStorageKeys.ACTIVE_CAIP_NETWORK_ID);
385
- const caipNetwork = previousNetwork
1231
+ const caipNetwork = previousNetwork && this.caipNetworks?.length
386
1232
  ? this.caipNetworks.find(n => n.caipNetworkId === previousNetwork)
387
1233
  : undefined;
388
- const network = caipNetwork || this.defaultCaipNetwork || this.caipNetworks[0];
389
- ChainController.setActiveCaipNetwork(network);
1234
+ const network = caipNetwork || this.defaultCaipNetwork || this.caipNetworks?.[0];
1235
+ if (network) {
1236
+ ChainController.setActiveCaipNetwork(network);
1237
+ }
390
1238
  }
391
1239
  async initOrContinue() {
392
1240
  if (!this.initPromise && !isInitialized && CoreHelperUtil.isClient()) {