Skip to content

v1.2.3-a#287

Merged
AugustoL merged 88 commits intomainfrom
dev
Mar 10, 2026
Merged

v1.2.3-a#287
AugustoL merged 88 commits intomainfrom
dev

Conversation

@AugustoL
Copy link
Collaborator

@AugustoL AugustoL commented Mar 10, 2026

Description

Release v1.2.3-alpha — merges all features, fixes, and improvements accumulated in dev into main.

Related Issue

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Refactoring
  • Performance improvement
  • Other (please describe):

Changes Made

Features

  • Proxy contract detection — EIP-1967, EIP-1822 support; shows proxy type, implementation address, and warning when implementation is not verified; Sourcify V2 proxy resolution
  • Kleros verified tag — displays "Verified by Kleros" on addresses from the Kleros curated list via The Graph ATQ subgraph; hardcoded public API key with authorized domains
  • Etherscan as parallel contract verification source — fetches verification data from Etherscan alongside Sourcify
  • Skeleton loaders — inline skeleton rows and cards across blocks, transactions, dashboard, and all Bitcoin pages for improved loading UX
  • Breadcrumb navigation — added to all EVM and Bitcoin detail pages (blocks, transactions, addresses)
  • CopyButton component — integrated into LongString, addresses, and transaction from/to/contract fields
  • Auto-sync RPCs by latency — on first load, tests and re-orders RPC endpoints by quality (privacy tier + latency) in the background after route settles for 1.5s; saves to storage only to avoid data refetches
  • Home page redesign — featured Ethereum/Bitcoin full-width card, testnet toggle in super user mode only, network IDs display in super user mode
  • SEO — canonical and alternate links added

Fixes

  • Address type detection: avoid false account fallback when type detection fails; prevent display component remount on background re-fetches
  • Proxy detection bugs and EOA misclassification
  • EVM Mempool page: replaced debug stub with proper placeholder
  • Search page: improved empty state with search bar, guidance, and Go Home button
  • Profile page: user-friendly error message and recovery options
  • Breadcrumbs: show network short name instead of chain ID
  • Skeleton loaders: match row structure and height to real rows in all tables
  • Pagination buttons visible during transactions loading state
  • Prevent card size changes between loading and loaded states
  • CSS: missing display:none defaults for show-mobile-* classes
  • Supporters page CTA copy clarified
  • Footer: removed About/Contact/Subscriptions internal pages, now link to docs site

Accessibility

  • Respect prefers-reduced-motion for background animation
  • Text contrast meets WCAG AA (4.5:1 ratio)
  • Global focus-visible outline for keyboard navigation
  • aria-live and role=alert on loading and timeout states

Refactoring

  • hasContractCode exported and reused in fallback logic with unit tests
  • About, Contact, and Subscriptions pages removed from app — replaced with links to the docs site (https://openscan-explorer.github.io/docs)

Checklist

  • I have run npm run format:fix and npm run lint:fix
  • I have run npm run typecheck with no errors
  • I have run tests with npm run test:run
  • I have tested my changes locally
  • I have updated documentation if needed
  • My code follows the project's architecture patterns

josealoha666 and others added 30 commits March 3, 2026 14:25
chore: bump version from 1.2.2-alpha to 1.2.3-alpha
Add source field support from explorer-metadata PR #11 to display
a "Verified by Kleros" tag next to addresses tagged by the Kleros
curated list.
- Add KlerosService with GraphQL query against Kleros ATQ subgraph
- Add useKlerosTag hook with fallback to metadata CDN
- Show Public Name Tag as clickable link to Kleros Curate item
- Add Kleros logo to tag badge
- Migrate REACT_APP_ENVIRONMENT to VITE_ENVIRONMENT
- Inject VITE_THE_GRAPH_API_KEY in CI workflows
…detection

fix: issue #271 Arbitrum contract shown as account
…1167)

Automatically detects proxy patterns and shows the implementation address
as a clickable link. Merges the implementation ABI into the interaction
panel so users can call implementation functions directly.

