diff --git a/src/utils/networks.ts b/src/utils/networks.ts index 3328451a..4344e31b 100644 --- a/src/utils/networks.ts +++ b/src/utils/networks.ts @@ -29,7 +29,6 @@ export const networkParams = { export async function isNetworkAdded(network: NetworkType): Promise { if (!(window as any).ethereum) return false; - try { const chainId = await (window as any).ethereum.request({ method: "eth_chainId", @@ -45,6 +44,8 @@ export async function isNetworkAdded(network: NetworkType): Promise { export type UseNetworkResponse = { isWalletInstalled: boolean; + // isAdded is a heuristic: true if this chain is active, or was added/ + // selected during this hook's lifetime. Resets on network change. isAdded: boolean; isSelected: boolean; addNetwork: () => Promise; @@ -58,22 +59,28 @@ export function useNetwork(network: NetworkType): UseNetworkResponse { // Check if network is added and selected on mount and when network changes useEffect(() => { + setIsAdded(false); + setIsSelected(false); + + let cancelled = false; // avoid stale writes if `network` changes mid-request + const checkNetwork = async () => { if (window.ethereum) { try { const chainId = await window.ethereum.request({ method: "eth_chainId", }); + if (cancelled) return; const isCurrentNetwork = chainId.toLowerCase() === networkParams[network].chainId.toLowerCase(); setIsSelected(isCurrentNetwork); - setIsAdded((prev) => isCurrentNetwork || prev); // If we're on the network, it must be added + setIsAdded((prev) => isCurrentNetwork || prev); } catch (error) { - console.error("Error checking network:", error); + if (!cancelled) console.error("Error checking network:", error); } } - setIsWalletInstalled(window.ethereum !== undefined); + if (!cancelled) setIsWalletInstalled(window.ethereum !== undefined); }; checkNetwork(); @@ -82,21 +89,32 @@ export function useNetwork(network: NetworkType): UseNetworkResponse { if (window.ethereum) { window.ethereum.on("chainChanged", checkNetwork); return () => { + cancelled = true; window.ethereum.removeListener("chainChanged", checkNetwork); }; } + return () => { + cancelled = true; + }; }, [network]); async function addNetwork(): Promise { if (!window.ethereum) return; - try { await window.ethereum.request({ method: "wallet_addEthereumChain", params: [networkParams[network]], }); setIsAdded(true); - await selectNetwork(); // Automatically switch to the network after adding + try { + await window.ethereum.request({ + method: "wallet_switchEthereumChain", + params: [{ chainId: networkParams[network].chainId }], + }); + setIsSelected(true); + } catch (switchError) { + console.error("Error selecting network after add:", switchError); + } } catch (error) { console.error("Error adding network:", error); } @@ -104,14 +122,18 @@ export function useNetwork(network: NetworkType): UseNetworkResponse { async function selectNetwork(): Promise { if (!window.ethereum) return; - try { await window.ethereum.request({ method: "wallet_switchEthereumChain", params: [{ chainId: networkParams[network].chainId }], }); setIsSelected(true); - } catch (error) { + setIsAdded(true); + } catch (error: any) { + if (error?.code === 4902) { + await addNetwork(); // unknown chain: add it, addNetwork does its own switch + return; + } console.error("Error switching network:", error); } }