diff --git a/packages/web/src/ChainContext.tsx b/packages/web/src/ChainContext.tsx index 9f05d78..2b2fdc8 100644 --- a/packages/web/src/ChainContext.tsx +++ b/packages/web/src/ChainContext.tsx @@ -14,7 +14,9 @@ export function ChainProvider({ chainId: number; children: ReactNode; }) { - const chain = supportedChains.find((c) => c.id === chainId); + const chain = supportedChains + .map((c) => c.chain) + .find((c) => c.id === chainId); // TODO: improve this if (!chain) throw new Error("Unsupported chain"); diff --git a/packages/web/src/EthereumProviders.tsx b/packages/web/src/EthereumProviders.tsx index d97fc32..c2ce202 100644 --- a/packages/web/src/EthereumProviders.tsx +++ b/packages/web/src/EthereumProviders.tsx @@ -12,17 +12,26 @@ import { configureChains, createConfig, WagmiConfig } from "wagmi"; import { jsonRpcProvider } from "wagmi/providers/jsonRpc"; import { publicProvider } from "wagmi/providers/public"; -import { rpcs } from "./rpcs"; import { supportedChains } from "./supportedChains"; -const { chains, publicClient } = configureChains(supportedChains, [ - jsonRpcProvider({ - rpc: (chain) => ({ - http: rpcs[chain.id], +const { chains, publicClient } = configureChains( + supportedChains.map((c) => c.chain), + [ + jsonRpcProvider({ + rpc: (chain) => { + // TODO: simplify, this feels wrong/ugly (maybe better in v2?) + const supportedChain = supportedChains.find( + (c) => c.chain.id === chain.id, + ); + if (!supportedChain) return null; + return { + http: supportedChain.rpcUrl, + }; + }, }), - }), - publicProvider(), -]); + publicProvider(), + ], +); const { connectors } = getDefaultWallets({ appName: "EthFS", diff --git a/packages/web/src/app/[chainId]/api/files/[filename]/contents/getFileContents.ts b/packages/web/src/app/[chainId]/api/files/[filename]/contents/getFileContents.ts index 35a99b8..db9e7ba 100644 --- a/packages/web/src/app/[chainId]/api/files/[filename]/contents/getFileContents.ts +++ b/packages/web/src/app/[chainId]/api/files/[filename]/contents/getFileContents.ts @@ -5,19 +5,19 @@ import deploys from "@ethfs/deploy/deploys.json"; import { createPublicClient, http } from "viem"; import { readContract } from "viem/actions"; -import { rpcs } from "../../../../../../rpcs"; +import { supportedChains } from "../../../../../../supportedChains"; export async function getFileContents( chainId: number, filename: string, ): Promise { - const rpc = rpcs[chainId]; - if (!rpc) { + const supportedChain = supportedChains.find((c) => c.chain.id === chainId); + if (!supportedChain) { throw new Error("Unsupported chain"); } const publicClient = createPublicClient({ - transport: http(rpc), + transport: http(supportedChain.rpcUrl), }); // TODO: handle reverts (e.g. FileNotFound) diff --git a/packages/web/src/app/[chainId]/api/files/[filename]/getFile.ts b/packages/web/src/app/[chainId]/api/files/[filename]/getFile.ts index a7cca64..687b281 100644 --- a/packages/web/src/app/[chainId]/api/files/[filename]/getFile.ts +++ b/packages/web/src/app/[chainId]/api/files/[filename]/getFile.ts @@ -2,7 +2,7 @@ import { OnchainFile } from "../../../../../common"; import { sql } from "../../../../../database"; -import { rpcs } from "../../../../../rpcs"; +import { supportedChains } from "../../../../../supportedChains"; import { getFileContents } from "./contents/getFileContents"; function parseJson(json: string) { @@ -17,8 +17,8 @@ export async function getFile( chainId: number, filename: string, ): Promise<(OnchainFile & { contents: string }) | null> { - const rpc = rpcs[chainId]; - if (!rpc) { + const supportedChain = supportedChains.find((c) => c.chain.id === chainId); + if (!supportedChain) { throw new Error("Unsupported chain"); } diff --git a/packages/web/src/middleware.ts b/packages/web/src/middleware.ts index 06f260f..731b504 100644 --- a/packages/web/src/middleware.ts +++ b/packages/web/src/middleware.ts @@ -1,15 +1,7 @@ import { NextRequest, NextResponse } from "next/server"; +import { goerli } from "viem/chains"; -import { includes } from "./includes"; - -const hostnameToChainId = { - "ethfs.xyz": 1, - "goerli.ethfs.xyz": 5, -}; - -const hostnames = Object.keys( - hostnameToChainId, -) as (keyof typeof hostnameToChainId)[]; +import { supportedChains } from "./supportedChains"; function isPathChainSpecific(pathname: string) { return pathname === "/" || /^\/api\//.test(pathname); @@ -17,9 +9,11 @@ function isPathChainSpecific(pathname: string) { export function middleware(req: NextRequest) { if (isPathChainSpecific(req.nextUrl.pathname)) { - const chainId = includes(hostnames, req.nextUrl.hostname) - ? hostnameToChainId[req.nextUrl.hostname] - : 5; + const supportedChain = supportedChains.find( + (c) => c.hostname === req.nextUrl.hostname, + ); + // Default to Goerli if we don't find the hostname in our supported chains + const chainId = supportedChain?.chain.id ?? goerli.id; const url = req.nextUrl.clone(); url.pathname = `/${chainId}${url.pathname}`; return NextResponse.rewrite(url); diff --git a/packages/web/src/rpcs.ts b/packages/web/src/rpcs.ts deleted file mode 100644 index 849f1ae..0000000 --- a/packages/web/src/rpcs.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const rpcs: { readonly [chainId: number]: string } = { - 5: process.env.NEXT_PUBLIC_RPC_HTTP_URL_5!, -}; diff --git a/packages/web/src/supportedChains.ts b/packages/web/src/supportedChains.ts index d6f1b57..2799f31 100644 --- a/packages/web/src/supportedChains.ts +++ b/packages/web/src/supportedChains.ts @@ -1,3 +1,122 @@ -import { goerli } from "wagmi/chains"; +import { + arbitrum, + arbitrumGoerli, + arbitrumSepolia, + base, + baseGoerli, + baseSepolia, + Chain, + goerli, + holesky, + mainnet, + optimism, + optimismGoerli, + optimismSepolia, + polygon, + polygonMumbai, + polygonZkEvm, + polygonZkEvmTestnet, + sepolia, +} from "wagmi/chains"; -export const supportedChains = [goerli]; +// TODO: combine with deploys + +type SupportedChain = { + readonly chain: Chain; + readonly hostname: string; + readonly rpcUrl: string; +}; + +export const supportedChains = [ + /* Ethereum */ + // { + // hostname: "ethfs.xyz", + // chain: mainnet, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_1!, + // }, + { + hostname: "goerli.ethfs.xyz", + chain: goerli, + rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_5!, + }, + // { + // hostname: "sepolia.ethfs.xyz", + // chain: sepolia, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_11155111!, + // }, + // { + // hostname: "holesky.ethfs.xyz", + // chain: holesky, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_17000!, + // }, + /* Base */ + // { + // hostname: "base.ethfs.xyz", + // chain: base, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_8453!, + // }, + // { + // hostname: "base-goerli.ethfs.xyz", + // chain: baseGoerli, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_84531!, + // }, + // { + // hostname: "base-sepolia.ethfs.xyz", + // chain: baseSepolia, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_84532!, + // }, + /* Optimism */ + // { + // hostname: "optimism.ethfs.xyz", + // chain: optimism, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_10!, + // }, + // { + // hostname: "optimism-goerli.ethfs.xyz", + // chain: optimismGoerli, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_420!, + // }, + // { + // hostname: "optimism-sepolia.ethfs.xyz", + // chain: optimismSepolia, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_11155420!, + // }, + /* Arbitrum */ + // { + // hostname: "arbitrum.ethfs.xyz", + // chain: arbitrum, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_42161!, + // }, + // { + // hostname: "arbitrum-goerli.ethfs.xyz", + // chain: arbitrumGoerli, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_421613!, + // }, + // { + // hostname: "arbitrum-sepolia.ethfs.xyz", + // chain: arbitrumSepolia, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_421614!, + // }, + /* TODO: Arbitrum Nova? */ + /* Polygon */ + // { + // hostname: "polygon.ethfs.xyz", + // chain: polygon, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_137!, + // }, + // { + // hostname: "polygon-mumbai.ethfs.xyz", + // chain: polygonMumbai, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_80001!, + // }, + // { + // hostname: "polygon-zkevm.ethfs.xyz", + // chain: polygonZkEvm, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_1101!, + // }, + // { + // hostname: "polygon-zkevm-testnet.ethfs.xyz", + // chain: polygonZkEvmTestnet, + // rpcUrl: process.env.NEXT_PUBLIC_RPC_HTTP_URL_1442!, + // }, +] as const satisfies readonly SupportedChain[];