- Add proxyDetection.ts utility supporting EIP-1967, EIP-1822 (UUPS),
  EIP-1967-Beacon, and EIP-1167 minimal proxy patterns
- Add useProxyInfo hook wrapping detection with AppContext RPC URLs
- Show proxy type and implementation address row in ContractInfoCard
- Add ABI tab switcher (Implementation / Proxy) when both ABIs exist
- Fetch implementation contract data from Sourcify when proxy detected
- Add abi-tab-switcher CSS styles
- Add i18n keys (proxyType, implementationAddress, implementationFunctions,
  proxyFunctions) to en, es, ja, pt-BR, zh locales

Closes #266
Proxy detection fixes:
- Add legacy OZ AdminUpgradeabilityProxy slot (keccak256("org.zeppelinos.proxy.implementation"))
  so Circle USDC (FiatTokenProxy) and other pre-EIP-1967 proxies are detected
- Use NetworkAdapter.getStorageAt/callContract instead of raw fetch calls,
  so the configured RPC strategy (fallback/parallel) is used for proxy checks
- Add slotToAddress validation: top 12 bytes must be zero (ABI-encoded address)
  to prevent false positives from contracts with incidental non-zero storage slots
- Run all four slot reads in parallel to reduce latency
- Add ProxyRpcClient interface satisfied by NetworkAdapter

EOA misclassification fixes:
- Pass pre-fetched addressData to fetchAddressWithType to avoid redundant
  eth_getCode call; secondary RPC failures no longer silently downgrade
  contracts to EOA
- When type detection fails or no RPC URL is configured, derive EOA/contract
  from the already-fetched code instead of defaulting to "account"

Contract Details panel fix:
- Show the Contract Details section (ABI + interaction) whenever a proxy is
  detected with a verified implementation ABI, even when the proxy contract
  itself has no Sourcify entry
ERC20 tokens that are also proxies (e.g. USDC/FiatTokenProxy) now
detect the proxy pattern and pass proxyInfo + implementationContractData
to ContractInfoCard, enabling the implementation ABI tab switcher.
…on Sourcify

When a proxy is detected but its implementation contract is not verified
on Sourcify (e.g. Aave V3 Pool on Optimism), show a clear note explaining
why no implementation ABI tab is available.
- Add useEtherscan hook fetching from Etherscan V2 API (single key, 60+ chains)
- Add useContractVerification hook running Sourcify and Etherscan simultaneously;
  source is an array — empty means unverified, ["sourcify"], ["etherscan"], or both
- Replace useSourcify calls in ContractDisplay, ERC20Display, ERC721Display,
  ERC1155Display with useContractVerification; add proxy detection to ERC721/ERC1155
