From 6f25680c1f376195a69537d60e5225c04b9cb387 Mon Sep 17 00:00:00 2001 From: Florent Tapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Fri, 4 Sep 2026 00:36:49 +0200 Subject: [PATCH] feat(speedtest): chain picker prefills the benchmarked no-key cohort --- .../speedtest/speedtest-rpc-client.tsx | 114 +++++++++++++++-- src/lib/speedtest/rpc-directory.ts | 116 ++++++++++++++++++ 2 files changed, 218 insertions(+), 12 deletions(-) create mode 100644 src/lib/speedtest/rpc-directory.ts diff --git a/src/components/speedtest/speedtest-rpc-client.tsx b/src/components/speedtest/speedtest-rpc-client.tsx index 0b16f132..26c4db54 100644 --- a/src/components/speedtest/speedtest-rpc-client.tsx +++ b/src/components/speedtest/speedtest-rpc-client.tsx @@ -14,6 +14,12 @@ */ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { + FEATURED_CHAINS, + RPC_DIRECTORY, + providerForUrl, + type DirectoryChain, +} from "@/lib/speedtest/rpc-directory"; // ─── Types ─────────────────────────────────────────────────────────── @@ -264,9 +270,17 @@ function hostOf(url: string): string { } } +/** Display name: benchmarked provider name when the URL is from our + * directory, bare host otherwise. */ +function epLabel(ep: { url: string; host: string }): string { + return providerForUrl(ep.url) ?? ep.host; +} + export function SpeedtestRpcClient() { const [stage, setStage] = useState("setup"); const [inputs, setInputs] = useState(["", ""]); + const [chainQuery, setChainQuery] = useState(""); + const [pickedChain, setPickedChain] = useState(null); const [durationSec, setDurationSec] = useState(30); const [endpoints, setEndpoints] = useState([]); const [activeId, setActiveId] = useState(null); @@ -280,6 +294,20 @@ export function SpeedtestRpcClient() { const removeInput = (i: number) => setInputs((xs) => (xs.length <= 1 ? xs : xs.filter((_, j) => j !== i))); + const chainMatches = useMemo(() => { + const q = chainQuery.trim().toLowerCase(); + if (!q) return []; + return RPC_DIRECTORY.filter( + (c) => c.name.toLowerCase().includes(q) || c.slug.includes(q), + ).slice(0, 8); + }, [chainQuery]); + + const pickChain = (c: DirectoryChain) => { + setInputs(c.endpoints.map((e) => e.url)); + setPickedChain(c.slug); + setChainQuery(""); + }; + const validCount = inputs.filter((u) => { try { const p = new URL(u.trim()); @@ -458,9 +486,73 @@ export function SpeedtestRpcClient() { {/* ── Stage: setup ─────────────────────────────────────────── */} {stage === "setup" && (
-

+

1 · Endpoints

+ + {/* Prefill from the benchmarked no-key cohort: pick a chain and + get exactly the endpoints the public per-chain benches probe + continuously (90 EVM chains, 291 endpoints). */} +
+

+ Prefill with the endpoints we already benchmark — pick a chain: +

+
+ {FEATURED_CHAINS.map((slug) => { + const c = RPC_DIRECTORY.find((x) => x.slug === slug); + if (!c) return null; + const activeChip = pickedChain === slug; + return ( + + ); + })} +
+
+ setChainQuery(e.target.value)} + placeholder={`Search ${RPC_DIRECTORY.length} benchmarked chains… (e.g. Sonic, Linea, Scroll)`} + spellCheck={false} + autoComplete="off" + className="w-full rounded-md border border-rule bg-transparent px-3 py-2 text-[13px] text-ink placeholder:text-ink-faint/60 focus:border-ink/50 focus:outline-none" + /> + {chainMatches.length > 0 && ( +
    + {chainMatches.map((c) => ( +
  • + +
  • + ))} +
+ )} +
+ {pickedChain && ( +

+ ✓ {RPC_DIRECTORY.find((c) => c.slug === pickedChain)?.name} — {inputs.length} benchmarked endpoints loaded. Add your own keyed URLs below to race them. +

+ )} +
{inputs.map((u, i) => (
@@ -491,13 +583,6 @@ export function SpeedtestRpcClient() { > + Add endpoint -

@@ -589,13 +674,13 @@ export function SpeedtestRpcClient() { <> @@ -639,7 +724,7 @@ export function SpeedtestRpcClient() {

Fastest from your connection

-

{ranked[0].ep.host}

+

{epLabel(ranked[0].ep)}

{Math.round(ranked[0].s.p50)}ms p50

@@ -655,7 +740,12 @@ export function SpeedtestRpcClient() { >
{String(i + 1).padStart(2, "0")} -

{ep.host}

+

+ {epLabel(ep)} + {providerForUrl(ep.url) && ( + {ep.host} + )} +

{Number.isNaN(s.p50) ? "no data" : `${Math.round(s.p50)} ms`} diff --git a/src/lib/speedtest/rpc-directory.ts b/src/lib/speedtest/rpc-directory.ts new file mode 100644 index 00000000..41591120 --- /dev/null +++ b/src/lib/speedtest/rpc-directory.ts @@ -0,0 +1,116 @@ +/** + * Public no-key RPC directory for the browser speed test, derived from + * the rpc-capabilities harness config (harnesses/rpc-capabilities/cmd/ + * script/config.go) — i.e. exactly the endpoints the public per-chain + * benches probe continuously. EVM chains only: the browser engine + * speaks eth_* (solana/cosmos/polkadot kinds need different payloads). + * + * GENERATED — regenerate by re-running the extraction against the + * harness config when chains/endpoints change (see PR #2241). + */ + +export type DirectoryEndpoint = { provider: string; url: string }; +export type DirectoryChain = { slug: string; name: string; endpoints: DirectoryEndpoint[] }; + +export const FEATURED_CHAINS = ["ethereum", "base", "arbitrum", "bnb", "polygon", "optimism", "avalanche", "monad"]; + +export const RPC_DIRECTORY: DirectoryChain[] = [ + { slug: "ethereum", name: "Ethereum", endpoints: [{ provider: "PublicNode", url: "https://ethereum-rpc.publicnode.com" }, { provider: "dRPC", url: "https://eth.drpc.org" }, { provider: "MeowRPC", url: "https://eth.meowrpc.com" }, { provider: "Flashbots Protect", url: "https://rpc.flashbots.net" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/mainnet" }, { provider: "Nodies (POKT)", url: "https://eth-pokt.nodies.app" }, { provider: "Lava Network", url: "https://eth1.lava.build" }, { provider: "bloXroute", url: "https://eth.rpc.blxrbdn.com" }] }, + { slug: "base", name: "Base", endpoints: [{ provider: "PublicNode", url: "https://base-rpc.publicnode.com" }, { provider: "dRPC", url: "https://base.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/base" }, { provider: "Nodies (POKT)", url: "https://base-pokt.nodies.app" }, { provider: "Base Official", url: "https://mainnet.base.org" }, { provider: "Blast API", url: "https://base-mainnet.public.blastapi.io" }, { provider: "bloXroute", url: "https://base.rpc.blxrbdn.com" }] }, + { slug: "arbitrum", name: "Arbitrum One", endpoints: [{ provider: "PublicNode", url: "https://arbitrum-one-rpc.publicnode.com" }, { provider: "dRPC", url: "https://arbitrum.drpc.org" }, { provider: "MeowRPC", url: "https://arbitrum.meowrpc.com" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/arbitrum" }, { provider: "Nodies (POKT)", url: "https://arb-pokt.nodies.app" }, { provider: "Lava Network", url: "https://arb1.lava.build" }, { provider: "Arbitrum Official", url: "https://arb1.arbitrum.io/rpc" }, { provider: "Blast API", url: "https://arbitrum-one.public.blastapi.io" }] }, + { slug: "bnb", name: "BNB Chain", endpoints: [{ provider: "PublicNode", url: "https://bsc-rpc.publicnode.com" }, { provider: "dRPC", url: "https://bsc.drpc.org" }, { provider: "Nodies (POKT)", url: "https://bsc-pokt.nodies.app" }, { provider: "Binance Official", url: "https://bsc-dataseed1.binance.org" }, { provider: "Blast API", url: "https://bsc-mainnet.public.blastapi.io" }, { provider: "bloXroute", url: "https://bsc.rpc.blxrbdn.com" }] }, + { slug: "polygon", name: "Polygon", endpoints: [{ provider: "PublicNode", url: "https://polygon-bor-rpc.publicnode.com" }, { provider: "dRPC", url: "https://polygon.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/polygon" }, { provider: "Nodies (POKT)", url: "https://polygon-pokt.nodies.app" }] }, + { slug: "optimism", name: "Optimism", endpoints: [{ provider: "PublicNode", url: "https://optimism-rpc.publicnode.com" }, { provider: "dRPC", url: "https://optimism.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/optimism" }, { provider: "Nodies (POKT)", url: "https://op-pokt.nodies.app" }, { provider: "Optimism Official", url: "https://mainnet.optimism.io" }] }, + { slug: "avalanche", name: "Avalanche C-Chain", endpoints: [{ provider: "PublicNode", url: "https://avalanche-c-chain-rpc.publicnode.com" }, { provider: "dRPC", url: "https://avalanche.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/avalanche" }, { provider: "Avalanche Official", url: "https://api.avax.network/ext/bc/C/rpc" }] }, + { slug: "monad", name: "Monad", endpoints: [{ provider: "Monad Official", url: "https://rpc.monad.xyz" }, { provider: "dRPC", url: "https://monad-mainnet.drpc.org" }, { provider: "Tenderly Gateway", url: "https://monad.gateway.tenderly.co" }, { provider: "bloXroute", url: "https://monad.rpc.blxrbdn.com" }, { provider: "OnFinality", url: "https://monad-mainnet.api.onfinality.io/public" }] }, + { slug: "abstract", name: "Abstract", endpoints: [{ provider: "Abstract Foundation", url: "https://api.mainnet.abs.xyz" }, { provider: "dRPC", url: "https://abstract.drpc.org" }, { provider: "Thirdweb", url: "https://abstract.rpc.thirdweb.com" }] }, + { slug: "apechain", name: "ApeChain", endpoints: [{ provider: "ApeChain", url: "https://rpc.apechain.com/http" }, { provider: "dRPC", url: "https://apechain.drpc.org" }, { provider: "Thirdweb", url: "https://apechain.rpc.thirdweb.com" }, { provider: "Tenderly", url: "https://gateway.tenderly.co/public/apechain" }] }, + { slug: "arbitrum-nova", name: "Arbitrum Nova", endpoints: [{ provider: "PublicNode", url: "https://arbitrum-nova-rpc.publicnode.com" }, { provider: "dRPC", url: "https://arbitrum-nova.drpc.org" }, { provider: "Thirdweb", url: "https://42170.rpc.thirdweb.com" }] }, + { slug: "astar", name: "Astar", endpoints: [{ provider: "OnFinality", url: "https://astar.api.onfinality.io/public" }, { provider: "1RPC", url: "https://1rpc.io/astr" }] }, + { slug: "aurora", name: "Aurora", endpoints: [{ provider: "Aurora Labs", url: "https://mainnet.aurora.dev" }] }, + { slug: "berachain", name: "Berachain", endpoints: [{ provider: "PublicNode", url: "https://berachain-rpc.publicnode.com" }, { provider: "dRPC", url: "https://berachain.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/berachain" }, { provider: "Berachain Official", url: "https://rpc.berachain.com" }] }, + { slug: "bitlayer", name: "Bitlayer", endpoints: [{ provider: "Bitlayer Official", url: "https://rpc.bitlayer.org" }, { provider: "dRPC", url: "https://bitlayer.drpc.org" }, { provider: "Ankr", url: "https://rpc.ankr.com/bitlayer" }] }, + { slug: "blast", name: "Blast", endpoints: [{ provider: "PublicNode", url: "https://blast-rpc.publicnode.com" }, { provider: "dRPC", url: "https://blast.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/blast" }, { provider: "Blast Official", url: "https://rpc.blast.io" }] }, + { slug: "bob", name: "BOB", endpoints: [{ provider: "BOB", url: "https://rpc.gobob.xyz" }, { provider: "Tenderly", url: "https://bob.gateway.tenderly.co" }, { provider: "dRPC", url: "https://bob.drpc.org" }, { provider: "Thirdweb", url: "https://60808.rpc.thirdweb.com" }] }, + { slug: "boba", name: "Boba Network", endpoints: [{ provider: "Boba Foundation", url: "https://mainnet.boba.network" }, { provider: "dRPC", url: "https://boba-eth.drpc.org" }] }, + { slug: "b2", name: "B\u00b2 Network", endpoints: [{ provider: "B\u00b2 Network Official", url: "https://rpc.bsquared.network" }, { provider: "dRPC", url: "https://b2-mainnet.drpc.org" }, { provider: "Thirdweb", url: "https://223.rpc.thirdweb.com" }] }, + { slug: "canto", name: "Canto", endpoints: [{ provider: "Canto Official", url: "https://canto.gravitychain.io/" }] }, + { slug: "celo", name: "Celo", endpoints: [{ provider: "PublicNode", url: "https://celo-rpc.publicnode.com" }, { provider: "dRPC", url: "https://celo.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/celo" }, { provider: "Celo Official (Forno)", url: "https://forno.celo.org" }] }, + { slug: "chiliz", name: "Chiliz", endpoints: [{ provider: "PublicNode", url: "https://chiliz-rpc.publicnode.com" }, { provider: "Ankr", url: "https://rpc.ankr.com/chiliz" }, { provider: "Chiliz Foundation", url: "https://rpc.chiliz.com" }] }, + { slug: "conflux", name: "Conflux", endpoints: [{ provider: "Conflux Official", url: "https://evm.confluxrpc.com" }, { provider: "Conflux Global", url: "https://evm.confluxrpc.org" }, { provider: "Unifra", url: "https://conflux-espace.nodereal.io/v1/pub" }] }, + { slug: "core", name: "Core Chain", endpoints: [{ provider: "Core DAO", url: "https://rpc.coredao.org" }, { provider: "dRPC", url: "https://core.drpc.org" }, { provider: "Thirdweb", url: "https://1116.rpc.thirdweb.com" }, { provider: "Ankr", url: "https://rpc.ankr.com/core" }] }, + { slug: "cronos", name: "Cronos", endpoints: [{ provider: "PublicNode", url: "https://cronos-evm-rpc.publicnode.com" }, { provider: "dRPC", url: "https://cronos.drpc.org" }, { provider: "Cronos Official", url: "https://evm.cronos.org" }] }, + { slug: "cronos-zkevm", name: "Cronos zkEVM", endpoints: [{ provider: "Crypto.com Foundation", url: "https://mainnet.zkevm.cronos.org" }, { provider: "dRPC", url: "https://cronos-zkevm.drpc.org" }] }, + { slug: "cyber", name: "Cyber", endpoints: [{ provider: "Cyber Network", url: "https://rpc.cyber.co" }, { provider: "AltLayer", url: "https://cyber.alt.technology" }, { provider: "Thirdweb", url: "https://7560.rpc.thirdweb.com" }] }, + { slug: "ethereum-classic", name: "Ethereum Classic", endpoints: [{ provider: "dRPC", url: "https://etc.drpc.org" }, { provider: "ETC Desktop", url: "https://rpc.etcdesktop.com" }, { provider: "ETCMC", url: "https://etcmc.rpc.nz" }] }, + { slug: "etherlink", name: "Etherlink", endpoints: [{ provider: "Etherlink Foundation", url: "https://node.mainnet.etherlink.com" }, { provider: "dRPC", url: "https://etherlink.drpc.org" }] }, + { slug: "fantom", name: "Fantom", endpoints: [{ provider: "Fantom Foundation", url: "https://rpcapi.fantom.network" }, { provider: "dRPC", url: "https://fantom.drpc.org" }, { provider: "Thirdweb", url: "https://250.rpc.thirdweb.com" }] }, + { slug: "filecoin", name: "Filecoin EVM", endpoints: [{ provider: "Glif", url: "https://api.node.glif.io/rpc/v1" }, { provider: "dRPC", url: "https://filecoin.drpc.org" }, { provider: "Ankr", url: "https://rpc.ankr.com/filecoin" }] }, + { slug: "flare", name: "Flare", endpoints: [{ provider: "Flare Foundation", url: "https://flare-api.flare.network/ext/bc/C/rpc" }, { provider: "dRPC", url: "https://flare.drpc.org" }, { provider: "Thirdweb", url: "https://14.rpc.thirdweb.com" }, { provider: "Ankr", url: "https://rpc.ankr.com/flare" }] }, + { slug: "fraxtal", name: "Fraxtal", endpoints: [{ provider: "PublicNode", url: "https://fraxtal-rpc.publicnode.com" }, { provider: "dRPC", url: "https://fraxtal.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/fraxtal" }, { provider: "Fraxtal Official", url: "https://rpc.frax.com" }] }, + { slug: "fuse", name: "Fuse Network", endpoints: [{ provider: "Fuse Foundation", url: "https://rpc.fuse.io" }, { provider: "dRPC", url: "https://fuse.drpc.org" }, { provider: "Thirdweb", url: "https://122.rpc.thirdweb.com" }] }, + { slug: "gnosis", name: "Gnosis", endpoints: [{ provider: "PublicNode", url: "https://gnosis-rpc.publicnode.com" }, { provider: "dRPC", url: "https://gnosis.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/gnosis" }, { provider: "Gnosis Official", url: "https://rpc.gnosischain.com" }] }, + { slug: "gravity", name: "Gravity", endpoints: [{ provider: "PublicNode", url: "https://rpc.gravity.xyz" }, { provider: "Ankr", url: "https://rpc.ankr.com/gravity" }] }, + { slug: "haqq", name: "HAQQ", endpoints: [{ provider: "PublicNode", url: "https://haqq-evm-rpc.publicnode.com" }, { provider: "dRPC", url: "https://haqq.drpc.org" }, { provider: "HAQQ Foundation", url: "https://rpc.eth.haqq.network" }] }, + { slug: "harmony", name: "Harmony", endpoints: [{ provider: "Harmony S0", url: "https://a.api.s0.t.hmny.io" }] }, + { slug: "hemi", name: "Hemi", endpoints: [{ provider: "Hemi Labs", url: "https://rpc.hemi.network/rpc" }, { provider: "dRPC", url: "https://hemi.drpc.org" }, { provider: "Thirdweb", url: "https://43111.rpc.thirdweb.com" }] }, + { slug: "hyperliquid", name: "Hyperliquid", endpoints: [{ provider: "Hyperliquid Labs", url: "https://rpc.hyperliquid.xyz/evm" }, { provider: "dRPC", url: "https://hyperliquid.drpc.org" }, { provider: "Stakely", url: "https://hyperliquid-json-rpc.stakely.io" }, { provider: "Purroof Group", url: "https://rpc.purroofgroup.com" }, { provider: "Hypurrscan", url: "https://rpc.hypurrscan.io" }] }, + { slug: "immutable", name: "Immutable zkEVM", endpoints: [{ provider: "Immutable", url: "https://rpc.immutable.com" }, { provider: "dRPC", url: "https://immutable-zkevm.drpc.org" }, { provider: "Tenderly Gateway", url: "https://immutable.gateway.tenderly.co" }, { provider: "Thirdweb", url: "https://immutable-zkevm.rpc.thirdweb.com" }] }, + { slug: "ink", name: "Ink", endpoints: [{ provider: "Gelato", url: "https://rpc-gel.inkonchain.com" }, { provider: "QuickNode", url: "https://rpc-qnd.inkonchain.com" }, { provider: "dRPC", url: "https://ink.drpc.org" }, { provider: "Tenderly Gateway", url: "https://ink.gateway.tenderly.co" }] }, + { slug: "iotex", name: "IoTeX", endpoints: [{ provider: "IoTeX Mirror", url: "https://babel-api.mainnet.iotex.one" }, { provider: "Ankr", url: "https://rpc.ankr.com/iotex" }, { provider: "Thirdweb", url: "https://4689.rpc.thirdweb.com" }] }, + { slug: "kaia", name: "Kaia", endpoints: [{ provider: "Kaia Foundation", url: "https://public-en.node.kaia.io" }] }, + { slug: "kava", name: "Kava", endpoints: [{ provider: "Kava Labs", url: "https://evm.kava.io" }, { provider: "dRPC", url: "https://kava.drpc.org" }, { provider: "Thirdweb", url: "https://kava.rpc.thirdweb.com" }, { provider: "PublicNode", url: "https://kava-evm-rpc.publicnode.com" }, { provider: "Ankr", url: "https://rpc.ankr.com/kava_evm" }] }, + { slug: "linea", name: "Linea", endpoints: [{ provider: "PublicNode", url: "https://linea-rpc.publicnode.com" }, { provider: "dRPC", url: "https://linea.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/linea" }] }, + { slug: "lisk", name: "Lisk", endpoints: [{ provider: "Lisk", url: "https://rpc.api.lisk.com" }, { provider: "dRPC", url: "https://lisk.drpc.org" }, { provider: "Thirdweb", url: "https://lisk.rpc.thirdweb.com" }, { provider: "Tenderly", url: "https://gateway.tenderly.co/public/lisk" }] }, + { slug: "manta", name: "Manta Pacific", endpoints: [{ provider: "Manta Network", url: "https://pacific-rpc.manta.network/http" }, { provider: "dRPC", url: "https://manta-pacific.drpc.org" }, { provider: "Thirdweb", url: "https://169.rpc.thirdweb.com" }, { provider: "1RPC", url: "https://1rpc.io/manta" }] }, + { slug: "mantle", name: "Mantle", endpoints: [{ provider: "PublicNode", url: "https://mantle-rpc.publicnode.com" }, { provider: "dRPC", url: "https://mantle.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/mantle" }] }, + { slug: "megaeth", name: "MegaETH", endpoints: [{ provider: "MegaETH Official", url: "https://mainnet.megaeth.com/rpc" }, { provider: "dRPC", url: "https://megaeth.drpc.org" }, { provider: "Tenderly Gateway", url: "https://megaeth.gateway.tenderly.co" }] }, + { slug: "merlin", name: "Merlin Chain", endpoints: [{ provider: "Merlin Official", url: "https://rpc.merlinchain.io" }, { provider: "dRPC", url: "https://merlin.drpc.org" }, { provider: "BlockPI", url: "https://merlin.blockpi.network/v1/rpc/public" }] }, + { slug: "metis", name: "Metis", endpoints: [{ provider: "Metis", url: "https://andromeda.metis.io/?owner=1088" }, { provider: "dRPC", url: "https://metis.drpc.org" }, { provider: "PublicNode", url: "https://metis-rpc.publicnode.com" }, { provider: "Thirdweb", url: "https://1088.rpc.thirdweb.com" }] }, + { slug: "mode", name: "Mode", endpoints: [{ provider: "Mode Labs", url: "https://mainnet.mode.network" }, { provider: "dRPC", url: "https://mode.drpc.org" }, { provider: "1RPC", url: "https://1rpc.io/mode" }, { provider: "Thirdweb", url: "https://mode.rpc.thirdweb.com" }] }, + { slug: "moonbeam", name: "Moonbeam", endpoints: [{ provider: "PublicNode", url: "https://moonbeam-rpc.publicnode.com" }, { provider: "dRPC", url: "https://moonbeam.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/moonbeam" }, { provider: "Moonbeam Official", url: "https://rpc.api.moonbeam.network" }] }, + { slug: "moonriver", name: "Moonriver", endpoints: [{ provider: "Moonbeam Foundation", url: "https://rpc.api.moonriver.moonbeam.network" }, { provider: "PublicNode", url: "https://moonriver-rpc.publicnode.com" }, { provider: "OnFinality", url: "https://moonriver.api.onfinality.io/public" }] }, + { slug: "morph", name: "Morph", endpoints: [{ provider: "Morph", url: "https://rpc.morphl2.io" }, { provider: "dRPC", url: "https://morph.drpc.org" }, { provider: "Thirdweb", url: "https://2818.rpc.thirdweb.com" }, { provider: "QuickNode", url: "https://rpc-quicknode.morph.network" }] }, + { slug: "neon", name: "Neon EVM", endpoints: [{ provider: "P2P Neon Proxy", url: "https://neon-proxy-mainnet.solana.p2p.org" }, { provider: "Thirdweb", url: "https://245022934.rpc.thirdweb.com" }, { provider: "Everstake", url: "https://neon-mainnet.everstake.one" }] }, + { slug: "oasis-emerald", name: "Oasis Emerald", endpoints: [{ provider: "PublicNode", url: "https://emerald.oasis.io" }] }, + { slug: "oasis-sapphire", name: "Oasis Sapphire", endpoints: [{ provider: "PublicNode", url: "https://sapphire.oasis.io" }] }, + { slug: "oktc", name: "OKTC", endpoints: [{ provider: "OKX Chain Official", url: "https://exchainrpc.okex.org" }, { provider: "1RPC", url: "https://1rpc.io/oktc" }, { provider: "dRPC", url: "https://oktc.drpc.org" }] }, + { slug: "opbnb", name: "opBNB", endpoints: [{ provider: "BNB Chain Team", url: "https://opbnb-mainnet-rpc.bnbchain.org" }, { provider: "PublicNode", url: "https://opbnb-rpc.publicnode.com" }, { provider: "dRPC", url: "https://opbnb.drpc.org" }] }, + { slug: "plume", name: "Plume", endpoints: [{ provider: "PublicNode", url: "https://plume-rpc.publicnode.com" }, { provider: "dRPC", url: "https://plume.drpc.org" }] }, + { slug: "polygon-zkevm", name: "Polygon zkEVM", endpoints: [{ provider: "Polygon", url: "https://zkevm-rpc.com" }, { provider: "dRPC", url: "https://polygon-zkevm.drpc.org" }, { provider: "Thirdweb", url: "https://1101.rpc.thirdweb.com" }] }, + { slug: "pulsechain", name: "PulseChain", endpoints: [{ provider: "PublicNode", url: "https://pulsechain-rpc.publicnode.com" }, { provider: "PulseChain Foundation", url: "https://rpc.pulsechain.com" }, { provider: "G4MM4", url: "https://rpc-pulsechain.g4mm4.io" }] }, + { slug: "reya", name: "Reya Network", endpoints: [{ provider: "PublicNode", url: "https://rpc.reya.network" }, { provider: "Thirdweb", url: "https://1729.rpc.thirdweb.com" }] }, + { slug: "ronin", name: "Ronin", endpoints: [{ provider: "Sky Mavis", url: "https://api.roninchain.com/rpc" }, { provider: "Tenderly Gateway", url: "https://ronin.gateway.tenderly.co" }, { provider: "Thirdweb", url: "https://ronin.rpc.thirdweb.com" }] }, + { slug: "rootstock", name: "Rootstock", endpoints: [{ provider: "Rootstock Foundation", url: "https://public-node.rsk.co" }, { provider: "dRPC", url: "https://rootstock.drpc.org" }, { provider: "Thirdweb", url: "https://30.rpc.thirdweb.com" }] }, + { slug: "scroll", name: "Scroll", endpoints: [{ provider: "PublicNode", url: "https://scroll-rpc.publicnode.com" }, { provider: "dRPC", url: "https://scroll.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/scroll-mainnet" }] }, + { slug: "sei", name: "Sei EVM", endpoints: [{ provider: "Sei Labs", url: "https://evm-rpc.sei-apis.com" }, { provider: "Thirdweb", url: "https://sei.rpc.thirdweb.com" }, { provider: "Stakeme", url: "https://sei-evm-rpc.stakeme.pro" }] }, + { slug: "soneium", name: "Soneium", endpoints: [{ provider: "PublicNode", url: "https://soneium-rpc.publicnode.com" }, { provider: "dRPC", url: "https://soneium.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/soneium" }, { provider: "Soneium Official", url: "https://rpc.soneium.org" }] }, + { slug: "songbird", name: "Songbird", endpoints: [{ provider: "Flare Foundation", url: "https://songbird-api.flare.network/ext/C/rpc" }] }, + { slug: "sonic", name: "Sonic", endpoints: [{ provider: "PublicNode", url: "https://sonic-rpc.publicnode.com" }, { provider: "dRPC", url: "https://sonic.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/sonic" }, { provider: "Lava Network", url: "https://sonic.lava.build" }, { provider: "Sonic Labs Official", url: "https://rpc.soniclabs.com" }] }, + { slug: "story", name: "Story", endpoints: [{ provider: "Story Foundation", url: "https://mainnet.storyrpc.io" }, { provider: "Ankr", url: "https://rpc.ankr.com/story_mainnet" }, { provider: "Stakely", url: "https://story-json-rpc.stakely.io" }, { provider: "PublicNode", url: "https://story-rpc.publicnode.com" }] }, + { slug: "swellchain", name: "Swellchain", endpoints: [{ provider: "Ankr", url: "https://rpc.ankr.com/swell" }, { provider: "Sentio", url: "https://swell-mainnet.rpc.sentio.xyz" }, { provider: "Thirdweb", url: "https://1923.rpc.thirdweb.com" }, { provider: "dRPC", url: "https://swell.drpc.org" }] }, + { slug: "taiko", name: "Taiko", endpoints: [{ provider: "PublicNode", url: "https://taiko-rpc.publicnode.com" }, { provider: "dRPC", url: "https://taiko.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/taiko-mainnet" }, { provider: "Taiko Official", url: "https://rpc.taiko.xyz" }] }, + { slug: "telos", name: "Telos", endpoints: [{ provider: "dRPC", url: "https://telos.drpc.org" }] }, + { slug: "thundercore", name: "ThunderCore", endpoints: [{ provider: "ThunderCore Official", url: "https://mainnet-rpc.thundercore.com" }, { provider: "ThunderToken", url: "https://mainnet-rpc.thundertoken.net" }, { provider: "dRPC", url: "https://thundercore.drpc.org" }] }, + { slug: "tron", name: "TRON", endpoints: [{ provider: "TronGrid", url: "https://api.trongrid.io/jsonrpc" }, { provider: "PublicNode", url: "https://tron.publicnode.com/jsonrpc" }] }, + { slug: "unichain", name: "Unichain", endpoints: [{ provider: "PublicNode", url: "https://unichain-rpc.publicnode.com" }, { provider: "dRPC", url: "https://unichain.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/unichain" }, { provider: "Unichain Official", url: "https://mainnet.unichain.org" }] }, + { slug: "vana", name: "Vana", endpoints: [{ provider: "PublicNode", url: "https://rpc.vana.org" }] }, + { slug: "viction", name: "Viction", endpoints: [{ provider: "Viction Official", url: "https://rpc.viction.xyz" }, { provider: "Viction RPC2", url: "https://rpc2.viction.xyz" }, { provider: "dRPC", url: "https://viction.drpc.org" }] }, + { slug: "warden", name: "Warden Protocol", endpoints: [{ provider: "PublicNode", url: "https://warden-evm-rpc.publicnode.com" }, { provider: "Warden Foundation", url: "https://evm.wardenprotocol.org" }] }, + { slug: "wemix", name: "WEMIX", endpoints: [{ provider: "WeMade", url: "https://api.wemix.com" }, { provider: "dRPC", url: "https://wemix.drpc.org" }] }, + { slug: "world-chain", name: "World Chain", endpoints: [{ provider: "World Chain", url: "https://worldchain-mainnet.g.alchemy.com/public" }, { provider: "dRPC", url: "https://worldchain.drpc.org" }, { provider: "Tenderly Gateway", url: "https://worldchain-mainnet.gateway.tenderly.co" }] }, + { slug: "xlayer", name: "X Layer", endpoints: [{ provider: "X Layer", url: "https://rpc.xlayer.tech" }, { provider: "dRPC", url: "https://xlayer.drpc.org" }, { provider: "Thirdweb", url: "https://196.rpc.thirdweb.com" }] }, + { slug: "xdc", name: "XDC Network", endpoints: [{ provider: "PublicNode", url: "https://rpc.xdc.org" }, { provider: "Ankr", url: "https://rpc.ankr.com/xdc" }, { provider: "XDC eRPC", url: "https://erpc.xinfin.network" }, { provider: "XDC.org", url: "https://rpc.xdc.org" }] }, + { slug: "zetachain", name: "ZetaChain", endpoints: [{ provider: "Thirdweb", url: "https://7000.rpc.thirdweb.com" }] }, + { slug: "zircuit", name: "Zircuit", endpoints: [{ provider: "Zircuit Foundation", url: "https://mainnet.zircuit.com" }] }, + { slug: "zksync", name: "zkSync Era", endpoints: [{ provider: "dRPC", url: "https://zksync.drpc.org" }, { provider: "Tenderly Gateway", url: "https://gateway.tenderly.co/public/zksync" }, { provider: "zkSync Official", url: "https://mainnet.era.zksync.io" }] }, + { slug: "zora", name: "Zora", endpoints: [{ provider: "Zora Network", url: "https://rpc.zora.energy" }, { provider: "dRPC", url: "https://zora.drpc.org" }, { provider: "Thirdweb", url: "https://zora.rpc.thirdweb.com" }, { provider: "Conduit", url: "https://rpc-zora-mainnet-0.t.conduit.xyz" }] }, +]; + +const URL_TO_PROVIDER = new Map(); +for (const c of RPC_DIRECTORY) for (const e of c.endpoints) URL_TO_PROVIDER.set(e.url, e.provider); + +/** Provider display name when the URL comes from the directory. */ +export function providerForUrl(url: string): string | null { + return URL_TO_PROVIDER.get(url.replace(/\/+$/, "")) ?? URL_TO_PROVIDER.get(url) ?? null; +}