From dca16774f6e4ea5343a25ad32fefb5efd3d6d6b3 Mon Sep 17 00:00:00 2001 From: sirakinb Date: Wed, 27 May 2026 10:37:05 -0400 Subject: [PATCH] fix: handle wrapped wallet chain switch errors --- public/locales/en/common.json | 2 + src/components/layout/unexpected_chain.tsx | 52 ++++++++++++++++++---- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index f7d64599..acb76f7e 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -34,6 +34,8 @@ "unexpected_network_title": "Unexpected network", "unexpected_network": "Please connect your wallet to '{{network}}'", "metamask_not_found": "Missing metamask plugin - get it from", + "wallet_provider_missing": "No browser wallet provider was found.", + "switch_network_failed": "Network switch failed.", "wallet_connect_failed": "WalletConnect login failed or cancelled", "field": { "required": "This field is required", diff --git a/src/components/layout/unexpected_chain.tsx b/src/components/layout/unexpected_chain.tsx index 3bae8408..3771329c 100644 --- a/src/components/layout/unexpected_chain.tsx +++ b/src/components/layout/unexpected_chain.tsx @@ -2,10 +2,13 @@ import { Alert, AlertTitle, Button, Paper } from "@mui/material"; import Box from "@mui/system/Box"; import { useTranslation } from "next-i18next"; +import { useState } from "react"; import { toHexString } from "../../utils/numbers"; export default function UnexpectedChain() { const { t } = useTranslation('common'); + const [switchError, setSwitchError] = useState(); + const [switching, setSwitching] = useState(false); const chainName = process.env.NEXT_PUBLIC_CHAIN_NAME; const chainId = process.env.NEXT_PUBLIC_CHAIN_ID; const chainRpcUrl = process.env.NEXT_PUBLIC_CHAIN_RPC_URL; @@ -16,23 +19,41 @@ export default function UnexpectedChain() { const allowAutoAdd = chainRpcUrl?.startsWith('https://'); // adding chain only works for https rpc URLs async function switchNetwork() { + setSwitchError(undefined); + setSwitching(true); + try { - // @ts-ignore - await window.ethereum.request({ + const ethereum = (window as any).ethereum; + if (!ethereum) { + throw new Error(t('error.wallet_provider_missing')); + } + + await ethereum.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: toHexString(chainId ?? '0') }], }); } catch(switchError) { - // @ts-ignore - if (allowAutoAdd && switchError.code === 4902) { - addNetwork(); + if (allowAutoAdd && isUnrecognizedChainError(switchError)) { + try { + await addNetwork(); + } catch(addError) { + setSwitchError(getWalletErrorMessage(addError)); + } + } else { + setSwitchError(getWalletErrorMessage(switchError)); } + } finally { + setSwitching(false); } } async function addNetwork() { - // @ts-ignore - await window.ethereum.request({ + const ethereum = (window as any).ethereum; + if (!ethereum) { + throw new Error(t('error.wallet_provider_missing')); + } + + await ethereum.request({ method: 'wallet_addEthereumChain', params: [ { @@ -50,6 +71,14 @@ export default function UnexpectedChain() { }); } + function isUnrecognizedChainError(error: any): boolean { + return error?.code === 4902 || error?.data?.originalError?.code === 4902; + } + + function getWalletErrorMessage(error: any): string { + return error?.data?.originalError?.message ?? error?.message ?? t('error.switch_network_failed'); + } + return (
@@ -57,12 +86,17 @@ export default function UnexpectedChain() { {t('error.unexpected_network_title')} {t('error.unexpected_network', { network: chainName})} - + {switchError && ( + + {switchError} + + )}
); -} \ No newline at end of file +}