diff --git a/.changeset/blue-pens-yawn.md b/.changeset/blue-pens-yawn.md new file mode 100644 index 0000000000..9451cf70bc --- /dev/null +++ b/.changeset/blue-pens-yawn.md @@ -0,0 +1,38 @@ +--- +'@reown/appkit-adapter-solana': patch +'@reown/appkit-adapter-wagmi': patch +'@reown/appkit': patch +'@reown/appkit-core': patch +'@apps/demo': patch +'@apps/gallery': patch +'@apps/laboratory': patch +'@examples/html-ethers': patch +'@examples/html-ethers5': patch +'@examples/html-wagmi': patch +'@examples/next-ethers': patch +'@examples/next-wagmi': patch +'@examples/react-ethers': patch +'@examples/react-ethers5': patch +'@examples/react-solana': patch +'@examples/react-wagmi': patch +'@examples/vue-ethers5': patch +'@examples/vue-solana': patch +'@examples/vue-wagmi': patch +'@reown/appkit-adapter-ethers': patch +'@reown/appkit-adapter-ethers5': patch +'@reown/appkit-adapter-polkadot': patch +'@reown/appkit-utils': patch +'@reown/appkit-cdn': patch +'@reown/appkit-common': patch +'@reown/appkit-ethers': patch +'@reown/appkit-ethers5': patch +'@reown/appkit-polyfills': patch +'@reown/appkit-scaffold-ui': patch +'@reown/appkit-siwe': patch +'@reown/appkit-solana': patch +'@reown/appkit-ui': patch +'@reown/appkit-wagmi': patch +'@reown/appkit-wallet': patch +--- + +Get correct data from session namespaces and set it for approved caip networks data on UniversalProvider usage" diff --git a/.changeset/fluffy-crabs-bathe.md b/.changeset/fluffy-crabs-bathe.md new file mode 100644 index 0000000000..71a7856432 --- /dev/null +++ b/.changeset/fluffy-crabs-bathe.md @@ -0,0 +1,38 @@ +--- +'@reown/appkit-adapter-ethers5': patch +'@reown/appkit-adapter-ethers': patch +'@reown/appkit-adapter-solana': patch +'@reown/appkit-adapter-wagmi': patch +'@reown/appkit': patch +'@reown/appkit-wallet': patch +'@reown/appkit-core': patch +'@apps/demo': patch +'@apps/gallery': patch +'@apps/laboratory': patch +'@examples/html-ethers': patch +'@examples/html-ethers5': patch +'@examples/html-wagmi': patch +'@examples/next-ethers': patch +'@examples/next-wagmi': patch +'@examples/react-ethers': patch +'@examples/react-ethers5': patch +'@examples/react-solana': patch +'@examples/react-wagmi': patch +'@examples/vue-ethers5': patch +'@examples/vue-solana': patch +'@examples/vue-wagmi': patch +'@reown/appkit-adapter-polkadot': patch +'@reown/appkit-utils': patch +'@reown/appkit-cdn': patch +'@reown/appkit-common': patch +'@reown/appkit-ethers': patch +'@reown/appkit-ethers5': patch +'@reown/appkit-polyfills': patch +'@reown/appkit-scaffold-ui': patch +'@reown/appkit-siwe': patch +'@reown/appkit-solana': patch +'@reown/appkit-ui': patch +'@reown/appkit-wagmi': patch +--- + +Implement the correct logic for getting available networks when using universal provider diff --git a/apps/laboratory/src/pages/library/solana.tsx b/apps/laboratory/src/pages/library/solana.tsx index 1f93821656..8be1bcac5f 100644 --- a/apps/laboratory/src/pages/library/solana.tsx +++ b/apps/laboratory/src/pages/library/solana.tsx @@ -1,4 +1,4 @@ -import { createAppKit, type CaipNetwork } from '@reown/appkit/react' +import { createAppKit } from '@reown/appkit/react' import { SolanaAdapter } from '@reown/appkit-adapter-solana/react' import { ThemeStore } from '../../utils/StoreUtil' import { ConstantsUtil } from '../../utils/ConstantsUtil' @@ -14,16 +14,6 @@ const solanaWeb3JsAdapter = new SolanaAdapter({ wallets: [new HuobiWalletAdapter(), new SolflareWalletAdapter()] }) -export const solanaNotExist = { - id: 'solana:chaindoesntexist', - chainId: 'chaindoesntexist', - name: 'Solana Unsupported', - currency: 'SOL', - explorerUrl: 'https://explorer.solana.com/?cluster=devnet', - rpcUrl: '', - chainNamespace: 'solana' -} as CaipNetwork - const modal = createAppKit({ adapters: [solanaWeb3JsAdapter], networks, diff --git a/apps/laboratory/src/utils/ConstantsUtil.ts b/apps/laboratory/src/utils/ConstantsUtil.ts index 64dc893a8e..bf49910b4a 100644 --- a/apps/laboratory/src/utils/ConstantsUtil.ts +++ b/apps/laboratory/src/utils/ConstantsUtil.ts @@ -8,9 +8,11 @@ import { solana, solanaTestnet, solanaDevnet, - base + base, + gnosis } from '@reown/appkit/networks' import { getLocalStorageItem } from './LocalStorage' +import type { CaipNetwork } from '@reown/appkit' const projectId = process.env['NEXT_PUBLIC_PROJECT_ID'] if (!projectId) { @@ -48,8 +50,19 @@ if (typeof window !== 'undefined') { const customWallet = storedCustomWallet ? [JSON.parse(storedCustomWallet)] : [] -const EvmNetworks = [mainnet, optimism, polygon, zkSync, arbitrum, base, sepolia] -const SolanaNetworks = [solana, solanaTestnet, solanaDevnet] +const EvmNetworks = [mainnet, optimism, polygon, zkSync, arbitrum, base, sepolia, gnosis] + +export const solanaNotExist = { + id: 'solana:chaindoesntexist', + chainId: 'chaindoesntexist', + name: 'Solana Unsupported', + currency: 'SOL', + explorerUrl: 'https://explorer.solana.com/?cluster=unsupported', + rpcUrl: 'https://api.unsupported.solana.com', + chainNamespace: 'solana' +} as CaipNetwork + +const SolanaNetworks = [solana, solanaTestnet, solanaDevnet, solanaNotExist] export const ConstantsUtil = { SigningSucceededToastTitle: 'Signing Succeeded', diff --git a/apps/laboratory/tests/multichain/multichain-ethers-solana.spec.ts b/apps/laboratory/tests/multichain/multichain-ethers-solana.spec.ts index acb57c34b3..948482a932 100644 --- a/apps/laboratory/tests/multichain/multichain-ethers-solana.spec.ts +++ b/apps/laboratory/tests/multichain/multichain-ethers-solana.spec.ts @@ -39,8 +39,8 @@ test('it should fetch balance as expected', async () => { await modalValidator.expectBalanceFetched('ETH') }) -test.skip('it should show disabled networks', async () => { - const disabledNetworks = 'Arbitrum' +test('it should show disabled networks', async () => { + const disabledNetworks = 'Gnosis' await modalPage.openModal() await modalPage.openNetworks() diff --git a/apps/laboratory/tests/multichain/multichain-ethers5-solana.spec.ts b/apps/laboratory/tests/multichain/multichain-ethers5-solana.spec.ts index 9957ebb962..3588dd2c4e 100644 --- a/apps/laboratory/tests/multichain/multichain-ethers5-solana.spec.ts +++ b/apps/laboratory/tests/multichain/multichain-ethers5-solana.spec.ts @@ -39,8 +39,8 @@ test('it should fetch balance as expected', async () => { await modalValidator.expectBalanceFetched('ETH') }) -test.skip('it should show disabled networks', async () => { - const disabledNetworks = 'Arbitrum' +test('it should show disabled networks', async () => { + const disabledNetworks = 'Gnosis' await modalPage.openModal() await modalPage.openNetworks() diff --git a/apps/laboratory/tests/multichain/multichain-wagmi-solana.spec.ts b/apps/laboratory/tests/multichain/multichain-wagmi-solana.spec.ts index 3aa394866d..41bfdca397 100644 --- a/apps/laboratory/tests/multichain/multichain-wagmi-solana.spec.ts +++ b/apps/laboratory/tests/multichain/multichain-wagmi-solana.spec.ts @@ -39,8 +39,8 @@ test('it should fetch balance as expected', async () => { await modalValidator.expectBalanceFetched('ETH') }) -test.skip('it should show disabled networks', async () => { - const disabledNetworks = 'Arbitrum' +test('it should show disabled networks', async () => { + const disabledNetworks = 'Gnosis' await modalPage.openModal() await modalPage.openNetworks() @@ -58,7 +58,6 @@ test('it should switch networks and sign', async () => { const chainName = chains[index] ?? DEFAULT_CHAIN_NAME await modalPage.switchNetwork(chainName) - await modalValidator.expectSwitchedNetwork(chainName) await modalPage.closeModal() // -- Sign ------------------------------------------------------------------ @@ -78,7 +77,6 @@ test('it should switch between multiple accounts', async () => { const chainName = 'Ethereum' await modalPage.switchNetwork(chainName) await modalPage.page.waitForTimeout(500) - await modalValidator.expectSwitchedNetwork(chainName) await modalPage.closeModal() const originalAddress = await modalPage.getAddress() await modalPage.openAccount() diff --git a/apps/laboratory/tests/siwe-sa.spec.ts b/apps/laboratory/tests/siwe-sa.spec.ts index 0fe55ee16f..5296c0f64e 100644 --- a/apps/laboratory/tests/siwe-sa.spec.ts +++ b/apps/laboratory/tests/siwe-sa.spec.ts @@ -36,6 +36,7 @@ smartAccountSiweTest.beforeAll(async ({ browser, library }) => { // Switch to a SA enabled network await validator.expectDisconnected() await page.switchNetworkWithNetworkButton('Polygon') + await validator.expectSwitchedNetworkOnNetworksView('Polygon') await page.closeModal() const tempEmail = await email.getEmailAddressToUse() await page.emailFlow(tempEmail, context, mailsacApiKey) diff --git a/apps/laboratory/tests/smart-account.spec.ts b/apps/laboratory/tests/smart-account.spec.ts index ba10bea139..9b92a781e5 100644 --- a/apps/laboratory/tests/smart-account.spec.ts +++ b/apps/laboratory/tests/smart-account.spec.ts @@ -34,7 +34,9 @@ smartAccountTest.beforeAll(async ({ browser, library }) => { // Switch to a SA enabled network await page.switchNetworkWithNetworkButton('Polygon') + await validator.expectSwitchedNetworkOnNetworksView('Polygon') await page.closeModal() + const tempEmail = await email.getEmailAddressToUse() await page.emailFlow(tempEmail, context, mailsacApiKey) diff --git a/apps/laboratory/tests/wallet.spec.ts b/apps/laboratory/tests/wallet.spec.ts index 6bf2319fc7..dd98cb135a 100644 --- a/apps/laboratory/tests/wallet.spec.ts +++ b/apps/laboratory/tests/wallet.spec.ts @@ -45,8 +45,8 @@ sampleWalletTest('it should fetch balance as expected', async ({ library }) => { await modalValidator.expectBalanceFetched(library === 'solana' ? 'SOL' : 'ETH') }) -sampleWalletTest.skip('it should show disabled networks', async ({ library }) => { - const disabledNetworks = library === 'solana' ? 'Solana Unsupported' : 'Arbitrum' +sampleWalletTest('it should show disabled networks', async ({ library }) => { + const disabledNetworks = library === 'solana' ? 'Solana Unsupported' : 'Gnosis' await modalPage.openModal() await modalPage.openNetworks() diff --git a/packages/adapters/solana/src/client.ts b/packages/adapters/solana/src/client.ts index 72d3162998..c4c0c828ba 100644 --- a/packages/adapters/solana/src/client.ts +++ b/packages/adapters/solana/src/client.ts @@ -25,7 +25,7 @@ import type { NetworkControllerClient, Connector } from '@reown/appkit-core' -import type { AdapterType, CaipAddress, CaipNetwork, CaipNetworkId } from '@reown/appkit-common' +import type { AdapterType, CaipAddress, CaipNetwork } from '@reown/appkit-common' import type { ChainNamespace } from '@reown/appkit-common' import { watchStandard } from './utils/watchStandard.js' @@ -43,7 +43,7 @@ import type { AppKit } from '@reown/appkit' import type { AppKitOptions as CoreOptions } from '@reown/appkit' import { ProviderUtil } from '@reown/appkit/store' import { W3mFrameProviderSingleton } from '@reown/appkit/auth-provider' -import { ConstantsUtil, PresetsUtil } from '@reown/appkit-utils' +import { ConstantsUtil } from '@reown/appkit-utils' import { createSendTransaction } from './utils/createSendTransaction.js' import { CoinbaseWalletProvider } from './providers/CoinbaseWalletProvider.js' @@ -153,34 +153,19 @@ export class SolanaAdapter implements ChainAdapter { } }, - getApprovedCaipNetworksData: async () => - new Promise(resolve => { - const walletId = SafeLocalStorage.getItem(SafeLocalStorageKeys.WALLET_ID) - - if (!walletId) { - throw new Error('No wallet id found to get approved networks data') - } - - const providerConfigs = { - [ConstantsUtil.AUTH_CONNECTOR_ID]: { - supportsAllNetworks: true, - approvedCaipNetworkIds: PresetsUtil.WalletConnectRpcChainIds.map( - id => `${ConstantsUtil.EIP155}:${id}` - ) as CaipNetworkId[] - } - } - - const networkData = providerConfigs[walletId as unknown as keyof typeof providerConfigs] + getApprovedCaipNetworksData: async () => { + if (this.provider) { + return Promise.resolve({ + supportsAllNetworks: false, + approvedCaipNetworkIds: this.provider.chains.map(chain => chain.id) + }) + } - if (networkData) { - resolve(networkData) - } else { - resolve({ - supportsAllNetworks: true, - approvedCaipNetworkIds: [] - }) - } + return Promise.resolve({ + supportsAllNetworks: false, + approvedCaipNetworkIds: [] }) + } } this.connectionControllerClient = { @@ -376,10 +361,7 @@ export class SolanaAdapter implements ChainAdapter { if (address && caipNetwork) { SolStoreUtil.setConnection(new Connection(caipNetwork.rpcUrl, this.connectionSettings)) this.appKit?.setAllAccounts([{ address, type: 'eoa' }], this.chainNamespace) - this.appKit?.setCaipAddress( - `${caipNetworkId as CaipNetworkId}:${address}`, - this.chainNamespace - ) + this.appKit?.setCaipAddress(`${caipNetworkId}:${address}` as CaipAddress, this.chainNamespace) await this.syncNetwork(address) } else { this.appKit?.resetWcConnection() @@ -398,7 +380,7 @@ export class SolanaAdapter implements ChainAdapter { } if (!this.appKit?.getCaipNetwork()) { - throw new Error('CaipNetwork is not set') + this.appKit?.setCaipNetwork(this.defaultCaipNetwork) } const balance = @@ -480,26 +462,29 @@ export class SolanaAdapter implements ChainAdapter { this.appKit?.setLoading(true) const address = await provider.connect() const caipChainId = SafeLocalStorage.getItem(SafeLocalStorageKeys.ACTIVE_CAIP_NETWORK_ID) - let connectionChain: CaipNetwork | undefined = undefined - const activeCaipNetwork = this.appKit?.getCaipNetwork() - - // eslint-disable-next-line no-nested-ternary - connectionChain = caipChainId - ? SolHelpersUtil.getChainFromCaip(this.caipNetworks, caipChainId) - : activeCaipNetwork?.chainNamespace === 'solana' - ? this.caipNetworks.find(chain => chain.chainNamespace === 'solana') - : activeCaipNetwork || this.caipNetworks.find(chain => chain.chainNamespace === 'solana') + const connectionChain = + provider.chains.find(chain => chain.id === caipChainId) || provider.chains[0] if (connectionChain) { - const caipAddress = `solana:${connectionChain.chainId}:${address}` as CaipAddress + const caipAddress = `solana:${connectionChain.chainId}:${address}` as const this.appKit?.setCaipAddress(caipAddress, this.chainNamespace) await this.switchNetwork(connectionChain) ProviderUtil.setProvider(this.chainNamespace, provider) this.provider = provider - ProviderUtil.setProviderId(this.chainNamespace, 'walletConnect') + + switch (provider.type) { + case 'WALLET_CONNECT': + ProviderUtil.setProviderId(this.chainNamespace, 'walletConnect') + break + case 'AUTH': + ProviderUtil.setProviderId(this.chainNamespace, 'w3mAuth') + break + default: + ProviderUtil.setProviderId(this.chainNamespace, 'injected') + } SafeLocalStorage.setItem(SafeLocalStorageKeys.WALLET_ID, provider.name) @@ -610,6 +595,8 @@ export class SolanaAdapter implements ChainAdapter { getActiveChain: () => this.appKit?.getCaipNetwork() }) + this.addProvider(walletConnectProvider) + return walletConnectProvider } @@ -671,9 +658,7 @@ export class SolanaAdapter implements ChainAdapter { for (const provider of providers) { this.availableProviders = this.availableProviders.filter(p => p.name !== provider.name) - if (provider.type !== 'WALLET_CONNECT') { - this.availableProviders.push(provider) - } + this.availableProviders.push(provider) if (provider.name === activeProviderName && isSolana) { this.setProvider(provider) diff --git a/packages/adapters/solana/src/providers/WalletConnectProvider.ts b/packages/adapters/solana/src/providers/WalletConnectProvider.ts index bb3e1417da..2696e89ad4 100644 --- a/packages/adapters/solana/src/providers/WalletConnectProvider.ts +++ b/packages/adapters/solana/src/providers/WalletConnectProvider.ts @@ -14,6 +14,7 @@ import { import { isVersionedTransaction } from '@solana/wallet-adapter-base' import type { CaipNetwork, ChainId } from '@reown/appkit-common' import { withSolanaNamespace } from '../utils/withSolanaNamespace.js' +import { WcHelpersUtil } from '@reown/appkit' import { WalletConnectMethodNotSupportedError } from './shared/Errors.js' export type WalletConnectProviderConfig = { @@ -261,20 +262,7 @@ export class WalletConnectProvider extends ProviderEventEmitter implements Provi } private get sessionChains() { - const solanaNamespace = this.session?.namespaces['solana'] - - if (!solanaNamespace) { - return [] - } - - const chains = solanaNamespace.chains || [] - const accountsChains = solanaNamespace.accounts.map(account => { - const [chainNamespace, chainId] = account.split(':') - - return `${chainNamespace}:${chainId}` - }) - - return Array.from(new Set([...chains, ...accountsChains])) + return WcHelpersUtil.getChainsFromNamespaces(this.session?.namespaces) } private serializeTransaction(transaction: AnyTransaction) { diff --git a/packages/adapters/solana/src/tests/client.test.ts b/packages/adapters/solana/src/tests/client.test.ts index 3c9907ce9c..cdbf6f2f0f 100644 --- a/packages/adapters/solana/src/tests/client.test.ts +++ b/packages/adapters/solana/src/tests/client.test.ts @@ -150,7 +150,8 @@ describe('SolanaAdapter', () => { const mockProvider = { connect: vi.fn().mockResolvedValue('DjPi1LtwrXJMAh2AUvuUMajCpMJEKg8N1J1PbLGjCH5B'), name: 'MockProvider', - on: vi.fn() + on: vi.fn(), + chains: [{ chainId: '5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' }] } vi.spyOn(SafeLocalStorage, 'getItem').mockReturnValue( 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' @@ -164,11 +165,16 @@ describe('SolanaAdapter', () => { 'solana' ) expect(ProviderUtil.setProvider).toHaveBeenCalledWith('solana', mockProvider) - expect(ProviderUtil.setProviderId).toHaveBeenCalledWith('solana', 'walletConnect') + expect(ProviderUtil.setProviderId).toHaveBeenCalledWith('solana', 'injected') }) it('should add provider', () => { - const mockProvider = { name: 'MockProvider', type: 'INJECTED', icon: 'mock-icon' } + const mockProvider = { + name: 'MockProvider', + type: 'INJECTED', + icon: 'mock-icon', + chains: [{ chainId: '5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' }] + } client['addProvider'](mockProvider as any) expect(client['availableProviders']).toContain(mockProvider) diff --git a/packages/adapters/wagmi/src/utils/helpers.ts b/packages/adapters/wagmi/src/utils/helpers.ts index 25bc2091b2..07e3da1577 100644 --- a/packages/adapters/wagmi/src/utils/helpers.ts +++ b/packages/adapters/wagmi/src/utils/helpers.ts @@ -6,6 +6,7 @@ import { fallback, http, type Hex } from 'viem' import type { Chain } from '@wagmi/core/chains' import type { Connector } from '@wagmi/core' import { CoreHelperUtil } from '@reown/appkit-core' +import { WcHelpersUtil } from '@reown/appkit' export async function getWalletConnectCaipNetworks(connector?: Connector) { if (!connector) { @@ -15,22 +16,13 @@ export async function getWalletConnectCaipNetworks(connector?: Connector) { ReturnType<(typeof UniversalProvider)['init']> > - const ns = provider?.session?.namespaces - - const nsChains: CaipNetworkId[] | undefined = [] - - if (ns) { - Object.keys(ns).forEach(key => { - const chains = ns?.[key]?.chains - if (chains) { - nsChains.push(...(chains as CaipNetworkId[])) - } - }) - } + const approvedCaipNetworkIds = WcHelpersUtil.getChainsFromNamespaces( + provider?.session?.namespaces + ) return { - supportsAllNetworks: true, - approvedCaipNetworkIds: nsChains + supportsAllNetworks: false, + approvedCaipNetworkIds } } diff --git a/packages/appkit/src/tests/universal-adapter.test.ts b/packages/appkit/src/tests/universal-adapter.test.ts index 4de82634d9..946dfac3dc 100644 --- a/packages/appkit/src/tests/universal-adapter.test.ts +++ b/packages/appkit/src/tests/universal-adapter.test.ts @@ -55,7 +55,7 @@ describe('UniversalAdapter', () => { await universalAdapter.networkControllerClient.getApprovedCaipNetworksData() expect(approvedCaipNetworksData).toMatchObject({ - supportsAllNetworks: true, + supportsAllNetworks: false, approvedCaipNetworkIds: [ mockProvider.session?.namespaces['eip155']?.chains?.[0], mockProvider.session?.namespaces['solana']?.chains?.[0] @@ -136,6 +136,14 @@ describe('UniversalAdapter', () => { expect(mockAppKit.resetAccount).toHaveBeenCalledWith('eip155') expect(mockAppKit.resetAccount).toHaveBeenCalledWith('solana') }) + + it('should set the ApprovedCaipNetworksData', async () => { + const mockOnUri = vi.fn() + await universalAdapter?.connectionControllerClient?.connectWalletConnect?.(mockOnUri) + + expect(mockAppKit.setApprovedCaipNetworksData).toHaveBeenCalledWith('eip155') + expect(mockAppKit.setApprovedCaipNetworksData).toHaveBeenCalledWith('solana') + }) }) describe('UniversalAdapter - ProviderUtil', () => { diff --git a/packages/appkit/src/tests/utils/HelpersUtil.test.ts b/packages/appkit/src/tests/utils/HelpersUtil.test.ts index 474f03f495..8add47da9d 100644 --- a/packages/appkit/src/tests/utils/HelpersUtil.test.ts +++ b/packages/appkit/src/tests/utils/HelpersUtil.test.ts @@ -1,6 +1,7 @@ import { describe, test, expect } from 'vitest' import { WcHelpersUtil } from '../../utils/HelpersUtil' import type { CaipNetwork } from '@reown/appkit-common' +import type { SessionTypes } from '@walletconnect/types' const mockEthereumNetwork = { id: 'eip155:1', @@ -128,4 +129,33 @@ describe('WcHelpersUtil', () => { expect(namespaces).toEqual({}) }) }) + + describe('getChainsFromNamespaces', () => { + test('returns correct chain ids', () => { + const namespaces = { + eip155: { + methods: [], + events: [], + chains: ['eip155:1', 'eip155:137'], + accounts: ['eip155:4000:0x123', 'eip155:3000:0x456'] + }, + solana: { + methods: [], + events: [], + chains: ['solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'], + accounts: ['solana:mainnet:address', 'solana:devnet:address'] + } + } as SessionTypes.Namespaces + + expect(WcHelpersUtil.getChainsFromNamespaces(namespaces)).toEqual([ + 'eip155:1', + 'eip155:137', + 'eip155:4000', + 'eip155:3000', + 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', + 'solana:mainnet', + 'solana:devnet' + ]) + }) + }) }) diff --git a/packages/appkit/src/universal-adapter/client.ts b/packages/appkit/src/universal-adapter/client.ts index f8ab685664..30325e1940 100644 --- a/packages/appkit/src/universal-adapter/client.ts +++ b/packages/appkit/src/universal-adapter/client.ts @@ -16,13 +16,7 @@ import type { UniversalProviderOpts } from '@walletconnect/universal-provider' import { WcHelpersUtil } from '../utils/HelpersUtil.js' import type { AppKit } from '../client.js' import type { SessionTypes } from '@walletconnect/types' -import type { - CaipNetwork, - CaipNetworkId, - CaipAddress, - ChainNamespace, - AdapterType -} from '@reown/appkit-common' +import type { CaipNetwork, CaipAddress, ChainNamespace, AdapterType } from '@reown/appkit-common' import { SafeLocalStorage, SafeLocalStorageKeys } from '@reown/appkit-common' import { ProviderUtil } from '../store/index.js' import type { AppKitOptions } from '../utils/TypesUtil.js' @@ -104,27 +98,22 @@ export class UniversalAdapterClient { }, getApprovedCaipNetworksData: async () => { - await this.getWalletConnectProvider() - - return new Promise(resolve => { - const ns = this.walletConnectProvider?.session?.namespaces - const nsChains: CaipNetworkId[] | undefined = [] + const provider = await this.getWalletConnectProvider() - if (ns) { - Object.keys(ns).forEach(key => { - const chains = ns?.[key]?.chains - if (chains) { - nsChains.push(...(chains as CaipNetworkId[])) - } - }) - } + if (!provider) { + return Promise.resolve({ + supportsAllNetworks: false, + approvedCaipNetworkIds: [] + }) + } - const result = { - supportsAllNetworks: true, - approvedCaipNetworkIds: nsChains as CaipNetworkId[] | undefined - } + const approvedCaipNetworkIds = WcHelpersUtil.getChainsFromNamespaces( + provider.session?.namespaces + ) - resolve(result) + return Promise.resolve({ + supportsAllNetworks: false, + approvedCaipNetworkIds }) } } @@ -160,7 +149,8 @@ export class UniversalAdapterClient { isSiweEnabled && siweParams && isProviderSupported && - isSiweParamsValid + isSiweParamsValid && + ChainController.state.activeChain === 'eip155' ) { const { SIWEController, getDidChainId, getDidAddress } = await import( '@reown/appkit-siwe' @@ -382,18 +372,18 @@ export class UniversalAdapterClient { const nameSpaces = this.walletConnectProvider?.session?.namespaces if (nameSpaces) { - Object.keys(nameSpaces) - .reverse() - .forEach(key => { - const caipAddress = nameSpaces?.[key]?.accounts[0] as CaipAddress + const reversedChainNamespaces = Object.keys(nameSpaces).reverse() as ChainNamespace[] + reversedChainNamespaces.forEach(chainNamespace => { + const caipAddress = nameSpaces?.[chainNamespace]?.accounts[0] as CaipAddress | undefined - ProviderUtil.setProvider(key as ChainNamespace, this.walletConnectProvider) - ProviderUtil.setProviderId(key as ChainNamespace, 'walletConnect') + ProviderUtil.setProvider(chainNamespace, this.walletConnectProvider) + ProviderUtil.setProviderId(chainNamespace, 'walletConnect') + this.appKit?.setApprovedCaipNetworksData(chainNamespace) - if (caipAddress) { - this.appKit?.setCaipAddress(caipAddress, key as ChainNamespace) - } - }) + if (caipAddress) { + this.appKit?.setCaipAddress(caipAddress, chainNamespace) + } + }) const storedCaipNetwork = StorageUtil.getStoredActiveCaipNetwork() const activeCaipNetwork = ChainController.state.activeCaipNetwork diff --git a/packages/appkit/src/utils/HelpersUtil.ts b/packages/appkit/src/utils/HelpersUtil.ts index 0787fe4691..ebc3f247dc 100644 --- a/packages/appkit/src/utils/HelpersUtil.ts +++ b/packages/appkit/src/utils/HelpersUtil.ts @@ -1,5 +1,6 @@ import type { NamespaceConfig, Namespace } from '@walletconnect/universal-provider' -import type { CaipNetwork, ChainNamespace } from '@reown/appkit-common' +import type { CaipNetwork, CaipNetworkId, ChainNamespace } from '@reown/appkit-common' +import type { SessionTypes } from '@walletconnect/types' export const WcHelpersUtil = { getMethodsByChainNamespace(chainNamespace: ChainNamespace): string[] { @@ -62,5 +63,18 @@ export const WcHelpersUtil = { return acc }, {}) + }, + + getChainsFromNamespaces(namespaces: SessionTypes.Namespaces = {}): CaipNetworkId[] { + return Object.values(namespaces).flatMap(namespace => { + const chains = (namespace.chains || []) as CaipNetworkId[] + const accountsChains = namespace.accounts.map(account => { + const [chainNamespace, chainId] = account.split(':') + + return `${chainNamespace}:${chainId}` as CaipNetworkId + }) + + return Array.from(new Set([...chains, ...accountsChains])) + }) } } diff --git a/packages/core/src/controllers/NetworkController.ts b/packages/core/src/controllers/NetworkController.ts index e9c96a558b..cf614c4483 100644 --- a/packages/core/src/controllers/NetworkController.ts +++ b/packages/core/src/controllers/NetworkController.ts @@ -204,18 +204,14 @@ export const NetworkController = { }, async setApprovedCaipNetworksData(chain: ChainNamespace | undefined) { - const networkControllerClient = ChainController.getNetworkControllerClient() - - const data = await networkControllerClient?.getApprovedCaipNetworksData() - if (!chain) { throw new Error('chain is required to set approved network data') } - ChainController.setChainNetworkData(chain, { - approvedCaipNetworkIds: data?.approvedCaipNetworkIds, - supportsAllNetworks: data?.supportsAllNetworks - }) + const networkControllerClient = ChainController.getNetworkControllerClient() + const data = await networkControllerClient?.getApprovedCaipNetworksData() + + ChainController.setChainNetworkData(chain, data) }, checkIfSupportedNetwork() { diff --git a/packages/scaffold-ui/src/modal/w3m-modal/index.ts b/packages/scaffold-ui/src/modal/w3m-modal/index.ts index 61c10a518a..622349e69c 100644 --- a/packages/scaffold-ui/src/modal/w3m-modal/index.ts +++ b/packages/scaffold-ui/src/modal/w3m-modal/index.ts @@ -218,6 +218,7 @@ export class W3mModal extends LitElement { private async onNewNetwork(nextCaipNetwork: CaipNetwork | undefined) { if (!this.caipAddress) { this.caipNetwork = nextCaipNetwork + RouterController.goBack() return } diff --git a/packages/scaffold-ui/src/partials/w3m-all-wallets-widget/index.ts b/packages/scaffold-ui/src/partials/w3m-all-wallets-widget/index.ts index 743f60dab1..caaa64cfe0 100644 --- a/packages/scaffold-ui/src/partials/w3m-all-wallets-widget/index.ts +++ b/packages/scaffold-ui/src/partials/w3m-all-wallets-widget/index.ts @@ -33,7 +33,7 @@ export class W3mAllWalletsWidget extends LitElement { // -- Render -------------------------------------------- // public override render() { - const wcConnector = this.connectors.find(c => c.type === 'WALLET_CONNECT') + const wcConnector = this.connectors.find(c => c.id === 'walletConnect') const { allWallets } = OptionsController.state if (!wcConnector || allWallets === 'HIDE') { diff --git a/packages/scaffold-ui/src/partials/w3m-connect-announced-widget/index.ts b/packages/scaffold-ui/src/partials/w3m-connect-announced-widget/index.ts index e54210dff3..08e16cca4f 100644 --- a/packages/scaffold-ui/src/partials/w3m-connect-announced-widget/index.ts +++ b/packages/scaffold-ui/src/partials/w3m-connect-announced-widget/index.ts @@ -68,7 +68,7 @@ export class W3mConnectAnnouncedWidget extends LitElement { // -- Private Methods ----------------------------------- // private onConnector(connector: Connector) { - if (connector.type === 'WALLET_CONNECT') { + if (connector.id === 'walletConnect') { if (CoreHelperUtil.isMobile()) { RouterController.push('AllWallets') } else { diff --git a/packages/scaffold-ui/src/partials/w3m-connect-recommended-widget/index.ts b/packages/scaffold-ui/src/partials/w3m-connect-recommended-widget/index.ts index afc35a2e3b..6afa3559d0 100644 --- a/packages/scaffold-ui/src/partials/w3m-connect-recommended-widget/index.ts +++ b/packages/scaffold-ui/src/partials/w3m-connect-recommended-widget/index.ts @@ -34,7 +34,7 @@ export class W3mConnectRecommendedWidget extends LitElement { // -- Render -------------------------------------------- // public override render() { - const connector = this.connectors.find(c => c.type === 'WALLET_CONNECT') + const connector = this.connectors.find(c => c.id === 'walletConnect') if (!connector) { return null } diff --git a/packages/scaffold-ui/src/partials/w3m-connect-walletconnect-widget/index.ts b/packages/scaffold-ui/src/partials/w3m-connect-walletconnect-widget/index.ts index 82b845fe62..9c060e01fd 100644 --- a/packages/scaffold-ui/src/partials/w3m-connect-walletconnect-widget/index.ts +++ b/packages/scaffold-ui/src/partials/w3m-connect-walletconnect-widget/index.ts @@ -38,7 +38,7 @@ export class W3mConnectWalletConnectWidget extends LitElement { return null } - const connector = this.connectors.find(c => c.type === 'WALLET_CONNECT') + const connector = this.connectors.find(c => c.id === 'walletConnect') if (!connector) { this.style.cssText = `display: none` diff --git a/packages/scaffold-ui/src/partials/w3m-connector-list/index.ts b/packages/scaffold-ui/src/partials/w3m-connector-list/index.ts index e92e02fc03..f00327fbfb 100644 --- a/packages/scaffold-ui/src/partials/w3m-connector-list/index.ts +++ b/packages/scaffold-ui/src/partials/w3m-connector-list/index.ts @@ -37,6 +37,7 @@ export class W3mConnectorList extends LitElement { public override render() { const { custom, recent, announced, injected, multiChain, recommended, featured, external } = this.getConnectorsByType() + const enableWalletConnect = OptionsController.state.enableWalletConnect return html` diff --git a/packages/scaffold-ui/src/partials/w3m-social-login-widget/index.ts b/packages/scaffold-ui/src/partials/w3m-social-login-widget/index.ts index 00993d7bc0..77340272e0 100644 --- a/packages/scaffold-ui/src/partials/w3m-social-login-widget/index.ts +++ b/packages/scaffold-ui/src/partials/w3m-social-login-widget/index.ts @@ -149,7 +149,7 @@ export class W3mSocialLoginWidget extends LitElement { } private separatorTemplate() { - const walletConnectConnector = this.connectors.find(c => c.type === 'WALLET_CONNECT') + const walletConnectConnector = this.connectors.find(c => c.id === 'walletConnect') const enableWallets = OptionsController.state.enableWallets if (walletConnectConnector && enableWallets) { diff --git a/packages/scaffold-ui/src/views/w3m-connecting-multi-chain-view/index.ts b/packages/scaffold-ui/src/views/w3m-connecting-multi-chain-view/index.ts index 661d2ab6a0..529eba39e7 100644 --- a/packages/scaffold-ui/src/views/w3m-connecting-multi-chain-view/index.ts +++ b/packages/scaffold-ui/src/views/w3m-connecting-multi-chain-view/index.ts @@ -100,7 +100,7 @@ export class W3mConnectingMultiChainView extends LitElement { return } - if (connector.type === 'WALLET_CONNECT') { + if (connector.id === 'walletConnect') { if (CoreHelperUtil.isMobile()) { RouterController.push('AllWallets') } else { diff --git a/packages/scaffold-ui/src/views/w3m-networks-view/index.ts b/packages/scaffold-ui/src/views/w3m-networks-view/index.ts index e3cc58e796..93b537fa31 100644 --- a/packages/scaffold-ui/src/views/w3m-networks-view/index.ts +++ b/packages/scaffold-ui/src/views/w3m-networks-view/index.ts @@ -146,47 +146,36 @@ export class W3mNetworksView extends LitElement { return !approvedCaipNetworkIds?.includes(network.id) } - private async onSwitchNetwork(network: CaipNetwork) { - const isCurrentNamespaceConnected = AccountController.state.caipAddress - const isNamespaceConnected = AccountController.getCaipAddress(network.chainNamespace) - const isSameNetwork = network.id === this.network?.id - - const supportsAllNetworks = NetworkController.state.supportsAllNetworks + private onSwitchNetwork(network: CaipNetwork) { const routerData = RouterController.state.data - - const type = StorageUtil.getConnectedConnector() - const authConnector = ConnectorController.getAuthConnector() - const isConnectedWithAuth = type === 'AUTH' && authConnector + const isSameNetwork = network.id === this.network?.id if (isSameNetwork) { return } - if (isNamespaceConnected) { - if (supportsAllNetworks || isConnectedWithAuth) { - RouterController.push('SwitchNetwork', { ...routerData, network }) - } else { - await NetworkController.switchActiveNetwork(network) - } + const isDifferentNamespace = network.chainNamespace !== ChainController.state.activeChain + const isNewNetworkConnected = ChainController.getAccountProp( + 'caipAddress', + network.chainNamespace + ) + const isCurrentNetworkConnected = AccountController.state.caipAddress + const isAuthConnected = StorageUtil.getConnectedConnector() === 'AUTH' + + if ( + isDifferentNamespace && + isCurrentNetworkConnected && + !isNewNetworkConnected && + !isAuthConnected + ) { + RouterController.push('SwitchActiveChain', { + switchToChain: network.chainNamespace, + navigateTo: 'Connect', + navigateWithReplace: true, + network + }) } else { - // eslint-disable-next-line no-lonely-if - if (ChainController.state.noAdapters) { - RouterController.push('ConnectingWalletConnect') - } else if (isConnectedWithAuth) { - RouterController.push('SwitchNetwork', { ...routerData, network }) - } else { - // eslint-disable-next-line no-lonely-if - if (isCurrentNamespaceConnected) { - RouterController.push('SwitchActiveChain', { - switchToChain: network.chainNamespace, - navigateTo: 'Connect', - navigateWithReplace: true, - network - }) - } else { - NetworkController.setActiveCaipNetwork(network) - } - } + RouterController.push('SwitchNetwork', { ...routerData, network }) } } }