From a9080c2a9da793dd830723c67567bc01ae4be724 Mon Sep 17 00:00:00 2001 From: Cardinal Date: Thu, 19 Mar 2026 12:39:04 +0100 Subject: [PATCH 1/4] remove custom gnosis RPC from env --- src/app/components/utils.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/app/components/utils.ts b/src/app/components/utils.ts index 0e33907..78bc8de 100644 --- a/src/app/components/utils.ts +++ b/src/app/components/utils.ts @@ -295,22 +295,19 @@ export const handleExchangeRateUpdate = async ( * @returns A public client configured for the Gnosis chain */ export const getGnosisPublicClient = (rpcIndex: number = 0) => { - // Use global custom RPC URL if set, otherwise fall back to env variable - const envRpcUrl = process.env.NEXT_PUBLIC_GNOSIS_RPC; - // Same RPC list as wagmi (single source of truth; no duplicate list here) const fallbackRpcs = getRpcUrlsForChain(gnosis.id)!; let rpcUrl: string; if (rpcIndex === 0) { - // Primary attempt: use custom/env RPC or first fallback - rpcUrl = globalCustomRpcUrl || envRpcUrl || fallbackRpcs[0]; + // Primary attempt: use global custom RPC or first fallback + rpcUrl = globalCustomRpcUrl || fallbackRpcs[0]; } else { // Fallback attempts: use specific fallback RPC rpcUrl = fallbackRpcs[rpcIndex] ?? fallbackRpcs[fallbackRpcs.length - 1]; } - // We are using public RPC for the Gnosis chain unless a custom RPC is set or env variable is set + // We are using public RPC for the Gnosis chain unless a global custom RPC is set const client = createPublicClient({ chain: gnosis, transport: rpcUrl ? http(rpcUrl) : http(), From 0b7ee738300b5288d848587134cbdb1f3d3adc7c Mon Sep 17 00:00:00 2001 From: Cardinal Date: Thu, 19 Mar 2026 13:05:17 +0100 Subject: [PATCH 2/4] remove private RPCs, just have public --- src/app/wagmi.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/app/wagmi.ts b/src/app/wagmi.ts index 6a03cfe..0314d0e 100644 --- a/src/app/wagmi.ts +++ b/src/app/wagmi.ts @@ -35,20 +35,16 @@ import { // 3 RPCs per chain — each verified with eth_chainId; failed ones replaced const RPC_FALLBACKS: Record = { [mainnet.id]: [ - 'https://eth-mainnet.g.alchemy.com/v2/IVUx4_9ohzDYHxS7mp4gG4FAyOJrggTV', 'https://eth.drpc.org', + 'https://eth.llamarpc.com', 'https://ethereum.publicnode.com', ], [gnosis.id]: [ - 'https://gnosis-mainnet.g.alchemy.com/v2/IVUx4_9ohzDYHxS7mp4gG4FAyOJrggTV', 'https://rpc.gnosischain.com', 'https://gnosis.drpc.org', + 'https://gnosis-rpc.publicnode.com', ], - [base.id]: [ - 'https://base-mainnet.g.alchemy.com/v2/IVUx4_9ohzDYHxS7mp4gG4FAyOJrggTV', - 'https://base.drpc.org', - 'https://mainnet.base.org', - ], + [base.id]: ['https://base.drpc.org', 'https://base.llamarpc.com', 'https://mainnet.base.org'], [arbitrum.id]: [ 'https://arb1.arbitrum.io/rpc', 'https://1rpc.io/arb', From c6e4487a2eceb116bcea55cdbb86c12b076ae8f2 Mon Sep 17 00:00:00 2001 From: Cardinal Date: Thu, 19 Mar 2026 13:19:46 +0100 Subject: [PATCH 3/4] remove local reverse --- src/app/wagmi.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/app/wagmi.ts b/src/app/wagmi.ts index 0314d0e..3e314a4 100644 --- a/src/app/wagmi.ts +++ b/src/app/wagmi.ts @@ -201,15 +201,10 @@ export function getPollingInterval(chainId: number): number { return CHAIN_POLLING_INTERVALS[chainId] ?? DEFAULT_POLLING_INTERVAL; } -// On localhost, try public RPCs first so whitelisted RPCs (e.g. Alchemy) don't 403. -const USE_PUBLIC_RPC_FIRST = - typeof window !== 'undefined' && window.location?.hostname === 'localhost'; - function transportForChain(chainId: number) { const urls = RPC_FALLBACKS[chainId]; if (!urls) return http(undefined, HTTP_TRANSPORT_OPTIONS); - const ordered = USE_PUBLIC_RPC_FIRST ? ([...urls].reverse() as [string, string, string]) : urls; - return fallback(ordered.map(url => http(url, HTTP_TRANSPORT_OPTIONS))); + return fallback(urls.map(url => http(url, HTTP_TRANSPORT_OPTIONS))); } export const config = getDefaultConfig({ From 053bec971dbcaa78eab45e96f364c4f8e9480118 Mon Sep 17 00:00:00 2001 From: Cardinal Date: Thu, 19 Mar 2026 13:31:04 +0100 Subject: [PATCH 4/4] add prepended values for each chain --- .env.local.example | 6 ++-- src/app/wagmi.ts | 83 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/.env.local.example b/.env.local.example index 9e55fce..366f0f3 100644 --- a/.env.local.example +++ b/.env.local.example @@ -25,5 +25,7 @@ # Destination token address (USDC) for cross-chain swaps #NEXT_PUBLIC_GNOSIS_DESTINATION_TOKEN=0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83 -# RPC used for GNOSIS calls -# NEXT_PUBLIC_GNOSIS_RPC=https://rpc.gnosischain.com \ No newline at end of file +# Optional private RPC per chain (prepended to fallbacks; used first). Key = chain id. +# NEXT_PUBLIC_RPC_1=https://eth-mainnet.g.alchemy.com/v2/your-key +# NEXT_PUBLIC_RPC_100=https://rpc.gnosischain.com +# NEXT_PUBLIC_RPC_8453=https://mainnet.base.org \ No newline at end of file diff --git a/src/app/wagmi.ts b/src/app/wagmi.ts index 3e314a4..0412716 100644 --- a/src/app/wagmi.ts +++ b/src/app/wagmi.ts @@ -144,6 +144,79 @@ const RPC_FALLBACKS: Record = { ], }; +/** Optional private RPC per chain from .env.local (e.g. NEXT_PUBLIC_RPC_100). Prepended to fallbacks when set. */ +function getPrivateRpcForChain(chainId: number): string | undefined { + switch (chainId) { + case mainnet.id: + return process.env.NEXT_PUBLIC_RPC_1; + case gnosis.id: + return process.env.NEXT_PUBLIC_RPC_100; + case base.id: + return process.env.NEXT_PUBLIC_RPC_8453; + case arbitrum.id: + return process.env.NEXT_PUBLIC_RPC_42161; + case optimism.id: + return process.env.NEXT_PUBLIC_RPC_10; + case avalanche.id: + return process.env.NEXT_PUBLIC_RPC_43114; + case bsc.id: + return process.env.NEXT_PUBLIC_RPC_56; + case celo.id: + return process.env.NEXT_PUBLIC_RPC_42220; + case polygon.id: + return process.env.NEXT_PUBLIC_RPC_137; + case mantle.id: + return process.env.NEXT_PUBLIC_RPC_5000; + case zksync.id: + return process.env.NEXT_PUBLIC_RPC_324; + case ink.id: + return process.env.NEXT_PUBLIC_RPC_57073; + case boba.id: + return process.env.NEXT_PUBLIC_RPC_288; + case cronos.id: + return process.env.NEXT_PUBLIC_RPC_25; + case gravity.id: + return process.env.NEXT_PUBLIC_RPC_1625; + case linea.id: + return process.env.NEXT_PUBLIC_RPC_59144; + case lisk.id: + return process.env.NEXT_PUBLIC_RPC_1135; + case metis.id: + return process.env.NEXT_PUBLIC_RPC_1088; + case mode.id: + return process.env.NEXT_PUBLIC_RPC_34443; + case polygonZkEvm.id: + return process.env.NEXT_PUBLIC_RPC_1101; + case scroll.id: + return process.env.NEXT_PUBLIC_RPC_534352; + case sei.id: + return process.env.NEXT_PUBLIC_RPC_1329; + case sonic.id: + return process.env.NEXT_PUBLIC_RPC_146; + case soneium.id: + return process.env.NEXT_PUBLIC_RPC_1868; + case taiko.id: + return process.env.NEXT_PUBLIC_RPC_167000; + case unichain.id: + return process.env.NEXT_PUBLIC_RPC_130; + case worldchain.id: + return process.env.NEXT_PUBLIC_RPC_480; + case sepolia.id: + return process.env.NEXT_PUBLIC_RPC_11155111; + default: + return undefined; + } +} + +/** RPC URLs for a chain: optional private RPC from env prepended, then fallbacks. Same order as wagmi transport. */ +function getEffectiveRpcUrls(chainId: number): readonly string[] | undefined { + const base = RPC_FALLBACKS[chainId]; + if (!base) return undefined; + const privateUrl = getPrivateRpcForChain(chainId); + if (privateUrl?.trim()) return [privateUrl.trim(), ...base]; + return base; +} + // No retries per URL so fallback kicks in immediately (e.g. 403 from whitelisted Alchemy on localhost). const HTTP_TRANSPORT_OPTIONS = { retryCount: 0, @@ -187,10 +260,10 @@ const DEFAULT_POLLING_INTERVAL = 4_000; /** * Returns the RPC URL list for a chain (same order as wagmi transport fallbacks). - * Use this so Gnosis and other chain RPCs stay in sync with wagmi config. + * If a private RPC is set in env (e.g. NEXT_PUBLIC_RPC_100), it is first in the list. */ -export function getRpcUrlsForChain(chainId: number): readonly [string, string, string] | undefined { - return RPC_FALLBACKS[chainId]; +export function getRpcUrlsForChain(chainId: number): readonly string[] | undefined { + return getEffectiveRpcUrls(chainId); } /** @@ -202,8 +275,8 @@ export function getPollingInterval(chainId: number): number { } function transportForChain(chainId: number) { - const urls = RPC_FALLBACKS[chainId]; - if (!urls) return http(undefined, HTTP_TRANSPORT_OPTIONS); + const urls = getEffectiveRpcUrls(chainId); + if (!urls?.length) return http(undefined, HTTP_TRANSPORT_OPTIONS); return fallback(urls.map(url => http(url, HTTP_TRANSPORT_OPTIONS))); }