Skip to content

chore: apply namehash-ui#109

Merged
lightwalker-eth merged 22 commits intomainfrom
y3drk/chore/apply-namehash-ui
Jan 21, 2026
Merged

chore: apply namehash-ui#109
lightwalker-eth merged 22 commits intomainfrom
y3drk/chore/apply-namehash-ui

Conversation

@Y3drk
Copy link
Copy Markdown
Collaborator

@Y3drk Y3drk commented Jan 19, 2026

Substantial PR → apply namehash-ui


Closes Issues #906 and #105

Note: Updated after this request from Slack

Reviewer Focus (Read This First)

What reviewers should focus on
  • This package consists of three major sets of changes:
    • Swaps of local components for the ones from namehash-ui
    • Bump of the versions of our packages to our newest (at the time of 01/20/26) snapshot version
    • Solve Issue Transition to using new ENSReferralsClient #105 (see ensawards.org/src/components/referral-awards-program/referrers/ReferrerLeaderboardSnippet.tsx and ensawards.org/src/components/referral-awards-program/referrers/ReferrerLeaderboard.tsx)
  • Therefore, I recommend reviewing the PR in two ways:
    • By reviewing the code changes
    • By reviewing the UI in the preview and comparing it to the current production site (there should be no changes)

Problem & Motivation

Why this exists
  • This PR is a part of a larger effort described in detail in #906, which in turn is part of #1467
  • It is generally supposed to be the second part of completing Phase 5 of the strategy suggested in the aforementioned Issue. The 1st part was about applying the package in ENSAdmin.
  • After the request mentioned at the top, a solution to Issue Transition to using new ENSReferralsClient #105 was also included in this PR.

What Changed (Concrete)

What actually changed
  • Swapped local ensadmin components for their counterparts from the namehash-ui package and deleted unused code. (changes mostly located in ensawards.org/src/components)
  • Bumped the versions of our packages (ensnode-react, ensnode-sdk, datasources, and ens-referrals) to the newest (at the time of 01/20/26) snapshot version
  • Solved Issue Transition to using new ENSReferralsClient #105 by replacing the ENSNodeClient with ENSReferralsClient in ensawards.org/src/components/referral-awards-program/referrers/ReferrerLeaderboardSnippet.tsx and ensawards.org/src/components/referral-awards-program/referrers/ReferrerLeaderboard.tsx
  • Added typescript as a devDependency (see pnpm-workspace.yaml:5, package.json:15, and ensawards.org/package.json:66)

Design & Planning

How this approach was chosen

Self-Review

  • Bugs caught:
    • During UI check, I spotted that the link to the referrer's profile opens in a new tab instead of just routing in the current one. Further investigation led to the discovery that this setting is hardcoded in the packages/namehash-ui/src/components/registrar-actions/RegistrarActionCard.tsx and therefore I had to make a small fixing PR in the ensnode repo (PR #1552). This bug is non-breaking.
  • Logic simplified: -
  • Naming / terminology improved: -
  • Dead or unnecessary code removed (or why none was): Removed all duplicated code of components that were swapped with their namehash-ui counterparts.

