diff --git a/apps/cowswap-frontend/.env b/apps/cowswap-frontend/.env index 1773c7002d..6e3cb38974 100644 --- a/apps/cowswap-frontend/.env +++ b/apps/cowswap-frontend/.env @@ -103,6 +103,17 @@ INTEGRATION_TESTS_INFURA_KEY= #REACT_APP_EXPLORER_URL_PROD= #REACT_APP_EXPLORER_URL_BARN= +####################################### +# Block Explorer Override +####################################### +# Override the default block explorer URL (e.g., Etherscan, Gnosisscan). +# Useful for local development with tools like Otterscan. +# When set, all block explorer links will use this URL instead of the chain's default. +# The URL should not include a trailing slash. +# +# Example for local Otterscan: +#REACT_APP_BLOCK_EXPLORER_URL=http://localhost:8003 + diff --git a/apps/explorer/.env.example b/apps/explorer/.env.example index 8bd1ce4ad6..c7d3883adc 100644 --- a/apps/explorer/.env.example +++ b/apps/explorer/.env.example @@ -22,3 +22,12 @@ THEGRAPH_API_KEY= # REACT_APP_DOMAIN_REGEX_DEVELOPMENT="^(dev\.explorer\.cow\.fi|explorer-develop\.vercel\.app)" # REACT_APP_DOMAIN_REGEX_STAGING="^(staging\.explorer\.cow\.fi|explorer-staging\.vercel\.app)" # REACT_APP_DOMAIN_REGEX_PRODUCTION="^(explorer\.cow\.fi|explorer-prod\.vercel\.app)$" + +# Block Explorer Override +# Override the default block explorer URL (e.g., Etherscan, Gnosisscan). +# Useful for local development with tools like Otterscan. +# When set, all block explorer links will use this URL instead of the chain's default. +# The URL should not include a trailing slash. +# +# Example for local Otterscan: +#REACT_APP_BLOCK_EXPLORER_URL=http://localhost:8003 diff --git a/libs/common-utils/src/getExplorerLink.ts b/libs/common-utils/src/getExplorerLink.ts index f86bc29b54..4b8ab268cd 100644 --- a/libs/common-utils/src/getExplorerLink.ts +++ b/libs/common-utils/src/getExplorerLink.ts @@ -8,6 +8,18 @@ export enum ExplorerDataType { BLOCK = 'block', } +/** + * Environment variable to override the block explorer URL. + * Useful for local development with tools like Otterscan. + * + * When set, this URL will be used instead of the chain's default block explorer (e.g., Etherscan). + * The URL should not include a trailing slash. + * + * @example + * REACT_APP_BLOCK_EXPLORER_URL=http://localhost:8003 + */ +const BLOCK_EXPLORER_URL_OVERRIDE = process.env.REACT_APP_BLOCK_EXPLORER_URL + /** * Return the explorer link for the given data and data type * @param chainId the ID of the chain for which to return the data @@ -21,7 +33,8 @@ export function getExplorerLink( type: ExplorerDataType, defaultPrefix = 'https://etherscan.io', ): string { - const prefix = CHAIN_INFO[chainId as SupportedChainId]?.explorer ?? defaultPrefix + // Allow override via environment variable for local development (e.g., Otterscan) + const prefix = BLOCK_EXPLORER_URL_OVERRIDE || CHAIN_INFO[chainId as SupportedChainId]?.explorer || defaultPrefix switch (type) { case ExplorerDataType.TRANSACTION: diff --git a/libs/common-utils/src/legacyAddressUtils.ts b/libs/common-utils/src/legacyAddressUtils.ts index 2441bd0808..c2691f07b8 100644 --- a/libs/common-utils/src/legacyAddressUtils.ts +++ b/libs/common-utils/src/legacyAddressUtils.ts @@ -9,6 +9,12 @@ import { t } from '@lingui/core/macro' import { getExplorerOrderLink } from './explorer' +/** + * Environment variable to override the block explorer URL. + * Useful for local development with tools like Otterscan. + */ +const BLOCK_EXPLORER_URL_OVERRIDE = process.env.REACT_APP_BLOCK_EXPLORER_URL + // returns the checksummed address if the address is valid, otherwise returns false export function isAddress(value: string | undefined | null): string | false { try { @@ -69,7 +75,8 @@ export type BlockExplorerLinkType = // eslint-disable-next-line complexity function getEtherscanUrl(chainId: SupportedChainId, data: string, type: BlockExplorerLinkType, base?: string): string { - const basePath = base || CHAIN_INFO[chainId]?.explorer + // Allow override via environment variable for local development (e.g., Otterscan) + const basePath = BLOCK_EXPLORER_URL_OVERRIDE || base || CHAIN_INFO[chainId]?.explorer if (!basePath) return ''