import type { Network, SwitchNetworkResult } from '@meshconnect/uwc-types' import { WalletConnectClient } from './walletconnect-client' import { ConnectionService } from './connection-service' import { parseAccount } from '../utils/account-utils' import { parseError } from '../utils/error-utils' /** * Service for handling network switching in WalletConnect */ export class NetworkSwitchService { constructor( private walletConnectClient: WalletConnectClient, private connectionService: ConnectionService ) {} /** * Switch to a different network */ async switchNetwork(network: Network): Promise { try { const session = this.connectionService.getSession() if (!session) { throw new Error('No active session. Please connect first.') } const client = await this.walletConnectClient.getClient() // Check if the requested network is available in the session const networkChain = network.id const namespace = network.namespace const approvedChains = session.namespaces[namespace]?.chains ?? [] const approvedAccounts = session.namespaces[namespace]?.accounts ?? [] // CAIP-25: accounts encode `chainId:address`, so they implicitly // declare chain approval. Some wallets (e.g. ZenGo) ship an empty // `chains` array even when accounts cover every requested chain. const chainsFromAccounts = new Set() for (const account of approvedAccounts) { try { chainsFromAccounts.add(parseAccount(account).networkId) } catch { // Skip malformed account strings } } const effectiveChains = new Set([ ...approvedChains, ...chainsFromAccounts ]) if (!effectiveChains.has(networkChain)) { throw new Error( `Network ${networkChain} is not available in the current session` ) } // For WalletConnect, we can't directly switch networks // The wallet controls the active network // We can only request methods on specific chains // Return the current address for the requested network const accounts = session.namespaces[namespace]?.accounts || [] const matchingAccount = accounts.find(account => account.startsWith(networkChain) ) if (!matchingAccount) { throw new Error(`No account found for network ${networkChain}`) } // Extract address from account string const { address } = parseAccount(matchingAccount) // Update the active network and address in the connection service this.connectionService.setActiveNetwork(network) this.connectionService.setActiveAddress(address) // Emit a chainChanged event if switching within the same namespace if (namespace === 'eip155') { try { await client.emit({ topic: session.topic, event: { name: 'chainChanged', data: networkChain }, chainId: networkChain }) } catch { // Some wallets may not support this event } } return { networkId: network.id, address } } catch (error) { throw parseError(error) } } }