- Show Sourcify and Etherscan as linked tag badges on the status row in
  ContractInfoCard, following the same style as Kleros tags (PR #277)
- Compute verification URLs internally in ContractInfoCard (correct partial_match
  path for Sourcify; per-chain explorer URL for Etherscan); remove sourcifyUrl prop
- Add Etherscan API key field to Settings (after Alchemy, before AI keys)
- Add etherscan key to ApiKeys type and all 5 locale files
- Fix double separator between EVM Version and Contract Details rows
…, hashes

- New reusable CopyButton component with clipboard icon → checkmark feedback
- LongString now shows copy button by default (copyable prop)
- Added copy buttons to: EVM address header, BTC address, BTC block hash, BTC tx ID/witness hash
- All EVM views using LongString (block hash, tx hash, addresses) get copy automatically
- CSS with hover/focus-visible states

Ticket 1 from UI/UX audit: copy buttons for hashes and addresses
… button

- Added inline SearchBox so users can search directly from the empty state
- Added descriptive help text explaining what can be searched
- Added magnifying glass icon for visual clarity
- Added 'Go Home' button as escape hatch
- i18n keys added for en/es

Ticket 2 from UI/UX audit: fix Search page dead end
…ry CTAs

- Replaced technical error message with friendly explanation
- Changed error text color from green to neutral (removed error-text-center class)
- Added info icon for visual softness
- Added 'Go to Homepage' and 'Browse Supporters' buttons as recovery paths
- Added role='alert' for accessibility
- i18n keys for en/es

Ticket 3 from UI/UX audit: fix Profile error page
…g cards

- Added 'Get Started' button to each pricing tier card
- Highlighted Partner tier with 'Most Popular' badge and accent border
- Cards use flex layout so CTA stays at bottom regardless of content height
- CSS for badge positioning, recommended styling
- i18n keys for en/es

Ticket 4 from UI/UX audit: CTA buttons on Subscriptions pricing
… pages

- New LoaderWithTimeout shows loading spinner for 15s then offers Retry + Go Home
- Replaced plain Loader with LoaderWithTimeout in all BTC pages:
  Address, Block, Blocks, Mempool, Transaction, Transactions, Dashboard
- Replaced in all EVM pages:
  Address, Block, Blocks, Txs, Tx, Network, Gas Tracker, Token Details
- Users no longer stuck on infinite loading spinners

Ticket 6 from UI/UX audit: timeout + error + retry states
- New SkeletonLoader module with SkeletonRow, SkeletonTable, SkeletonCard, SkeletonDashboard, SkeletonDetail
- CSS shimmer animation for skeleton placeholders
- EVM Network dashboard: replaced spinner with SkeletonDashboard (stat cards + table placeholders)
- EVM Blocks list: replaced spinner with SkeletonTable (10 rows × 6 cols)
- EVM Txs list: replaced spinner with SkeletonTable (10 rows × 7 cols)
- Detail pages keep LoaderWithTimeout (single item loading)
- Reduces layout shift (CLS) and improves perceived performance

Ticket 7 from UI/UX audit: skeleton loaders
- New Breadcrumb component with aria-label, aria-current, semantic nav/ol
- Integrated breadcrumbs into:
  EVM: Block detail, Transaction detail, Address detail
  BTC: Block detail, Transaction detail, Address detail
- Path: Home › Chain › [Blocks/Transactions] › Current item
- CSS with proper styling, hover states, separators

Ticket 9 from UI/UX audit: breadcrumb navigation
- IsometricBlocks: skip spawning new cubes when prefers-reduced-motion is set
- base.css: global reduced-motion media query disables all animations/transitions
- Users with vestibular disorders or motion sensitivity get a static experience

Ticket 11 from UI/UX audit: prefers-reduced-motion
- Dark mode textSecondary: #8a8f98 → #9ea3ad (~5.2:1 ratio)
- Dark mode textTertiary: #5c6370 → #8b919b (~4.5:1 ratio)
- Both now pass WCAG AA for normal text against dark backgrounds

Ticket 12 from UI/UX audit: fix contrast for gray text
- Green outline (2px solid, 2px offset) on :focus-visible
- Remove outline for mouse users via :focus:not(:focus-visible)
- Keyboard users now see clear focus indicators on all interactive elements

Ticket 13 from UI/UX audit: focus visible styles
- LoaderWithTimeout: aria-live='polite' + aria-busy on loading state
- Timeout state: role='alert' for screen reader announcement
- Screen readers now announce loading/timeout state changes

Ticket 14 from UI/UX audit: accessible loading states
- Removed raw debug output (networkId/filter params displayed as text)
- Added proper 'under development' page with:
  - Descriptive messaging about upcoming features
  - Icon for visual clarity
  - CTAs: 'View Gas Tracker', 'Back to Dashboard', 'Go Home'
- No longer exposes internal parameters to end users

Ticket 15 from UI/UX audit: fix ETH Mempool page
- 'subscribing a network' → 'becoming a subscriber' (less ambiguous)

Ticket 17 from UI/UX audit: fix ambiguous CTA copy
MatiasOS and others added 23 commits March 6, 2026 18:48
feat: UX, accessibility, and loading-state improvements across Explorer
- useSourcify: add SourcifyV2Raw internal type and mapV2Response() to
  correctly extract compilation fields (name, compilerVersion, evmVersion,
  language, optimizer) from the nested 'compilation' object returned by
  V2 API — these were previously undefined because the raw JSON was
  assigned directly without mapping
- useSourcify: normalize match values ('exact_match' -> 'perfect')
- useSourcify: add proxyResolution field (isProxy, proxyType, implementations)
- useSourcify: remove dead code — SOURCIFY_API_BASE (V1 URL) and
  useSourcifyFiles hook (never imported anywhere)
- ContractDisplay: merge Sourcify proxyResolution with RPC detection;
  Sourcify provides the implementation address reliably, RPC provides
  accurate Transparent vs UUPS distinction
- ContractDisplay: expose sourcifyImplName from proxyResolution so the
  implementation contract name is available immediately without waiting
  for a second verification fetch
- ContractDisplay: rename sourcifyData -> contractVerifiedData (also in
  ERC20/721/1155Display) to reflect it may come from Etherscan fallback
- ContractInfoCard: add language, optimizerEnabled, optimizerRuns fields
  and display rows; use sourcifyImplName as immediate name fallback
- index.tsx: only reset addressType when navigating to a new address
  (use prevAddressRef); keeps display component mounted on background
  re-fetches, preserving all hook state
- useProxyInfo: keep last known proxyInfo on RPC failure instead of
  resetting to null, preventing verified impl data from disappearing
- i18n: add language, optimizer, optimizerEnabled, optimizerDisabled
  keys in all 5 locales
…contract tabs

- Derive sourceFiles from activeSourceData (same as activeABI) so
  implementation source code shows when on the Implementation tab
- Suppress bottom bytecode section when contract-details-section
  already renders bytecode (prevents duplication for unverified proxy
  with verified implementation)
- Add runtimeBytecode field to SourcifyContractDetails and map it
  from Sourcify V2 API response so bytecode switches with active tab
- Add NetworkAdapter.getCode() for direct eth_getCode calls
- Fetch implementation bytecode via RPC in ContractDisplay as fallback
  when Sourcify runtimeBytecode is unavailable (Etherscan-only contracts)
…tection

feat(address): proxy contract detection + Etherscan verification source
.show-mobile-flex, .show-mobile-inline and .show-mobile-inline-flex had
no default display:none outside the mobile media query, causing them to
render on all screen sizes. This made the address hash appear duplicated
on the address page (both the full desktop span and the truncated mobile
span were visible simultaneously).

Also ignores package-lock.json and .claude/plans/ in .gitignore.
…inks

feat(seo): Add canonical and alternate links
Automatically tests and re-orders RPC endpoints by quality (privacy
tier + latency) on first load, removing the need for manual sync.
A rpcsSynced flag prevents re-running on every page load and is reset
when the user clears cache data.
feat(settings): auto-sync RPCs by latency on first load
…of-docs

refactor: remove about/contact/subscriptions pages in favor of docs site
@github-actions
Copy link

github-actions bot commented Mar 10, 2026

🚀 Preview: https://pr-287--openscan.netlify.app
📝 Commit: 932c68a47ffcc0ef70f7c651f81182ea10839d86

josealoha666 and others added 2 commits March 10, 2026 08:35
The address page passes the route parameter (e.g. 'eth') as networkId to
display components, which call Number(networkId). Number('eth') returns NaN,
causing metadata fetches to use NaN as chainId (404s).

Fix: use existing getNetworkById() + getChainIdFromNetwork() to properly
resolve the slug to a numeric chainId before passing to display components.
…displays

fix: resolve NaN chainId when networkId is a slug
@AugustoL AugustoL requested a review from MatiasOS March 10, 2026 11:39
Copy link
Member

@MatiasOS MatiasOS left a comment

Choose a reason for hiding this comment

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

:shipit:

@AugustoL AugustoL merged commit c439b31 into main Mar 10, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants