From f79b8d885df7503096cb7475923e65a50996cef1 Mon Sep 17 00:00:00 2001 From: Goader Date: Wed, 15 Apr 2026 23:07:18 +0200 Subject: [PATCH 1/3] docs(changeset): --- .changeset/every-areas-draw.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changeset/every-areas-draw.md diff --git a/.changeset/every-areas-draw.md b/.changeset/every-areas-draw.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/every-areas-draw.md @@ -0,0 +1,2 @@ +--- +--- From b17bea8c10856323660eea72997daf4cad8fb924 Mon Sep 17 00:00:00 2001 From: Goader Date: Thu, 16 Apr 2026 01:43:09 +0200 Subject: [PATCH 2/3] using normalizedaddress in ens-referrals --- .changeset/every-areas-draw.md | 3 +++ packages/ens-referrals/README.md | 2 +- packages/ens-referrals/src/address.ts | 2 +- packages/ens-referrals/src/api/types.ts | 4 ++-- .../ens-referrals/src/award-models/pie-split/leaderboard.ts | 6 +++--- .../src/award-models/rev-share-cap/leaderboard.ts | 2 +- .../ens-referrals/src/award-models/rev-share-cap/rules.ts | 4 ++-- .../src/award-models/shared/leaderboard-page.ts | 4 ++-- packages/ens-referrals/src/leaderboard-page.test.ts | 6 +++--- packages/ens-referrals/src/referrer-metrics.ts | 4 ++-- 10 files changed, 20 insertions(+), 17 deletions(-) diff --git a/.changeset/every-areas-draw.md b/.changeset/every-areas-draw.md index a845151cc8..449d477842 100644 --- a/.changeset/every-areas-draw.md +++ b/.changeset/every-areas-draw.md @@ -1,2 +1,5 @@ --- +"@namehash/ens-referrals": patch --- + +Tighten referral program types to use `NormalizedAddress` instead of `Address` in the remaining public surfaces. No runtime behavior change. diff --git a/packages/ens-referrals/README.md b/packages/ens-referrals/README.md index b0f584d307..394acad876 100644 --- a/packages/ens-referrals/README.md +++ b/packages/ens-referrals/README.md @@ -158,7 +158,7 @@ The package also includes helpers for building referral links. ```typescript import { buildEnsReferralUrl } from "@namehash/ens-referrals"; -import type { Address } from "viem"; +import type { Address } from "enssdk"; const referrerAddress: Address = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; diff --git a/packages/ens-referrals/src/address.ts b/packages/ens-referrals/src/address.ts index 2580243b7a..fb8f6fe042 100644 --- a/packages/ens-referrals/src/address.ts +++ b/packages/ens-referrals/src/address.ts @@ -1,7 +1,7 @@ import type { NormalizedAddress } from "enssdk"; import { isNormalizedAddress } from "enssdk"; -export const validateAddress = (address: NormalizedAddress): void => { +export const validateNormalizedAddress = (address: NormalizedAddress): void => { if (!isNormalizedAddress(address)) { throw new Error(`Invalid address: '${address}'. Address must be a lowercase EVM Address.`); } diff --git a/packages/ens-referrals/src/api/types.ts b/packages/ens-referrals/src/api/types.ts index d23898965d..0a22f238fa 100644 --- a/packages/ens-referrals/src/api/types.ts +++ b/packages/ens-referrals/src/api/types.ts @@ -1,4 +1,4 @@ -import type { Address } from "enssdk"; +import type { NormalizedAddress } from "enssdk"; import type { ReferrerLeaderboardPageParams } from "../award-models/shared/leaderboard-page"; import type { ReferralProgramEditionSlug } from "../edition"; @@ -72,7 +72,7 @@ export const MAX_EDITIONS_PER_REQUEST = 20; */ export interface ReferrerMetricsEditionsRequest { /** The Ethereum address of the referrer to query */ - referrer: Address; + referrer: NormalizedAddress; /** Array of edition slugs to query (min 1, max {@link MAX_EDITIONS_PER_REQUEST}, must be distinct) */ editions: ReferralProgramEditionSlug[]; } diff --git a/packages/ens-referrals/src/award-models/pie-split/leaderboard.ts b/packages/ens-referrals/src/award-models/pie-split/leaderboard.ts index 236894a58c..d1cfb40f64 100644 --- a/packages/ens-referrals/src/award-models/pie-split/leaderboard.ts +++ b/packages/ens-referrals/src/award-models/pie-split/leaderboard.ts @@ -1,4 +1,4 @@ -import type { Address, UnixTimestamp } from "enssdk"; +import type { NormalizedAddress, UnixTimestamp } from "enssdk"; import type { ReferrerMetrics } from "../../referrer-metrics"; import { assertLeaderboardInputs } from "../shared/leaderboard-guards"; @@ -42,13 +42,13 @@ export interface ReferrerLeaderboardPieSplit { * @invariant Map entries are ordered by `rank` (ascending). * @invariant Map is empty if there are no referrers with 1 or more `totalReferrals` * within the `rules` as of `accurateAsOf`. - * @invariant If a fully-lowercase `Address` is not a key in this map then that `Address` had + * @invariant If a `NormalizedAddress` is not a key in this map then that `NormalizedAddress` had * 0 `totalReferrals`, `totalIncrementalDuration`, and `score` within the * `rules` as of `accurateAsOf`. * @invariant Each value in this map is guaranteed to have a non-zero * `totalReferrals`, `totalIncrementalDuration`, and `score`. */ - referrers: Map; + referrers: Map; /** * The {@link UnixTimestamp} of when the data used to build the {@link ReferrerLeaderboardPieSplit} was accurate as of. diff --git a/packages/ens-referrals/src/award-models/rev-share-cap/leaderboard.ts b/packages/ens-referrals/src/award-models/rev-share-cap/leaderboard.ts index 04fdf86a16..e6e0537e26 100644 --- a/packages/ens-referrals/src/award-models/rev-share-cap/leaderboard.ts +++ b/packages/ens-referrals/src/award-models/rev-share-cap/leaderboard.ts @@ -47,7 +47,7 @@ export interface ReferrerLeaderboardRevShareCap { * @invariant Map entries are ordered by `rank` (ascending). * @invariant Map is empty if there are no referrers with 1 or more `totalReferrals` * within the `rules` as of `accurateAsOf`. - * @invariant If a fully-lowercase `Address` is not a key in this map then that `Address` had + * @invariant If a `NormalizedAddress` is not a key in this map then that `NormalizedAddress` had * 0 `totalReferrals`, `totalIncrementalDuration`, and `totalRevenueContribution` within the * `rules` as of `accurateAsOf`. * @invariant Each value in this map is guaranteed to have a non-zero diff --git a/packages/ens-referrals/src/award-models/rev-share-cap/rules.ts b/packages/ens-referrals/src/award-models/rev-share-cap/rules.ts index 2781a15cc2..d78e34d34d 100644 --- a/packages/ens-referrals/src/award-models/rev-share-cap/rules.ts +++ b/packages/ens-referrals/src/award-models/rev-share-cap/rules.ts @@ -3,7 +3,7 @@ import type { AccountId, NormalizedAddress, UnixTimestamp } from "enssdk"; import type { PriceUsdc } from "@ensnode/ensnode-sdk"; import { makePriceUsdcSchema } from "@ensnode/ensnode-sdk/internal"; -import { validateAddress } from "../../address"; +import { validateNormalizedAddress } from "../../address"; import { type BaseReferralProgramRules, ReferralProgramAwardModels, @@ -102,7 +102,7 @@ export const validateReferralProgramRulesRevShareCap = ( } for (const d of rules.disqualifications) { - validateAddress(d.referrer); + validateNormalizedAddress(d.referrer); if (d.reason.trim().length === 0) { throw new Error( "ReferralProgramRulesRevShareCap: disqualification reason must not be empty.", diff --git a/packages/ens-referrals/src/award-models/shared/leaderboard-page.ts b/packages/ens-referrals/src/award-models/shared/leaderboard-page.ts index da5fb662e7..72a436223c 100644 --- a/packages/ens-referrals/src/award-models/shared/leaderboard-page.ts +++ b/packages/ens-referrals/src/award-models/shared/leaderboard-page.ts @@ -1,4 +1,4 @@ -import type { Address, UnixTimestamp } from "enssdk"; +import type { NormalizedAddress, UnixTimestamp } from "enssdk"; import type { ReferrerLeaderboard } from "../../leaderboard"; import { isNonNegativeInteger, isPositiveInteger } from "../../number"; @@ -309,7 +309,7 @@ export interface ReferrerLeaderboardPageUnrecognized extends BaseReferrerLeaderb * Generic over the referrer type so each model variant retains its specific type. */ export function sliceReferrers( - referrers: Map, + referrers: Map, pageContext: ReferrerLeaderboardPageContext, ): T[] { // pageContext invariants: startIndex and endIndex are defined iff totalRecords > 0 diff --git a/packages/ens-referrals/src/leaderboard-page.test.ts b/packages/ens-referrals/src/leaderboard-page.test.ts index 98c71e724c..df902cc168 100644 --- a/packages/ens-referrals/src/leaderboard-page.test.ts +++ b/packages/ens-referrals/src/leaderboard-page.test.ts @@ -1,4 +1,4 @@ -import type { Address } from "enssdk"; +import type { NormalizedAddress } from "enssdk"; import { describe, expect, it, vi } from "vitest"; import { priceEth, priceUsdc } from "@ensnode/ensnode-sdk"; @@ -41,7 +41,7 @@ describe("buildReferrerLeaderboardPageContext", () => { grandTotalQualifiedReferrersFinalScore: 28.05273061366773, minFinalScoreToQualify: 0, }, - referrers: new Map([ + referrers: new Map([ [ "0x03c098d2bed4609e6ed9beb2c4877741f45f290d", { @@ -130,7 +130,7 @@ describe("buildReferrerLeaderboardPageContext", () => { grandTotalQualifiedReferrersFinalScore: 28.05273061366773, minFinalScoreToQualify: 0, }, - referrers: new Map(), + referrers: new Map(), accurateAsOf: 1764580368, }; diff --git a/packages/ens-referrals/src/referrer-metrics.ts b/packages/ens-referrals/src/referrer-metrics.ts index 56cd2381e4..111e099168 100644 --- a/packages/ens-referrals/src/referrer-metrics.ts +++ b/packages/ens-referrals/src/referrer-metrics.ts @@ -3,7 +3,7 @@ import type { Duration, NormalizedAddress } from "enssdk"; import type { PriceEth } from "@ensnode/ensnode-sdk"; import { makePriceEthSchema } from "@ensnode/ensnode-sdk/internal"; -import { validateAddress } from "./address"; +import { validateNormalizedAddress } from "./address"; import { validateNonNegativeInteger } from "./number"; import { ReferralProgramRules } from "./rules"; import { validateDuration } from "./time"; @@ -60,7 +60,7 @@ export const buildReferrerMetrics = ( }; export const validateReferrerMetrics = (metrics: ReferrerMetrics): void => { - validateAddress(metrics.referrer); + validateNormalizedAddress(metrics.referrer); validateNonNegativeInteger(metrics.totalReferrals); validateDuration(metrics.totalIncrementalDuration); From d9ba3d6bad84996f48771a6b747096d902af25e8 Mon Sep 17 00:00:00 2001 From: Goader Date: Thu, 16 Apr 2026 02:23:25 +0200 Subject: [PATCH 3/3] review --- .changeset/every-areas-draw.md | 2 +- packages/ens-referrals/src/api/types.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.changeset/every-areas-draw.md b/.changeset/every-areas-draw.md index 449d477842..8c6b9fa03c 100644 --- a/.changeset/every-areas-draw.md +++ b/.changeset/every-areas-draw.md @@ -2,4 +2,4 @@ "@namehash/ens-referrals": patch --- -Tighten referral program types to use `NormalizedAddress` instead of `Address` in the remaining public surfaces. No runtime behavior change. +Tighten referral program types to use `NormalizedAddress` instead of `Address` in internal leaderboard map keys (pie-split, shared `sliceReferrers`) and related JSDoc. No runtime behavior change. diff --git a/packages/ens-referrals/src/api/types.ts b/packages/ens-referrals/src/api/types.ts index 0a22f238fa..d23898965d 100644 --- a/packages/ens-referrals/src/api/types.ts +++ b/packages/ens-referrals/src/api/types.ts @@ -1,4 +1,4 @@ -import type { NormalizedAddress } from "enssdk"; +import type { Address } from "enssdk"; import type { ReferrerLeaderboardPageParams } from "../award-models/shared/leaderboard-page"; import type { ReferralProgramEditionSlug } from "../edition"; @@ -72,7 +72,7 @@ export const MAX_EDITIONS_PER_REQUEST = 20; */ export interface ReferrerMetricsEditionsRequest { /** The Ethereum address of the referrer to query */ - referrer: NormalizedAddress; + referrer: Address; /** Array of edition slugs to query (min 1, max {@link MAX_EDITIONS_PER_REQUEST}, must be distinct) */ editions: ReferralProgramEditionSlug[]; }