Cross-Codebase Alignment

  • Search terms used: None (had a look at other apps in our repo, mostly ENSAdmin and of course the namehash-ui and ens-referrals packages)
  • Reviewed but unchanged: apps/ensadmin, packages/ens-referrals, packages/namehash-ui (in ensnode repo, there is a small, separate PR #1552 with a minor refactor)
  • Deferred alignment (with rationale): Unification of tooltip styles across ENSAdmin & ENSAwards (needs @sskvts's help, left related comment as a TODO in packages/namehash-ui/src/components/identity/Identity.tsx:120-121)

Downstream & Consumer Impact

Who this affects and how
  • These changes will affect ENSAward's developers (new dependency, deduplication of code, change of referrers' leaderboard-fetching client), but at the same time shouldn't affect the users (no changes to the UX and UI).
  • Overall, it's a final step to make the UI part of our apps (ENSAdmin, ENSAwards, and co) easier to maintain and faster to develop.
  • No terminology was changed between this PR and changes from ENSAdmin-related PRs
  • Public APIs affected: None (only swapping the clients: ENSNodeClientENSReferralsClient)
  • Docs updated: None (swapping shouldn't affect anything other than the code itself, not even the UI)
  • Naming decisions worth calling out: None

Testing Evidence

  • Testing performed: Run the CI tests and built previews (as per our usual workflow) and tested the UI locally and in the Vercel preview by going through the pages containing swapped components, checking out the layout, and comparing the UI with the current production version of ENSAwards
  • Known gaps: As of yet, we're not using an official namehash-ui package version but the preview one (@next)
  • What reviewers have to reason about manually (and why): I suppose the UI double-check falls into this category.
  • If this is wrong, what breaks first: ENSAwards's UI (some styling errors or layout breaks, although very unlikely) or the fetching of the referrer leaderboards (also low probability).

Scope Reductions

What you intentionally didn't do

No scope reductions.

  • Follow-ups: -
  • Why they were deferred: -

Risk Analysis

How this could go wrong
  • Assumptions this PR relies on: We can use the @next version of the package in the production deployment of ENSAwards (not illegal per se, but against good practices. We could also wait for a new release before merging, but that seems unnecessary).
  • Likely failure modes: Broken ENSAwards UI (some styles not applied, layouts broken → all in all highly unlikely after the testing) or the referrer leaderboards of ENSAwards not showing (a very low probability after testing)
  • Blast radius if it breaks: ENSAwards
  • Risk areas: ENSAwards
  • Mitigations or rollback options: Rollback this PR (reinstate local ensawards components and use older versions of our packages)
  • Named owner if this causes problems: @Y3drk

Pre-Review Checklist (Blocking)

  • I reviewed every line of this diff and understand it end-to-end
  • I'm prepared to defend this PR line-by-line in review
  • I'm comfortable being the on-call owner for this change

@Y3drk Y3drk self-assigned this Jan 19, 2026
Copilot AI review requested due to automatic review settings January 19, 2026 17:48
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Jan 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
ensawards.org Ready Ready Preview, Comment Jan 20, 2026 6:27pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 19, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Removed many local UI primitives, icons, datetime/hooks, identity utilities, cards, footer, and synced-clock code; replaced usages with imports from @namehash/namehash-ui and related packages; added a Sonner Toaster wrapper and updated package dependencies.

Changes

Cohort / File(s) Summary
Dependencies
package.json, pnpm-workspace.yaml
Pin several @ensnode/@namehash packages to pre-release next versions, add @namehash/namehash-ui, @namehash/ens-referrals, sonner, and catalog TypeScript entries.
Layout & Toaster
src/components/ui/sonner.tsx, src/layouts/Layout.astro
Add Toaster wrapper (sonner) and inject <Toaster client:load />; switch Footer import to @namehash/namehash-ui.
Global styles
src/styles/global.css
Replace tw-animate-css import with @namehash/namehash-ui/styles.css; remove local dark-mode overrides.
Icons & primitives
src/components/atoms/icons/*, src/components/atoms/ChainIcon.tsx, src/components/atoms/icons/chains/*
Delete many local icon components and chain icons; call sites now import icons from @namehash/namehash-ui; one rename: ArbitrumIconArbitrumProjectIcon.
Identity & avatar
src/components/atoms/identity/*, src/components/atoms/identity/utils.tsx, src/components/atoms/identity/EnsAvatar.tsx
Remove local identity resolution/display and avatar implementations; callers moved to @namehash/namehash-ui equivalents.
Datetime & clock hooks
src/components/atoms/datetime/*, src/utils/hooks/*, src/utils/syncedClock.ts, src/utils/systemClock.ts, src/utils/synced-clock.test.ts
Remove AbsoluteTime/RelativeTime/DisplayDuration and hooks (useNow, useIsMobile/useSystemClock), synced-clock implementation and tests; replace imports with @namehash/namehash-ui where applicable.
Cards / CopyButton / Footer
src/components/atoms/cards/RegistrarActionCard.tsx, src/components/atoms/CopyButton.tsx, src/components/organisms/Footer.astro
Remove local RegistrarActionCard, CopyButton, Footer; consumers now use RegistrarActionCardMemo/RegistrarActionCardLoading, CopyButton, and Footer from @namehash/namehash-ui.
Registrar feed & referral changes
src/components/referral-awards-program/referrals/DisplayRegistrarActionsFeed.tsx
Swap to external RegistrarActionCardMemo/Loading, pass new links and referralProgramField props, compute referral qualification info and construct internal/external links. Attention: changed control flow and new prop surface on card.
Referrals client swap
src/components/referral-awards-program/referrers/*
Replace ENSNodeClient with ENSReferralsClient and update related types/imports to @namehash/ens-referrals.
Pages & small components
multiple files (examples: EnsManagerAppLink.tsx, ReferralProgramTimeline.tsx, BenchmarkResultBadge.tsx, ReferrerCard.tsx, JoinTelegram.astro, src/pages/*)
Replace many local imports (icons, AbsoluteTime/useNow, identity components, CopyButton, useIsMobile, chain utilities) with @namehash/namehash-ui equivalents; small prop adjustments (icon sizes, tooltip offsets).
Utilities removed / reduced
src/utils/chains.ts, src/utils/namespace.ts
Remove local chain constants and URL builders (SUPPORTED_CHAINS, getChainName, block explorer and ENS manager/profile builders); only DEFAULT_ENS_NAMESPACE retained.
Misc tests/data
src/data/*.test.ts, src/data/projects.ts
Update tests/data imports to external packages for chains/icons; minor adjustments to test imports.
New util
src/utils/index.ts
Add getEnsAwardsBaseUrl() to return document.baseURI in browser or fallback URL on server.

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant Feed as DisplayRegistrarActionsFeed
  participant Referrals as ENSReferralsClient
  participant Utils as getReferralQualificationInfo
  participant Card as RegistrarActionCardMemo

  Browser->>Feed: render DisplayRegistrarActionsFeed
  Feed->>Referrals: fetch registrar actions
  Referrals-->>Feed: actions list
  Feed->>Utils: compute qualification info for action
  Utils-->>Feed: qualification info
  Feed->>Card: render RegistrarActionCardMemo(links, referralProgramField)
  Card-->>Browser: rendered card with links & program info
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

"I nibble through the icon maze,
I swap the clocks for shared displays.
Toasts now pop where footers slept,
Removed old pieces, stitched and kept.
A rabbit cheers the unified ways. 🐇"

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'chore: apply namehash-ui' accurately reflects the main objective of replacing local components with counterparts from the namehash-ui package, though it is concise and doesn't capture the full scope (dependency bumps, Issue #105 resolution).
Description check ✅ Passed The PR description is comprehensive and directly related to the changeset, detailing component swaps, version bumps, and Issue #105 resolution.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch y3drk/chore/apply-namehash-ui

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates the ENSAwards application to use the @namehash/namehash-ui package (v1.5.1), replacing locally implemented UI components and utilities with standardized exports from the shared library. The changes also add the sonner toast notification library as a dependency.

Changes:

  • Added @namehash/namehash-ui (v1.5.1) and sonner (v2.0.7) as dependencies
  • Removed local implementations of common components (icons, datetime utilities, identity displays, chain utilities) in favor of namehash-ui exports
  • Updated imports across the codebase to reference the new package

Reviewed changes

Copilot reviewed 61 out of 62 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
package.json / pnpm-lock.yaml Added namehash-ui and sonner dependencies
ensawards.org/src/styles/global.css Imported namehash-ui styles, removed duplicate dark theme CSS
ensawards.org/src/utils/* Removed local clock, chain, and namespace utilities replaced by package exports
ensawards.org/src/components/atoms/* Removed local icon, datetime, identity components replaced by namehash-ui
ensawards.org/src/components/ui/sonner.tsx Added Toaster component wrapper
ensawards.org/src/layouts/Layout.astro Integrated Toaster component
Various component files Updated imports to use namehash-ui exports
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ensawards.org/src/components/atoms/cards/ReferrerCard.tsx Outdated
Comment thread ensawards.org/src/components/atoms/badges/BenchmarkResultBadge.tsx Outdated
Comment thread ensawards.org/src/components/atoms/EnsManagerAppLink.tsx
Comment thread ensawards.org/src/components/atoms/cards/ReferrerCard.tsx Outdated
Comment thread ensawards.org/src/components/atoms/cards/ReferrerCard.tsx Outdated
Comment thread ensawards.org/src/components/atoms/cards/ReferrerCard.tsx Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ensawards.org/src/pages/mocks/alert-countdown.astro (1)

73-88: Remove extraneous props from AbsoluteTime.

The ctaText and link props (lines 77-78) appear to be copy-paste artifacts from AlertCountdown usage. A datetime formatting component like AbsoluteTime wouldn't use these props. They will either be silently ignored or cause runtime warnings.

Suggested fix
            <AbsoluteTime
              client:load
              timestamp={(Date.now() + 1.75 * millisecondsInMinute) /
                millisecondsInSecond}
-             ctaText="Learn more"
-             link="/ens-referral-awards"
              options={{
                year: "numeric",
                month: "short",
                day: "numeric",
                hour: "numeric",
                minute: "numeric",
                second: "numeric",
                hour12: false,
              }}
            />
🤖 Fix all issues with AI agents
In `@ensawards.org/src/components/atoms/badges/BenchmarkResultBadge.tsx`:
- Around line 36-42: In BenchmarkResultBadge.tsx fix the malformed base passed
to new URL when building identityLinkDetails: replace the string
"https:ensawards.org/" with a proper origin like "https://ensawards.org/" so new
URL(getEnsAdvocateDetailsRelativePath(identity.address),
"https://ensawards.org/") constructs correct absolute links; locate the new URL
invocation inside the identityLinkDetails object and update the base
accordingly.

In `@ensawards.org/src/components/atoms/cards/ContractCard.astro`:
- Around line 58-61: The href prop is being passed the full object returned by
getBlockExplorerAddressDetailsUrl instead of the URL string; update the usage in
ContractCard (where getBlockExplorerAddressDetailsUrl(...) is called) to safely
access the href property with optional chaining (use the returned object's .href
via ?.) so null/unsupported chains are handled and the anchor receives a proper
string or undefined.

In `@ensawards.org/src/components/atoms/cards/ReferrerCard.tsx`:
- Around line 66-72: The base URL string used when constructing
identityLinkDetails is malformed (missing "//"); in ReferrerCard.tsx update the
URL construction that wraps getEnsAdvocateDetailsRelativePath(referrer.referrer)
to use "https://ensawards.org/" instead of "https:ensawards.org/" in all
occurrences (the identityLinkDetails blocks around lines where
getEnsAdvocateDetailsRelativePath is used—e.g., the four instances that build
new URL(..., "https:ensawards.org/")). Ensure each identityLinkDetails.link uses
new URL(getEnsAdvocateDetailsRelativePath(...), "https://ensawards.org/").

In `@ensawards.org/src/components/atoms/ReferralProgramTimeline.tsx`:
- Around line 12-13: There are two separate imports from the same module
(`AbsoluteTime` and `useNow` from "@namehash/namehash-ui"); consolidate them
into a single import statement by replacing the two import lines with one that
imports both symbols (e.g., import { AbsoluteTime, useNow } from
"@namehash/namehash-ui") and remove the duplicate import.

In
`@ensawards.org/src/components/ens-advocates/details-page-components/advocate-profile/AdvocateProfileWithoutName.tsx`:
- Around line 43-45: The anchor href can become undefined because
getBlockExplorerAddressDetailsUrl and getEnsManagerAddressDetailsUrl may return
null; update AdvocateProfileWithoutName.tsx to handle nulls by checking the
result of getBlockExplorerAddressDetailsUrl(getENSRootChainId(namespaceId),
address) and getEnsManagerAddressDetailsUrl(getENSRootChainId(namespaceId),
namespaceId) before using .href — if either returns null, either don't render
the <a> (render plain text or a disabled link with aria-disabled and a
tooltip/message) or render a clear fallback (e.g., "Explorer unavailable") so
users aren’t presented with an anchor without a navigable href; ensure to
reference those functions and the component name when making the change.

In
`@ensawards.org/src/components/referral-awards-program/referrals/DisplayRegistrarActionsFeed.tsx`:
- Around line 61-64: The URL base string in DisplayRegistrarActionsFeed (where
link is constructed with new
URL(getEnsAdvocateDetailsRelativePath(namedRegistrarAction.action.registrant),
"https:ensawards.org/")) is malformed (missing "//"); update the base to a valid
origin such as "https://ensawards.org/" so new URL(...) constructs correctly;
locate the link construction in DisplayRegistrarActionsFeed.tsx (the new URL
call that uses getEnsAdvocateDetailsRelativePath and
namedRegistrarAction.action.registrant) and replace the base string accordingly.
- Line 45: Remove the unnecessary computation of qualifiedReferralPrograms in
DisplayRegistrarActionsFeed.tsx: delete the line that assigns const
qualifiedReferralPrograms = getReferralQualificationInfo(namedRegistrarAction)
and remove the getReferralQualificationInfo import if it’s no longer used, since
referralProgramField logic is not yet active; reintroduce the call only when the
referralProgramField prop and the commented usage are enabled.

In `@ensawards.org/src/components/ui/sonner.tsx`:
- Around line 5-22: The Toaster component spreads {...props} after setting
toastOptions on the Sonner component so a caller-supplied toastOptions will
completely override the default classNames; fix by destructuring props (e.g.,
const { toastOptions: userToastOptions, ...rest } = props) and pass merged
toastOptions to Sonner: merge the top-level toastOptions and deep-merge
classNames (use spreads to combine default classNames with
userToastOptions?.classNames) and then spread ...rest into Sonner so callers can
override other props without clobbering the preset classNames.

In `@ensawards.org/src/utils/chains.ts`:
- Around line 3-4: Update the TODO above the SUPPORTED_CHAINS export to
reference the exact blocking source in `@namehash/namehash-ui`: find the PR number
or the minimum released package version that adds SUPPORTED_CHAINS (e.g., PR
#<number> or vX.Y.Z) and replace the generic TODO with that identifier and a
short action (e.g., "remove when `@namehash/namehash-ui`@vX.Y.Z is released" or
"remove when PR #<number> is merged"); keep the note adjacent to the
SUPPORTED_CHAINS constant so future maintainers know the precise condition for
removal.

In `@ensawards.org/src/utils/hooks/useMobile.tsx`:
- Line 21: Replace the inline TODO in useMobile.tsx (the comment about replacing
after new `@next` version of namehash-ui adding export of useIsMobile) with a
tracked reference: either a link/ID to the issue or PR that will perform the
migration, or a short rationale plus the specific target version that will
remove the TODO; update the comment to include the issue/PR number (or repo URL)
and an expected milestone (e.g., "remove when namehash-ui vX.Y.Z is released")
so the note is actionable and not easily overlooked.

Comment thread ensawards.org/src/components/atoms/badges/BenchmarkResultBadge.tsx
Comment thread ensawards.org/src/components/atoms/cards/ContractCard.astro Outdated
Comment thread ensawards.org/src/components/atoms/cards/ReferrerCard.tsx
Comment thread ensawards.org/src/components/atoms/ReferralProgramTimeline.tsx Outdated
Comment thread ensawards.org/src/components/ui/sonner.tsx
Comment thread ensawards.org/src/utils/chains.ts Outdated
Comment thread ensawards.org/src/utils/hooks/useMobile.tsx Outdated
Comment thread ensawards.org/src/data/contracts.test.ts Fixed
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
ensawards.org/src/components/atoms/ReferralProgramTimeline.tsx (1)

33-36: Missing dependency in useMemo dependency array.

The memoization callback uses both referralProgramRules and now, but only now is listed in the dependency array. If referralProgramRules changes while the component remains mounted, the status will not recalculate, leading to stale UI.

🐛 Proposed fix
   const referralProgramStatus = useMemo(
     () => calcReferralProgramStatus(referralProgramRules, now),
-    [now],
+    [referralProgramRules, now],
   );
ensawards.org/src/components/atoms/badges/BenchmarkResultBadge.tsx (1)

61-63: Remove unused client variable.

The ENSNodeClient instance is created but never referenced in this component. This is dead code left over from refactoring.

♻️ Proposed fix
-const client = new ENSNodeClient({
-  url: getENSNodeUrl(),
-});
-
 const ensNodeReactConfig = createConfig({
   url: getENSNodeUrl(),
 });
ensawards.org/src/components/ens-advocates/details-page-components/advocate-profile/AdvocateProfileWithoutName.tsx (1)

41-70: Add rel="noopener noreferrer" to external links.

Both anchors open new tabs without rel, which enables reverse-tabnabbing.

🔒 Proposed fix
             {address !== null && (
               <a
                 href={
                   getBlockExplorerAddressDetailsUrl(getENSRootChainId(namespaceId), address)?.href
                 }
                 target="_blank"
+                rel="noopener noreferrer"
                 className={cn(
                   shadcnButtonVariants({
                     variant: "secondary",
@@
             <a
               href={getEnsManagerAddressDetailsUrl(address, namespaceId)?.href}
               target="_blank"
+              rel="noopener noreferrer"
               className={cn(
                 shadcnButtonVariants({
                   variant: "default",
ensawards.org/src/components/referral-awards-program/referrals/DisplayRegistrarActionsFeed.tsx (1)

40-69: Centralize the ENS Awards origin to avoid future typos.

The base URL is duplicated; extracting it to a single constant reduces drift and makes updates safer.

♻️ Suggested refactor
 export function DisplayRegistrarActionsList({
   namespaceId,
   registrarActions,
   showReferrer = true,
 }: DisplayRegistrarActionsListProps) {
   const [animationParent] = useAutoAnimate();
   const now = useNow();
+  const ensAwardsOrigin = "https://ensawards.org/";

   return (
     <div
       ref={animationParent}
       className="w-full h-fit box-border flex flex-col justify-start items-center gap-3 relative"
     >
       {registrarActions.map((namedRegistrarAction) => {
         const qualifiedReferralPrograms = getReferralQualificationInfo(namedRegistrarAction);

         return (
           <RegistrarActionCardMemo
             key={namedRegistrarAction.action.id}
             namespaceId={namespaceId}
             namedRegistrarAction={namedRegistrarAction}
             now={now}
             showReferrer={showReferrer}
             links={{
               name: {
                 isExternal: true,
                 link: getEnsManagerNameDetailsUrl(namedRegistrarAction.name, namespaceId),
               },
               registrant: {
                 isExternal: false,
                 link: new URL(
                   getEnsAdvocateDetailsRelativePath(namedRegistrarAction.action.registrant),
-                  "https://ensawards.org/",
+                  ensAwardsOrigin,
                 ),
               },
               referrerLinkFunction: (address, namespaceId) =>
-                new URL(getEnsAdvocateDetailsRelativePath(address), "https://ensawards.org/"),
+                new URL(getEnsAdvocateDetailsRelativePath(address), ensAwardsOrigin),
             }}
🤖 Fix all issues with AI agents
In `@ensawards.org/src/components/atoms/cards/ReferrerCard.tsx`:
- Around line 66-72: The same construction new
URL(getEnsAdvocateDetailsRelativePath(...), "https://ensawards.org/") is
repeated; create a single local constant (e.g., advocateUrl) once at the top of
ReferrerCard's render/functional body using
getEnsAdvocateDetailsRelativePath(referrer.referrer) and reuse that constant for
all identityLinkDetails.link usages (the occurrences around identityLinkDetails,
and the other blocks at the same component: the repeats at the other three
locations). Update references to use advocateUrl instead of recreating the URL
to avoid duplication and extra allocations.

In `@ensawards.org/src/data/contracts.test.ts`:
- Around line 18-19: The import millisecondsInSecond is unused; either remove
the import from contracts.test.ts or replace the hardcoded timeout value 3000
with millisecondsInSecond * 3 (or another appropriate multiplier) where the test
timeout is set (referencing the timeout literal 3000 in the test file), and
ensure any replaced usage updates any related comments or variable names
accordingly.
♻️ Duplicate comments (1)
ensawards.org/src/components/atoms/cards/ContractCard.astro (1)

58-61: Fix correctly applied — ?.href access now in place.

The optional chaining properly extracts the URL string from the returned object, consistent with usage elsewhere in the codebase. Based on learnings, the null case shouldn't occur in practice since ENSAwards only supports chains with block explorers, but this defensive pattern is still appropriate.

Comment thread ensawards.org/src/components/atoms/cards/ReferrerCard.tsx
Comment thread ensawards.org/src/data/contracts.test.ts Outdated
Copilot AI review requested due to automatic review settings January 20, 2026 12:17
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 67 out of 68 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ensawards.org/src/components/atoms/cards/ReferrerCard.tsx
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@ensawards.org/src/components/atoms/cards/ReferrerCard.tsx`:
- Around line 54-57: Refactor the creation of advocateDetailsUrl in
ReferrerCard.tsx to avoid using import.meta.url during SSR: detect runtime
(e.g., typeof window !== 'undefined') and, when client-side, construct the URL
with window.location.origin (or location.href) +
getEnsAdvocateDetailsRelativePath(referrer.referrer); when server-side, use a
safe server base (env-provided SITE_ORIGIN or a relative path string) so
import.meta.url is never used on the server; update the symbol
advocateDetailsUrl and the call to
getEnsAdvocateDetailsRelativePath(referrer.referrer) accordingly and apply the
same pattern to BenchmarkResultBadge.tsx and DisplayRegistrarActionsFeed.tsx.
♻️ Duplicate comments (2)
ensawards.org/src/components/atoms/badges/BenchmarkResultBadge.tsx (1)

36-39: Avoid import.meta.url as the base for internal links.

Using import.meta.url can drop a configured base path and can produce file:// links during SSR/pre-render. Prefer document.baseURI (or a configured site origin) to keep internal links correct across environments.

🛠️ Suggested fix
           identityLinkDetails={{
             isExternal: false,
-            link: new URL(getEnsAdvocateDetailsRelativePath(identity.address), import.meta.url),
+            link: new URL(
+              getEnsAdvocateDetailsRelativePath(identity.address),
+              typeof document !== "undefined" ? document.baseURI : "https://ensawards.org/",
+            ),
           }}
ensawards.org/src/components/referral-awards-program/referrals/DisplayRegistrarActionsFeed.tsx (1)

33-71: import.meta.url can resolve to file/CDN origin; internal links may misroute.

If this renders in SSR or assets are served from a different origin, new URL(..., import.meta.url) can yield file://… or the asset host, sending users to the wrong origin. Prefer a runtime-origin/env base with an SSR-safe fallback and reuse it for both links.

🐛 Proposed fix
   const [animationParent] = useAutoAnimate();
   const now = useNow();
+  const baseOrigin = globalThis.location?.origin ?? "https://ensawards.org";
@@
               registrant: {
                 isExternal: false,
                 link: new URL(
                   getEnsAdvocateDetailsRelativePath(namedRegistrarAction.action.registrant),
-                  import.meta.url,
+                  baseOrigin,
                 ),
               },
               referrer: {
                 isExternal: false,
                 getLink: (address: Address, _namespaceId: ENSNamespaceId) =>
-                  new URL(getEnsAdvocateDetailsRelativePath(address), import.meta.url),
+                  new URL(getEnsAdvocateDetailsRelativePath(address), baseOrigin),
               },

Comment thread ensawards.org/src/components/atoms/cards/ReferrerCard.tsx
Comment thread ensawards.org/src/utils/index.ts Fixed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 68 out of 69 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Y3drk Y3drk marked this pull request as ready for review January 21, 2026 06:54
@Y3drk Y3drk requested a review from a team as a code owner January 21, 2026 06:54
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Jan 21, 2026

Greptile Summary

This PR successfully migrates ENSAwards to use the @namehash/namehash-ui package and resolves Issue #105 by switching from ENSNodeClient to ENSReferralsClient for referral-related queries.

Key Changes:

  • Updated all packages (@ensnode/*, @namehash/ens-referrals) to snapshot version 0.0.0-next-20260120123821
  • Added @namehash/namehash-ui package and replaced local components with their shared counterparts
  • Migrated referral leaderboard queries from ENSNodeClient to ENSReferralsClient in ReferrerLeaderboard.tsx and ReferrerLeaderboardSnippet.tsx
  • Added sonner toast notification library with Toaster component
  • Deleted ~2,530 lines of duplicated code (icons, identity components, datetime utilities, etc.)
  • Added TypeScript to workspace catalog for consistent version management
  • Enhanced components with proper link configuration (identityLinkDetails, internal vs external links)

Implementation Quality:

  • The migration is clean and systematic, following the established pattern from ENSAdmin
  • All import updates are correct and consistent
  • The ENSReferralsClient migration properly addresses the dependency flip from PR #1542
  • Component props are correctly configured with link details for internal navigation
  • Toast notifications are properly integrated for copy actions

Considerations:

  • Uses @next snapshot versions instead of stable releases (acknowledged in PR description as temporary)
  • The getEnsAwardsBaseUrl() fallback is hardcoded which may not work in preview environments

Confidence Score: 4/5

  • This PR is safe to merge with low risk
  • The changes are well-structured and follow established patterns, with proper migration from ENSNodeClient to ENSReferralsClient. The code removal (2,530 lines) indicates successful deduplication. However, the use of snapshot versions (@next) instead of stable releases introduces a minor risk, and the hardcoded fallback URL in getEnsAwardsBaseUrl() could cause issues in non-production environments
  • Pay close attention to ensawards.org/src/utils/index.ts for the base URL fallback implementation

Important Files Changed

Filename Overview
ensawards.org/package.json Updated dependencies to snapshot versions (0.0.0-next-20260120123821) and added @namehash/namehash-ui, sonner, and typescript
ensawards.org/src/components/referral-awards-program/referrers/ReferrerLeaderboard.tsx Correctly migrated from ENSNodeClient to ENSReferralsClient with proper import updates from @namehash/ens-referrals
ensawards.org/src/components/referral-awards-program/referrers/ReferrerLeaderboardSnippet.tsx Correctly migrated from ENSNodeClient to ENSReferralsClient with proper import updates from @namehash/ens-referrals
ensawards.org/src/components/referral-awards-program/referrals/DisplayRegistrarActionsFeed.tsx Migrated to use RegistrarActionCardMemo from @namehash/namehash-ui with proper link configuration and added incentive program field
ensawards.org/src/utils/index.ts Added getEnsAwardsBaseUrl() helper that returns document.baseURI in browser or hardcoded fallback URL
ensawards.org/src/layouts/Layout.astro Migrated Footer from local to @namehash/namehash-ui and added Toaster component for toast notifications

Sequence Diagram

sequenceDiagram
    participant User
    participant ReferrerLeaderboard
    participant ENSReferralsClient
    participant ENSNodeAPI
    participant RegistrarActionsFeed
    participant NamehashUI

    User->>ReferrerLeaderboard: View leaderboard page
    ReferrerLeaderboard->>ENSReferralsClient: new ENSReferralsClient({url})
    ReferrerLeaderboard->>ENSReferralsClient: getReferrerLeaderboardPage({page, recordsPerPage})
    ENSReferralsClient->>ENSNodeAPI: GET /referrer-leaderboard
    ENSNodeAPI-->>ENSReferralsClient: ReferrerLeaderboardPage data
    ENSReferralsClient-->>ReferrerLeaderboard: response with leaderboard data
    ReferrerLeaderboard->>NamehashUI: ResolveAndDisplayIdentity (referrer info)
    NamehashUI-->>ReferrerLeaderboard: Rendered referrer cards

    User->>RegistrarActionsFeed: View registrar actions
    RegistrarActionsFeed->>NamehashUI: RegistrarActionCardMemo (with links config)
    NamehashUI-->>RegistrarActionsFeed: Rendered action cards
    RegistrarActionsFeed->>RegistrarActionsFeed: getReferralQualificationInfo()
    RegistrarActionsFeed->>NamehashUI: LabeledField (incentive program)
    NamehashUI-->>User: Display actions with referral programs
Loading

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

68 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread ensawards.org/src/utils/index.ts
Copy link
Copy Markdown
Member

@lightwalker-eth lightwalker-eth left a comment

Choose a reason for hiding this comment

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

@Y3drk Super work here 🚀

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.

Transition to using new ENSReferralsClient Create new package in ENSNode monorepo: namehash-ui

3 participants