Skip to content

Clusters Feature Integration #2816

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 84 commits into
base: main
Choose a base branch
from
Open

Conversation

ayv8er
Copy link

@ayv8er ayv8er commented Jun 27, 2025

Description and Related Issue(s)

This PR introduces Clusters Universal Name Service integration into the Blockscout explorer. Clusters is a cross-chain identity service that allows users to track multiple wallets across various networks under a single unified name (like vitalik/ or foobar/).

This optional integration adds a new Clusters directory, Clusters leaderboard, individual cluster details page, and search capability. The feature follows established patterns for optional service and includes proper env handling.

Proposed Changes

Environment Variables:

  • Added two new environment variables:
    • NEXT_PUBLIC_CLUSTERS_API_HOST - for Clusters API endpoint
    • NEXT_PUBLIC_CLUSTERS_CDN_URL - for Clusters CDN assets
  • Updated environment preset files in configs/envs/.env.jest and configs/envs/.env.localhost
  • Added validation schema in deploy/tools/envs-validator/schema.ts
  • Updated Helm deployment values in review YAML templates - deploy/values/

Documentation and Configuration:

  • Added Clusters feature documentation to docs/ENVS.md
  • Updated Jest configuration jest.config.ts and added test mocks jest/mocks/ and jest/setupAfterEnv.ts

API Configuration and Types:

  • Added clustersApi configuration in configs/app/apis.ts with optional Clusters API integration
  • Created lib/api/services/clusters.ts for Clusters API service layer
  • Added Clusters feature configuration in configs/app/features/clusters.ts
  • Updated API resources and types in lib/api/resources.ts and lib/api/types.ts

TypeScript Types and Stubs:

  • Created TypeScript type definitions in types/api/clusters.ts
  • Added test stubs in stubs/clusters.ts
  • Updated search types in types/api/search.ts

Core Library and Utilities:

  • Added complete lib/clusters/ directory with utilities for action bar, page utils, and input detection
  • Created specialized hooks in lib/hooks/:
    • useAddressClusters.ts - for address specific cluster data
    • useClusterPagination.ts - for cluster pagination logic
    • useClusterSearch.ts - for cluster search functionality
    • useClustersData.ts - for main clusters data fetching
    • useQueryParams.ts - for URL query parameter handling
  • Updated navigation in lib/hooks/useNavItems.tsx
  • Updated metadata and analytics mappings for cluster pages in lib/metadata/ and lib/mixpanel/

Testing and QA:

  • Added comprehensive test coverage for all new utilities and hooks:
    • lib/clusters/ utilities - action bar, page utils, input detection
    • All custom hooks - useAddressClusters, useClusterPagination, useClusterSearch, useClustersData
    • Search integration - useSearchWithClusters
    • UI components - ClustersEntity
  • Updated Jest configuration and added testing infrastructure
  • Added test mocks for Next.js routes, SVG imports, and React hooks

Pages and Routing:

  • Added pages/clusters/index.tsx - main clusters directory page
  • Added pages/clusters/[name].tsx - individual cluster details page
  • Created corresponding page components:
    • ui/pages/Clusters.tsx - clusters directory page component
    • ui/pages/Cluster.tsx - individual cluster page component
  • Updated Next.js routing types in nextjs/nextjs-routes.d.ts

UI Components:

  • Clusters Directory/Leaderboard - ui/clusters/:
    • ClustersActionBar.tsx - search and filter controls
    • ClustersDirectoryTable.tsx and ClustersDirectoryTableItem.tsx - directory views
    • ClustersDirectoryListItem.tsx - directory list item
    • ClustersLeaderboardTable.tsx and ClustersLeaderboardTableItem.tsx - leaderboard views
    • ClustersLeaderboardListItem.tsx - leaderboard list items
  • Individual Cluster Details - ui/cluster/:
    • ClusterDetails.tsx - main cluster detail component
  • Address Integration - ui/address/clusters/:
    • AddressClusters.tsx - clusters tab for address pages
  • Shared Components:
    • ui/shared/ClusterIcon.tsx - cluster icon component
    • ui/shared/entities/clusters/ClustersEntity.tsx - cluster entity display

Search and Navigation Integration:

  • Added cluster search suggestions in ui/snippets/searchBar/SearchBarSuggest/SearchBarSuggestCluster.tsx
  • Created ui/snippets/searchBar/useSearchWithClusters.tsx
  • Updated search utilities in ui/shared/search/utils.ts
  • Updated navigation components in ui/snippets/navigation/NavLinkIcon.tsx
  • Updated search bar components: SearchBar.tsx, SearchBarInput.tsx, SearchBarSuggest.tsx, SearchBarSuggestItem.tsx

Assets and Icons:

  • Added icons/clusters.svg for cluster-specific logo use
  • Updated icon type definitions in public/icons/name.d.ts

Breaking or Incompatible Changes

None. This is an additive feature that introduces optional clusters functionality. Existing installations will continue to work unchanged, and the new feature can be optionally enabled by setting the NEXT_PUBLIC_CLUSTERS_API_HOST environment variable.

Additional Information

5 minute Loom video displaying the Clusters feature - https://www.loom.com/share/6278c920204249b398a6f227b1cb701d?sid=5b7d6a88-b13e-4002-8fab-0c531ac92090

Checklist for PR author

  • I have tested these changes locally.
  • I added tests to cover any new functionality, following this guide
  • Whenever I fix a bug, I include a regression test to ensure that the bug does not reappear silently.
  • If I have added, changed, renamed, or removed an environment variable
    • I updated the list of environment variables in the documentation
    • I made the necessary changes to the validator script according to the guide
    • I added "ENVs" label to this pull request

ayv8er added 30 commits June 22, 2025 14:40
…user is searching for a cluster name vs a evm address
ayv8er added 22 commits July 2, 2025 22:49
s.isEnabled to top of the function and utilizes select function of useQuery in useAp
iQuery
return {
...clusterQuery,
data: clusterQuery.data || [],
isError: false,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you explain the reasoning behind why the isError flag should always be false?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Cloning the entire query object here doesn't seem like a good idea to me in terms of memory usage. I just want to ensure that it is truly necessary.

Copy link
Author

Choose a reason for hiding this comment

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

isError: false UI reason
In SearchBarSuggest, when query.isError is true, it displays "Something went wrong. Try refreshing the page or come back later."

For better UX where cluster service outages don't break the search experience, cluster search failures show "No results found" while regular search failures show the error message. This behavior is tested and intentional (see test line 415 in useSearchWithClusters.test.tsx).

query object cloning
The UseQueryResult interface has many properties (data, isError, isFetching, refetch, etc.) and needs to return an object matching useQuickSearchQuery's interface since SearchBar.tsx uses them interchangeably.

The cloning preserves all other properties the UI depends on while overriding specific ones for cluster behavior. Memory impact should be minimal since it's a shallow spread of lightweight React Query metadata objects, only for cluster searches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants