From b8089c67ec0b8bc9014c32ab556d79aa8d8ecc19 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Thu, 11 Apr 2024 09:32:45 -0400 Subject: [PATCH] Simplify DevEx so that new chain support is completely encapsulated in src/providers/NetworkConfig/networks/* --- .../NetworkConfig/NetworkConfigProvider.tsx | 17 ++----- src/providers/NetworkConfig/networks/base.ts | 3 ++ .../NetworkConfig/networks/baseSepolia.ts | 3 ++ .../NetworkConfig/networks/mainnet.ts | 3 ++ .../NetworkConfig/networks/polygon.ts | 3 ++ .../NetworkConfig/networks/sepolia.ts | 3 ++ .../NetworkConfig/web3-modal.config.ts | 44 +++++-------------- src/types/network.ts | 3 ++ 8 files changed, 32 insertions(+), 47 deletions(-) diff --git a/src/providers/NetworkConfig/NetworkConfigProvider.tsx b/src/providers/NetworkConfig/NetworkConfigProvider.tsx index 67fb7ccf96..3cda6ef46e 100644 --- a/src/providers/NetworkConfig/NetworkConfigProvider.tsx +++ b/src/providers/NetworkConfig/NetworkConfigProvider.tsx @@ -1,26 +1,15 @@ import { Context, createContext, ReactNode, useContext, useEffect, useState } from 'react'; import { useChainId } from 'wagmi'; import { NetworkConfig } from '../../types/network'; -import { - sepoliaConfig, - mainnetConfig, - polygonConfig, - baseSepoliaConfig, - baseConfig, -} from './networks'; + +import * as networks from './networks'; export const NetworkConfigContext = createContext({} as NetworkConfig); export const useNetworkConfig = (): NetworkConfig => useContext(NetworkConfigContext as Context); -export const supportedChains: NetworkConfig[] = [ - mainnetConfig, - sepoliaConfig, - polygonConfig, - baseSepoliaConfig, - baseConfig, -]; +export const supportedChains = Object.values(networks).sort((a, b) => a.order - b.order); const getNetworkConfig = (chainId: number) => { const foundChain = supportedChains.find(chain => chain.chainId === chainId); diff --git a/src/providers/NetworkConfig/networks/base.ts b/src/providers/NetworkConfig/networks/base.ts index 0edeb27bba..1514787213 100644 --- a/src/providers/NetworkConfig/networks/base.ts +++ b/src/providers/NetworkConfig/networks/base.ts @@ -27,6 +27,9 @@ const CHAIN_ID = 8453; const SAFE_VERSION = '1.3.0'; export const baseConfig: NetworkConfig = { + order: 10, + chain: base, + rpcEndpoint: `https://base-mainnet.g.alchemy.com/v2/${import.meta.env.VITE_APP_ALCHEMY_BASE_API_KEY}`, safeBaseURL: 'https://safe-transaction-base.safe.global', etherscanBaseURL: 'https://basescan.org/', etherscanAPIUrl: `https://api.basescan.com/api?apikey=${import.meta.env.VITE_APP_ETHERSCAN_BASE_API_KEY}`, diff --git a/src/providers/NetworkConfig/networks/baseSepolia.ts b/src/providers/NetworkConfig/networks/baseSepolia.ts index 6263538c3b..98da229398 100644 --- a/src/providers/NetworkConfig/networks/baseSepolia.ts +++ b/src/providers/NetworkConfig/networks/baseSepolia.ts @@ -27,6 +27,9 @@ const CHAIN_ID = 84532; const SAFE_VERSION = '1.3.0'; export const baseSepoliaConfig: NetworkConfig = { + order: 40, + chain: baseSepolia, + rpcEndpoint: `https://base-sepolia.g.alchemy.com/v2/${import.meta.env.VITE_APP_ALCHEMY_BASE_SEPOLIA_API_KEY}`, safeBaseURL: 'https://safe-transaction-base-sepolia.safe.global', etherscanBaseURL: 'https://sepolia.basescan.org/', etherscanAPIUrl: `https://api-sepolia.basescan.com/api?apikey=${import.meta.env.VITE_APP_ETHERSCAN_BASE_SEPOLIA_API_KEY}`, diff --git a/src/providers/NetworkConfig/networks/mainnet.ts b/src/providers/NetworkConfig/networks/mainnet.ts index 1c1ee5cd5c..79fc9bd9f5 100644 --- a/src/providers/NetworkConfig/networks/mainnet.ts +++ b/src/providers/NetworkConfig/networks/mainnet.ts @@ -27,6 +27,9 @@ const CHAIN_ID = 1; const SAFE_VERSION = '1.3.0'; export const mainnetConfig: NetworkConfig = { + order: 0, + chain: mainnet, + rpcEndpoint: `https://eth-mainnet.g.alchemy.com/v2/${import.meta.env.VITE_APP_ALCHEMY_MAINNET_API_KEY}`, safeBaseURL: 'https://safe-transaction-mainnet.safe.global', etherscanBaseURL: 'https://etherscan.io', etherscanAPIUrl: `https://api.etherscan.io/api?apikey=${import.meta.env.VITE_APP_ETHERSCAN_MAINNET_API_KEY}`, diff --git a/src/providers/NetworkConfig/networks/polygon.ts b/src/providers/NetworkConfig/networks/polygon.ts index 20e033cf0b..a325bf25d6 100644 --- a/src/providers/NetworkConfig/networks/polygon.ts +++ b/src/providers/NetworkConfig/networks/polygon.ts @@ -27,6 +27,9 @@ const CHAIN_ID = 137; const SAFE_VERSION = '1.3.0'; export const polygonConfig: NetworkConfig = { + order: 20, + chain: polygon, + rpcEndpoint: `https://polygon-mainnet.g.alchemy.com/v2/${import.meta.env.VITE_APP_ALCHEMY_POLYGON_API_KEY}`, safeBaseURL: 'https://safe-transaction-polygon.safe.global', etherscanBaseURL: 'https://polygonscan.com', etherscanAPIUrl: `https://api.polygonscan.com/api?apikey=${import.meta.env.VITE_APP_ETHERSCAN_POLYGON_API_KEY}`, diff --git a/src/providers/NetworkConfig/networks/sepolia.ts b/src/providers/NetworkConfig/networks/sepolia.ts index a6b73a3ffa..e7b35fea2a 100644 --- a/src/providers/NetworkConfig/networks/sepolia.ts +++ b/src/providers/NetworkConfig/networks/sepolia.ts @@ -27,6 +27,9 @@ const CHAIN_ID = 11155111; const SAFE_VERSION = '1.3.0'; export const sepoliaConfig: NetworkConfig = { + order: 30, + chain: sepolia, + rpcEndpoint: `https://eth-sepolia.g.alchemy.com/v2/${import.meta.env.VITE_APP_ALCHEMY_SEPOLIA_API_KEY}`, safeBaseURL: 'https://safe-transaction-sepolia.safe.global', etherscanBaseURL: 'https://sepolia.etherscan.io', etherscanAPIUrl: `https://api-sepolia.etherscan.io/api?apikey=${import.meta.env.VITE_APP_ETHERSCAN_SEPOLIA_API_KEY}`, diff --git a/src/providers/NetworkConfig/web3-modal.config.ts b/src/providers/NetworkConfig/web3-modal.config.ts index ecd3f2aa1e..d39bdb4277 100644 --- a/src/providers/NetworkConfig/web3-modal.config.ts +++ b/src/providers/NetworkConfig/web3-modal.config.ts @@ -1,8 +1,10 @@ import { QueryClient } from '@tanstack/react-query'; import { createWeb3Modal } from '@web3modal/wagmi/react'; import { defaultWagmiConfig } from '@web3modal/wagmi/react/config'; +import { HttpTransport } from 'viem'; import { http } from 'wagmi'; -import { Chain, hardhat, sepolia, mainnet, polygon, baseSepolia, base } from 'wagmi/chains'; +import { Chain, hardhat } from 'wagmi/chains'; +import { NetworkConfig } from '../../types/network'; import { supportedChains } from './NetworkConfigProvider'; const supportedWagmiChains = supportedChains.map(config => config.wagmiChain); @@ -23,42 +25,18 @@ const wagmiMetadata = { icons: [`${import.meta.env.VITE_APP_SITE_URL}favicon.icon`], }; +const transportsReducer = (accumulator: Record, network: NetworkConfig) => { + accumulator[network.chain.id] = http(network.rpcEndpoint, { + batch: true, + }); + return accumulator; +}; + export const wagmiConfig = defaultWagmiConfig({ chains: supportedWagmiChains as [Chain, ...Chain[]], projectId: walletConnectProjectId, metadata: wagmiMetadata, - transports: { - [mainnet.id]: http( - `https://eth-mainnet.g.alchemy.com/v2/${import.meta.env.VITE_APP_ALCHEMY_MAINNET_API_KEY}`, - { - batch: true, - }, - ), - [sepolia.id]: http( - `https://eth-sepolia.g.alchemy.com/v2/${import.meta.env.VITE_APP_ALCHEMY_SEPOLIA_API_KEY}`, - { - batch: true, - }, - ), - [polygon.id]: http( - `https://polygon-mainnet.g.alchemy.com/v2/${import.meta.env.VITE_APP_ALCHEMY_POLYGON_API_KEY}`, - { - batch: true, - }, - ), - [baseSepolia.id]: http( - `https://base-sepolia.g.alchemy.com/v2/${import.meta.env.VITE_APP_ALCHEMY_BASE_SEPOLIA_API_KEY}`, - { - batch: true, - }, - ), - [base.id]: http( - `https://base-mainnet.g.alchemy.com/v2/${import.meta.env.VITE_APP_ALCHEMY_BASE_API_KEY}`, - { - batch: true, - }, - ), - }, + transports: supportedChains.reduce(transportsReducer, {}), }); if (walletConnectProjectId) { diff --git a/src/types/network.ts b/src/types/network.ts index 1cbea60908..f5b35ce118 100644 --- a/src/types/network.ts +++ b/src/types/network.ts @@ -8,6 +8,9 @@ export type Providers = | ethers.providers.BaseProvider; export type NetworkConfig = { + order: number; // any arbitrary integer, used to "order" the networks in the dropdown + chain: Chain; + rpcEndpoint: string; safeBaseURL: string; etherscanBaseURL: string; etherscanAPIUrl: string;