From d46ef3b36120a90ce4dc1c5202e9b75f35400cbf Mon Sep 17 00:00:00 2001 From: Shubham Tiwari Date: Tue, 1 Sep 2026 21:16:52 +0530 Subject: [PATCH 1/2] remove 21 duplicate rpc urls and add a test that catches them --- constants/extraRpcs.js | 57 ------------------------------- tests/check-duplicate-keys.js | 64 +++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 57 deletions(-) diff --git a/constants/extraRpcs.js b/constants/extraRpcs.js index 3715350ee1..64c51c2c28 100644 --- a/constants/extraRpcs.js +++ b/constants/extraRpcs.js @@ -3106,11 +3106,6 @@ export const extraRpcs = { tracking: "none", trackingDetails: privacyStatement.omnia, }, - { - url: "https://endpoints.omniatech.io/v1/merlin/mainnet/public", - tracking: "none", - trackingDetails: privacyStatement.omnia, - }, { url: "https://merlin.drpc.org", tracking: "none", @@ -3696,16 +3691,6 @@ export const extraRpcs = { tracking: "none", trackingDetails: privacyStatement.radiumblock, }, - { - url: "https://moonbeam.drpc.org", - tracking: "none", - trackingDetails: privacyStatement.drpc, - }, - { - url: "wss://moonbeam.drpc.org", - tracking: "none", - trackingDetails: privacyStatement.drpc, - }, { url: "https://rpc.poolz.finance/moonbeam", tracking: "limited", @@ -4472,7 +4457,6 @@ export const extraRpcs = { "https://rpc.xdc.org", "https://rpc.xdc.network", "https://earpc.xinfin.network/", - "https://erpc.xinfin.network/", "wss://ews.xinfin.network/ws", { url: "https://rpc.ankr.com/xdc", @@ -4497,7 +4481,6 @@ export const extraRpcs = { "https://apothem.xdcrpc.com", "https://rpc.ankr.com/xdc_testnet", "https://earpc.apothem.network/", - "https://erpc.apothem.network/", "wss://eaws.apothem.network/", { url: "https://xdc-testnet.drpc.org", @@ -5561,7 +5544,6 @@ export const extraRpcs = { "https://rpc.dogechain.dog", "https://rpc-us.dogechain.dog", "https://rpc-sg.dogechain.dog", - "https://rpc.dogechain.dog", "https://rpc01-sg.dogechain.dog", "https://rpc02-sg.dogechain.dog", "https://rpc03-sg.dogechain.dog", @@ -6120,7 +6102,6 @@ export const extraRpcs = { "https://rpc-evm.testnet.evmos.dragonstake.io", "https://evmos-testnet-rpc.stake-town.com", "https://evmos-testnet-jsonrpc.stake-town.com", - "https://api.evmos-test.theamsolutions.info", "https://jsonrpc-t.evmos.nodestake.top", "https://evmos-testnet-jsonrpc.autostake.com", "https://evmos-testnet-jsonrpc.alkadeta.com", @@ -6635,11 +6616,6 @@ export const extraRpcs = { tracking: "limited", trackingDetails: privacyStatement.dwellir, }, - { - url: "https://base.drpc.org", - tracking: "none", - trackingDetails: privacyStatement.drpc, - }, { url: "wss://base.drpc.org", tracking: "none", @@ -6914,11 +6890,6 @@ export const extraRpcs = { tracking: "limited", trackingDetails: privacyStatement.therpc, }, - { - url: "https://scroll.api.pocket.network", - tracking: "none", - trackingDetails: privacyStatement.pokt, - }, { url: "https://api-scroll-mainnet.n.dwellir.com/2ccf18bf-2916-4198-8856-42172854353c", tracking: "limited", @@ -7265,7 +7236,6 @@ export const extraRpcs = { trackingDetails: privacyStatement.routemesh, }, "https://palm-testnet.infura.io/v3/${INFURA_API_KEY}", - "https://palm-testnet.public.blastapi.io", { url: "https://palm-testnet.public.blastapi.io", tracking: "limited", @@ -7558,7 +7528,6 @@ export const extraRpcs = { }, 50001: { rpcs: [ - "https://rpc.oracle.liveplex.io", { url: "https://rpc.oracle.liveplex.io", tracking: "yes", @@ -7818,11 +7787,6 @@ export const extraRpcs = { tracking: "none", trackingDetails: privacyStatement.omnia, }, - { - url: "https://rpc.ankr.com/scroll_sepolia_testnet", - tracking: "none", - trackingDetails: privacyStatement.ankr, - }, { url: "https://scroll-sepolia.therpc.io", tracking: "limited", @@ -7895,7 +7859,6 @@ export const extraRpcs = { tracking: "limited", trackingDetails: privacyStatement.routemesh, }, - "https://rpc.jfinchain.com", { url: "https://rpc.jfinchain.com", tracking: "limited", @@ -8871,7 +8834,6 @@ export const extraRpcs = { tracking: "limited", trackingDetails: privacyStatement.routemesh, }, - "https://rpc-v2.powerloom.network", { url: "https://rpc-v2.powerloom.network", tracking: "yes", @@ -9048,8 +9010,6 @@ export const extraRpcs = { trackingDetails: privacyStatement.routemesh, }, "https://rpc.immutable.com", - "https://immutable-zkevm.drpc.org", - "wss://immutable-zkevm.drpc.org", { url: "https://immutable-zkevm.drpc.org", tracking: "none", @@ -9257,7 +9217,6 @@ export const extraRpcs = { }, 20230825: { rpcs: [ - "https://testnet.vcity.app", { url: "https://testnet.vcity.app", tracking: "none", @@ -9393,7 +9352,6 @@ export const extraRpcs = { 16600: { rpcs: [ "https://evmrpc-testnet.0g.ai", - "https://0g-json-rpc-public.originstake.com", "https://og-testnet-jsonrpc.blockhub.id", { url: "https://0g-json-rpc-public.originstake.com", @@ -10364,11 +10322,6 @@ export const extraRpcs = { tracking: "none", trackingDetails: privacyStatement.ankr, }, - { - url: "https://rpc.ankr.com/monad_testnet", - tracking: "none", - trackingDetails: privacyStatement.ankr, - }, { url: "https://monad-testnet.gateway.tatum.io/", tracking: "yes", @@ -10380,11 +10333,6 @@ export const extraRpcs = { trackingDetails: privacyStatement.onfinality, }, "https://rpc-testnet.monadinfra.com", - { - url: "https://monad-testnet.api.onfinality.io/public", - tracking: "limited", - trackingDetails: privacyStatement.onfinality, - }, { url: "https://monad-testnet-rpc.huginn.tech", tracking: "none", @@ -10723,11 +10671,6 @@ export const extraRpcs = { tracking: "none", trackingDetails: privacyStatement.drpc, }, - { - url: "https://lens.drpc.org", - tracking: "none", - trackingDetails: privacyStatement.drpc, - }, { url: "wss://lens.drpc.org", tracking: "none", diff --git a/tests/check-duplicate-keys.js b/tests/check-duplicate-keys.js index 4109d50bfb..03c71bf457 100644 --- a/tests/check-duplicate-keys.js +++ b/tests/check-duplicate-keys.js @@ -146,6 +146,64 @@ function checkChainIdsDuplicates() { console.log(`✓ No duplicate keys found in chainIds (checked ${chainIds.size} keys)`); } +/** + * Check for the same rpc url listed more than once inside one chain's rpcs array. + * Arrays keep every entry, so these are invisible to the duplicate-key checks above. + */ +function checkDuplicateRpcUrls() { + console.log("Checking extraRpcs for duplicate rpc urls within a chain..."); + + const filePath = path.join(__dirname, "../constants/extraRpcs.js"); + const lines = fs.readFileSync(filePath, "utf-8").split("\n"); + + const normalize = (url) => url.trim().replace(/\/+$/, "").toLowerCase(); + const duplicates = []; + let chainId = null; + let inRpcs = false; + let seen = new Set(); + let checked = 0; + + for (const line of lines) { + const chainMatch = line.match(/^\s{2}(\d+):\s*\{/); + if (chainMatch) { + chainId = chainMatch[1]; + inRpcs = false; + seen = new Set(); + continue; + } + if (/^\s{4}rpcs:\s*\[/.test(line)) { + inRpcs = true; + continue; + } + if (inRpcs && /^\s{4}\],/.test(line)) { + inRpcs = false; + continue; + } + if (!inRpcs || chainId === null) continue; + + const urlMatch = + line.match(/^\s{6}"((?:https?|wss?):\/\/[^"]+)",?\s*$/) || + line.match(/^\s{8}url:\s*"([^"]+)"/); + if (!urlMatch) continue; + + const key = normalize(urlMatch[1]); + checked++; + if (seen.has(key)) { + duplicates.push(`${chainId}: ${urlMatch[1]}`); + } else { + seen.add(key); + } + } + + if (duplicates.length > 0) { + console.error("ERROR: Duplicate rpc urls found in extraRpcs:"); + duplicates.forEach((d) => console.error(` - ${d}`)); + throw new Error(`Duplicate rpc urls found in extraRpcs: ${duplicates.length}`); + } + + console.log(`✓ No duplicate rpc urls found in extraRpcs (checked ${checked} urls)`); +} + // Run all tests and collect errors console.log("=".repeat(60)); console.log("Running syntax and duplicate key checks..."); @@ -185,6 +243,12 @@ try { errors.push(error.message); } +try { + checkDuplicateRpcUrls(); +} catch (error) { + errors.push(error.message); +} + console.log("=".repeat(60)); if (errors.length > 0) { From 9c2ea739db2eeba062e927b3774456fd7bbccf58 Mon Sep 17 00:00:00 2001 From: Shubham Tiwari Date: Mon, 28 Sep 2026 07:29:29 +0530 Subject: [PATCH 2/2] check duplicate rpc urls on the exported object, the line scan skipped one-line arrays (2,774 of 2,982 urls) --- tests/check-duplicate-keys.js | 57 ++++++++++++++--------------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/tests/check-duplicate-keys.js b/tests/check-duplicate-keys.js index 03c71bf457..01bf3257a9 100644 --- a/tests/check-duplicate-keys.js +++ b/tests/check-duplicate-keys.js @@ -148,50 +148,39 @@ function checkChainIdsDuplicates() { /** * Check for the same rpc url listed more than once inside one chain's rpcs array. - * Arrays keep every entry, so these are invisible to the duplicate-key checks above. + * Arrays keep every entry, so these are invisible to the duplicate-key checks above, + * and unlike keys they survive an import intact, so this reads the exported object + * instead of parsing lines (rpcs written on one line would otherwise be skipped). */ function checkDuplicateRpcUrls() { console.log("Checking extraRpcs for duplicate rpc urls within a chain..."); const filePath = path.join(__dirname, "../constants/extraRpcs.js"); - const lines = fs.readFileSync(filePath, "utf-8").split("\n"); + const script = [ + `import { extraRpcs } from ${JSON.stringify(filePath)};`, + "const out = {};", + "for (const [chainId, { rpcs = [] }] of Object.entries(extraRpcs)) out[chainId] = rpcs.map((rpc) => (typeof rpc === 'string' ? rpc : rpc.url));", + "console.log(JSON.stringify(out));", + ].join("\n"); + const rpcsByChain = JSON.parse( + execSync("node --input-type=module", { input: script, encoding: "utf-8", stdio: "pipe", maxBuffer: 64 * 1024 * 1024 }) + ); const normalize = (url) => url.trim().replace(/\/+$/, "").toLowerCase(); const duplicates = []; - let chainId = null; - let inRpcs = false; - let seen = new Set(); let checked = 0; - for (const line of lines) { - const chainMatch = line.match(/^\s{2}(\d+):\s*\{/); - if (chainMatch) { - chainId = chainMatch[1]; - inRpcs = false; - seen = new Set(); - continue; - } - if (/^\s{4}rpcs:\s*\[/.test(line)) { - inRpcs = true; - continue; - } - if (inRpcs && /^\s{4}\],/.test(line)) { - inRpcs = false; - continue; - } - if (!inRpcs || chainId === null) continue; - - const urlMatch = - line.match(/^\s{6}"((?:https?|wss?):\/\/[^"]+)",?\s*$/) || - line.match(/^\s{8}url:\s*"([^"]+)"/); - if (!urlMatch) continue; - - const key = normalize(urlMatch[1]); - checked++; - if (seen.has(key)) { - duplicates.push(`${chainId}: ${urlMatch[1]}`); - } else { - seen.add(key); + for (const [chainId, urls] of Object.entries(rpcsByChain)) { + const seen = new Set(); + for (const url of urls) { + if (typeof url !== "string") continue; + checked++; + const key = normalize(url); + if (seen.has(key)) { + duplicates.push(`${chainId}: ${url}`); + } else { + seen.add(key); + } } }