{"id":"EIP-3326","name":"wallet_switchEthereumChain","status":"Stagnant","chain":"ethereum","category":{"id":"transaction-friction","name":"Transaction Friction","description":"Reducing clicks, signatures, and mental overhead"},"journeyStages":[{"id":"discovery","name":"Discovery & Connection","description":"Finding and connecting wallet to dApp"},{"id":"executing","name":"Executing Transactions","description":"Performing on-chain actions"}],"uxImpact":"EIP-3326 defines wallet_switchEthereumChain, a request for a wallet with an active-chain concept to switch to a known chain. The specification is Stagnant and recommends explicit confirmation and cancellation of chain-specific pending work; implementation details, supported chains, and error handling remain wallet-specific.","slug":"eip-3326","officialUrl":"https://eips.ethereum.org/EIPS/eip-3326","sources":[{"label":"Official specification","url":"https://eips.ethereum.org/EIPS/eip-3326","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=EIP-3326","type":"discussion"},{"label":"MetaMask wallet_switchEthereumChain reference","url":"https://docs.metamask.io/metamask-connect/evm/reference/json-rpc-api/wallet_switchEthereumChain/","type":"implementation"}],"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","hasDetailedContent":true,"content":{"id":"EIP-3326","specConstraints":[{"id":"wallet-switch-validation","constraint":"A wallet rejects a chain-switch request when its fields are invalid, the chain is unknown, or the wallet cannot service the chain.","appliesTo":"wallet","normativity":"normative","specQuote":"If a field does not meet the requirements of this specification, the wallet **MUST** reject the request.","specSection":"Specification — walletswitchEthereumChain — Parameters","specUrl":"https://eips.ethereum.org/EIPS/eip-3326#parameters","designImplication":"Show a clear unsupported or unavailable network state before asking the user to confirm a switch."},{"id":"wallet-switch-return-state","constraint":"A successful chain switch returns `null`; an unsupported active-chain concept or other failure returns an error.","appliesTo":"application","normativity":"normative","specQuote":"The method **MUST** return `null` if the request was successful, and an error otherwise.","specSection":"Specification — walletswitchEthereumChain — Returns","specUrl":"https://eips.ethereum.org/EIPS/eip-3326#returns","designImplication":"Wait for the wallet result and then refresh network-specific data. Do not treat a request dispatch as a completed switch."},{"id":"wallet-switch-confirmation","constraint":"Wallets should confirm the requester and target chain, then cancel pending chain-specific requests and confirmations after a switch.","appliesTo":"wallet","normativity":"security-considerations","specQuote":"## Security Considerations\n\nFor wallets with a concept of an active chain, switching the active chain has significant implications for pending RPC requests and the user's experience.\nIf the active chain switches without the user's awareness, a dapp could induce the user to take actions for unintended chains.\n\nIn light of this, the wallet should:\n\n- Display a confirmation whenever a `wallet_switchEthereumChain` is received, clearly identifying the requester and the chain that will be switched to.\n  - The confirmation used in [EIP-1102](./eip-1102.md) may serve as a point of reference.\n- When switching the active chain, cancel all pending RPC requests and chain-specific user confirmations.","specSection":"Security Considerations","specUrl":"https://eips.ethereum.org/EIPS/eip-3326#security-considerations","designImplication":"Name the requesting app and target chain in the confirmation. Clear stale network-specific forms and pending confirmations after the switch."},{"id":"wallet-switch-privacy","constraint":"Automatically rejecting unsupported chains can reveal which chains a wallet supports.","appliesTo":"wallet","normativity":"security-considerations","specQuote":"### Preserving User Privacy\n\nAutomatically rejecting requests for chains that aren't supported or have yet to be added by the wallet allows requesters to infer which chains are supported by the wallet.\nWallet implementers should consider whether this communication channel violates any security properties of the wallet, and if so, take appropriate steps to mitigate it.","specSection":"Security Considerations — Preserving User Privacy","specUrl":"https://eips.ethereum.org/EIPS/eip-3326#preserving-user-privacy","designImplication":"Treat unsupported-chain responses as a privacy decision and avoid exposing the wallet’s full supported-chain inventory unnecessarily."}],"sources":[{"label":"EIP-3326 official specification","url":"https://eips.ethereum.org/EIPS/eip-3326","type":"official-spec"},{"label":"MetaMask wallet_switchEthereumChain reference","url":"https://docs.metamask.io/metamask-connect/evm/reference/json-rpc-api/wallet_switchEthereumChain/","type":"implementation"}],"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","summary":"EIP-3326 defines wallet_switchEthereumChain, a request for a wallet with an active-chain concept to switch to a known chain. The specification is Stagnant and recommends explicit confirmation and cancellation of chain-specific pending work; implementation details, supported chains, and error handling remain wallet-specific.","partialDeployment":{"body":"MetaMask Connect documents a current implementation, including error 4902 for an unrecognized chain. That documentation does not establish support in every wallet or connection type. Feature-detect the method, handle rejection and unknown-chain errors, and verify the active chain after the request."},"designerTakeaways":["Name the requester and destination network in the handoff, then verify the provider's active chain before resuming an action.","Cancel or invalidate pending network-specific quotes, signatures, and transaction requests when the chain changes.","Treat an unknown-chain response as a separate add-network step rather than repeatedly prompting the user to switch."],"applicability":{"whenToUse":["A dapp has a verified network requirement and the wallet exposes one active chain.","The product can safely pause and revalidate the current action after a chain change.","The user benefits from returning to the same task after a wallet network handoff."],"whenToAvoid":["The connection model supports multiple active chains or the wallet does not implement the method.","The app would continue using a quote, signature, or pending request created for the previous chain.","The target chain is not already known to the wallet and no explicit add-network flow is available."]},"prototypeFirst":[{"screen":"Switch-network confirmation","why":"A chain switch changes where subsequent reads, signatures, and transactions are directed.","covers":["Supported chain","User rejection","Unknown chain"],"include":["Requester identity","Current and destination chain","Pending-work cancellation notice","Back-to-task behavior"]},{"screen":"Stale action recovery","why":"A switch can invalidate the assumptions behind the action that triggered it.","covers":["Quote expired","Wrong-chain signature","Action revalidated"],"include":["Fresh quote marker","Network-bound data refresh","Retry and cancel"]}],"mentalModel":[{"label":"Active chain","description":"The wallet forwards chain-specific RPC requests to one selected network for this connection."},{"label":"Switch request","description":"The dapp asks the wallet to select a known chain by hexadecimal chain ID; the wallet decides whether to approve it."},{"label":"Pending-work boundary","description":"A switch changes the context for reads and confirmations, so pending chain-specific work must be cancelled or rechecked."},{"label":"Verified return","description":"The app resumes only after the provider reports the expected chain ID and the current action has been rebuilt for that chain."}],"statesToDesign":[{"state":"Switch pending","trigger":"The wallet confirmation is open.","userNeed":"Know why the wallet is asking to change networks.","designResponse":"Show current and destination chains and hold the action in a paused state."},{"state":"Switched, action revalidating","trigger":"The provider emits the expected chain change.","userNeed":"Know whether the original action is still valid.","designResponse":"Refresh chain-bound reads and quotes before restoring the primary action."},{"state":"Unknown chain","trigger":"The wallet does not know the requested chain; MetaMask documents error code 4902 for this case.","userNeed":"Understand why switching stopped and what setup is required.","designResponse":"Offer an add-network handoff using verified metadata, then retry switching only after the add result is known."},{"state":"Rejected or unsupported","trigger":"The user declines or the provider does not implement the method.","userNeed":"A clear way to remain safe on the current chain.","designResponse":"Keep the current context explicit, preserve the action where safe, and show manual switching instructions."},{"state":"Wrong chain after request","trigger":"The request returned but eth_chainId does not match the destination.","userNeed":"Avoid signing or submitting to the wrong network.","designResponse":"Block the chain-specific action and ask the user to recheck the wallet network."}],"designDecisions":[{"question":"What should the user see before a switch?","recommendation":"Show the current chain, destination chain ID and name, requester, and which pending work will be refreshed.","rationale":"A silent chain switch can make a familiar action target a different contract or asset."},{"question":"What happens to a pending signature?","recommendation":"Cancel or discard chain-specific confirmations and rebuild the request after the switch.","rationale":"The EIP calls for cancelling pending RPC requests and confirmations tied to the old chain."},{"question":"When should add-network appear?","recommendation":"Use an explicit add step after a recognized unknown-chain response, with the same metadata review as EIP-3085.","rationale":"Switching does not define how an unknown chain becomes known to the wallet."}],"problemsSolved":[{"problem":"Users must open wallet settings to reach a known network","oldWay":"Leave the dapp, search for the network, switch manually, then find the task again.","newWay":"A compatible wallet can request a switch to a known chain from the dapp.","impact":"high"},{"problem":"A dapp continues using stale data after the network changes","oldWay":"Keep the previous quote, contract address, or signature request alive across the switch.","newWay":"Invalidate chain-specific work and rebuild it after provider verification.","impact":"critical"},{"problem":"Users cannot tell whether the handoff completed","oldWay":"Dismiss the error or spinner and hope the wallet changed networks.","newWay":"Listen for the provider chain change and show a verified return state.","impact":"high"}],"uxPatterns":[{"name":"Safe Network Handoff","description":"Pause the current task, request a wallet switch, then revalidate and continue on the selected chain.","components":["Current-network badge","Destination-network card","Pending-work notice","Revalidation status"],"userFlow":["Detect the required chain","Show current and destination network","Request wallet_switchEthereumChain","Listen for chainChanged and verify eth_chainId","Refresh chain-specific data","Resume or show a recovery action"]},{"name":"Add Then Switch","description":"Handle an unknown destination as a verified add-network step before retrying the switch.","components":["Add-network handoff","Unknown-chain explanation","Retry switch","Manual fallback"],"userFlow":["Request a switch to a known chain ID","Receive an unknown-chain response","Review verified add-network metadata","Request wallet_addEthereumChain","Retry switch and verify active chain"]}],"uiComponents":[{"name":"NetworkSwitchStatus","description":"Shows the current chain, requested destination, wallet response, and active-chain verification.","kind":"status","states":["ready","waiting","switched","unknown-chain","rejected","mismatch"],"props":["currentChainId","requestedChainId","error","onRetry","onCancel"]},{"name":"StaleActionNotice","description":"Explains which quote, signature, or request was invalidated by the chain change.","kind":"status","states":["refreshing","refreshed","blocked"],"props":["resourceType","oldChainId","newChainId","onRefresh"]}],"antiPatterns":[{"pattern":"Switching silently in the background","why":"A dapp could cause a user to take a sensitive action on an unintended chain.","instead":"Name the requester and destination chain and rely on wallet confirmation.","severity":"critical"},{"pattern":"Continuing with a quote or signature from the old chain","why":"Chain-bound data can point to the wrong contract, asset, or replay domain.","instead":"Invalidate and refresh chain-specific work after chainChanged.","severity":"critical"},{"pattern":"Treating error 4902 as a generic transaction failure","why":"The user needs a network-add recovery path, not a retry loop.","instead":"Offer EIP-3085 setup when the wallet supports it and otherwise explain manual setup.","severity":"high"},{"pattern":"Calling the switch method without feature detection","why":"Provider implementations differ and may reject unknown methods.","instead":"Detect support, handle user rejection, and keep manual switching available.","severity":"medium"}],"vocabulary":[{"use":"Switch network","avoid":"Move funds","why":"The method changes the wallet's active RPC context; it does not transfer assets."},{"use":"Refreshing for [network]","avoid":"Transaction pending","why":"A chain switch is a provider context change, not an on-chain transaction."},{"use":"This network is not added yet","avoid":"Network unavailable","why":"The chain may be healthy; the wallet simply may not know its configuration."}],"technicalNotes":"wallet_switchEthereumChain accepts an object with a hexadecimal chainId and returns null if the wallet switched its active chain. The wallet must reject malformed or unknown chain IDs and may reject a valid request. If the wallet has no active-chain concept it must reject the request. Wallets should show confirmation, identify the requester and destination, and cancel pending chain-specific RPC requests and confirmations. MetaMask documents error 4902 for an unrecognized chain.","relatedStandards":[{"id":"EIP-3085","relationship":"Request a wallet to add the destination chain when it is not known."},{"id":"EIP-1193","relationship":"Provider request and chainChanged event transport."},{"id":"EIP-155","relationship":"Chain ID used to distinguish transaction domains."}],"keyTakeaways":["EIP-3326 is Stagnant; current support is wallet-specific.","A switch must be visible and must invalidate chain-specific pending work.","Error 4902 can lead to EIP-3085 add-network recovery in supported wallets.","Verify the active chain before signing or submitting the resumed action."]},"urls":{"canonical":"https://www.eipsfordesigners.com/standards/EIP-3326","markdown":"https://www.eipsfordesigners.com/standards/EIP-3326/content.md","agent":"https://www.eipsfordesigners.com/standards/EIP-3326/agent.md","api":"https://www.eipsfordesigners.com/api/standards/EIP-3326","official":"https://eips.ethereum.org/EIPS/eip-3326","discussion":"https://ethereum-magicians.org/search?q=EIP-3326"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}