Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions apps/cowswap-frontend/.env
Original file line number Diff line number Diff line change
Expand Up @@ -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




Expand Down
9 changes: 9 additions & 0 deletions apps/explorer/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
15 changes: 14 additions & 1 deletion libs/common-utils/src/getExplorerLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down
9 changes: 8 additions & 1 deletion libs/common-utils/src/legacyAddressUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Comment on lines 77 to +79
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix the fallback priority order.

The current fallback order OVERRIDE || base || CHAIN_INFO places the base parameter before the chain's default explorer, which is inconsistent with getExplorerLink.ts (line 37) and likely incorrect.

For known chains with entries in CHAIN_INFO, the chain's default explorer should take precedence over the generic base parameter. The base parameter should serve as a final fallback for unsupported chains, not override known chain explorers.

🔎 Proposed fix to align fallback priority
  // Allow override via environment variable for local development (e.g., Otterscan)
- const basePath = BLOCK_EXPLORER_URL_OVERRIDE || base || CHAIN_INFO[chainId]?.explorer
+ const basePath = BLOCK_EXPLORER_URL_OVERRIDE || CHAIN_INFO[chainId]?.explorer || base

This ensures:

  1. Environment override takes precedence (for local dev)
  2. Chain default is used for known chains
  3. Function parameter serves as final fallback for unknown chains
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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
function getEtherscanUrl(chainId: SupportedChainId, data: string, type: BlockExplorerLinkType, base?: string): string {
// Allow override via environment variable for local development (e.g., Otterscan)
const basePath = BLOCK_EXPLORER_URL_OVERRIDE || CHAIN_INFO[chainId]?.explorer || base
🤖 Prompt for AI Agents
In libs/common-utils/src/legacyAddressUtils.ts around lines 77 to 79, the
fallback order for determining the explorer base is wrong: currently it uses
BLOCK_EXPLORER_URL_OVERRIDE || base || CHAIN_INFO[chainId]?.explorer but should
prefer the chain's configured explorer over the supplied base parameter. Change
the priority so it reads BLOCK_EXPLORER_URL_OVERRIDE ||
CHAIN_INFO[chainId]?.explorer || base, keeping the env override first, the chain
default second, and the function parameter as the final fallback.


if (!basePath) return ''

Expand Down
Loading