@namehash/ens-referrals 1.8.1 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -14
- package/dist/index.cjs +2360 -828
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1525 -426
- package/dist/index.d.ts +1525 -426
- package/dist/index.js +2347 -825
- package/dist/index.js.map +1 -1
- package/package.json +4 -13
- package/dist/v1/index.cjs +0 -20902
- package/dist/v1/index.cjs.map +0 -1
- package/dist/v1/index.d.cts +0 -2098
- package/dist/v1/index.d.ts +0 -2098
- package/dist/v1/index.js +0 -20879
- package/dist/v1/index.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/address.ts","../src/number.ts","../src/revenue-contribution.ts","../src/time.ts","../src/score.ts","../src/aggregations.ts","../src/api/deserialize.ts","../src/api/zod-schemas.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/spec.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/utils.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/chain.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/account.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/assetName.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/assetType.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/assetId.ts","../../ensnode-sdk/src/shared/zod-schemas.ts","../../ensnode-sdk/src/shared/address.ts","../src/leaderboard-page.ts","../src/rank.ts","../src/referrer-metrics.ts","../src/referrer-detail.ts","../src/api/types.ts","../src/api/serialize.ts","../src/client.ts","../src/currency.ts","../src/leaderboard.ts","../src/link.ts","../src/rules.ts","../src/status.ts"],"sourcesContent":["import { type Address, isAddress } from \"viem\";\n\nexport const validateLowercaseAddress = (address: Address): void => {\n if (!isAddress(address, { strict: false })) {\n throw new Error(`Invalid address: ${address}. Address must be a valid EVM address.`);\n }\n\n if (address !== address.toLowerCase()) {\n throw new Error(`Invalid address: ${address}. Address must be in lowercase format.`);\n }\n};\n\nexport const normalizeAddress = (address: Address): Address => {\n return address.toLowerCase() as Address;\n};\n","export const isInteger = (value: number): boolean => {\n return Number.isInteger(value);\n};\n\nexport const isNonNegativeInteger = (value: number): boolean => {\n return value >= 0 && Number.isInteger(value);\n};\n\nexport const isPositiveInteger = (value: number): boolean => {\n return value >= 1 && Number.isInteger(value);\n};\n\nexport const validateNonNegativeInteger = (value: number): void => {\n if (!isNonNegativeInteger(value)) {\n throw new Error(`Invalid non-negative integer: ${value}.`);\n }\n};\n\nexport const isFiniteNonNegativeNumber = (value: number): boolean => {\n return value >= 0 && Number.isFinite(value);\n};\n","/**\n * Revenue Contribution\n *\n * Represents the total revenue contribution (in Wei) made to the ENS DAO.\n *\n * This is the sum of the total cost paid by registrants for registrar actions.\n * From the perspective of the ENS DAO, this represents revenue received.\n *\n * @invariant Guaranteed to be a non-negative bigint value (>= 0n)\n * @invariant Never null (records with null `total` in the database are treated as 0 when summing)\n */\nexport type RevenueContribution = bigint;\n\n/**\n * Check if a value is a valid revenue contribution.\n *\n * @param value - The value to check\n * @returns true if the value is a non-negative bigint, false otherwise\n */\nexport function isValidRevenueContribution(value: unknown): value is RevenueContribution {\n return typeof value === \"bigint\" && value >= 0n;\n}\n\n/**\n * Validate that a value is a valid revenue contribution.\n *\n * @param value - The value to validate\n * @throws {Error} If the value is not a valid revenue contribution\n */\nexport function validateRevenueContribution(value: unknown): void {\n if (typeof value !== \"bigint\") {\n throw new Error(`Invalid revenue contribution: must be a bigint, got: ${typeof value}`);\n }\n\n if (value < 0n) {\n throw new Error(`Invalid revenue contribution: must be non-negative, got: ${value.toString()}`);\n }\n}\n","import type { Duration, UnixTimestamp } from \"@ensnode/ensnode-sdk\";\n\nimport { isInteger, isNonNegativeInteger } from \"./number\";\n\nexport const validateUnixTimestamp = (timestamp: UnixTimestamp): void => {\n if (!isInteger(timestamp)) {\n throw new Error(`Invalid Unix timestamp: ${timestamp}. Unix timestamp must be an integer.`);\n }\n};\n\n/**\n * The number of seconds in a year.\n *\n * (60 seconds per minute * 60 minutes per hour *\n * 24 hours per day * 365.2425 days on average per year).\n */\nexport const SECONDS_PER_YEAR: Duration = 31556952;\n\nexport function isValidDuration(duration: Duration): boolean {\n return isNonNegativeInteger(duration);\n}\n\nexport function validateDuration(duration: Duration): void {\n if (!isValidDuration(duration)) {\n throw new Error(`Invalid duration: ${duration}. Duration must be a non-negative integer.`);\n }\n}\n","import type { Duration } from \"@ensnode/ensnode-sdk\";\n\nimport { SECONDS_PER_YEAR } from \"./time\";\n\n/**\n * The score of a referrer.\n *\n * @invariant Guaranteed to be a finite non-negative number (>= 0)\n */\nexport type ReferrerScore = number;\n\nexport const isValidReferrerScore = (score: ReferrerScore): boolean => {\n return score >= 0 && Number.isFinite(score);\n};\n\nexport const validateReferrerScore = (score: ReferrerScore): void => {\n if (!isValidReferrerScore(score)) {\n throw new Error(\n `Invalid referrer score: ${score}. Referrer score must be a finite non-negative number.`,\n );\n }\n};\n\n/**\n * Calculate the score of a referrer based on the total incremental duration\n * (in seconds) of registrations and renewals for direct subnames of .eth\n * referred by the referrer within the ENS Holiday Awards period.\n *\n * @param totalIncrementalDuration - The total incremental duration (in seconds)\n * of referrals made by a referrer within the {@link ReferralProgramRules}.\n * @returns The score of the referrer.\n */\nexport const calcReferrerScore = (totalIncrementalDuration: Duration): ReferrerScore => {\n return totalIncrementalDuration / SECONDS_PER_YEAR;\n};\n","import type { Duration } from \"@ensnode/ensnode-sdk\";\n\nimport { validateNonNegativeInteger } from \"./number\";\nimport type { RankedReferrerMetrics } from \"./referrer-metrics\";\nimport type { RevenueContribution } from \"./revenue-contribution\";\nimport { validateRevenueContribution } from \"./revenue-contribution\";\nimport type { ReferralProgramRules } from \"./rules\";\nimport { type ReferrerScore, validateReferrerScore } from \"./score\";\nimport { validateDuration } from \"./time\";\n\n/**\n * Represents aggregated metrics for a list of `RankedReferrerMetrics`.\n */\nexport interface AggregatedReferrerMetrics {\n /**\n * @invariant The sum of `totalReferrals` across all `RankedReferrerMetrics` in the list.\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n grandTotalReferrals: number;\n\n /**\n * @invariant The sum of `totalIncrementalDuration` across all `RankedReferrerMetrics` in the list.\n */\n grandTotalIncrementalDuration: Duration;\n\n /**\n * The total revenue contribution (in Wei) to the ENS DAO from all referrals\n * across all referrers on the leaderboard.\n *\n * This is the sum of `totalRevenueContribution` across all `RankedReferrerMetrics` in the list.\n *\n * @invariant Guaranteed to be a non-negative bigint value (>= 0n)\n */\n grandTotalRevenueContribution: RevenueContribution;\n\n /**\n * @invariant The sum of `finalScore` across all `RankedReferrerMetrics` where `isQualified` is `true`.\n */\n grandTotalQualifiedReferrersFinalScore: ReferrerScore;\n\n /**\n * @invariant Identifies the minimum final score required to become a qualified referrer.\n * @invariant If `rules.maxQualifiedReferrers` is 0, then `minFinalScoreToQualify` is guaranteed to\n * be `Number.MAX_SAFE_INTEGER`.\n * @invariant If `rules.maxQualifiedReferrers` is greater than 0, and there are no current referrers\n * matching the `rules`, then `minFinalScoreToQualify` is guaranteed to be `0`.\n */\n minFinalScoreToQualify: ReferrerScore;\n}\n\nexport const validateAggregatedReferrerMetrics = (metrics: AggregatedReferrerMetrics): void => {\n validateNonNegativeInteger(metrics.grandTotalReferrals);\n validateDuration(metrics.grandTotalIncrementalDuration);\n validateRevenueContribution(metrics.grandTotalRevenueContribution);\n validateReferrerScore(metrics.grandTotalQualifiedReferrersFinalScore);\n validateReferrerScore(metrics.minFinalScoreToQualify);\n};\n\nexport const buildAggregatedReferrerMetrics = (\n referrers: RankedReferrerMetrics[],\n rules: ReferralProgramRules,\n): AggregatedReferrerMetrics => {\n let grandTotalReferrals = 0;\n let grandTotalIncrementalDuration = 0;\n let grandTotalRevenueContribution = 0n;\n let grandTotalQualifiedReferrersFinalScore = 0;\n let minFinalScoreToQualify = Number.MAX_SAFE_INTEGER;\n\n for (const referrer of referrers) {\n grandTotalReferrals += referrer.totalReferrals;\n grandTotalIncrementalDuration += referrer.totalIncrementalDuration;\n grandTotalRevenueContribution += referrer.totalRevenueContribution;\n if (referrer.isQualified) {\n grandTotalQualifiedReferrersFinalScore += referrer.finalScore;\n if (referrer.finalScore < minFinalScoreToQualify) {\n minFinalScoreToQualify = referrer.finalScore;\n }\n }\n }\n\n if (minFinalScoreToQualify === Number.MAX_SAFE_INTEGER) {\n if (rules.maxQualifiedReferrers === 0) {\n // ... because it's impossible to qualify based on the rules\n // therefore keep minFinalScoreToQualify as Number.MAX_SAFE_INTEGER\n } else {\n // ... because there are no referrers at all on the leaderboard\n if (referrers.length !== 0) {\n // invariant sanity check\n throw new Error(\n \"AggregatedReferrerMetrics: There are referrers on the leaderboard, and the rules allow for qualified referrers, but no qualified referrers.\",\n );\n }\n\n minFinalScoreToQualify = 0;\n }\n }\n\n const result = {\n grandTotalReferrals,\n grandTotalIncrementalDuration,\n grandTotalRevenueContribution,\n grandTotalQualifiedReferrersFinalScore,\n minFinalScoreToQualify,\n };\n\n validateAggregatedReferrerMetrics(result);\n\n return result;\n};\n","import { prettifyError } from \"zod/v4\";\n\nimport type { AggregatedReferrerMetrics } from \"../aggregations\";\nimport type { ReferrerLeaderboardPage } from \"../leaderboard-page\";\nimport type { ReferrerDetailRanked, ReferrerDetailUnranked } from \"../referrer-detail\";\nimport type { AwardedReferrerMetrics, UnrankedReferrerMetrics } from \"../referrer-metrics\";\nimport type { RevenueContribution } from \"../revenue-contribution\";\nimport type { ReferralProgramRules } from \"../rules\";\nimport type {\n SerializedAggregatedReferrerMetrics,\n SerializedAwardedReferrerMetrics,\n SerializedReferralProgramRules,\n SerializedReferrerDetailRanked,\n SerializedReferrerDetailResponse,\n SerializedReferrerDetailUnranked,\n SerializedReferrerLeaderboardPage,\n SerializedReferrerLeaderboardPageResponse,\n SerializedUnrankedReferrerMetrics,\n} from \"./serialized-types\";\nimport type { ReferrerDetailResponse, ReferrerLeaderboardPageResponse } from \"./types\";\nimport {\n makeReferrerDetailResponseSchema,\n makeReferrerLeaderboardPageResponseSchema,\n} from \"./zod-schemas\";\n\n/**\n * Deserializes a string representation of {@link RevenueContribution} back to bigint.\n */\nfunction deserializeRevenueContribution(value: string): RevenueContribution {\n return BigInt(value);\n}\n\n/**\n * Deserializes a {@link SerializedReferralProgramRules} object.\n */\nfunction deserializeReferralProgramRules(\n rules: SerializedReferralProgramRules,\n): ReferralProgramRules {\n // All fields are already deserializable primitives\n return rules;\n}\n\n/**\n * Deserializes an {@link SerializedAwardedReferrerMetrics} object.\n */\nfunction deserializeAwardedReferrerMetrics(\n metrics: SerializedAwardedReferrerMetrics,\n): AwardedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: deserializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Deserializes an {@link SerializedUnrankedReferrerMetrics} object.\n */\nfunction deserializeUnrankedReferrerMetrics(\n metrics: SerializedUnrankedReferrerMetrics,\n): UnrankedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: deserializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Deserializes an {@link SerializedAggregatedReferrerMetrics} object.\n */\nfunction deserializeAggregatedReferrerMetrics(\n metrics: SerializedAggregatedReferrerMetrics,\n): AggregatedReferrerMetrics {\n return {\n grandTotalReferrals: metrics.grandTotalReferrals,\n grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,\n grandTotalRevenueContribution: deserializeRevenueContribution(\n metrics.grandTotalRevenueContribution,\n ),\n grandTotalQualifiedReferrersFinalScore: metrics.grandTotalQualifiedReferrersFinalScore,\n minFinalScoreToQualify: metrics.minFinalScoreToQualify,\n };\n}\n\n/**\n * Deserializes a {@link SerializedReferrerLeaderboardPage} object.\n */\nfunction deserializeReferrerLeaderboardPage(\n page: SerializedReferrerLeaderboardPage,\n): ReferrerLeaderboardPage {\n return {\n rules: deserializeReferralProgramRules(page.rules),\n referrers: page.referrers.map(deserializeAwardedReferrerMetrics),\n aggregatedMetrics: deserializeAggregatedReferrerMetrics(page.aggregatedMetrics),\n pageContext: page.pageContext,\n accurateAsOf: page.accurateAsOf,\n };\n}\n\n/**\n * Deserializes a {@link SerializedReferrerDetailRanked} object.\n */\nfunction deserializeReferrerDetailRanked(\n detail: SerializedReferrerDetailRanked,\n): ReferrerDetailRanked {\n return {\n type: detail.type,\n rules: deserializeReferralProgramRules(detail.rules),\n referrer: deserializeAwardedReferrerMetrics(detail.referrer),\n aggregatedMetrics: deserializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Deserializes a {@link SerializedReferrerDetailUnranked} object.\n */\nfunction deserializeReferrerDetailUnranked(\n detail: SerializedReferrerDetailUnranked,\n): ReferrerDetailUnranked {\n return {\n type: detail.type,\n rules: deserializeReferralProgramRules(detail.rules),\n referrer: deserializeUnrankedReferrerMetrics(detail.referrer),\n aggregatedMetrics: deserializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Deserialize a {@link ReferrerLeaderboardPageResponse} object.\n *\n * Note: This function explicitly deserializes each subobject to convert string\n * RevenueContribution values back to bigint, then validates using Zod schemas\n * to enforce invariants on the data.\n */\nexport function deserializeReferrerLeaderboardPageResponse(\n maybeResponse: SerializedReferrerLeaderboardPageResponse,\n valueLabel?: string,\n): ReferrerLeaderboardPageResponse {\n let deserialized: ReferrerLeaderboardPageResponse;\n switch (maybeResponse.responseCode) {\n case \"ok\": {\n deserialized = {\n responseCode: maybeResponse.responseCode,\n data: deserializeReferrerLeaderboardPage(maybeResponse.data),\n } as ReferrerLeaderboardPageResponse;\n break;\n }\n\n case \"error\":\n deserialized = maybeResponse;\n break;\n }\n\n // Then validate the deserialized structure using zod schemas\n const schema = makeReferrerLeaderboardPageResponseSchema(valueLabel);\n const parsed = schema.safeParse(deserialized);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize SerializedReferrerLeaderboardPageResponse:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserialize a {@link ReferrerDetailResponse} object.\n *\n * Note: This function explicitly deserializes each subobject to convert string\n * RevenueContribution values back to bigint, then validates using Zod schemas\n * to enforce invariants on the data.\n */\nexport function deserializeReferrerDetailResponse(\n maybeResponse: SerializedReferrerDetailResponse,\n valueLabel?: string,\n): ReferrerDetailResponse {\n let deserialized: ReferrerDetailResponse;\n switch (maybeResponse.responseCode) {\n case \"ok\": {\n switch (maybeResponse.data.type) {\n case \"ranked\":\n deserialized = {\n responseCode: maybeResponse.responseCode,\n data: deserializeReferrerDetailRanked(maybeResponse.data),\n } as ReferrerDetailResponse;\n break;\n\n case \"unranked\":\n deserialized = {\n responseCode: maybeResponse.responseCode,\n data: deserializeReferrerDetailUnranked(maybeResponse.data),\n } as ReferrerDetailResponse;\n break;\n }\n break;\n }\n\n case \"error\":\n deserialized = maybeResponse;\n break;\n }\n\n // Then validate the deserialized structure using zod schemas\n const schema = makeReferrerDetailResponseSchema(valueLabel);\n const parsed = schema.safeParse(deserialized);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize ReferrerDetailResponse:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\n\nimport { z } from \"zod/v4\";\n\nimport {\n makeAccountIdSchema,\n makeDurationSchema,\n makeFiniteNonNegativeNumberSchema,\n makeLowercaseAddressSchema,\n makeNonNegativeIntegerSchema,\n makePositiveIntegerSchema,\n makeUnixTimestampSchema,\n} from \"@ensnode/ensnode-sdk/internal\";\n\nimport { REFERRERS_PER_LEADERBOARD_PAGE_MAX } from \"../leaderboard-page\";\nimport { type ReferrerDetailRanked, ReferrerDetailTypeIds } from \"../referrer-detail\";\nimport type { RevenueContribution } from \"../revenue-contribution\";\nimport { ReferrerDetailResponseCodes, ReferrerLeaderboardPageResponseCodes } from \"./types\";\n\n/**\n * Schema for {@link RevenueContribution}\n */\nconst makeRevenueContributionSchema = (valueLabel: string = \"RevenueContribution\") =>\n z.coerce\n .bigint({\n error: `${valueLabel} must represent a bigint.`,\n })\n .nonnegative({\n error: `${valueLabel} must not be negative.`,\n });\n\n/**\n * Schema for ReferralProgramRules\n */\nexport const makeReferralProgramRulesSchema = (valueLabel: string = \"ReferralProgramRules\") =>\n z.object({\n totalAwardPoolValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.totalAwardPoolValue`),\n maxQualifiedReferrers: makeNonNegativeIntegerSchema(`${valueLabel}.maxQualifiedReferrers`),\n startTime: makeUnixTimestampSchema(`${valueLabel}.startTime`),\n endTime: makeUnixTimestampSchema(`${valueLabel}.endTime`),\n subregistryId: makeAccountIdSchema(`${valueLabel}.subregistryId`),\n });\n\n/**\n * Schema for AwardedReferrerMetrics (with numeric rank)\n */\nexport const makeAwardedReferrerMetricsSchema = (valueLabel: string = \"AwardedReferrerMetrics\") =>\n z.object({\n referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),\n totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),\n totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),\n totalRevenueContribution: makeRevenueContributionSchema(\n `${valueLabel}.totalRevenueContribution`,\n ),\n score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),\n rank: makePositiveIntegerSchema(`${valueLabel}.rank`),\n isQualified: z.boolean(),\n finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(\n 1,\n `${valueLabel}.finalScoreBoost must be <= 1`,\n ),\n finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),\n awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(\n 1,\n `${valueLabel}.awardPoolShare must be <= 1`,\n ),\n awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`),\n });\n\n/**\n * Schema for UnrankedReferrerMetrics (with null rank)\n */\nexport const makeUnrankedReferrerMetricsSchema = (valueLabel: string = \"UnrankedReferrerMetrics\") =>\n z.object({\n referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),\n totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),\n totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),\n totalRevenueContribution: makeRevenueContributionSchema(\n `${valueLabel}.totalRevenueContribution`,\n ),\n score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),\n rank: z.null(),\n isQualified: z.literal(false),\n finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(\n 1,\n `${valueLabel}.finalScoreBoost must be <= 1`,\n ),\n finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),\n awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(\n 1,\n `${valueLabel}.awardPoolShare must be <= 1`,\n ),\n awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`),\n });\n\n/**\n * Schema for AggregatedReferrerMetrics\n */\nexport const makeAggregatedReferrerMetricsSchema = (\n valueLabel: string = \"AggregatedReferrerMetrics\",\n) =>\n z.object({\n grandTotalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.grandTotalReferrals`),\n grandTotalIncrementalDuration: makeDurationSchema(\n `${valueLabel}.grandTotalIncrementalDuration`,\n ),\n grandTotalRevenueContribution: makeRevenueContributionSchema(\n `${valueLabel}.grandTotalRevenueContribution`,\n ),\n grandTotalQualifiedReferrersFinalScore: makeFiniteNonNegativeNumberSchema(\n `${valueLabel}.grandTotalQualifiedReferrersFinalScore`,\n ),\n minFinalScoreToQualify: makeFiniteNonNegativeNumberSchema(\n `${valueLabel}.minFinalScoreToQualify`,\n ),\n });\n\nexport const makeReferrerLeaderboardPageContextSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageContext\",\n) =>\n z.object({\n page: makePositiveIntegerSchema(`${valueLabel}.page`),\n recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(\n REFERRERS_PER_LEADERBOARD_PAGE_MAX,\n `${valueLabel}.recordsPerPage must not exceed ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}`,\n ),\n totalRecords: makeNonNegativeIntegerSchema(`${valueLabel}.totalRecords`),\n totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),\n hasNext: z.boolean(),\n hasPrev: z.boolean(),\n startIndex: z.optional(makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`)),\n endIndex: z.optional(makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`)),\n });\n\n/**\n * Schema for ReferrerLeaderboardPage\n */\nexport const makeReferrerLeaderboardPageSchema = (valueLabel: string = \"ReferrerLeaderboardPage\") =>\n z.object({\n rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),\n referrers: z.array(makeAwardedReferrerMetricsSchema(`${valueLabel}.referrers[record]`)),\n aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),\n pageContext: makeReferrerLeaderboardPageContextSchema(`${valueLabel}.pageContext`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponseOk}\n */\nexport const makeReferrerLeaderboardPageResponseOkSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageResponseOk\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerLeaderboardPageResponseCodes.Ok),\n data: makeReferrerLeaderboardPageSchema(`${valueLabel}.data`),\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponseError}\n */\nexport const makeReferrerLeaderboardPageResponseErrorSchema = (\n _valueLabel: string = \"ReferrerLeaderboardPageResponseError\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerLeaderboardPageResponseCodes.Error),\n error: z.string(),\n errorMessage: z.string(),\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponse}\n */\nexport const makeReferrerLeaderboardPageResponseSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageResponse\",\n) =>\n z.union([\n makeReferrerLeaderboardPageResponseOkSchema(valueLabel),\n makeReferrerLeaderboardPageResponseErrorSchema(valueLabel),\n ]);\n\n/**\n * Schema for {@link ReferrerDetailRanked} (with ranked metrics)\n */\nexport const makeReferrerDetailRankedSchema = (valueLabel: string = \"ReferrerDetailRanked\") =>\n z.object({\n type: z.literal(ReferrerDetailTypeIds.Ranked),\n rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),\n referrer: makeAwardedReferrerMetricsSchema(`${valueLabel}.referrer`),\n aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n });\n\n/**\n * Schema for {@link ReferrerDetailUnranked} (with unranked metrics)\n */\nexport const makeReferrerDetailUnrankedSchema = (valueLabel: string = \"ReferrerDetailUnranked\") =>\n z.object({\n type: z.literal(ReferrerDetailTypeIds.Unranked),\n rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),\n referrer: makeUnrankedReferrerMetricsSchema(`${valueLabel}.referrer`),\n aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n });\n\n/**\n * Schema for {@link ReferrerDetailResponseOk}\n * Accepts either ranked or unranked referrer detail data\n */\nexport const makeReferrerDetailResponseOkSchema = (valueLabel: string = \"ReferrerDetailResponse\") =>\n z.object({\n responseCode: z.literal(ReferrerDetailResponseCodes.Ok),\n data: z.union([\n makeReferrerDetailRankedSchema(`${valueLabel}.data`),\n makeReferrerDetailUnrankedSchema(`${valueLabel}.data`),\n ]),\n });\n\n/**\n * Schema for {@link ReferrerDetailResponseError}\n */\nexport const makeReferrerDetailResponseErrorSchema = (\n _valueLabel: string = \"ReferrerDetailResponse\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerDetailResponseCodes.Error),\n error: z.string(),\n errorMessage: z.string(),\n });\n\n/**\n * Schema for {@link ReferrerDetailResponse}\n */\nexport const makeReferrerDetailResponseSchema = (valueLabel: string = \"ReferrerDetailResponse\") =>\n z.union([\n makeReferrerDetailResponseOkSchema(valueLabel),\n makeReferrerDetailResponseErrorSchema(valueLabel),\n ]);\n","import { IdentifierSpec } from \"./types\";\n\nconst CAIP2: IdentifierSpec = {\n name: \"chainId\",\n regex: \"[-:a-zA-Z0-9]{5,41}\",\n parameters: {\n delimiter: \":\",\n values: {\n 0: {\n name: \"namespace\",\n regex: \"[-a-z0-9]{3,8}\",\n },\n 1: {\n name: \"reference\",\n regex: \"[-a-zA-Z0-9]{1,32}\",\n },\n },\n },\n};\n\nconst CAIP10: IdentifierSpec = {\n name: \"accountId\",\n regex: \"[-:a-zA-Z0-9]{7,106}\",\n parameters: {\n delimiter: \":\",\n values: {\n 0: {\n name: \"namespace\",\n regex: \"[-a-z0-9]{3,8}\",\n },\n 1: {\n name: \"reference\",\n regex: \"[-a-zA-Z0-9]{1,32}\",\n },\n 2: {\n name: \"address\",\n regex: \"[a-zA-Z0-9]{1,64}\",\n },\n },\n },\n};\n\n// represents namespace:reference in CAIP-19\nconst AssetName: IdentifierSpec = {\n name: \"assetName\",\n regex: \"[-:a-zA-Z0-9]{5,73}\",\n parameters: {\n delimiter: \":\",\n values: {\n 0: {\n name: \"namespace\",\n regex: \"[-a-z0-9]{3,8}\",\n },\n 1: {\n name: \"reference\",\n regex: \"[-a-zA-Z0-9]{1,64}\",\n },\n },\n },\n};\n\nconst CAIP19AssetType: IdentifierSpec = {\n name: \"assetType\",\n regex: \"[-:a-zA-Z0-9]{11,115}\",\n parameters: {\n delimiter: \"/\",\n values: {\n 0: CAIP2,\n 1: AssetName,\n },\n },\n};\n\nconst CAIP19AssetId: IdentifierSpec = {\n name: \"assetId\",\n regex: \"[-:a-zA-Z0-9]{13,148}\",\n parameters: {\n delimiter: \"/\",\n values: {\n 0: CAIP2,\n 1: AssetName,\n 2: {\n name: \"tokenId\",\n regex: \"[-a-zA-Z0-9]{1,32}\",\n },\n },\n },\n};\n\nexport const CAIP = {\n \"2\": CAIP2,\n \"10\": CAIP10,\n \"19\": {\n assetName: AssetName,\n assetType: CAIP19AssetType,\n assetId: CAIP19AssetId,\n },\n};\n","import { IdentifierSpec, Params } from \"./types\";\n\nexport function splitParams(id: string, spec: IdentifierSpec): string[] {\n return id.split(spec.parameters.delimiter);\n}\n\nexport function getParams<T>(id: string, spec: IdentifierSpec): T {\n const arr = splitParams(id, spec);\n const params = {};\n arr.forEach((value, index) => {\n params[spec.parameters.values[index].name] = value;\n });\n return params as T;\n}\n\nexport function joinParams(params: Params, spec: IdentifierSpec): string {\n return Object.values(spec.parameters.values)\n .map(parameter => {\n const param = params[parameter.name];\n return typeof param === \"string\"\n ? param\n : joinParams(param, parameter as IdentifierSpec);\n })\n .join(spec.parameters.delimiter);\n}\n\nexport function isValidId(id: string, spec: IdentifierSpec): boolean {\n // console.log(\"id\", id);\n // console.log(\"spec\", spec);\n // console.log(\"before regex\");\n if (!new RegExp(spec.regex).test(id)) return false;\n // console.log(\"after regex\");\n // console.log(\"before split\");\n const params = splitParams(id, spec);\n // console.log(\"after split\");\n // console.log(\"params\", params);\n // console.log(\"before length\");\n if (params.length !== Object.keys(spec.parameters.values).length)\n return false;\n // console.log(\"after length\");\n // console.log(\"before matches\");\n const matches = params\n .map((param, index) =>\n new RegExp(spec.parameters.values[index].regex).test(param)\n )\n .filter(x => !!x);\n if (matches.length !== params.length) return false;\n // console.log(\"after matches\");\n return true;\n}\n","import { CAIP } from \"./spec\";\nimport { IdentifierSpec } from \"./types\";\nimport { isValidId, joinParams, getParams } from \"./utils\";\n\nexport interface ChainIdParams {\n namespace: string;\n reference: string;\n}\n\nexport class ChainId {\n public static spec: IdentifierSpec = CAIP[\"2\"];\n\n public static parse(id: string): ChainIdParams {\n if (!isValidId(id, this.spec)) {\n throw new Error(`Invalid ${this.spec.name} provided: ${id}`);\n }\n return new ChainId(getParams<ChainIdParams>(id, this.spec)).toJSON();\n }\n\n public static format(params: ChainIdParams): string {\n return joinParams(params as any, this.spec);\n }\n\n public namespace: string;\n public reference: string;\n\n constructor(params: ChainIdParams | string) {\n if (typeof params === \"string\") {\n params = ChainId.parse(params);\n }\n\n this.namespace = params.namespace;\n this.reference = params.reference;\n }\n\n public toString(): string {\n return ChainId.format(this.toJSON());\n }\n\n public toJSON(): ChainIdParams {\n return {\n namespace: this.namespace,\n reference: this.reference,\n };\n }\n}\n","import { ChainId, ChainIdParams } from \"./chain\";\nimport { CAIP } from \"./spec\";\nimport { IdentifierSpec } from \"./types\";\nimport { isValidId, joinParams, getParams } from \"./utils\";\n\nexport interface AccountIdSplitParams extends ChainIdParams {\n address: string;\n}\nexport interface AccountIdParams {\n chainId: string | ChainIdParams;\n address: string;\n}\n\nexport class AccountId {\n public static spec: IdentifierSpec = CAIP[\"10\"];\n\n public static parse(id: string): AccountIdParams {\n if (!isValidId(id, this.spec)) {\n throw new Error(`Invalid ${this.spec.name} provided: ${id}`);\n }\n const { namespace, reference, address } = getParams<AccountIdSplitParams>(\n id,\n this.spec\n );\n const chainId = new ChainId({ namespace, reference });\n return new AccountId({ chainId, address }).toJSON();\n }\n\n public static format(params: AccountIdParams): string {\n const chainId = new ChainId(params.chainId);\n const splitParams: AccountIdSplitParams = {\n ...chainId.toJSON(),\n address: params.address,\n };\n return joinParams(splitParams as any, this.spec);\n }\n\n public chainId: ChainId;\n public address: string;\n\n constructor(params: AccountIdParams | string) {\n if (typeof params === \"string\") {\n params = AccountId.parse(params);\n }\n\n this.chainId = new ChainId(params.chainId);\n this.address = params.address;\n }\n\n public toString(): string {\n return AccountId.format(this.toJSON());\n }\n\n public toJSON(): AccountIdParams {\n return {\n chainId: this.chainId.toJSON(),\n address: this.address,\n };\n }\n}\n","import { CAIP } from \"./spec\";\nimport { IdentifierSpec } from \"./types\";\nimport { isValidId, joinParams, getParams } from \"./utils\";\n\nexport interface AssetNameParams {\n namespace: string;\n reference: string;\n}\n\nexport class AssetName {\n public static spec: IdentifierSpec = CAIP[\"19\"].assetName;\n\n public static parse(id: string): AssetNameParams {\n if (!isValidId(id, this.spec)) {\n throw new Error(`Invalid ${this.spec.name} provided: ${id}`);\n }\n return new AssetName(getParams<AssetNameParams>(id, this.spec)).toJSON();\n }\n\n public static format(params: AssetNameParams): string {\n return joinParams(params as any, this.spec);\n }\n\n public namespace: string;\n public reference: string;\n\n constructor(params: AssetNameParams | string) {\n if (typeof params === \"string\") {\n params = AssetName.parse(params);\n }\n\n this.namespace = params.namespace;\n this.reference = params.reference;\n }\n\n public toString(): string {\n return AssetName.format(this.toJSON());\n }\n\n public toJSON(): AssetNameParams {\n return {\n namespace: this.namespace,\n reference: this.reference,\n };\n }\n}\n","import { AssetName, AssetNameParams } from \"./assetName\";\nimport { ChainId, ChainIdParams } from \"./chain\";\nimport { CAIP } from \"./spec\";\nimport { IdentifierSpec } from \"./types\";\nimport { isValidId, joinParams, getParams } from \"./utils\";\n\nexport interface AssetTypeParams {\n chainId: string | ChainIdParams;\n assetName: string | AssetNameParams;\n}\n\nexport class AssetType {\n public static spec: IdentifierSpec = CAIP[\"19\"].assetType;\n\n public static parse(id: string): AssetTypeParams {\n if (!isValidId(id, this.spec)) {\n throw new Error(`Invalid ${this.spec.name} provided: ${id}`);\n }\n return new AssetType(getParams<AssetTypeParams>(id, this.spec)).toJSON();\n }\n\n public static format(params: AssetTypeParams): string {\n return joinParams(params as any, this.spec);\n }\n\n public chainId: ChainId;\n public assetName: AssetName;\n\n constructor(params: AssetTypeParams | string) {\n if (typeof params === \"string\") {\n params = AssetType.parse(params);\n }\n\n this.chainId = new ChainId(params.chainId);\n this.assetName = new AssetName(params.assetName);\n }\n\n public toString(): string {\n return AssetType.format(this.toJSON());\n }\n\n public toJSON(): AssetTypeParams {\n return {\n chainId: this.chainId.toJSON(),\n assetName: this.assetName,\n };\n }\n}\n","import { AssetName, AssetNameParams } from \"./assetName\";\nimport { ChainId, ChainIdParams } from \"./chain\";\nimport { CAIP } from \"./spec\";\nimport { IdentifierSpec } from \"./types\";\nimport { isValidId, joinParams, getParams } from \"./utils\";\n\nexport interface AssetIdParams {\n chainId: string | ChainIdParams;\n assetName: string | AssetNameParams;\n tokenId: string;\n}\n\nexport class AssetId {\n public static spec: IdentifierSpec = CAIP[\"19\"].assetId;\n\n public static parse(id: string): AssetIdParams {\n if (!isValidId(id, this.spec)) {\n throw new Error(`Invalid ${this.spec.name} provided: ${id}`);\n }\n return new AssetId(getParams<AssetIdParams>(id, this.spec)).toJSON();\n }\n\n public static format(params: AssetIdParams): string {\n return joinParams(params as any, this.spec);\n }\n\n public chainId: ChainId;\n public assetName: AssetName;\n public tokenId: string;\n\n constructor(params: AssetIdParams | string) {\n if (typeof params === \"string\") {\n params = AssetId.parse(params);\n }\n\n this.chainId = new ChainId(params.chainId);\n this.assetName = new AssetName(params.assetName);\n this.tokenId = params.tokenId;\n }\n\n public toString(): string {\n return AssetId.format(this.toJSON());\n }\n\n public toJSON(): AssetIdParams {\n return {\n chainId: this.chainId.toJSON(),\n assetName: this.assetName.toJSON(),\n tokenId: this.tokenId,\n };\n }\n}\n","import type { CoinType } from \"@ensdomains/address-encoder\";\nimport { AccountId as CaipAccountId } from \"caip\";\nimport { type Address, type Hex, isAddress, isHex, size } from \"viem\";\n/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\nimport { z } from \"zod/v4\";\n\nimport { ENSNamespaceIds, type InterpretedName, type Node } from \"../ens\";\nimport { asLowerCaseAddress } from \"./address\";\nimport {\n type CurrencyId,\n CurrencyIds,\n type PriceDai,\n type PriceEth,\n type PriceUsdc,\n} from \"./currencies\";\nimport { reinterpretName } from \"./interpretation/reinterpretation\";\nimport type { AccountIdString } from \"./serialized-types\";\nimport type {\n AccountId,\n BlockRef,\n ChainId,\n Datetime,\n DefaultableChainId,\n Duration,\n UnixTimestamp,\n} from \"./types\";\n\n/**\n * Parses a string value as a boolean.\n */\nexport const makeBooleanStringSchema = (valueLabel: string = \"Value\") =>\n z\n .string()\n .pipe(\n z.enum([\"true\", \"false\"], {\n error: `${valueLabel} must be 'true' or 'false'.`,\n }),\n )\n .transform((val) => val === \"true\");\n\n/**\n * Parses a numeric value as a finite non-negative number.\n */\nexport const makeFiniteNonNegativeNumberSchema = (valueLabel: string = \"Value\") =>\n z\n .number({\n // NOTE: Zod's implementation of `number` automatically rejects NaN and Infinity values.\n // and therefore the finite check is implicit.\n error: `${valueLabel} must be a finite number.`,\n })\n .nonnegative({\n error: `${valueLabel} must be a non-negative number (>=0).`,\n });\n\n/**\n * Parses a numeric value as an integer.\n */\nexport const makeIntegerSchema = (valueLabel: string = \"Value\") =>\n z.int({\n error: `${valueLabel} must be an integer.`,\n });\n\n/**\n * Parses a numeric value as a positive integer.\n */\nexport const makePositiveIntegerSchema = (valueLabel: string = \"Value\") =>\n makeIntegerSchema(valueLabel).positive({\n error: `${valueLabel} must be a positive integer (>0).`,\n });\n\n/**\n * Parses a numeric value as a non-negative integer.\n */\nexport const makeNonNegativeIntegerSchema = (valueLabel: string = \"Value\") =>\n makeIntegerSchema(valueLabel).nonnegative({\n error: `${valueLabel} must be a non-negative integer (>=0).`,\n });\n\n/**\n * Parses a numeric value as {@link Duration}\n */\nexport const makeDurationSchema = (valueLabel: string = \"Value\") =>\n z\n .number({\n error: `${valueLabel} must be a number.`,\n })\n .pipe(makeNonNegativeIntegerSchema(valueLabel));\n\n/**\n * Parses Chain ID\n *\n * {@link ChainId}\n */\nexport const makeChainIdSchema = (valueLabel: string = \"Chain ID\") =>\n makePositiveIntegerSchema(valueLabel).transform((val) => val as ChainId);\n\n/**\n * Parses a serialized representation of {@link ChainId}.\n */\nexport const makeChainIdStringSchema = (valueLabel: string = \"Chain ID String\") =>\n z\n .string({ error: `${valueLabel} must be a string representing a chain ID.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a positive integer (>0).` }))\n .pipe(makeChainIdSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses Defaultable Chain ID\n *\n * {@link DefaultableChainId}\n */\nexport const makeDefaultableChainIdSchema = (valueLabel: string = \"Defaultable Chain ID\") =>\n makeNonNegativeIntegerSchema(valueLabel).transform((val) => val as DefaultableChainId);\n\n/**\n * Parses a serialized representation of {@link DefaultableChainId}.\n */\nexport const makeDefaultableChainIdStringSchema = (\n valueLabel: string = \"Defaultable Chain ID String\",\n) =>\n z\n .string({ error: `${valueLabel} must be a string representing a chain ID.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a non-negative integer (>=0).` }))\n .pipe(makeDefaultableChainIdSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses {@link CoinType}.\n */\nexport const makeCoinTypeSchema = (valueLabel: string = \"Coin Type\") =>\n z\n .number({ error: `${valueLabel} must be a number.` })\n .int({ error: `${valueLabel} must be an integer.` })\n .nonnegative({ error: `${valueLabel} must be a non-negative integer (>=0).` })\n .transform((val) => val as CoinType);\n\n/**\n * Parses a serialized representation of {@link CoinType}.\n */\nexport const makeCoinTypeStringSchema = (valueLabel: string = \"Coin Type String\") =>\n z\n .string({ error: `${valueLabel} must be a string representing a coin type.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a non-negative integer (>=0).` }))\n .pipe(makeCoinTypeSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses a serialized representation of an EVM address into a lowercase Address.\n */\nexport const makeLowercaseAddressSchema = (valueLabel: string = \"EVM address\") =>\n z\n .string()\n .check((ctx) => {\n if (!isAddress(ctx.value)) {\n ctx.issues.push({\n code: \"custom\",\n message: `${valueLabel} must be a valid EVM address`,\n input: ctx.value,\n });\n }\n })\n .transform((val) => asLowerCaseAddress(val as Address));\n\n/**\n * Parses an ISO 8601 string representations of {@link Datetime}\n */\nexport const makeDatetimeSchema = (valueLabel: string = \"Datetime string\") =>\n z.iso\n .datetime({ error: `${valueLabel} must be a string in ISO 8601 format.` })\n .transform((v) => new Date(v));\n\n/**\n * Parses value as {@link UnixTimestamp}.\n */\nexport const makeUnixTimestampSchema = (valueLabel: string = \"Timestamp\") =>\n makeIntegerSchema(valueLabel);\n\n/**\n * Parses a string representations of {@link URL}\n */\nexport const makeUrlSchema = (valueLabel: string = \"Value\") =>\n z\n .url({\n error: `${valueLabel} must be a valid URL string (e.g., http://localhost:8080 or https://example.com).`,\n abort: true,\n })\n .transform((v) => new URL(v));\n\n/**\n * Parses a serialized representation of a comma separated list.\n */\nexport const makeCommaSeparatedList = (valueLabel: string = \"Value\") =>\n z\n .string({ error: `${valueLabel} must be a comma separated list.` })\n .transform((val) => val.split(\",\").filter(Boolean))\n .refine((val) => val.length > 0, {\n error: `${valueLabel} must be a comma separated list with at least one value.`,\n });\n\n/**\n * Parses a numeric value as a block number.\n */\nexport const makeBlockNumberSchema = (valueLabel: string = \"Block number\") =>\n makeNonNegativeIntegerSchema(valueLabel);\n\n/**\n * Parses an object value as the {@link BlockRef} object.\n */\nexport const makeBlockRefSchema = (valueLabel: string = \"Value\") =>\n z.strictObject(\n {\n timestamp: makeUnixTimestampSchema(`${valueLabel}.timestamp`),\n number: makeBlockNumberSchema(`${valueLabel}.number`),\n },\n {\n error: `${valueLabel} must be a valid BlockRef object.`,\n },\n );\n\n/**\n * Parses a string value as ENSNamespaceId.\n */\nexport const makeENSNamespaceIdSchema = (valueLabel: string = \"ENSNamespaceId\") =>\n z.enum(ENSNamespaceIds, {\n error() {\n return `Invalid ${valueLabel}. Supported ENS namespace IDs are: ${Object.keys(ENSNamespaceIds).join(\", \")}`;\n },\n });\n\nconst makePriceAmountSchema = (valueLabel: string = \"Amount\") =>\n z.coerce\n .bigint({\n error: `${valueLabel} must represent a bigint.`,\n })\n .nonnegative({\n error: `${valueLabel} must not be negative.`,\n });\n\nexport const makePriceCurrencySchema = (\n currency: CurrencyId,\n valueLabel: string = \"Price Currency\",\n) =>\n z.strictObject({\n amount: makePriceAmountSchema(`${valueLabel} amount`),\n\n currency: z.literal(currency, {\n error: `${valueLabel} currency must be set to '${currency}'.`,\n }),\n });\n\n/**\n * Schema for {@link Price} type.\n */\nexport const makePriceSchema = (valueLabel: string = \"Price\") =>\n z.discriminatedUnion(\n \"currency\",\n [\n makePriceCurrencySchema(CurrencyIds.ETH, valueLabel),\n makePriceCurrencySchema(CurrencyIds.USDC, valueLabel),\n makePriceCurrencySchema(CurrencyIds.DAI, valueLabel),\n ],\n { error: `${valueLabel} currency must be one of ${Object.values(CurrencyIds).join(\", \")}` },\n );\n\n/**\n * Schema for {@link PriceEth} type.\n */\nexport const makePriceEthSchema = (valueLabel: string = \"Price ETH\") =>\n makePriceCurrencySchema(CurrencyIds.ETH, valueLabel).transform((v) => v as PriceEth);\n\n/**\n * Schema for {@link PriceUsdc} type.\n */\nexport const makePriceUsdcSchema = (valueLabel: string = \"Price USDC\") =>\n makePriceCurrencySchema(CurrencyIds.USDC, valueLabel).transform((v) => v as PriceUsdc);\n\n/**\n * Schema for {@link PriceDai} type.\n */\nexport const makePriceDaiSchema = (valueLabel: string = \"Price DAI\") =>\n makePriceCurrencySchema(CurrencyIds.DAI, valueLabel).transform((v) => v as PriceDai);\n\n/**\n * Schema for {@link AccountId} type.\n */\nexport const makeAccountIdSchema = (valueLabel: string = \"AccountId\") =>\n z.strictObject({\n chainId: makeChainIdSchema(`${valueLabel} chain ID`),\n address: makeLowercaseAddressSchema(`${valueLabel} address`),\n });\n\n/**\n * Schema for {@link AccountIdString} type.\n */\nexport const makeAccountIdStringSchema = (valueLabel: string = \"Account ID String\") =>\n z.coerce\n .string()\n .transform((v) => {\n const result = new CaipAccountId(v);\n\n return {\n chainId: Number(result.chainId.reference),\n address: result.address,\n };\n })\n .pipe(makeAccountIdSchema(valueLabel));\n\n/**\n * Make a schema for {@link Hex} representation of bytes array.\n *\n * @param {number} options.bytesCount expected count of bytes to be hex-encoded\n */\nexport const makeHexStringSchema = (\n options: { bytesCount: number },\n valueLabel: string = \"String representation of bytes array\",\n) =>\n z\n .string()\n .check(function invariant_isHexEncoded(ctx) {\n if (!isHex(ctx.value)) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} must be a hexadecimal value which starts with '0x'.`,\n });\n }\n })\n .transform((v) => v as Hex)\n .check(function invariant_encodesRequiredBytesCount(ctx) {\n const expectedBytesCount = options.bytesCount;\n const actualBytesCount = size(ctx.value);\n\n if (actualBytesCount !== expectedBytesCount) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} must represent exactly ${expectedBytesCount} bytes. Currently represented bytes count: ${actualBytesCount}.`,\n });\n }\n });\n\n/**\n * Make schema for {@link Node}.\n */\nexport const makeNodeSchema = (valueLabel: string = \"Node\") =>\n makeHexStringSchema({ bytesCount: 32 }, valueLabel);\n\n/**\n * Make schema for Transaction Hash\n */\nexport const makeTransactionHashSchema = (valueLabel: string = \"Transaction hash\") =>\n makeHexStringSchema({ bytesCount: 32 }, valueLabel);\n\n/**\n * Make schema for {@link ReinterpretedName}.\n */\nexport const makeReinterpretedNameSchema = (valueLabel: string = \"Reinterpreted Name\") =>\n z\n .string()\n .transform((v) => v as InterpretedName)\n .check((ctx) => {\n try {\n reinterpretName(ctx.value);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} cannot be reinterpreted: ${errorMessage}`,\n });\n }\n })\n .transform(reinterpretName);\n","import type { Address } from \"viem\";\n\n/**\n * Converts an EVM address to its lowercase representation.\n *\n * @param address - EVM address to convert.\n * @returns The lowercase representation of the EVM address.\n */\nexport function asLowerCaseAddress(address: Address): Address {\n return address.toLowerCase() as Address;\n}\n","import type { UnixTimestamp } from \"@ensnode/ensnode-sdk\";\n\nimport type { AggregatedReferrerMetrics } from \"./aggregations\";\nimport type { ReferrerLeaderboard } from \"./leaderboard\";\nimport { isNonNegativeInteger, isPositiveInteger } from \"./number\";\nimport type { AwardedReferrerMetrics } from \"./referrer-metrics\";\nimport type { ReferralProgramRules } from \"./rules\";\n\n/**\n * The default number of referrers per leaderboard page.\n */\nexport const REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT = 25;\n\n/**\n * The maximum number of referrers per leaderboard page.\n */\n\nexport const REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;\n\n/**\n * Pagination params for leaderboard queries.\n */\nexport interface ReferrerLeaderboardPageParams {\n /**\n * Requested referrer leaderboard page number (1-indexed)\n * @invariant Must be a positive integer (>= 1)\n * @default 1\n */\n page?: number;\n\n /**\n * Maximum number of referrers to return per leaderboard page\n * @invariant Must be a positive integer (>= 1) and less than or equal to {@link REFERRERS_PER_LEADERBOARD_PAGE_MAX}\n * @default {@link REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT}\n */\n recordsPerPage?: number;\n}\n\nconst validateReferrerLeaderboardPageParams = (params: ReferrerLeaderboardPageParams): void => {\n if (params.page !== undefined && !isPositiveInteger(params.page)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.page}. page must be a positive integer.`,\n );\n }\n if (params.recordsPerPage !== undefined && !isPositiveInteger(params.recordsPerPage)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be a positive integer.`,\n );\n }\n if (\n params.recordsPerPage !== undefined &&\n params.recordsPerPage > REFERRERS_PER_LEADERBOARD_PAGE_MAX\n ) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be less than or equal to ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}.`,\n );\n }\n};\n\nexport const buildReferrerLeaderboardPageParams = (\n params: ReferrerLeaderboardPageParams,\n): Required<ReferrerLeaderboardPageParams> => {\n const result = {\n page: params.page ?? 1,\n recordsPerPage: params.recordsPerPage ?? REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT,\n } satisfies Required<ReferrerLeaderboardPageParams>;\n validateReferrerLeaderboardPageParams(result);\n return result;\n};\n\nexport interface ReferrerLeaderboardPageContext extends Required<ReferrerLeaderboardPageParams> {\n /**\n * Total number of referrers across all leaderboard pages\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n totalRecords: number;\n\n /**\n * Total number of pages in the leaderboard\n * @invariant Guaranteed to be a positive integer (>= 1)\n */\n totalPages: number;\n\n /**\n * Indicates if there is a next page available\n * @invariant true if and only if (`page` * `recordsPerPage` < `total`)\n */\n hasNext: boolean;\n\n /**\n * Indicates if there is a previous page available\n * @invariant true if and only if (`page` > 1)\n */\n hasPrev: boolean;\n\n /**\n * The start index of the referrers on the page (0-indexed)\n *\n * `undefined` if and only if `totalRecords` is 0.\n *\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n startIndex?: number;\n\n /**\n * The end index of the referrers on the page (0-indexed)\n *\n * `undefined` if and only if `totalRecords` is 0.\n *\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n * @invariant If `totalRecords` is > 0:\n * - Guaranteed to be greater than or equal to `startIndex`.\n * - Guaranteed to be less than `totalRecords`.\n */\n endIndex?: number;\n}\n\nexport const validateReferrerLeaderboardPageContext = (\n context: ReferrerLeaderboardPageContext,\n): void => {\n validateReferrerLeaderboardPageParams(context);\n if (!isNonNegativeInteger(context.totalRecords)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: total must be a non-negative integer but is ${context.totalRecords}.`,\n );\n }\n const startIndex = (context.page - 1) * context.recordsPerPage;\n const endIndex = startIndex + context.recordsPerPage;\n\n if (!context.hasNext && endIndex < context.totalRecords) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasNext is false, endIndex (${endIndex}) must be greater than or equal to total (${context.totalRecords}).`,\n );\n } else if (context.hasNext && context.page * context.recordsPerPage >= context.totalRecords) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasNext is true, endIndex (${endIndex}) must be less than total (${context.totalRecords}).`,\n );\n }\n if (!context.hasPrev && context.page !== 1) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasPrev is false, page must be the first page (1) but is ${context.page}.`,\n );\n } else if (context.hasPrev && context.page === 1) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasPrev is true, page must not be the first page (1) but is ${context.page}.`,\n );\n }\n};\n\nexport const buildReferrerLeaderboardPageContext = (\n optionalParams: ReferrerLeaderboardPageParams,\n leaderboard: ReferrerLeaderboard,\n): ReferrerLeaderboardPageContext => {\n const materializedParams = buildReferrerLeaderboardPageParams(optionalParams);\n\n const totalRecords = leaderboard.referrers.size;\n\n const totalPages = Math.max(1, Math.ceil(totalRecords / materializedParams.recordsPerPage));\n\n if (materializedParams.page > totalPages) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: page ${materializedParams.page} exceeds total pages ${totalPages}.`,\n );\n }\n\n if (totalRecords === 0) {\n return {\n ...materializedParams,\n totalRecords: 0,\n totalPages: 1,\n hasNext: false,\n hasPrev: false,\n startIndex: undefined,\n endIndex: undefined,\n } satisfies ReferrerLeaderboardPageContext;\n }\n\n const startIndex = (materializedParams.page - 1) * materializedParams.recordsPerPage;\n const maxTheoreticalIndexOnPage = startIndex + (materializedParams.recordsPerPage - 1);\n const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);\n const hasNext = maxTheoreticalIndexOnPage < totalRecords - 1;\n const hasPrev = materializedParams.page > 1;\n\n const result = {\n ...materializedParams,\n totalRecords,\n totalPages,\n hasNext,\n hasPrev,\n startIndex,\n endIndex,\n } satisfies ReferrerLeaderboardPageContext;\n validateReferrerLeaderboardPageContext(result);\n return result;\n};\n\n/**\n * A page of referrers from the referrer leaderboard.\n */\nexport interface ReferrerLeaderboardPage {\n /**\n * The {@link ReferralProgramRules} used to generate the {@link ReferrerLeaderboard}\n * that this {@link ReferrerLeaderboardPage} comes from.\n */\n rules: ReferralProgramRules;\n\n /**\n * Ordered list of {@link AwardedReferrerMetrics} for the {@link ReferrerLeaderboardPage}\n * described by `pageContext` within the related {@link ReferrerLeaderboard}.\n *\n * @invariant Array will be empty if `pageContext.totalRecords` is 0.\n * @invariant Array entries are ordered by `rank` (ascending).\n */\n referrers: AwardedReferrerMetrics[];\n\n /**\n * Aggregated metrics for all referrers on the leaderboard.\n */\n aggregatedMetrics: AggregatedReferrerMetrics;\n\n /**\n * The {@link ReferrerLeaderboardPageContext} of this {@link ReferrerLeaderboardPage} relative to the overall\n * {@link ReferrerLeaderboard}.\n */\n pageContext: ReferrerLeaderboardPageContext;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link ReferrerLeaderboardPage} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\nexport const getReferrerLeaderboardPage = (\n pageParams: ReferrerLeaderboardPageParams,\n leaderboard: ReferrerLeaderboard,\n): ReferrerLeaderboardPage => {\n const pageContext = buildReferrerLeaderboardPageContext(pageParams, leaderboard);\n\n let referrers: AwardedReferrerMetrics[];\n\n if (\n pageContext.totalRecords > 0 &&\n typeof pageContext.startIndex !== \"undefined\" &&\n typeof pageContext.endIndex !== \"undefined\"\n ) {\n // extract the referrers from the leaderboard in the range specified by `pageContext`.\n referrers = Array.from(leaderboard.referrers.values()).slice(\n pageContext.startIndex,\n pageContext.endIndex + 1, // For `slice`, this is exclusive of the element at the index 'end'. We need it to be inclusive, hence plus one.\n );\n } else {\n referrers = [];\n }\n\n return {\n rules: leaderboard.rules,\n referrers,\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n pageContext,\n accurateAsOf: leaderboard.accurateAsOf,\n };\n};\n","import type { Address } from \"viem\";\n\nimport type { Duration } from \"@ensnode/ensnode-sdk\";\n\nimport { isPositiveInteger } from \"./number\";\nimport type { ReferralProgramRules } from \"./rules\";\nimport { calcReferrerScore, type ReferrerScore } from \"./score\";\n\n/**\n * The rank of a referrer relative to all other referrers, where 1 is the\n * top-ranked referrer.\n *\n * @invariant Guaranteed to be a positive integer (> 0)\n */\nexport type ReferrerRank = number;\n\nexport const validateReferrerRank = (rank: ReferrerRank): void => {\n if (!isPositiveInteger(rank)) {\n throw new Error(`Invalid ReferrerRank: ${rank}. ReferrerRank must be a positive integer.`);\n }\n};\n\n/**\n * Determine if a referrer with the given `rank` is qualified to receive a non-zero `awardPoolShare` according to the given `rules`.\n *\n * @param rank - The rank of the referrer relative to all other referrers on a {@link ReferrerLeaderboard}.\n * @param rules - The rules of the referral program that generated the `rank`.\n */\nexport function isReferrerQualified(rank: ReferrerRank, rules: ReferralProgramRules): boolean {\n return rank <= rules.maxQualifiedReferrers;\n}\n\n/**\n * Calculate the final score boost of a referrer based on their rank.\n *\n * @param rank - The rank of the referrer relative to all other referrers, where 1 is the\n * top-ranked referrer.\n * @returns The final score boost of the referrer as a number between 0 and 1 (inclusive).\n */\nexport function calcReferrerFinalScoreBoost(\n rank: ReferrerRank,\n rules: ReferralProgramRules,\n): number {\n if (!isReferrerQualified(rank, rules)) return 0;\n\n return 1 - (rank - 1) / (rules.maxQualifiedReferrers - 1);\n}\n\n/**\n * Calculate the final score multiplier of a referrer based on their rank.\n *\n * @param rank - The rank of the referrer relative to all other referrers, where 1 is the\n * top-ranked referrer.\n * @returns The final score multiplier of the referrer as a number between 1 and 2 (inclusive).\n */\nexport function calcReferrerFinalScoreMultiplier(\n rank: ReferrerRank,\n rules: ReferralProgramRules,\n): number {\n return 1 + calcReferrerFinalScoreBoost(rank, rules);\n}\n\n/**\n * Calculate the final score of a referrer based on their score and final score boost.\n *\n * @param rank - The rank of the referrer relative to all other referrers.\n * @param totalIncrementalDuration - The total incremental duration (in seconds)\n * of referrals made by the referrer within the `rules`.\n * @param rules - The rules of the referral program that generated the `rank`.\n * @returns The final score of the referrer.\n */\nexport function calcReferrerFinalScore(\n rank: ReferrerRank,\n totalIncrementalDuration: Duration,\n rules: ReferralProgramRules,\n): ReferrerScore {\n return (\n calcReferrerScore(totalIncrementalDuration) * calcReferrerFinalScoreMultiplier(rank, rules)\n );\n}\n\nexport interface ReferrerMetricsForComparison {\n /**\n * The total incremental duration (in seconds) of all referrals made by the referrer within\n * the {@link ReferralProgramRules}.\n */\n totalIncrementalDuration: Duration;\n\n /**\n * The fully lowercase Ethereum address of the referrer.\n *\n * @invariant Guaranteed to be a valid EVM address in lowercase format.\n */\n referrer: Address;\n}\n\nexport const compareReferrerMetrics = (\n a: ReferrerMetricsForComparison,\n b: ReferrerMetricsForComparison,\n): number => {\n // Primary sort: totalIncrementalDuration (descending)\n if (a.totalIncrementalDuration !== b.totalIncrementalDuration) {\n return b.totalIncrementalDuration - a.totalIncrementalDuration;\n }\n\n // Secondary sort: referrer address using lexicographic comparison of ASCII hex strings (descending)\n if (b.referrer > a.referrer) return 1;\n if (b.referrer < a.referrer) return -1;\n return 0;\n};\n","import type { Address } from \"viem\";\n\nimport type { Duration } from \"@ensnode/ensnode-sdk\";\n\nimport { normalizeAddress, validateLowercaseAddress } from \"./address\";\nimport type { AggregatedReferrerMetrics } from \"./aggregations\";\nimport type { USDQuantity } from \"./currency\";\nimport { validateNonNegativeInteger } from \"./number\";\nimport {\n calcReferrerFinalScore,\n calcReferrerFinalScoreBoost,\n compareReferrerMetrics,\n isReferrerQualified,\n type ReferrerRank,\n validateReferrerRank,\n} from \"./rank\";\nimport type { RevenueContribution } from \"./revenue-contribution\";\nimport { validateRevenueContribution } from \"./revenue-contribution\";\nimport type { ReferralProgramRules } from \"./rules\";\nimport { calcReferrerScore, type ReferrerScore, validateReferrerScore } from \"./score\";\nimport { validateDuration } from \"./time\";\n\n/**\n * Represents metrics for a single referrer independent of other referrers.\n */\nexport interface ReferrerMetrics {\n /**\n * The fully lowercase Ethereum address of the referrer.\n *\n * @invariant Guaranteed to be a valid EVM address in lowercase format\n */\n referrer: Address;\n\n /**\n * The total number of referrals made by the referrer within the {@link ReferralProgramRules}.\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n totalReferrals: number;\n\n /**\n * The total incremental duration (in seconds) of all referrals made by the referrer within\n * the {@link ReferralProgramRules}.\n */\n totalIncrementalDuration: Duration;\n\n /**\n * The total revenue contribution (in Wei) made to the ENS DAO by all referrals\n * from this referrer.\n *\n * This is the sum of the total cost paid by registrants for all registrar actions\n * where this address was the referrer.\n *\n * @invariant Guaranteed to be a non-negative bigint value (>= 0n)\n * @invariant Never null (records with null `total` in the database are treated as 0 when summing)\n */\n totalRevenueContribution: RevenueContribution;\n}\n\nexport const buildReferrerMetrics = (\n referrer: Address,\n totalReferrals: number,\n totalIncrementalDuration: Duration,\n totalRevenueContribution: RevenueContribution,\n): ReferrerMetrics => {\n const result = {\n referrer: normalizeAddress(referrer),\n totalReferrals,\n totalIncrementalDuration,\n totalRevenueContribution,\n } satisfies ReferrerMetrics;\n\n validateReferrerMetrics(result);\n return result;\n};\n\nexport const validateReferrerMetrics = (metrics: ReferrerMetrics): void => {\n validateLowercaseAddress(metrics.referrer);\n validateNonNegativeInteger(metrics.totalReferrals);\n validateDuration(metrics.totalIncrementalDuration);\n validateRevenueContribution(metrics.totalRevenueContribution);\n};\n\nexport const sortReferrerMetrics = (referrers: ReferrerMetrics[]): ReferrerMetrics[] => {\n return [...referrers].sort(compareReferrerMetrics);\n};\n\n/**\n * Represents metrics for a single referrer independent of other referrers,\n * including a calculation of the referrer's score.\n */\nexport interface ScoredReferrerMetrics extends ReferrerMetrics {\n /**\n * The referrer's score.\n *\n * @invariant Guaranteed to be `calcReferrerScore(totalIncrementalDuration)`\n */\n score: ReferrerScore;\n}\n\nexport const buildScoredReferrerMetrics = (referrer: ReferrerMetrics): ScoredReferrerMetrics => {\n const result = {\n ...referrer,\n score: calcReferrerScore(referrer.totalIncrementalDuration),\n } satisfies ScoredReferrerMetrics;\n\n validateScoredReferrerMetrics(result);\n return result;\n};\n\nexport const validateScoredReferrerMetrics = (metrics: ScoredReferrerMetrics): void => {\n validateReferrerMetrics(metrics);\n validateReferrerScore(metrics.score);\n\n const expectedScore = calcReferrerScore(metrics.totalIncrementalDuration);\n if (metrics.score !== expectedScore) {\n throw new Error(`Referrer: Invalid score: ${metrics.score}, expected: ${expectedScore}.`);\n }\n};\n\n/**\n * Extends {@link ScoredReferrerMetrics} to include additional metrics\n * relative to all other referrers on a {@link ReferrerLeaderboard} and {@link ReferralProgramRules}.\n */\nexport interface RankedReferrerMetrics extends ScoredReferrerMetrics {\n /**\n * The referrer's rank on the {@link ReferrerLeaderboard} relative to all other referrers.\n */\n rank: ReferrerRank;\n\n /**\n * Identifies if the referrer meets the qualifications of the {@link ReferralProgramRules} to receive a non-zero `awardPoolShare`.\n *\n * @invariant true if and only if `rank` is less than or equal to {@link ReferralProgramRules.maxQualifiedReferrers}\n */\n isQualified: boolean;\n\n /**\n * The referrer's final score boost.\n *\n * @invariant Guaranteed to be a number between 0 and 1 (inclusive)\n * @invariant Calculated as: `1-((rank-1)/({@link ReferralProgramRules.maxQualifiedReferrers}-1))` if `isQualified` is `true`, else `0`\n */\n finalScoreBoost: number;\n\n /**\n * The referrer's final score.\n *\n * @invariant Calculated as: `score * (1 + finalScoreBoost)`\n */\n finalScore: ReferrerScore;\n}\n\nexport const validateRankedReferrerMetrics = (\n metrics: RankedReferrerMetrics,\n rules: ReferralProgramRules,\n): void => {\n validateScoredReferrerMetrics(metrics);\n validateReferrerRank(metrics.rank);\n\n if (metrics.finalScoreBoost < 0 || metrics.finalScoreBoost > 1) {\n throw new Error(\n `Invalid RankedReferrerMetrics: Invalid finalScoreBoost: ${metrics.finalScoreBoost}. finalScoreBoost must be between 0 and 1 (inclusive).`,\n );\n }\n\n validateReferrerScore(metrics.finalScore);\n\n const expectedIsQualified = isReferrerQualified(metrics.rank, rules);\n if (metrics.isQualified !== expectedIsQualified) {\n throw new Error(\n `RankedReferrerMetrics: Invalid isQualified: ${metrics.isQualified}, expected: ${expectedIsQualified}.`,\n );\n }\n\n const expectedFinalScoreBoost = calcReferrerFinalScoreBoost(metrics.rank, rules);\n if (metrics.finalScoreBoost !== expectedFinalScoreBoost) {\n throw new Error(\n `RankedReferrerMetrics: Invalid finalScoreBoost: ${metrics.finalScoreBoost}, expected: ${expectedFinalScoreBoost}.`,\n );\n }\n\n const expectedFinalScore = calcReferrerFinalScore(\n metrics.rank,\n metrics.totalIncrementalDuration,\n rules,\n );\n if (metrics.finalScore !== expectedFinalScore) {\n throw new Error(\n `RankedReferrerMetrics: Invalid finalScore: ${metrics.finalScore}, expected: ${expectedFinalScore}.`,\n );\n }\n};\n\nexport const buildRankedReferrerMetrics = (\n referrer: ScoredReferrerMetrics,\n rank: ReferrerRank,\n rules: ReferralProgramRules,\n): RankedReferrerMetrics => {\n const result = {\n ...referrer,\n rank,\n isQualified: isReferrerQualified(rank, rules),\n finalScoreBoost: calcReferrerFinalScoreBoost(rank, rules),\n finalScore: calcReferrerFinalScore(rank, referrer.totalIncrementalDuration, rules),\n } satisfies RankedReferrerMetrics;\n validateRankedReferrerMetrics(result, rules);\n return result;\n};\n\n/**\n * Calculate the share of the award pool for a referrer.\n * @param referrer - The referrer to calculate the award pool share for.\n * @param aggregatedMetrics - Aggregated metrics for all referrers.\n * @param rules - The rules of the referral program.\n * @returns The referrer's share of the award pool as a number between 0 and 1 (inclusive).\n */\nexport const calcReferrerAwardPoolShare = (\n referrer: RankedReferrerMetrics,\n aggregatedMetrics: AggregatedReferrerMetrics,\n rules: ReferralProgramRules,\n): number => {\n if (!isReferrerQualified(referrer.rank, rules)) return 0;\n if (aggregatedMetrics.grandTotalQualifiedReferrersFinalScore === 0) return 0;\n\n return (\n calcReferrerFinalScore(referrer.rank, referrer.totalIncrementalDuration, rules) /\n aggregatedMetrics.grandTotalQualifiedReferrersFinalScore\n );\n};\n\n/**\n * Extends {@link RankedReferrerMetrics} to include additional metrics\n * relative to {@link AggregatedRankedReferrerMetrics}.\n */\nexport interface AwardedReferrerMetrics extends RankedReferrerMetrics {\n /**\n * The referrer's share of the award pool.\n *\n * @invariant Guaranteed to be a number between 0 and 1 (inclusive)\n * @invariant Calculated as: `finalScore / {@link AggregatedRankedReferrerMetrics.grandTotalQualifiedReferrersFinalScore}` if `isQualified` is `true`, else `0`\n */\n awardPoolShare: number;\n\n /**\n * The approximate {@link USDQuantity} of the referrer's share of the {@link ReferralProgramRules.totalAwardPoolValue}.\n *\n * @invariant Guaranteed to be a number between 0 and {@link ReferralProgramRules.totalAwardPoolValue} (inclusive)\n * @invariant Calculated as: `awardPoolShare` * {@link ReferralProgramRules.totalAwardPoolValue}\n */\n awardPoolApproxValue: USDQuantity;\n}\n\nexport const validateAwardedReferrerMetrics = (\n referrer: AwardedReferrerMetrics,\n rules: ReferralProgramRules,\n): void => {\n validateRankedReferrerMetrics(referrer, rules);\n if (referrer.awardPoolShare < 0 || referrer.awardPoolShare > 1) {\n throw new Error(\n `Invalid AwardedReferrerMetrics: ${referrer.awardPoolShare}. awardPoolShare must be between 0 and 1 (inclusive).`,\n );\n }\n\n if (\n referrer.awardPoolApproxValue < 0 ||\n referrer.awardPoolApproxValue > rules.totalAwardPoolValue\n ) {\n throw new Error(\n `Invalid AwardedReferrerMetrics: ${referrer.awardPoolApproxValue}. awardPoolApproxValue must be between 0 and ${rules.totalAwardPoolValue} (inclusive).`,\n );\n }\n};\n\nexport const buildAwardedReferrerMetrics = (\n referrer: RankedReferrerMetrics,\n aggregatedMetrics: AggregatedReferrerMetrics,\n rules: ReferralProgramRules,\n): AwardedReferrerMetrics => {\n const awardPoolShare = calcReferrerAwardPoolShare(referrer, aggregatedMetrics, rules);\n\n const result = {\n ...referrer,\n awardPoolShare,\n awardPoolApproxValue: awardPoolShare * rules.totalAwardPoolValue,\n };\n validateAwardedReferrerMetrics(result, rules);\n return result;\n};\n\n/**\n * Extends {@link AwardedReferrerMetrics} but with rank set to null to represent\n * a referrer who is not on the leaderboard (has zero referrals within the rules associated with the leaderboard).\n */\nexport interface UnrankedReferrerMetrics\n extends Omit<AwardedReferrerMetrics, \"rank\" | \"isQualified\"> {\n /**\n * The referrer is not on the leaderboard and therefore has no rank.\n */\n rank: null;\n\n /**\n * Always false for unranked referrers.\n */\n isQualified: false;\n}\n\nexport const validateUnrankedReferrerMetrics = (metrics: UnrankedReferrerMetrics): void => {\n validateScoredReferrerMetrics(metrics);\n\n if (metrics.rank !== null) {\n throw new Error(`Invalid UnrankedReferrerMetrics: rank must be null, got: ${metrics.rank}.`);\n }\n\n if (metrics.isQualified !== false) {\n throw new Error(\n `Invalid UnrankedReferrerMetrics: isQualified must be false, got: ${metrics.isQualified}.`,\n );\n }\n\n if (metrics.totalReferrals !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetrics: totalReferrals must be 0, got: ${metrics.totalReferrals}.`,\n );\n }\n\n if (metrics.totalIncrementalDuration !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetrics: totalIncrementalDuration must be 0, got: ${metrics.totalIncrementalDuration}.`,\n );\n }\n\n if (metrics.totalRevenueContribution !== 0n) {\n throw new Error(\n `Invalid UnrankedReferrerMetrics: totalRevenueContribution must be 0n, got: ${metrics.totalRevenueContribution.toString()}.`,\n );\n }\n\n if (metrics.score !== 0) {\n throw new Error(`Invalid UnrankedReferrerMetrics: score must be 0, got: ${metrics.score}.`);\n }\n\n if (metrics.finalScoreBoost !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetrics: finalScoreBoost must be 0, got: ${metrics.finalScoreBoost}.`,\n );\n }\n\n if (metrics.finalScore !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetrics: finalScore must be 0, got: ${metrics.finalScore}.`,\n );\n }\n\n if (metrics.awardPoolShare !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetrics: awardPoolShare must be 0, got: ${metrics.awardPoolShare}.`,\n );\n }\n\n if (metrics.awardPoolApproxValue !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetrics: awardPoolApproxValue must be 0, got: ${metrics.awardPoolApproxValue}.`,\n );\n }\n};\n\n/**\n * Build an unranked zero-score referrer record for a referrer address that is not in the leaderboard.\n *\n * This is useful when you want to return a referrer record for an address that has no referrals\n * and is not qualified for the leaderboard.\n *\n * @param referrer - The referrer address\n * @returns An {@link UnrankedReferrerMetrics} with zero values for all metrics and null rank\n */\nexport const buildUnrankedReferrerMetrics = (referrer: Address): UnrankedReferrerMetrics => {\n const baseMetrics = buildReferrerMetrics(referrer, 0, 0, 0n);\n const scoredMetrics = buildScoredReferrerMetrics(baseMetrics);\n\n const result = {\n ...scoredMetrics,\n rank: null,\n isQualified: false,\n finalScoreBoost: 0,\n finalScore: 0,\n awardPoolShare: 0,\n awardPoolApproxValue: 0,\n } satisfies UnrankedReferrerMetrics;\n\n validateUnrankedReferrerMetrics(result);\n return result;\n};\n","import type { Address } from \"viem\";\n\nimport type { UnixTimestamp } from \"@ensnode/ensnode-sdk\";\n\nimport type { AggregatedReferrerMetrics } from \"./aggregations\";\nimport type { ReferrerLeaderboard } from \"./leaderboard\";\nimport {\n type AwardedReferrerMetrics,\n buildUnrankedReferrerMetrics,\n type UnrankedReferrerMetrics,\n} from \"./referrer-metrics\";\nimport type { ReferralProgramRules } from \"./rules\";\n\n/**\n * The type of referrer detail data.\n */\nexport const ReferrerDetailTypeIds = {\n /**\n * Represents a referrer who is ranked on the leaderboard.\n */\n Ranked: \"ranked\",\n\n /**\n * Represents a referrer who is not ranked on the leaderboard.\n */\n Unranked: \"unranked\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerDetailTypeIds}.\n */\nexport type ReferrerDetailTypeId =\n (typeof ReferrerDetailTypeIds)[keyof typeof ReferrerDetailTypeIds];\n\n/**\n * Referrer detail data for a specific referrer address on the leaderboard.\n *\n * Includes the referrer's awarded metrics from the leaderboard plus timestamp.\n *\n * Invariants:\n * - `type` is always {@link ReferrerDetailTypeIds.Ranked}.\n *\n * @see {@link AwardedReferrerMetrics}\n */\nexport interface ReferrerDetailRanked {\n /**\n * The type of referrer detail data.\n */\n type: typeof ReferrerDetailTypeIds.Ranked;\n\n /**\n * The {@link ReferralProgramRules} used to calculate the {@link AwardedReferrerMetrics}.\n */\n rules: ReferralProgramRules;\n\n /**\n * The awarded referrer metrics from the leaderboard.\n *\n * Contains all calculated metrics including score, rank, qualification status,\n * and award pool share information.\n */\n referrer: AwardedReferrerMetrics;\n\n /**\n * Aggregated metrics for all referrers on the leaderboard.\n */\n aggregatedMetrics: AggregatedReferrerMetrics;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link ReferrerDetailData} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\n/**\n * Referrer detail data for a specific referrer address NOT on the leaderboard.\n *\n * Includes the referrer's unranked metrics (with null rank and isQualified: false) plus timestamp.\n *\n * Invariants:\n * - `type` is always {@link ReferrerDetailTypeIds.Unranked}.\n *\n * @see {@link UnrankedReferrerMetrics}\n */\nexport interface ReferrerDetailUnranked {\n /**\n * The type of referrer detail data.\n */\n type: typeof ReferrerDetailTypeIds.Unranked;\n\n /**\n * The {@link ReferralProgramRules} used to calculate the {@link UnrankedReferrerMetrics}.\n */\n rules: ReferralProgramRules;\n\n /**\n * The unranked referrer metrics (not on the leaderboard).\n *\n * Contains all calculated metrics with rank set to null and isQualified set to false.\n */\n referrer: UnrankedReferrerMetrics;\n\n /**\n * Aggregated metrics for all referrers on the leaderboard.\n */\n aggregatedMetrics: AggregatedReferrerMetrics;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link UnrankedReferrerDetailData} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\n/**\n * Referrer detail data for a specific referrer address.\n *\n * Use the `type` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferrerDetail = ReferrerDetailRanked | ReferrerDetailUnranked;\n\n/**\n * Get the detail for a specific referrer from the leaderboard.\n *\n * Returns a {@link ReferrerDetailRanked} if the referrer is on the leaderboard,\n * or a {@link ReferrerDetailUnranked} if the referrer has no referrals.\n *\n * @param referrer - The referrer address to look up\n * @param leaderboard - The referrer leaderboard to query\n * @returns The appropriate {@link ReferrerDetail} (ranked or unranked)\n */\nexport const getReferrerDetail = (\n referrer: Address,\n leaderboard: ReferrerLeaderboard,\n): ReferrerDetail => {\n const awardedReferrerMetrics = leaderboard.referrers.get(referrer);\n\n // If referrer is on the leaderboard, return their ranked metrics\n if (awardedReferrerMetrics) {\n return {\n type: ReferrerDetailTypeIds.Ranked,\n rules: leaderboard.rules,\n referrer: awardedReferrerMetrics,\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n accurateAsOf: leaderboard.accurateAsOf,\n };\n }\n\n // If referrer not found, return an unranked referrer record\n return {\n type: ReferrerDetailTypeIds.Unranked,\n rules: leaderboard.rules,\n referrer: buildUnrankedReferrerMetrics(referrer),\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n accurateAsOf: leaderboard.accurateAsOf,\n };\n};\n","import type { Address } from \"viem\";\n\nimport type { ReferrerLeaderboardPage, ReferrerLeaderboardPageParams } from \"../leaderboard-page\";\nimport type { ReferrerDetail } from \"../referrer-detail\";\n\n/**\n * Request parameters for a referrer leaderboard page query.\n */\nexport interface ReferrerLeaderboardPageRequest extends ReferrerLeaderboardPageParams {}\n\n/**\n * A status code for a referrer leaderboard page API response.\n */\nexport const ReferrerLeaderboardPageResponseCodes = {\n /**\n * Represents that the requested referrer leaderboard page is available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that the referrer leaderboard data is not available.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerLeaderboardPageResponseCodes}.\n */\nexport type ReferrerLeaderboardPageResponseCode =\n (typeof ReferrerLeaderboardPageResponseCodes)[keyof typeof ReferrerLeaderboardPageResponseCodes];\n\n/**\n * A referrer leaderboard page response when the data is available.\n */\nexport type ReferrerLeaderboardPageResponseOk = {\n responseCode: typeof ReferrerLeaderboardPageResponseCodes.Ok;\n data: ReferrerLeaderboardPage;\n};\n\n/**\n * A referrer leaderboard page response when the data is not available.\n */\nexport type ReferrerLeaderboardPageResponseError = {\n responseCode: typeof ReferrerLeaderboardPageResponseCodes.Error;\n error: string;\n errorMessage: string;\n};\n\n/**\n * A referrer leaderboard page API response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferrerLeaderboardPageResponse =\n | ReferrerLeaderboardPageResponseOk\n | ReferrerLeaderboardPageResponseError;\n\n/**\n * Request parameters for referrer detail query.\n */\nexport interface ReferrerDetailRequest {\n /** The Ethereum address of the referrer to query */\n referrer: Address;\n}\n\n/**\n * A status code for referrer detail API responses.\n */\nexport const ReferrerDetailResponseCodes = {\n /**\n * Represents that the referrer detail data is available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that an error occurred while fetching the data.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerDetailResponseCodes}.\n */\nexport type ReferrerDetailResponseCode =\n (typeof ReferrerDetailResponseCodes)[keyof typeof ReferrerDetailResponseCodes];\n\n/**\n * A referrer detail response when the data is available for a referrer on the leaderboard.\n */\nexport type ReferrerDetailResponseOk = {\n responseCode: typeof ReferrerDetailResponseCodes.Ok;\n data: ReferrerDetail;\n};\n\n/**\n * A referrer detail response when an error occurs.\n */\nexport type ReferrerDetailResponseError = {\n responseCode: typeof ReferrerDetailResponseCodes.Error;\n error: string;\n errorMessage: string;\n};\n\n/**\n * A referrer detail API response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferrerDetailResponse = ReferrerDetailResponseOk | ReferrerDetailResponseError;\n","import type { AggregatedReferrerMetrics } from \"../aggregations\";\nimport type { ReferrerLeaderboardPage } from \"../leaderboard-page\";\nimport type { ReferrerDetailRanked, ReferrerDetailUnranked } from \"../referrer-detail\";\nimport type { AwardedReferrerMetrics, UnrankedReferrerMetrics } from \"../referrer-metrics\";\nimport type { RevenueContribution } from \"../revenue-contribution\";\nimport type { ReferralProgramRules } from \"../rules\";\nimport type {\n SerializedAggregatedReferrerMetrics,\n SerializedAwardedReferrerMetrics,\n SerializedReferralProgramRules,\n SerializedReferrerDetailRanked,\n SerializedReferrerDetailResponse,\n SerializedReferrerDetailUnranked,\n SerializedReferrerLeaderboardPage,\n SerializedReferrerLeaderboardPageResponse,\n SerializedUnrankedReferrerMetrics,\n} from \"./serialized-types\";\nimport {\n type ReferrerDetailResponse,\n ReferrerDetailResponseCodes,\n type ReferrerLeaderboardPageResponse,\n ReferrerLeaderboardPageResponseCodes,\n} from \"./types\";\n\n/**\n * Serializes a {@link RevenueContribution} value into its string representation.\n */\nfunction serializeRevenueContribution(revenueContribution: RevenueContribution): string {\n return revenueContribution.toString();\n}\n\n/**\n * Serializes a {@link ReferralProgramRules} object.\n */\nfunction serializeReferralProgramRules(\n rules: ReferralProgramRules,\n): SerializedReferralProgramRules {\n // All fields are already serializable primitives\n return rules;\n}\n\n/**\n * Serializes an {@link AwardedReferrerMetrics} object.\n */\nfunction serializeAwardedReferrerMetrics(\n metrics: AwardedReferrerMetrics,\n): SerializedAwardedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: serializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Serializes an {@link UnrankedReferrerMetrics} object.\n */\nfunction serializeUnrankedReferrerMetrics(\n metrics: UnrankedReferrerMetrics,\n): SerializedUnrankedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: serializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Serializes an {@link AggregatedReferrerMetrics} object.\n */\nfunction serializeAggregatedReferrerMetrics(\n metrics: AggregatedReferrerMetrics,\n): SerializedAggregatedReferrerMetrics {\n return {\n grandTotalReferrals: metrics.grandTotalReferrals,\n grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,\n grandTotalRevenueContribution: serializeRevenueContribution(\n metrics.grandTotalRevenueContribution,\n ),\n grandTotalQualifiedReferrersFinalScore: metrics.grandTotalQualifiedReferrersFinalScore,\n minFinalScoreToQualify: metrics.minFinalScoreToQualify,\n };\n}\n\n/**\n * Serializes a {@link ReferrerLeaderboardPage} object.\n */\nfunction serializeReferrerLeaderboardPage(\n page: ReferrerLeaderboardPage,\n): SerializedReferrerLeaderboardPage {\n return {\n rules: serializeReferralProgramRules(page.rules),\n referrers: page.referrers.map(serializeAwardedReferrerMetrics),\n aggregatedMetrics: serializeAggregatedReferrerMetrics(page.aggregatedMetrics),\n pageContext: page.pageContext,\n accurateAsOf: page.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferrerDetailRanked} object.\n */\nfunction serializeReferrerDetailRanked(\n detail: ReferrerDetailRanked,\n): SerializedReferrerDetailRanked {\n return {\n type: detail.type,\n rules: serializeReferralProgramRules(detail.rules),\n referrer: serializeAwardedReferrerMetrics(detail.referrer),\n aggregatedMetrics: serializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferrerDetailUnranked} object.\n */\nfunction serializeReferrerDetailUnranked(\n detail: ReferrerDetailUnranked,\n): SerializedReferrerDetailUnranked {\n return {\n type: detail.type,\n rules: serializeReferralProgramRules(detail.rules),\n referrer: serializeUnrankedReferrerMetrics(detail.referrer),\n aggregatedMetrics: serializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Serialize a {@link ReferrerLeaderboardPageResponse} object.\n */\nexport function serializeReferrerLeaderboardPageResponse(\n response: ReferrerLeaderboardPageResponse,\n): SerializedReferrerLeaderboardPageResponse {\n switch (response.responseCode) {\n case ReferrerLeaderboardPageResponseCodes.Ok:\n return {\n responseCode: response.responseCode,\n data: serializeReferrerLeaderboardPage(response.data),\n };\n\n case ReferrerLeaderboardPageResponseCodes.Error:\n return response;\n }\n}\n\n/**\n * Serialize a {@link ReferrerDetailResponse} object.\n */\nexport function serializeReferrerDetailResponse(\n response: ReferrerDetailResponse,\n): SerializedReferrerDetailResponse {\n switch (response.responseCode) {\n case ReferrerDetailResponseCodes.Ok:\n switch (response.data.type) {\n case \"ranked\":\n return {\n responseCode: response.responseCode,\n data: serializeReferrerDetailRanked(response.data),\n };\n\n case \"unranked\":\n return {\n responseCode: response.responseCode,\n data: serializeReferrerDetailUnranked(response.data),\n };\n }\n break;\n\n case ReferrerDetailResponseCodes.Error:\n return response;\n }\n}\n","import {\n deserializeReferrerDetailResponse,\n deserializeReferrerLeaderboardPageResponse,\n type ReferrerDetailRequest,\n type ReferrerDetailResponse,\n type ReferrerLeaderboardPageRequest,\n type ReferrerLeaderboardPageResponse,\n type SerializedReferrerDetailResponse,\n type SerializedReferrerLeaderboardPageResponse,\n} from \"./api\";\n\n/**\n * Default ENSNode API endpoint URL\n */\nexport const DEFAULT_ENSNODE_API_URL = \"https://api.alpha.ensnode.io\" as const;\n\n/**\n * Configuration options for ENS Referrals API client\n */\nexport interface ClientOptions {\n /** The ENSNode API URL */\n url: URL;\n}\n\n/**\n * ENS Referrals API Client\n *\n * Provides access to ENS Referrals data and leaderboard information.\n *\n * @example\n * ```typescript\n * // Create client with default options\n * const client = new ENSReferralsClient();\n *\n * // Get referrer leaderboard\n * const leaderboardPage = await client.getReferrerLeaderboardPage({\n * page: 1,\n * recordsPerPage: 25\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Custom configuration\n * const client = new ENSReferralsClient({\n * url: new URL(\"https://my-ensnode-instance.com\"),\n * });\n * ```\n */\nexport class ENSReferralsClient {\n private readonly options: ClientOptions;\n\n static defaultOptions(): ClientOptions {\n return {\n url: new URL(DEFAULT_ENSNODE_API_URL),\n };\n }\n\n constructor(options: Partial<ClientOptions> = {}) {\n this.options = {\n ...ENSReferralsClient.defaultOptions(),\n ...options,\n };\n }\n\n getOptions(): Readonly<ClientOptions> {\n return Object.freeze({\n url: new URL(this.options.url.href),\n });\n }\n\n /**\n * Fetch Referrer Leaderboard Page\n *\n * Retrieves a paginated list of referrer leaderboard metrics with contribution percentages.\n * Each referrer's contribution is calculated as a percentage of the grand totals across all referrers.\n *\n * @param request - Pagination parameters\n * @param request.page - The page number to retrieve (1-indexed, default: 1)\n * @param request.recordsPerPage - Number of records per page (default: 25, max: 100)\n * @returns {ReferrerLeaderboardPageResponse}\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n *\n * @example\n * ```typescript\n * // Get first page with default page size (25 records)\n * const response = await client.getReferrerLeaderboardPage();\n * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Ok) {\n * const {\n * aggregatedMetrics,\n * referrers,\n * rules,\n * pageContext,\n * updatedAt\n * } = response.data;\n * console.log(aggregatedMetrics);\n * console.log(referrers);\n * console.log(rules);\n * console.log(updatedAt);\n * console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Get second page with 50 records per page\n * const response = await client.getReferrerLeaderboardPage({ page: 2, recordsPerPage: 50 });\n * ```\n *\n * @example\n * ```typescript\n * // Handle error response, ie. when Referrer Leaderboard is not currently available.\n * const response = await client.getReferrerLeaderboardPage();\n *\n * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Error) {\n * console.error(response.error);\n * console.error(response.errorMessage);\n * }\n * ```\n */\n async getReferrerLeaderboardPage(\n request?: ReferrerLeaderboardPageRequest,\n ): Promise<ReferrerLeaderboardPageResponse> {\n const url = new URL(`/ensanalytics/referrers`, this.options.url);\n\n if (request?.page) url.searchParams.set(\"page\", request.page.toString());\n if (request?.recordsPerPage)\n url.searchParams.set(\"recordsPerPage\", request.recordsPerPage.toString());\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // The API can return errors with 500 status, but they're still in the\n // PaginatedAggregatedReferrersResponse format with responseCode: 'error'\n // So we don't need to check response.ok here, just deserialize and let\n // the caller handle the responseCode\n\n return deserializeReferrerLeaderboardPageResponse(\n responseData as SerializedReferrerLeaderboardPageResponse,\n );\n }\n\n /**\n * Fetch Referrer Detail\n *\n * Retrieves detailed information about a specific referrer, whether they are on the\n * leaderboard or not.\n *\n * The response data is a discriminated union type with a `type` field:\n *\n * **For referrers on the leaderboard** (`ReferrerDetailRanked`):\n * - `type`: {@link ReferrerDetailTypeIds.Ranked}\n * - `referrer`: The `AwardedReferrerMetrics` from @namehash/ens-referrals\n * - `rules`: The referral program rules\n * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard\n * - `accurateAsOf`: Unix timestamp indicating when the data was last updated\n *\n * **For referrers NOT on the leaderboard** (`ReferrerDetailUnranked`):\n * - `type`: {@link ReferrerDetailTypeIds.Unranked}\n * - `referrer`: The `UnrankedReferrerMetrics` from @namehash/ens-referrals\n * - `rules`: The referral program rules\n * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard\n * - `accurateAsOf`: Unix timestamp indicating when the data was last updated\n *\n * @see {@link https://www.npmjs.com/package/@namehash/ens-referrals|@namehash/ens-referrals} for calculation details\n *\n * @param request The referrer address to query\n * @returns {ReferrerDetailResponse} Returns the referrer detail response\n *\n * @throws if the ENSNode request fails\n * @throws if the response data is malformed\n *\n * @example\n * ```typescript\n * // Get referrer detail for a specific address\n * const response = await client.getReferrerDetail({\n * referrer: \"0x1234567890123456789012345678901234567890\"\n * });\n * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {\n * const { type, referrer, rules, aggregatedMetrics, accurateAsOf } = response.data;\n * console.log(type); // ReferrerDetailTypeIds.Ranked or ReferrerDetailTypeIds.Unranked\n * console.log(referrer);\n * console.log(accurateAsOf);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Use discriminated union to check if referrer is ranked\n * const response = await client.getReferrerDetail({\n * referrer: \"0x1234567890123456789012345678901234567890\"\n * });\n * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {\n * if (response.data.type === ReferrerDetailTypeIds.Ranked) {\n * // TypeScript knows this is ReferrerDetailRanked\n * console.log(`Rank: ${response.data.referrer.rank}`);\n * console.log(`Qualified: ${response.data.referrer.isQualified}`);\n * console.log(`Award Pool Share: ${response.data.referrer.awardPoolShare * 100}%`);\n * } else {\n * // TypeScript knows this is ReferrerDetailUnranked\n * console.log(\"Referrer is not on the leaderboard (no referrals yet)\");\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Handle error response, ie. when Referrer Detail is not currently available.\n * const response = await client.getReferrerDetail({\n * referrer: \"0x1234567890123456789012345678901234567890\"\n * });\n *\n * if (response.responseCode === ReferrerDetailResponseCodes.Error) {\n * console.error(response.error);\n * console.error(response.errorMessage);\n * }\n * ```\n */\n async getReferrerDetail(request: ReferrerDetailRequest): Promise<ReferrerDetailResponse> {\n const url = new URL(\n `/ensanalytics/referrers/${encodeURIComponent(request.referrer)}`,\n this.options.url,\n );\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // The API can return errors with 500 status, but they're still in the\n // ReferrerDetailResponse format with responseCode: 'error'\n // So we don't need to check response.ok here, just deserialize and let\n // the caller handle the responseCode\n\n return deserializeReferrerDetailResponse(responseData as SerializedReferrerDetailResponse);\n }\n}\n","import { isFiniteNonNegativeNumber } from \"./number\";\n\n/**\n * Represents a quantity of USD.\n *\n * @invariant Guaranteed to be a finite non-negative number (>= 0)\n */\nexport type USDQuantity = number;\n\nexport function isValidUSDQuantity(value: USDQuantity): boolean {\n return isFiniteNonNegativeNumber(value);\n}\n\nexport function validateUSDQuantity(value: USDQuantity): void {\n if (!isValidUSDQuantity(value)) {\n throw new Error(`Invalid USD quantity: ${value}.`);\n }\n}\n","import type { Address } from \"viem\";\n\nimport type { UnixTimestamp } from \"@ensnode/ensnode-sdk\";\n\nimport { type AggregatedReferrerMetrics, buildAggregatedReferrerMetrics } from \"./aggregations\";\nimport {\n type AwardedReferrerMetrics,\n buildAwardedReferrerMetrics,\n buildRankedReferrerMetrics,\n buildScoredReferrerMetrics,\n type ReferrerMetrics,\n sortReferrerMetrics,\n} from \"./referrer-metrics\";\nimport type { ReferralProgramRules } from \"./rules\";\n\n/**\n * Represents a leaderboard for any number of referrers.\n */\nexport interface ReferrerLeaderboard {\n /**\n * The rules of the referral program that generated the {@link ReferrerLeaderboard}.\n */\n rules: ReferralProgramRules;\n\n /**\n * The {@link AggregatedReferrerMetrics} for all `RankedReferrerMetrics` values in `leaderboard`.\n */\n aggregatedMetrics: AggregatedReferrerMetrics;\n\n /**\n * Ordered map containing `AwardedReferrerMetrics` for all referrers with 1 or more\n * `totalReferrals` within the `rules` as of `updatedAt`.\n *\n * @invariant Map entries are ordered by `rank` (ascending).\n * @invariant Map is empty if there are no referrers with 1 or more `totalReferrals`\n * within the `rules` as of `updatedAt`.\n * @invariant If a fully-lowercase `Address` is not a key in this map then that `Address` had\n * 0 `totalReferrals`, `totalIncrementalDuration`, and `score` within the\n * `rules` as of `updatedAt`.\n * @invariant Each value in this map is guaranteed to have a non-zero\n * `totalReferrals`, `totalIncrementalDuration`, and `score`.\n */\n referrers: Map<Address, AwardedReferrerMetrics>;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link ReferrerLeaderboard} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\nexport const buildReferrerLeaderboard = (\n allReferrers: ReferrerMetrics[],\n rules: ReferralProgramRules,\n accurateAsOf: UnixTimestamp,\n): ReferrerLeaderboard => {\n const uniqueReferrers = allReferrers.map((referrer) => referrer.referrer);\n if (uniqueReferrers.length !== allReferrers.length) {\n throw new Error(\n \"ReferrerLeaderboard: Cannot buildReferrerLeaderboard containing duplicate referrers\",\n );\n }\n\n if (accurateAsOf < rules.startTime && allReferrers.length > 0) {\n throw new Error(\n `ReferrerLeaderboard: accurateAsOf (${accurateAsOf}) is before startTime (${rules.startTime}) which indicates allReferrers should be empty, but allReferrers is not empty.`,\n );\n }\n\n const sortedReferrers = sortReferrerMetrics(allReferrers);\n\n const scoredReferrers = sortedReferrers.map((referrer) => buildScoredReferrerMetrics(referrer));\n\n const rankedReferrers = scoredReferrers.map((referrer, index) => {\n return buildRankedReferrerMetrics(referrer, index + 1, rules);\n });\n\n const aggregatedMetrics = buildAggregatedReferrerMetrics(rankedReferrers, rules);\n\n const awardedReferrers = rankedReferrers.map((referrer) => {\n return buildAwardedReferrerMetrics(referrer, aggregatedMetrics, rules);\n });\n\n // Transform ordered list into an ordered map (preserves sort order)\n const referrers = new Map(\n awardedReferrers.map((referrer) => {\n return [referrer.referrer, referrer];\n }),\n );\n\n return {\n rules,\n aggregatedMetrics,\n referrers,\n accurateAsOf,\n };\n};\n","import { type Address, getAddress } from \"viem\";\n\n/**\n * Build a URL to the official ENS manager app\n * where the given {@link Address} is set as the referrer.\n */\nexport function buildEnsReferralUrl(address: Address): URL {\n const ensAppUrl = new URL(\"https://app.ens.domains\");\n\n ensAppUrl.searchParams.set(\"referrer\", getAddress(address));\n\n return ensAppUrl;\n}\n","import type { AccountId, UnixTimestamp } from \"@ensnode/ensnode-sdk\";\n\nimport { type USDQuantity, validateUSDQuantity } from \"./currency\";\nimport { validateNonNegativeInteger } from \"./number\";\nimport { validateUnixTimestamp } from \"./time\";\n\n/**\n * Start date for the ENS Holiday Awards referral program.\n * 2025-12-01T00:00:00Z (December 1, 2025 at 00:00:00 UTC)\n */\nexport const ENS_HOLIDAY_AWARDS_START_DATE: UnixTimestamp = 1764547200;\n\n/**\n * End date for the ENS Holiday Awards referral program.\n * 2025-12-31T23:59:59Z (December 31, 2025 at 23:59:59 UTC)\n */\nexport const ENS_HOLIDAY_AWARDS_END_DATE: UnixTimestamp = 1767225599;\n\n/**\n * The maximum number of qualified referrers for ENS Holiday Awards.\n */\nexport const ENS_HOLIDAY_AWARDS_MAX_QUALIFIED_REFERRERS = 10;\n\n/**\n * The total value of the award pool in USD.\n */\nexport const ENS_HOLIDAY_AWARDS_TOTAL_AWARD_POOL_VALUE: USDQuantity = 10_000.0;\n\nexport interface ReferralProgramRules {\n /**\n * The total value of the award pool in USD.\n *\n * NOTE: Awards will actually be distributed in $ENS tokens.\n */\n totalAwardPoolValue: USDQuantity;\n\n /**\n * The maximum number of referrers that will qualify to receive a non-zero `awardPoolShare`.\n *\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n maxQualifiedReferrers: number;\n\n /**\n * The start time of the referral program.\n */\n startTime: UnixTimestamp;\n\n /**\n * The end time of the referral program.\n * @invariant Guaranteed to be greater than or equal to `startTime`\n */\n endTime: UnixTimestamp;\n\n /**\n * The account ID of the subregistry for the referral program.\n */\n subregistryId: AccountId;\n}\n\nexport const validateReferralProgramRules = (rules: ReferralProgramRules): void => {\n validateUSDQuantity(rules.totalAwardPoolValue);\n validateNonNegativeInteger(rules.maxQualifiedReferrers);\n validateUnixTimestamp(rules.startTime);\n validateUnixTimestamp(rules.endTime);\n\n if (rules.endTime < rules.startTime) {\n throw new Error(\n `ReferralProgramRules: startTime: ${rules.startTime} is after endTime: ${rules.endTime}.`,\n );\n }\n};\n\nexport const buildReferralProgramRules = (\n totalAwardPoolValue: USDQuantity,\n maxQualifiedReferrers: number,\n startTime: UnixTimestamp,\n endTime: UnixTimestamp,\n subregistryId: AccountId,\n): ReferralProgramRules => {\n const result = {\n totalAwardPoolValue,\n maxQualifiedReferrers,\n startTime,\n endTime,\n subregistryId,\n } satisfies ReferralProgramRules;\n\n validateReferralProgramRules(result);\n\n return result;\n};\n","import type { UnixTimestamp } from \"@ensnode/ensnode-sdk\";\n\nimport type { ReferralProgramRules } from \"./rules.ts\";\n\n/**\n * The type of referral program's status.\n */\nexport const ReferralProgramStatuses = {\n /**\n * Represents a referral program that has been announced, but hasn't started yet.\n */\n Scheduled: \"Scheduled\",\n\n /**\n * Represents a currently ongoing referral program.\n */\n Active: \"Active\",\n\n /**\n * Represents a referral program that has already ended.\n */\n Closed: \"Closed\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferralProgramStatuses}.\n */\nexport type ReferralProgramStatusId =\n (typeof ReferralProgramStatuses)[keyof typeof ReferralProgramStatuses];\n\n/**\n * Calculate the status of the referral program based on the current date\n * and program's timeframe available in its rules.\n *\n * @param referralProgramRules - Related referral program's rules containing\n * program's start date and end date.\n *\n * @param now - Current date in {@link UnixTimestamp} format.\n */\nexport const calcReferralProgramStatus = (\n referralProgramRules: ReferralProgramRules,\n now: UnixTimestamp,\n): ReferralProgramStatusId => {\n // if the program has not started return \"Scheduled\"\n if (now < referralProgramRules.startTime) return ReferralProgramStatuses.Scheduled;\n\n // if the program has ended return \"Closed\"\n if (now > referralProgramRules.endTime) return ReferralProgramStatuses.Closed;\n\n // otherwise, return \"Active\"\n return ReferralProgramStatuses.Active;\n};\n"],"mappings":"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","names":["z","CAIP2","name","regex","parameters","delimiter","values","CAIP10","AssetName","CAIP19AssetType","CAIP19AssetId","CAIP","assetName","assetType","assetId","splitParams","id","spec","split","getParams","arr","params","forEach","value","index","joinParams","Object","map","parameter","param","join","isValidId","RegExp","test","length","keys","matches","filter","x","ChainId","parse","namespace","reference","Error","toJSON","format","toString","AccountId","chainId","address","AssetType","AssetId","tokenId","isAddress","isAddress","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/address.ts","../src/api/deserialize.ts","../src/api/zod-schemas.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/spec.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/utils.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/chain.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/account.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/assetName.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/assetType.ts","../../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/src/assetId.ts","../../ensnode-sdk/src/shared/zod-schemas.ts","../../ensnode-sdk/src/shared/currencies.ts","../../ensnode-sdk/src/shared/numbers.ts","../../ensnode-sdk/src/shared/serialize.ts","../src/award-models/pie-split/api/zod-schemas.ts","../src/award-models/shared/api/zod-schemas.ts","../src/number.ts","../src/award-models/shared/leaderboard-page.ts","../src/award-models/shared/status.ts","../src/award-models/shared/edition-metrics.ts","../src/time.ts","../src/award-models/shared/rules.ts","../src/award-models/rev-share-cap/api/zod-schemas.ts","../src/award-models/rev-share-cap/rules.ts","../src/api/types.ts","../src/award-models/pie-split/api/serialize.ts","../src/award-models/rev-share-cap/api/serialize.ts","../src/api/serialize.ts","../src/award-models/shared/score.ts","../src/award-models/pie-split/aggregations.ts","../src/edition.ts","../src/award-models/shared/edition-summary.ts","../src/award-models/pie-split/rules.ts","../src/award-models/pie-split/status.ts","../src/award-models/pie-split/edition-summary.ts","../src/award-models/shared/leaderboard-guards.ts","../src/award-models/shared/rank.ts","../src/referrer-metrics.ts","../src/award-models/pie-split/score.ts","../src/award-models/pie-split/rank.ts","../src/award-models/pie-split/metrics.ts","../src/award-models/pie-split/leaderboard.ts","../src/award-models/pie-split/leaderboard-page.ts","../src/award-models/rev-share-cap/aggregations.ts","../src/award-models/rev-share-cap/status.ts","../src/award-models/rev-share-cap/edition-summary.ts","../src/award-models/rev-share-cap/metrics.ts","../src/award-models/rev-share-cap/sort-referral-events.ts","../src/award-models/rev-share-cap/leaderboard.ts","../src/award-models/rev-share-cap/leaderboard-page.ts","../src/client.ts","../src/edition-metrics.ts","../src/edition-summary.ts","../src/leaderboard-page.ts","../src/link.ts"],"sourcesContent":["import type { NormalizedAddress } from \"enssdk\";\nimport { isNormalizedAddress } from \"enssdk\";\n\nexport const validateNormalizedAddress = (address: NormalizedAddress): void => {\n if (!isNormalizedAddress(address)) {\n throw new Error(`Invalid address: '${address}'. Address must be a lowercase EVM Address.`);\n }\n};\n","import { prettifyError } from \"zod/v4\";\n\nimport type { ReferralProgramEditionConfig } from \"../edition\";\nimport type {\n SerializedReferralProgramEditionSummariesResponse,\n SerializedReferrerLeaderboardPageResponse,\n SerializedReferrerMetricsEditionsResponse,\n} from \"./serialized-types\";\nimport type {\n ReferralProgramEditionSummariesResponse,\n ReferrerLeaderboardPageResponse,\n ReferrerMetricsEditionsResponse,\n} from \"./types\";\nimport {\n makeReferralProgramEditionConfigSetArraySchema,\n makeReferralProgramEditionSummariesResponseSchema,\n makeReferrerLeaderboardPageResponseSchema,\n makeReferrerMetricsEditionsResponseSchema,\n} from \"./zod-schemas\";\n\n/**\n * Deserialize a {@link ReferrerLeaderboardPageResponse} object.\n */\nexport function deserializeReferrerLeaderboardPageResponse(\n maybeResponse: SerializedReferrerLeaderboardPageResponse,\n valueLabel?: string,\n): ReferrerLeaderboardPageResponse {\n const schema = makeReferrerLeaderboardPageResponseSchema(valueLabel);\n const parsed = schema.safeParse(maybeResponse);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize SerializedReferrerLeaderboardPageResponse:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserialize a {@link ReferrerMetricsEditionsResponse} object.\n */\nexport function deserializeReferrerMetricsEditionsResponse(\n maybeResponse: SerializedReferrerMetricsEditionsResponse,\n valueLabel?: string,\n): ReferrerMetricsEditionsResponse {\n const schema = makeReferrerMetricsEditionsResponseSchema(valueLabel);\n const parsed = schema.safeParse(maybeResponse);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize ReferrerMetricsEditionsResponse:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserializes an array of {@link ReferralProgramEditionConfig} objects.\n */\nexport function deserializeReferralProgramEditionConfigSetArray(\n maybeArray: unknown,\n valueLabel?: string,\n): ReferralProgramEditionConfig[] {\n const schema = makeReferralProgramEditionConfigSetArraySchema(valueLabel);\n const parsed = schema.safeParse(maybeArray);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize ReferralProgramEditionConfigSetArray:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserialize a {@link ReferralProgramEditionSummariesResponse} object.\n */\nexport function deserializeReferralProgramEditionSummariesResponse(\n maybeResponse: SerializedReferralProgramEditionSummariesResponse,\n valueLabel?: string,\n): ReferralProgramEditionSummariesResponse {\n const schema = makeReferralProgramEditionSummariesResponseSchema(valueLabel);\n const parsed = schema.safeParse(maybeResponse);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize ReferralProgramEditionSummariesResponse:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n","/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\n\nimport z from \"zod/v4\";\n\nimport { makeNormalizedAddressSchema } from \"@ensnode/ensnode-sdk/internal\";\n\nimport {\n makeReferralProgramEditionSummaryPieSplitSchema,\n makeReferralProgramRulesPieSplitSchema,\n makeReferrerEditionMetricsPieSplitSchema,\n makeReferrerLeaderboardPagePieSplitSchema,\n} from \"../award-models/pie-split/api/zod-schemas\";\nimport {\n makeReferralProgramEditionSummaryRevShareCapSchema,\n makeReferralProgramRulesRevShareCapSchema,\n makeReferrerEditionMetricsRevShareCapSchema,\n makeReferrerLeaderboardPageRevShareCapSchema,\n} from \"../award-models/rev-share-cap/api/zod-schemas\";\nimport {\n makeBaseReferralProgramEditionSummarySchema,\n makeBaseReferralProgramRulesSchema,\n makeBaseReferrerLeaderboardPageSchema,\n} from \"../award-models/shared/api/zod-schemas\";\nimport type { ReferrerEditionMetricsUnrecognized } from \"../award-models/shared/edition-metrics\";\nimport type { ReferralProgramEditionSummaryUnrecognized } from \"../award-models/shared/edition-summary\";\nimport type { ReferrerLeaderboardPageUnrecognized } from \"../award-models/shared/leaderboard-page\";\nimport type { ReferralProgramRulesUnrecognized } from \"../award-models/shared/rules\";\nimport { ReferralProgramAwardModels } from \"../award-models/shared/rules\";\nimport type { ReferralProgramEditionConfig } from \"../edition\";\nimport type { ReferrerEditionMetrics } from \"../edition-metrics\";\nimport type { ReferralProgramEditionSummary } from \"../edition-summary\";\nimport type { ReferrerLeaderboardPage } from \"../leaderboard-page\";\nimport {\n MAX_EDITIONS_PER_REQUEST,\n ReferralProgramEditionSummariesResponseCodes,\n ReferrerLeaderboardPageResponseCodes,\n ReferrerMetricsEditionsResponseCodes,\n} from \"./types\";\n\n/**\n * Re-emit issues from a nested safeParse into the outer transform context.\n * Preserves the original issue's code, expected/received, params and other metadata;\n * only the path is rewritten (optionally prefixed — used when the outer schema is an array).\n */\nconst reemitIssues = (\n ctx: z.RefinementCtx,\n issues: readonly z.core.$ZodIssue[],\n pathPrefix: PropertyKey[] = [],\n) => {\n for (const issue of issues) {\n ctx.addIssue({\n ...issue,\n path: [...pathPrefix, ...(issue.path as PropertyKey[])],\n });\n }\n};\n\n/**\n * Schema for {@link ReferralProgramRules}\n */\nexport const makeReferralProgramRulesSchema = (valueLabel: string = \"ReferralProgramRules\") =>\n z.discriminatedUnion(\"awardModel\", [\n makeReferralProgramRulesPieSplitSchema(valueLabel),\n makeReferralProgramRulesRevShareCapSchema(valueLabel),\n ]);\n\n/**\n * Schema for {@link ReferrerLeaderboardPage}.\n *\n * Forward-compatible — peeks at `awardModel` before committing to full validation:\n * - Known award models are fully validated with the model-specific schema.\n * - Unknown award models are wrapped as {@link ReferrerLeaderboardPageUnrecognized}.\n */\nexport const makeReferrerLeaderboardPageSchema = (\n valueLabel: string = \"ReferrerLeaderboardPage\",\n) => {\n const knownAwardModels = Object.values(ReferralProgramAwardModels).filter(\n (m) => m !== ReferralProgramAwardModels.Unrecognized,\n ) as string[];\n\n // Loose schema used only to peek at awardModel before full validation.\n const looseSchema = z.looseObject({ awardModel: z.string() });\n\n // Schema for known award models — dispatch is handled automatically by discriminatedUnion.\n const knownSchema = z.discriminatedUnion(\"awardModel\", [\n makeReferrerLeaderboardPagePieSplitSchema(valueLabel),\n makeReferrerLeaderboardPageRevShareCapSchema(valueLabel),\n ]);\n\n // Base schema for fields present on all leaderboard page variants (used for Unrecognized).\n const baseSchema = makeBaseReferrerLeaderboardPageSchema(valueLabel);\n\n return looseSchema.transform((data, ctx): ReferrerLeaderboardPage => {\n if (knownAwardModels.includes(data.awardModel)) {\n const parsed = knownSchema.safeParse(data);\n if (!parsed.success) {\n reemitIssues(ctx, parsed.error.issues);\n return z.NEVER;\n }\n return parsed.data;\n }\n\n // Unknown awardModel — preserve as ReferrerLeaderboardPageUnrecognized using base fields.\n const parsed = baseSchema.safeParse(data);\n if (!parsed.success) {\n reemitIssues(ctx, parsed.error.issues);\n return z.NEVER;\n }\n return {\n ...parsed.data,\n awardModel: ReferralProgramAwardModels.Unrecognized,\n originalAwardModel: data.awardModel,\n } satisfies ReferrerLeaderboardPageUnrecognized;\n });\n};\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponseOk}\n */\nexport const makeReferrerLeaderboardPageResponseOkSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageResponseOk\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerLeaderboardPageResponseCodes.Ok),\n data: makeReferrerLeaderboardPageSchema(`${valueLabel}.data`),\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponseError}\n */\nexport const makeReferrerLeaderboardPageResponseErrorSchema = (\n _valueLabel: string = \"ReferrerLeaderboardPageResponseError\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerLeaderboardPageResponseCodes.Error),\n error: z.string(),\n errorMessage: z.string(),\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponse}\n */\nexport const makeReferrerLeaderboardPageResponseSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageResponse\",\n) =>\n z.discriminatedUnion(\"responseCode\", [\n makeReferrerLeaderboardPageResponseOkSchema(valueLabel),\n makeReferrerLeaderboardPageResponseErrorSchema(valueLabel),\n ]);\n\n/**\n * Schema for {@link ReferrerEditionMetrics} (all ranked and unranked model variants, plus Unrecognized).\n *\n * Forward-compatible — peeks at `awardModel` before committing to full validation:\n * - Known award models are fully validated with the model-specific schema.\n * - Unknown award models are wrapped as {@link ReferrerEditionMetricsUnrecognized}.\n */\nexport const makeReferrerEditionMetricsSchema = (valueLabel: string = \"ReferrerEditionMetrics\") => {\n const knownAwardModels = Object.values(ReferralProgramAwardModels).filter(\n (m) => m !== ReferralProgramAwardModels.Unrecognized,\n ) as string[];\n\n // Loose schema used only to peek at awardModel before full validation.\n const looseSchema = z.looseObject({ awardModel: z.string() });\n\n // Schema for known award models — dispatch is handled automatically by discriminatedUnion.\n const knownSchema = z.discriminatedUnion(\"awardModel\", [\n makeReferrerEditionMetricsPieSplitSchema(valueLabel),\n makeReferrerEditionMetricsRevShareCapSchema(valueLabel),\n ]);\n\n return looseSchema.transform((data, ctx): ReferrerEditionMetrics => {\n if (knownAwardModels.includes(data.awardModel)) {\n const parsed = knownSchema.safeParse(data);\n if (!parsed.success) {\n reemitIssues(ctx, parsed.error.issues);\n return z.NEVER;\n }\n return parsed.data;\n }\n\n // Unknown awardModel — wrap as ReferrerEditionMetricsUnrecognized.\n // No base fields are extracted here (unlike ReferrerLeaderboardPageUnrecognized) because\n // callers are expected to skip unrecognized edition metrics entirely rather than inspect them.\n return {\n awardModel: ReferralProgramAwardModels.Unrecognized,\n originalAwardModel: data.awardModel,\n } satisfies ReferrerEditionMetricsUnrecognized;\n });\n};\n\n/**\n * Schema for validating a {@link ReferralProgramEditionSlug}.\n *\n * Runtime validation against configured editions happens at the business logic level.\n */\nexport const makeReferralProgramEditionSlugSchema = (\n valueLabel: string = \"ReferralProgramEditionSlug\",\n) =>\n z\n .string()\n .min(1, `${valueLabel} must not be empty`)\n .regex(\n /^[a-z0-9]+(-[a-z0-9]+)*$/,\n `${valueLabel} must contain only lowercase letters, digits, and hyphens. Must not start or end with a hyphen.`,\n );\n\n/**\n * Schema for validating editions array (min 1, max {@link MAX_EDITIONS_PER_REQUEST}, distinct values).\n */\nexport const makeReferrerMetricsEditionsArraySchema = (\n valueLabel: string = \"ReferrerMetricsEditionsArray\",\n) =>\n z\n .array(makeReferralProgramEditionSlugSchema(`${valueLabel}[edition]`))\n .min(1, `${valueLabel} must contain at least 1 edition`)\n .max(\n MAX_EDITIONS_PER_REQUEST,\n `${valueLabel} must not contain more than ${MAX_EDITIONS_PER_REQUEST} editions`,\n )\n .refine(\n (editions) => {\n const uniqueEditions = new Set(editions);\n return uniqueEditions.size === editions.length;\n },\n { message: `${valueLabel} must not contain duplicate edition slugs` },\n );\n\n/**\n * Schema for {@link ReferrerMetricsEditionsRequest}\n */\nexport const makeReferrerMetricsEditionsRequestSchema = (\n valueLabel: string = \"ReferrerMetricsEditionsRequest\",\n) =>\n z.object({\n referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`),\n editions: makeReferrerMetricsEditionsArraySchema(`${valueLabel}.editions`),\n });\n\n/**\n * Schema for {@link ReferrerMetricsEditionsResponseOk}\n */\nexport const makeReferrerMetricsEditionsResponseOkSchema = (\n valueLabel: string = \"ReferrerMetricsEditionsResponseOk\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerMetricsEditionsResponseCodes.Ok),\n data: z.record(\n makeReferralProgramEditionSlugSchema(`${valueLabel}.data[edition]`),\n makeReferrerEditionMetricsSchema(`${valueLabel}.data[edition]`),\n ),\n });\n\n/**\n * Schema for {@link ReferrerMetricsEditionsResponseError}\n */\nexport const makeReferrerMetricsEditionsResponseErrorSchema = (\n _valueLabel: string = \"ReferrerMetricsEditionsResponseError\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerMetricsEditionsResponseCodes.Error),\n error: z.string(),\n errorMessage: z.string(),\n });\n\n/**\n * Schema for {@link ReferrerMetricsEditionsResponse}\n */\nexport const makeReferrerMetricsEditionsResponseSchema = (\n valueLabel: string = \"ReferrerMetricsEditionsResponse\",\n) =>\n z.discriminatedUnion(\"responseCode\", [\n makeReferrerMetricsEditionsResponseOkSchema(valueLabel),\n makeReferrerMetricsEditionsResponseErrorSchema(valueLabel),\n ]);\n\n/**\n * Schema for the shared base fields of a {@link ReferralProgramEditionConfig}.\n */\nconst makeReferralProgramEditionConfigBaseSchema = (valueLabel: string) =>\n z.object({\n slug: makeReferralProgramEditionSlugSchema(`${valueLabel}.slug`),\n displayName: z.string().min(1, `${valueLabel}.displayName must not be empty`),\n rules: makeBaseReferralProgramRulesSchema(`${valueLabel}.rules`),\n });\n\n/**\n * Schema for validating a {@link ReferralProgramEditionConfig}.\n */\nexport const makeReferralProgramEditionConfigSchema = (\n valueLabel: string = \"ReferralProgramEditionConfig\",\n) =>\n makeReferralProgramEditionConfigBaseSchema(valueLabel).safeExtend({\n rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),\n });\n\n/**\n * Schema for validating referral program edition config set array.\n *\n * Editions whose `rules.awardModel` is not recognized by this client version are preserved as\n * {@link ReferralProgramRulesUnrecognized} for forward compatibility — nothing is silently dropped.\n * Downstream code (e.g., leaderboard cache setup) is responsible for skipping unrecognized\n * editions with a warning log rather than crashing.\n *\n * The list may be empty. Duplicate slugs are not allowed.\n *\n * Two-pass approach:\n * 1. Each item is loosely parsed (based on `rules.awardModel` field).\n * - Known award models are fully validated with {@link makeReferralProgramEditionConfigSchema}.\n * - Unknown award models are parsed with {@link makeBaseReferralProgramRulesSchema} and wrapped as\n * `ReferralProgramRulesUnrecognized`.\n * 2. After processing all items, the result must have no duplicate slugs.\n */\nexport const makeReferralProgramEditionConfigSetArraySchema = (\n valueLabel: string = \"ReferralProgramEditionConfigSetArray\",\n) => {\n const knownAwardModels = Object.values(ReferralProgramAwardModels).filter(\n (m) => m !== ReferralProgramAwardModels.Unrecognized,\n ) as string[];\n const configSchema = makeReferralProgramEditionConfigSchema(`${valueLabel}[edition]`);\n\n // Loose schema used only to peek at rules.awardModel before full validation.\n const looseItemSchema = z.looseObject({\n rules: z.looseObject({ awardModel: z.string() }),\n });\n\n // Schema for extracting base fields from an unrecognized edition.\n const unrecognizedBaseSchema = makeReferralProgramEditionConfigBaseSchema(\n `${valueLabel}[edition]`,\n );\n\n return z.array(looseItemSchema).transform((items, ctx): ReferralProgramEditionConfig[] => {\n const result: ReferralProgramEditionConfig[] = [];\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n\n if (knownAwardModels.includes(item.rules.awardModel)) {\n // Known award model — fully validate.\n const parsed = configSchema.safeParse(item);\n if (!parsed.success) {\n reemitIssues(ctx, parsed.error.issues, [i]);\n } else {\n result.push(parsed.data);\n }\n } else {\n // Unknown award model — preserve as ReferralProgramRulesUnrecognized using base fields.\n const parsed = unrecognizedBaseSchema.safeParse(item);\n if (!parsed.success) {\n reemitIssues(ctx, parsed.error.issues, [i]);\n continue;\n }\n\n result.push({\n ...parsed.data,\n rules: {\n ...parsed.data.rules,\n awardModel: ReferralProgramAwardModels.Unrecognized,\n originalAwardModel: item.rules.awardModel,\n } satisfies ReferralProgramRulesUnrecognized,\n });\n }\n }\n\n const slugs = new Set<string>();\n for (const edition of result) {\n if (slugs.has(edition.slug)) {\n ctx.addIssue({\n code: \"custom\",\n message: `${valueLabel} must not contain duplicate edition slugs`,\n });\n // Issue above causes the overall parse to fail; this value is never used.\n return [];\n }\n slugs.add(edition.slug);\n }\n\n return result;\n });\n};\n\n/**\n * Schema for {@link ReferralProgramEditionSummary}.\n *\n * Forward-compatible — peeks at `awardModel` before committing to full validation:\n * - Known award models are fully validated with the model-specific schema.\n * - Unknown award models are wrapped as {@link ReferralProgramEditionSummaryUnrecognized}.\n */\nexport const makeReferralProgramEditionSummarySchema = (\n valueLabel: string = \"ReferralProgramEditionSummary\",\n) => {\n const knownAwardModels = Object.values(ReferralProgramAwardModels).filter(\n (m) => m !== ReferralProgramAwardModels.Unrecognized,\n ) as string[];\n\n // Loose schema used only to peek at awardModel before full validation.\n const looseSchema = z.looseObject({ awardModel: z.string() });\n\n // Schema for known award models — dispatch handled automatically by discriminatedUnion.\n const knownSchema = z.discriminatedUnion(\"awardModel\", [\n makeReferralProgramEditionSummaryPieSplitSchema(valueLabel),\n makeReferralProgramEditionSummaryRevShareCapSchema(valueLabel),\n ]);\n\n // Base schema for fields present on all edition summary variants (used for Unrecognized).\n const baseSchema = makeBaseReferralProgramEditionSummarySchema(valueLabel);\n\n return looseSchema.transform((data, ctx): ReferralProgramEditionSummary => {\n if (knownAwardModels.includes(data.awardModel)) {\n const parsed = knownSchema.safeParse(data);\n if (!parsed.success) {\n reemitIssues(ctx, parsed.error.issues);\n return z.NEVER;\n }\n return parsed.data;\n }\n\n // Unknown awardModel — preserve as ReferralProgramEditionSummaryUnrecognized using base fields.\n const parsed = baseSchema.safeParse(data);\n if (!parsed.success) {\n reemitIssues(ctx, parsed.error.issues);\n return z.NEVER;\n }\n return {\n ...parsed.data,\n awardModel: ReferralProgramAwardModels.Unrecognized,\n rules: {\n ...parsed.data.rules,\n awardModel: ReferralProgramAwardModels.Unrecognized,\n originalAwardModel: data.awardModel,\n },\n } satisfies ReferralProgramEditionSummaryUnrecognized;\n });\n};\n\n/**\n * Schema for {@link ReferralProgramEditionSummariesData}.\n */\nexport const makeReferralProgramEditionSummariesDataSchema = (\n valueLabel: string = \"ReferralProgramEditionSummariesData\",\n) =>\n z.object({\n editions: z.array(makeReferralProgramEditionSummarySchema(`${valueLabel}.editions[edition]`)),\n });\n\n/**\n * Schema for {@link ReferralProgramEditionSummariesResponseOk}.\n */\nexport const makeReferralProgramEditionSummariesResponseOkSchema = (\n valueLabel: string = \"ReferralProgramEditionSummariesResponseOk\",\n) =>\n z.object({\n responseCode: z.literal(ReferralProgramEditionSummariesResponseCodes.Ok),\n data: makeReferralProgramEditionSummariesDataSchema(`${valueLabel}.data`),\n });\n\n/**\n * Schema for {@link ReferralProgramEditionSummariesResponseError}.\n */\nexport const makeReferralProgramEditionSummariesResponseErrorSchema = (\n _valueLabel: string = \"ReferralProgramEditionSummariesResponseError\",\n) =>\n z.object({\n responseCode: z.literal(ReferralProgramEditionSummariesResponseCodes.Error),\n error: z.string(),\n errorMessage: z.string(),\n });\n\n/**\n * Schema for {@link ReferralProgramEditionSummariesResponse}.\n */\nexport const makeReferralProgramEditionSummariesResponseSchema = (\n valueLabel: string = \"ReferralProgramEditionSummariesResponse\",\n) =>\n z.discriminatedUnion(\"responseCode\", [\n makeReferralProgramEditionSummariesResponseOkSchema(valueLabel),\n makeReferralProgramEditionSummariesResponseErrorSchema(valueLabel),\n ]);\n","import { IdentifierSpec } from \"./types\";\n\nconst CAIP2: IdentifierSpec = {\n name: \"chainId\",\n regex: \"[-:a-zA-Z0-9]{5,41}\",\n parameters: {\n delimiter: \":\",\n values: {\n 0: {\n name: \"namespace\",\n regex: \"[-a-z0-9]{3,8}\",\n },\n 1: {\n name: \"reference\",\n regex: \"[-a-zA-Z0-9]{1,32}\",\n },\n },\n },\n};\n\nconst CAIP10: IdentifierSpec = {\n name: \"accountId\",\n regex: \"[-:a-zA-Z0-9]{7,106}\",\n parameters: {\n delimiter: \":\",\n values: {\n 0: {\n name: \"namespace\",\n regex: \"[-a-z0-9]{3,8}\",\n },\n 1: {\n name: \"reference\",\n regex: \"[-a-zA-Z0-9]{1,32}\",\n },\n 2: {\n name: \"address\",\n regex: \"[a-zA-Z0-9]{1,64}\",\n },\n },\n },\n};\n\n// represents namespace:reference in CAIP-19\nconst AssetName: IdentifierSpec = {\n name: \"assetName\",\n regex: \"[-:a-zA-Z0-9]{5,73}\",\n parameters: {\n delimiter: \":\",\n values: {\n 0: {\n name: \"namespace\",\n regex: \"[-a-z0-9]{3,8}\",\n },\n 1: {\n name: \"reference\",\n regex: \"[-a-zA-Z0-9]{1,64}\",\n },\n },\n },\n};\n\nconst CAIP19AssetType: IdentifierSpec = {\n name: \"assetType\",\n regex: \"[-:a-zA-Z0-9]{11,115}\",\n parameters: {\n delimiter: \"/\",\n values: {\n 0: CAIP2,\n 1: AssetName,\n },\n },\n};\n\nconst CAIP19AssetId: IdentifierSpec = {\n name: \"assetId\",\n regex: \"[-:a-zA-Z0-9]{13,148}\",\n parameters: {\n delimiter: \"/\",\n values: {\n 0: CAIP2,\n 1: AssetName,\n 2: {\n name: \"tokenId\",\n regex: \"[-a-zA-Z0-9]{1,32}\",\n },\n },\n },\n};\n\nexport const CAIP = {\n \"2\": CAIP2,\n \"10\": CAIP10,\n \"19\": {\n assetName: AssetName,\n assetType: CAIP19AssetType,\n assetId: CAIP19AssetId,\n },\n};\n","import { IdentifierSpec, Params } from \"./types\";\n\nexport function splitParams(id: string, spec: IdentifierSpec): string[] {\n return id.split(spec.parameters.delimiter);\n}\n\nexport function getParams<T>(id: string, spec: IdentifierSpec): T {\n const arr = splitParams(id, spec);\n const params = {};\n arr.forEach((value, index) => {\n params[spec.parameters.values[index].name] = value;\n });\n return params as T;\n}\n\nexport function joinParams(params: Params, spec: IdentifierSpec): string {\n return Object.values(spec.parameters.values)\n .map(parameter => {\n const param = params[parameter.name];\n return typeof param === \"string\"\n ? param\n : joinParams(param, parameter as IdentifierSpec);\n })\n .join(spec.parameters.delimiter);\n}\n\nexport function isValidId(id: string, spec: IdentifierSpec): boolean {\n // console.log(\"id\", id);\n // console.log(\"spec\", spec);\n // console.log(\"before regex\");\n if (!new RegExp(spec.regex).test(id)) return false;\n // console.log(\"after regex\");\n // console.log(\"before split\");\n const params = splitParams(id, spec);\n // console.log(\"after split\");\n // console.log(\"params\", params);\n // console.log(\"before length\");\n if (params.length !== Object.keys(spec.parameters.values).length)\n return false;\n // console.log(\"after length\");\n // console.log(\"before matches\");\n const matches = params\n .map((param, index) =>\n new RegExp(spec.parameters.values[index].regex).test(param)\n )\n .filter(x => !!x);\n if (matches.length !== params.length) return false;\n // console.log(\"after matches\");\n return true;\n}\n","import { CAIP } from \"./spec\";\nimport { IdentifierSpec } from \"./types\";\nimport { isValidId, joinParams, getParams } from \"./utils\";\n\nexport interface ChainIdParams {\n namespace: string;\n reference: string;\n}\n\nexport class ChainId {\n public static spec: IdentifierSpec = CAIP[\"2\"];\n\n public static parse(id: string): ChainIdParams {\n if (!isValidId(id, this.spec)) {\n throw new Error(`Invalid ${this.spec.name} provided: ${id}`);\n }\n return new ChainId(getParams<ChainIdParams>(id, this.spec)).toJSON();\n }\n\n public static format(params: ChainIdParams): string {\n return joinParams(params as any, this.spec);\n }\n\n public namespace: string;\n public reference: string;\n\n constructor(params: ChainIdParams | string) {\n if (typeof params === \"string\") {\n params = ChainId.parse(params);\n }\n\n this.namespace = params.namespace;\n this.reference = params.reference;\n }\n\n public toString(): string {\n return ChainId.format(this.toJSON());\n }\n\n public toJSON(): ChainIdParams {\n return {\n namespace: this.namespace,\n reference: this.reference,\n };\n }\n}\n","import { ChainId, ChainIdParams } from \"./chain\";\nimport { CAIP } from \"./spec\";\nimport { IdentifierSpec } from \"./types\";\nimport { isValidId, joinParams, getParams } from \"./utils\";\n\nexport interface AccountIdSplitParams extends ChainIdParams {\n address: string;\n}\nexport interface AccountIdParams {\n chainId: string | ChainIdParams;\n address: string;\n}\n\nexport class AccountId {\n public static spec: IdentifierSpec = CAIP[\"10\"];\n\n public static parse(id: string): AccountIdParams {\n if (!isValidId(id, this.spec)) {\n throw new Error(`Invalid ${this.spec.name} provided: ${id}`);\n }\n const { namespace, reference, address } = getParams<AccountIdSplitParams>(\n id,\n this.spec\n );\n const chainId = new ChainId({ namespace, reference });\n return new AccountId({ chainId, address }).toJSON();\n }\n\n public static format(params: AccountIdParams): string {\n const chainId = new ChainId(params.chainId);\n const splitParams: AccountIdSplitParams = {\n ...chainId.toJSON(),\n address: params.address,\n };\n return joinParams(splitParams as any, this.spec);\n }\n\n public chainId: ChainId;\n public address: string;\n\n constructor(params: AccountIdParams | string) {\n if (typeof params === \"string\") {\n params = AccountId.parse(params);\n }\n\n this.chainId = new ChainId(params.chainId);\n this.address = params.address;\n }\n\n public toString(): string {\n return AccountId.format(this.toJSON());\n }\n\n public toJSON(): AccountIdParams {\n return {\n chainId: this.chainId.toJSON(),\n address: this.address,\n };\n }\n}\n","import { CAIP } from \"./spec\";\nimport { IdentifierSpec } from \"./types\";\nimport { isValidId, joinParams, getParams } from \"./utils\";\n\nexport interface AssetNameParams {\n namespace: string;\n reference: string;\n}\n\nexport class AssetName {\n public static spec: IdentifierSpec = CAIP[\"19\"].assetName;\n\n public static parse(id: string): AssetNameParams {\n if (!isValidId(id, this.spec)) {\n throw new Error(`Invalid ${this.spec.name} provided: ${id}`);\n }\n return new AssetName(getParams<AssetNameParams>(id, this.spec)).toJSON();\n }\n\n public static format(params: AssetNameParams): string {\n return joinParams(params as any, this.spec);\n }\n\n public namespace: string;\n public reference: string;\n\n constructor(params: AssetNameParams | string) {\n if (typeof params === \"string\") {\n params = AssetName.parse(params);\n }\n\n this.namespace = params.namespace;\n this.reference = params.reference;\n }\n\n public toString(): string {\n return AssetName.format(this.toJSON());\n }\n\n public toJSON(): AssetNameParams {\n return {\n namespace: this.namespace,\n reference: this.reference,\n };\n }\n}\n","import { AssetName, AssetNameParams } from \"./assetName\";\nimport { ChainId, ChainIdParams } from \"./chain\";\nimport { CAIP } from \"./spec\";\nimport { IdentifierSpec } from \"./types\";\nimport { isValidId, joinParams, getParams } from \"./utils\";\n\nexport interface AssetTypeParams {\n chainId: string | ChainIdParams;\n assetName: string | AssetNameParams;\n}\n\nexport class AssetType {\n public static spec: IdentifierSpec = CAIP[\"19\"].assetType;\n\n public static parse(id: string): AssetTypeParams {\n if (!isValidId(id, this.spec)) {\n throw new Error(`Invalid ${this.spec.name} provided: ${id}`);\n }\n return new AssetType(getParams<AssetTypeParams>(id, this.spec)).toJSON();\n }\n\n public static format(params: AssetTypeParams): string {\n return joinParams(params as any, this.spec);\n }\n\n public chainId: ChainId;\n public assetName: AssetName;\n\n constructor(params: AssetTypeParams | string) {\n if (typeof params === \"string\") {\n params = AssetType.parse(params);\n }\n\n this.chainId = new ChainId(params.chainId);\n this.assetName = new AssetName(params.assetName);\n }\n\n public toString(): string {\n return AssetType.format(this.toJSON());\n }\n\n public toJSON(): AssetTypeParams {\n return {\n chainId: this.chainId.toJSON(),\n assetName: this.assetName,\n };\n }\n}\n","import { AssetName, AssetNameParams } from \"./assetName\";\nimport { ChainId, ChainIdParams } from \"./chain\";\nimport { CAIP } from \"./spec\";\nimport { IdentifierSpec } from \"./types\";\nimport { isValidId, joinParams, getParams } from \"./utils\";\n\nexport interface AssetIdParams {\n chainId: string | ChainIdParams;\n assetName: string | AssetNameParams;\n tokenId: string;\n}\n\nexport class AssetId {\n public static spec: IdentifierSpec = CAIP[\"19\"].assetId;\n\n public static parse(id: string): AssetIdParams {\n if (!isValidId(id, this.spec)) {\n throw new Error(`Invalid ${this.spec.name} provided: ${id}`);\n }\n return new AssetId(getParams<AssetIdParams>(id, this.spec)).toJSON();\n }\n\n public static format(params: AssetIdParams): string {\n return joinParams(params as any, this.spec);\n }\n\n public chainId: ChainId;\n public assetName: AssetName;\n public tokenId: string;\n\n constructor(params: AssetIdParams | string) {\n if (typeof params === \"string\") {\n params = AssetId.parse(params);\n }\n\n this.chainId = new ChainId(params.chainId);\n this.assetName = new AssetName(params.assetName);\n this.tokenId = params.tokenId;\n }\n\n public toString(): string {\n return AssetId.format(this.toJSON());\n }\n\n public toJSON(): AssetIdParams {\n return {\n chainId: this.chainId.toJSON(),\n assetName: this.assetName.toJSON(),\n tokenId: this.tokenId,\n };\n }\n}\n","import type { CoinType } from \"@ensdomains/address-encoder\";\nimport { AccountId as CaipAccountId } from \"caip\";\nimport type {\n AccountId,\n AccountIdString,\n ChainId,\n DefaultableChainId,\n Duration,\n Hex,\n InterpretedName,\n Node,\n} from \"enssdk\";\nimport { reinterpretName, toNormalizedAddress } from \"enssdk\";\nimport { isAddress, isHex, size } from \"viem\";\n/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\nimport { z } from \"zod/v4\";\n\nimport { ENSNamespaceIds } from \"../ens\";\nimport {\n type CurrencyId,\n CurrencyIds,\n type PriceDai,\n type PriceEth,\n type PriceUsdc,\n type SerializedPriceEth,\n} from \"./currencies\";\nimport type { BlockRef, Datetime } from \"./types\";\n\n/**\n * Parses a string value as a boolean.\n */\nexport const makeBooleanStringSchema = (valueLabel: string = \"Value\") =>\n z\n .string()\n .pipe(\n z.enum([\"true\", \"false\"], {\n error: `${valueLabel} must be 'true' or 'false'.`,\n }),\n )\n .transform((val) => val === \"true\");\n\n/**\n * Parses a numeric value as a finite non-negative number.\n */\nexport const makeFiniteNonNegativeNumberSchema = (valueLabel: string = \"Value\") =>\n z\n .number({\n // NOTE: Zod's implementation of `number` automatically rejects NaN and Infinity values.\n // and therefore the finite check is implicit.\n error: `${valueLabel} must be a finite number.`,\n })\n .nonnegative({\n error: `${valueLabel} must be a non-negative number (>=0).`,\n });\n\n/**\n * Parses a numeric value as an integer.\n */\nexport const makeIntegerSchema = (valueLabel: string = \"Value\") =>\n z.int({\n error: `${valueLabel} must be an integer.`,\n });\n\n/**\n * Parses a numeric value as a positive integer.\n */\nexport const makePositiveIntegerSchema = (valueLabel: string = \"Value\") =>\n makeIntegerSchema(valueLabel).positive({\n error: `${valueLabel} must be a positive integer (>0).`,\n });\n\n/**\n * Parses a numeric value as a non-negative integer.\n */\nexport const makeNonNegativeIntegerSchema = (valueLabel: string = \"Value\") =>\n makeIntegerSchema(valueLabel).nonnegative({\n error: `${valueLabel} must be a non-negative integer (>=0).`,\n });\n\n/**\n * Parses a numeric value as {@link Duration}\n */\nexport const makeDurationSchema = (valueLabel: string = \"Value\") =>\n z\n .number({\n error: `${valueLabel} must be a number.`,\n })\n .pipe(makeNonNegativeIntegerSchema(valueLabel));\n\n/**\n * Parses Chain ID\n *\n * {@link ChainId}\n */\nexport const makeChainIdSchema = (valueLabel: string = \"Chain ID\") =>\n makePositiveIntegerSchema(valueLabel).transform((val) => val as ChainId);\n\n/**\n * Parses a serialized representation of {@link ChainId}.\n */\nexport const makeChainIdStringSchema = (valueLabel: string = \"Chain ID String\") =>\n z\n .string({ error: `${valueLabel} must be a string representing a chain ID.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a positive integer (>0).` }))\n .pipe(makeChainIdSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses Defaultable Chain ID\n *\n * {@link DefaultableChainId}\n */\nexport const makeDefaultableChainIdSchema = (valueLabel: string = \"Defaultable Chain ID\") =>\n makeNonNegativeIntegerSchema(valueLabel).transform((val) => val as DefaultableChainId);\n\n/**\n * Parses a serialized representation of {@link DefaultableChainId}.\n */\nexport const makeDefaultableChainIdStringSchema = (\n valueLabel: string = \"Defaultable Chain ID String\",\n) =>\n z\n .string({ error: `${valueLabel} must be a string representing a chain ID.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a non-negative integer (>=0).` }))\n .pipe(makeDefaultableChainIdSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses {@link CoinType}.\n */\nexport const makeCoinTypeSchema = (valueLabel: string = \"Coin Type\") =>\n z\n .number({ error: `${valueLabel} must be a number.` })\n .int({ error: `${valueLabel} must be an integer.` })\n .nonnegative({ error: `${valueLabel} must be a non-negative integer (>=0).` })\n .transform((val) => val as CoinType);\n\n/**\n * Parses a serialized representation of {@link CoinType}.\n */\nexport const makeCoinTypeStringSchema = (valueLabel: string = \"Coin Type String\") =>\n z\n .string({ error: `${valueLabel} must be a string representing a coin type.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a non-negative integer (>=0).` }))\n .pipe(makeCoinTypeSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses a serialized representation of an EVM address into a {@link NormalizedAddress}.\n */\nexport const makeNormalizedAddressSchema = (valueLabel: string = \"EVM address\") =>\n z\n .string()\n .check((ctx) => {\n // NOTE: we intentionally use isAddress here instead of isNormalizedAddress, which allows this\n // schema to transform (via toNormalizedAddress) the input into a normalized address.\n if (!isAddress(ctx.value, { strict: false })) {\n ctx.issues.push({\n code: \"custom\",\n message: `${valueLabel} must be a valid EVM address`,\n input: ctx.value,\n });\n }\n })\n .transform((val) => toNormalizedAddress(val));\n\n/**\n * Parses an ISO 8601 string representations of {@link Datetime}\n */\nexport const makeDatetimeSchema = (valueLabel: string = \"Datetime string\") =>\n z.iso\n .datetime({ error: `${valueLabel} must be a string in ISO 8601 format.` })\n .transform((v) => new Date(v));\n\n/**\n * Parses value as {@link UnixTimestamp}.\n */\nexport const makeUnixTimestampSchema = (valueLabel: string = \"Timestamp\") =>\n makeIntegerSchema(valueLabel);\n\n/**\n * Parses a string representations of {@link URL}\n */\nexport const makeUrlSchema = (valueLabel: string = \"Value\") =>\n z\n .url({\n error: `${valueLabel} must be a valid URL string (e.g., http://localhost:8080 or https://example.com).`,\n abort: true,\n })\n .transform((v) => new URL(v));\n\n/**\n * Parses a serialized representation of a comma separated list.\n */\nexport const makeCommaSeparatedList = (valueLabel: string = \"Value\") =>\n z\n .string({ error: `${valueLabel} must be a comma separated list.` })\n .transform((val) => val.split(\",\").filter(Boolean))\n .refine((val) => val.length > 0, {\n error: `${valueLabel} must be a comma separated list with at least one value.`,\n });\n\n/**\n * Parses a numeric value as a block number.\n */\nexport const makeBlockNumberSchema = (valueLabel: string = \"Block number\") =>\n makeNonNegativeIntegerSchema(valueLabel);\n\n/**\n * Parses an object value as the {@link BlockRef} object.\n */\nexport const makeBlockRefSchema = (valueLabel: string = \"Value\") =>\n z.strictObject(\n {\n timestamp: makeUnixTimestampSchema(`${valueLabel}.timestamp`),\n number: makeBlockNumberSchema(`${valueLabel}.number`),\n },\n {\n error: `${valueLabel} must be a valid BlockRef object.`,\n },\n );\n\n/**\n * Parses a string value as ENSNamespaceId.\n */\nexport const makeENSNamespaceIdSchema = (valueLabel: string = \"ENSNamespaceId\") =>\n z.enum(ENSNamespaceIds, {\n error() {\n return `Invalid ${valueLabel}. Supported ENS namespace IDs are: ${Object.keys(ENSNamespaceIds).join(\", \")}`;\n },\n });\n\nconst makePriceAmountSchema = (valueLabel: string = \"Amount\") =>\n z.coerce\n .bigint({\n error: `${valueLabel} must represent a bigint.`,\n })\n .nonnegative({\n error: `${valueLabel} must not be negative.`,\n });\n\nconst makeSerializedCurrencyAmountSchema = (valueLabel: string = \"Serialized Currency Amount\") =>\n z.string({ error: `${valueLabel} must be a string.` }).regex(/^\\d+$/, {\n error: `${valueLabel} can only contain digits (0-9) and must represent a non-negative integer.`,\n });\n\nexport const makePriceCurrencySchema = (\n currency: CurrencyId,\n valueLabel: string = \"Price Currency\",\n) =>\n z.strictObject({\n amount: makePriceAmountSchema(`${valueLabel} amount`),\n\n currency: z.literal(currency, {\n error: `${valueLabel} currency must be set to '${currency}'.`,\n }),\n });\n\nexport const makeSerializedPriceCurrencySchema = (\n currency: CurrencyId,\n valueLabel: string = \"Price Currency\",\n) =>\n z.strictObject({\n amount: makeSerializedCurrencyAmountSchema(`${valueLabel} amount`),\n\n currency: z.literal(currency, {\n error: `${valueLabel} currency must be set to '${currency}'.`,\n }),\n });\n\n/**\n * Schema for {@link Price} type.\n */\nexport const makePriceSchema = (valueLabel: string = \"Price\") =>\n z.discriminatedUnion(\n \"currency\",\n [\n makePriceCurrencySchema(CurrencyIds.ETH, valueLabel),\n makePriceCurrencySchema(CurrencyIds.USDC, valueLabel),\n makePriceCurrencySchema(CurrencyIds.DAI, valueLabel),\n ],\n { error: `${valueLabel} currency must be one of ${Object.values(CurrencyIds).join(\", \")}` },\n );\n\n/**\n * Schema for {@link PriceEth} type.\n */\nexport const makePriceEthSchema = (valueLabel: string = \"Price ETH\") =>\n makePriceCurrencySchema(CurrencyIds.ETH, valueLabel).transform((v) => v as PriceEth);\n\nexport const makeSerializedPriceEthSchema = (valueLabel: string = \"Serialized Price ETH\") =>\n makeSerializedPriceCurrencySchema(CurrencyIds.ETH, valueLabel).transform(\n (v) => v as SerializedPriceEth,\n );\n\n/**\n * Schema for {@link PriceUsdc} type.\n */\nexport const makePriceUsdcSchema = (valueLabel: string = \"Price USDC\") =>\n makePriceCurrencySchema(CurrencyIds.USDC, valueLabel).transform((v) => v as PriceUsdc);\n\n/**\n * Schema for {@link PriceDai} type.\n */\nexport const makePriceDaiSchema = (valueLabel: string = \"Price DAI\") =>\n makePriceCurrencySchema(CurrencyIds.DAI, valueLabel).transform((v) => v as PriceDai);\n\n/**\n * Schema for {@link AccountId} type.\n */\nexport const makeAccountIdSchema = (valueLabel: string = \"AccountId\") =>\n z.strictObject({\n chainId: makeChainIdSchema(`${valueLabel} chain ID`),\n address: makeNormalizedAddressSchema(`${valueLabel} address`),\n });\n\n/**\n * Schema for {@link AccountIdString} type.\n */\nexport const makeAccountIdStringSchema = (valueLabel: string = \"Account ID String\") =>\n z.coerce\n .string()\n .transform((v) => {\n const result = new CaipAccountId(v);\n\n return {\n chainId: Number(result.chainId.reference),\n address: result.address,\n };\n })\n .pipe(makeAccountIdSchema(valueLabel));\n\n/**\n * Make a schema for {@link Hex} representation of bytes array.\n *\n * @param {number} options.bytesCount expected count of bytes to be hex-encoded\n */\nexport const makeHexStringSchema = (\n options: { bytesCount: number },\n valueLabel: string = \"String representation of bytes array\",\n) =>\n z\n .string()\n .check(function invariant_isHexEncoded(ctx) {\n if (!isHex(ctx.value)) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} must be a hexadecimal value which starts with '0x'.`,\n });\n }\n })\n .transform((v) => v as Hex)\n .check(function invariant_encodesRequiredBytesCount(ctx) {\n const expectedBytesCount = options.bytesCount;\n const actualBytesCount = size(ctx.value);\n\n if (actualBytesCount !== expectedBytesCount) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} must represent exactly ${expectedBytesCount} bytes. Currently represented bytes count: ${actualBytesCount}.`,\n });\n }\n });\n\n/**\n * Make schema for {@link Node}.\n */\nexport const makeNodeSchema = (valueLabel: string = \"Node\") =>\n makeHexStringSchema({ bytesCount: 32 }, valueLabel);\n\n/**\n * Make schema for Transaction Hash\n */\nexport const makeTransactionHashSchema = (valueLabel: string = \"Transaction hash\") =>\n makeHexStringSchema({ bytesCount: 32 }, valueLabel);\n\n/**\n * Make schema for {@link ReinterpretedName}.\n */\nexport const makeReinterpretedNameSchema = (valueLabel: string = \"Reinterpreted Name\") =>\n z\n .string()\n .transform((v) => v as InterpretedName)\n .check((ctx) => {\n try {\n reinterpretName(ctx.value);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} cannot be reinterpreted: ${errorMessage}`,\n });\n }\n })\n .transform(reinterpretName);\n","import { parseUnits } from \"viem\";\n\nimport { scaleBigintByNumber } from \"./numbers\";\n\n/**\n * Identifiers for supported currencies.\n *\n * TODO: Add support for WETH\n */\nexport const CurrencyIds = {\n ETH: \"ETH\",\n USDC: \"USDC\",\n DAI: \"DAI\",\n} as const;\n\nexport type CurrencyId = (typeof CurrencyIds)[keyof typeof CurrencyIds];\n\n/**\n * The amount of the currency in the smallest unit of the currency\n * (see {@link CurrencyInfo.decimals} for the currency).\n *\n * Guaranteed to be non-negative.\n */\nexport type CurrencyAmount = bigint;\n\n/**\n * Serialized representation of {@link CurrencyAmount}.\n */\nexport type SerializedCurrencyAmount = string;\n\nexport interface PriceEth {\n currency: typeof CurrencyIds.ETH;\n\n amount: CurrencyAmount;\n}\n\nexport interface PriceDai {\n currency: typeof CurrencyIds.DAI;\n\n amount: CurrencyAmount;\n}\n\nexport interface PriceUsdc {\n currency: typeof CurrencyIds.USDC;\n\n amount: CurrencyAmount;\n}\n\nexport type Price = PriceEth | PriceDai | PriceUsdc;\n\n/**\n * Serialized representation of {@link PriceEth}.\n */\nexport interface SerializedPriceEth extends Omit<PriceEth, \"amount\"> {\n amount: SerializedCurrencyAmount;\n}\n\n/**\n * Serialized representation of {@link PriceDai}.\n */\nexport interface SerializedPriceDai extends Omit<PriceDai, \"amount\"> {\n amount: SerializedCurrencyAmount;\n}\n\n/**\n * Serialized representation of {@link PriceUsdc}.\n */\nexport interface SerializedPriceUsdc extends Omit<PriceUsdc, \"amount\"> {\n amount: SerializedCurrencyAmount;\n}\n\n/**\n * Serialized representation of {@link Price}.\n */\nexport type SerializedPrice = SerializedPriceEth | SerializedPriceDai | SerializedPriceUsdc;\n\nexport interface CurrencyInfo {\n id: CurrencyId;\n name: string;\n decimals: number;\n}\n\nconst currencyInfo: Record<CurrencyId, CurrencyInfo> = {\n [CurrencyIds.ETH]: {\n id: CurrencyIds.ETH,\n name: \"ETH\",\n decimals: 18,\n },\n [CurrencyIds.USDC]: {\n id: CurrencyIds.USDC,\n name: \"USDC\",\n decimals: 6,\n },\n [CurrencyIds.DAI]: {\n id: CurrencyIds.DAI,\n name: \"Dai Stablecoin\",\n decimals: 18,\n },\n};\n\n/**\n * Get currency info for a provided currency.\n */\nexport function getCurrencyInfo(currencyId: CurrencyId): CurrencyInfo {\n return currencyInfo[currencyId];\n}\n\n/**\n * Create price in ETH for given amount.\n */\nexport function priceEth(amount: Price[\"amount\"]): PriceEth {\n return {\n amount,\n currency: CurrencyIds.ETH,\n };\n}\n\n/**\n * Create price in USDC for given amount.\n */\nexport function priceUsdc(amount: Price[\"amount\"]): PriceUsdc {\n return {\n amount,\n currency: CurrencyIds.USDC,\n };\n}\n\n/**\n * Create price in DAI for given amount.\n */\nexport function priceDai(amount: Price[\"amount\"]): PriceDai {\n return {\n amount,\n currency: CurrencyIds.DAI,\n };\n}\n\n/**\n * Check if two prices have the same currency.\n */\nexport function isPriceCurrencyEqual(priceA: Price, priceB: Price): boolean {\n return priceA.currency === priceB.currency;\n}\n\n/**\n * Check if two {@link Price} values have the same currency and amount.\n */\nexport function isPriceEqual(priceA: Price, priceB: Price): boolean {\n return isPriceCurrencyEqual(priceA, priceB) && priceA.amount === priceB.amount;\n}\n\n/**\n * Add prices\n *\n * @param prices at least two {@link Price} values to be added together.\n * @returns total of all prices.\n * @throws if not all prices have the same currency.\n */\nexport function addPrices<const PriceType extends Price = Price>(\n ...prices: [PriceType, PriceType, ...PriceType[]]\n): PriceType {\n const firstPrice = prices[0];\n const allPricesInSameCurrency = prices.every((price) => isPriceCurrencyEqual(firstPrice, price));\n\n if (allPricesInSameCurrency === false) {\n throw new Error(\"All prices must have the same currency to be added together.\");\n }\n\n const { currency } = firstPrice;\n\n return prices.reduce(\n (acc, price) => ({\n amount: acc.amount + price.amount,\n currency,\n }),\n {\n amount: 0n,\n currency: firstPrice.currency,\n },\n ) as PriceType;\n}\n\n/**\n * Scales a Price object by a floating-point number while maintaining precision.\n *\n * **Important:** The precision of this method is bound to the precision of float\n * in JavaScript. For more information, see {@link scaleBigintByNumber}.\n *\n * @param price - The Price object to scale\n * @param scaleFactor - The number to multiply by (can be a decimal like 0.5)\n * @returns A new Price object with the scaled amount and same currency\n *\n * @throws {Error} If scaleFactor is negative, NaN, or infinite\n * @throws {Error} If price amount is negative\n *\n * @example\n * // Scale USDC price by 0.5\n * const price = priceUsdc(1000000n); // 1 USDC\n * const scaled = scalePrice(price, 0.5); // 0.5 USDC\n * // scaled = { currency: \"USDC\", amount: 500000n }\n *\n * @example\n * // Calculate 33.3% of ETH price\n * const ethPrice = priceEth(1000000000000000000n); // 1 ETH\n * const share = scalePrice(ethPrice, 0.333);\n * // share = { currency: \"ETH\", amount: 333000000000000000n }\n */\nexport function scalePrice<T extends Price>(price: T, scaleFactor: number): T {\n const scaledAmount = scaleBigintByNumber(price.amount, scaleFactor);\n\n return {\n ...price,\n amount: scaledAmount,\n };\n}\n\n/**\n * Validates a decimal string for currency parsing.\n *\n * @param value - The decimal string to validate\n * @throws {Error} If value is empty, whitespace-only or untrimmed\n * @throws {Error} If value represents a negative number\n */\nfunction validateAmountToParse(value: string): void {\n const trimmed = value.trim();\n if (trimmed === \"\") {\n throw new Error(\"amount must be a non-negative decimal string\");\n }\n if (value !== trimmed) {\n throw new Error(\"amount must not have leading or trailing whitespace\");\n }\n if (trimmed.startsWith(\"-\")) {\n throw new Error(\"amount must be a non-negative decimal string\");\n }\n}\n\n/**\n * Parses a string representation of ETH into a {@link PriceEth} object.\n *\n * Uses {@link getCurrencyInfo} to get the correct number of decimals (18) for ETH\n * and {@link parseUnits} from viem to convert the decimal string to a bigint.\n *\n * **Note:** Values with more than 18 decimal places will be truncated/rounded by viem's `parseUnits`.\n *\n * @param value - The decimal string to parse (e.g., \"0.015\" for 0.015 ETH)\n * @returns A PriceEth object with the amount in wei (smallest unit)\n *\n * @throws {Error} If value is empty, whitespace-only or untrimmed\n * @throws {Error} If value represents a negative number\n * @throws {Error} If value is not a valid decimal string (e.g., \"abc\", \"1.2.3\")\n *\n * @example\n * parseEth(\"0.015\") // returns { currency: \"ETH\", amount: 15000000000000000n }\n * parseEth(\"1\") // returns { currency: \"ETH\", amount: 1000000000000000000n }\n * parseEth(\"123.456789012345678\") // returns { currency: \"ETH\", amount: 123456789012345678000n }\n */\nexport function parseEth(value: string): PriceEth {\n validateAmountToParse(value);\n const currencyInfo = getCurrencyInfo(CurrencyIds.ETH);\n const amount = parseUnits(value, currencyInfo.decimals);\n return priceEth(amount);\n}\n\n/**\n * Parses a string representation of USDC into a {@link PriceUsdc} object.\n *\n * Uses {@link getCurrencyInfo} to get the correct number of decimals (6) for USDC\n * and {@link parseUnits} from viem to convert the decimal string to a bigint.\n *\n * **Note:** Values with more than 6 decimal places will be truncated/rounded by viem's `parseUnits`.\n *\n * @param value - The decimal string to parse (e.g., \"123.45678\" for $123.45678)\n * @returns A PriceUsdc object with the amount in the smallest unit (6 decimals)\n *\n * @throws {Error} If value is empty, whitespace-only or untrimmed\n * @throws {Error} If value represents a negative number\n * @throws {Error} If value is not a valid decimal string (e.g., \"abc\", \"1.2.3\")\n *\n * @example\n * parseUsdc(\"123.45678\") // returns { currency: \"USDC\", amount: 123456780n }\n * parseUsdc(\"1\") // returns { currency: \"USDC\", amount: 1000000n }\n * parseUsdc(\"0.001\") // returns { currency: \"USDC\", amount: 1000n }\n */\nexport function parseUsdc(value: string): PriceUsdc {\n validateAmountToParse(value);\n const currencyInfo = getCurrencyInfo(CurrencyIds.USDC);\n const amount = parseUnits(value, currencyInfo.decimals);\n return priceUsdc(amount);\n}\n\n/**\n * Parses a string representation of DAI into a {@link PriceDai} object.\n *\n * Uses {@link getCurrencyInfo} to get the correct number of decimals (18) for DAI\n * and {@link parseUnits} from viem to convert the decimal string to a bigint.\n *\n * **Note:** Values with more than 18 decimal places will be truncated/rounded by viem's `parseUnits`.\n *\n * @param value - The decimal string to parse (e.g., \"123.456789012345678\" for 123.456789012345678 DAI)\n * @returns A PriceDai object with the amount in the smallest unit (18 decimals)\n *\n * @throws {Error} If value is empty, whitespace-only or untrimmed\n * @throws {Error} If value represents a negative number\n * @throws {Error} If value is not a valid decimal string (e.g., \"abc\", \"1.2.3\")\n *\n * @example\n * parseDai(\"123.456789012345678\") // returns { currency: \"DAI\", amount: 123456789012345678000n }\n * parseDai(\"1\") // returns { currency: \"DAI\", amount: 1000000000000000000n }\n * parseDai(\"0.001\") // returns { currency: \"DAI\", amount: 1000000000000000n }\n */\nexport function parseDai(value: string): PriceDai {\n validateAmountToParse(value);\n const currencyInfo = getCurrencyInfo(CurrencyIds.DAI);\n const amount = parseUnits(value, currencyInfo.decimals);\n return priceDai(amount);\n}\n","/**\n * Converts a bigint value into a number value.\n *\n * @throws when value is outside the range of `Number.MIN_SAFE_INTEGER` and\n * `Number.MAX_SAFE_INTEGER`.\n */\nexport function bigIntToNumber(n: bigint): number {\n if (n < Number.MIN_SAFE_INTEGER) {\n throw new Error(\n `The bigint '${n.toString()}' value is too low to be to converted into a number.'`,\n );\n }\n\n if (n > Number.MAX_SAFE_INTEGER) {\n throw new Error(\n `The bigint '${n.toString()}' value is too high to be to converted into a number.'`,\n );\n }\n\n return Number(n);\n}\n\n/**\n * Scales a bigint value by a floating-point number while maintaining precision.\n *\n * **How it works:**\n * Converts the float to a fixed-point decimal string, extracts the decimal digits,\n * and performs multiplication using bigint arithmetic: `(value * numerator) / denominator`.\n *\n * **Important:** JavaScript floats (IEEE 754 double-precision) have ~15-17 significant\n * decimal digits. Any imprecision in the input `scaleFactor` will be reflected in the result.\n * For example, `1/3` in JavaScript is `0.3333333333333333...` (not infinite threes), and\n * this function accurately preserves that limitation.\n *\n * @param value - The bigint value to scale (must be non-negative)\n * @param scaleFactor - The non-negative number to multiply by (can be a decimal like 0.5 or 0.333)\n * @returns The scaled bigint value, rounded down via integer division\n *\n * @throws {Error} If value is negative\n * @throws {Error} If scaleFactor is negative, NaN, infinite, or >= 1e21\n *\n * @example\n * // Scale by 0.5\n * scaleBigintByNumber(1000n, 0.5) // returns 500n\n *\n * @example\n * // Scale by 1/3 (uses JavaScript's float representation)\n * scaleBigintByNumber(1000n, 1/3) // returns 333n\n *\n * @example\n * // Scale USDC amount (6 decimals) by percentage\n * scaleBigintByNumber(5000000000n, 0.4) // 5000 USDC * 0.4 = 2000000000n (2000 USDC)\n */\nexport function scaleBigintByNumber(value: bigint, scaleFactor: number): bigint {\n // Validate inputs\n if (value < 0n) {\n throw new Error(`scaleBigintByNumber: value must be non-negative, got: ${value.toString()}`);\n }\n\n if (!Number.isFinite(scaleFactor)) {\n throw new Error(\n `scaleBigintByNumber: scaleFactor must be a finite number, got: ${scaleFactor}`,\n );\n }\n\n if (scaleFactor < 0) {\n throw new Error(`scaleBigintByNumber: scaleFactor must be non-negative, got: ${scaleFactor}`);\n }\n\n // Reject scaleFactor >= 1e21 to prevent toFixed(20) from producing exponential notation that breaks BigInt parsing\n if (scaleFactor >= 1e21) {\n throw new Error(`scaleBigintByNumber: scaleFactor must be less than 1e21, got: ${scaleFactor}`);\n }\n\n // Handle special cases\n if (value === 0n || scaleFactor === 0) {\n return 0n;\n }\n\n if (scaleFactor === 1) {\n return value;\n }\n\n // Convert the float to a fixed-point decimal string with 20 decimal places.\n // Why 20?\n // - JavaScript floats have ~15-17 significant digits of precision (IEEE 754)\n // - Using 20 ensures we capture all meaningful precision\n // - Avoids scientific notation (e.g., \"1e-10\") which would break our parsing\n // - Extra digits beyond float precision are deterministic (not random noise)\n const fixedStr = scaleFactor.toFixed(20);\n\n // Split into integer and decimal parts\n // Example: \"0.50000000000000000000\" -> [\"0\", \"50000000000000000000\"]\n const [integerPart, decimalPart = \"\"] = fixedStr.split(\".\");\n\n // Remove trailing zeros to get the minimal precision needed\n // Example: \"50000000000000000000\" -> \"5\"\n // This optimization reduces the size of numerator/denominator\n const trimmedDecimal = decimalPart.replace(/0+$/, \"\") || \"0\";\n\n // Construct the numerator by concatenating integer and decimal parts\n // Example: integerPart=\"0\", trimmedDecimal=\"5\" -> \"05\" -> BigInt = 5n\n const numerator = BigInt(integerPart + trimmedDecimal);\n\n // Denominator is 10^(number of decimal digits we kept)\n // Example: trimmedDecimal.length = 1 -> 10^1 = 10n\n const denominator = 10n ** BigInt(trimmedDecimal.length);\n\n // Perform the multiplication and division in bigint space\n // Formula: (value * numerator) / denominator\n // Example: (1000n * 5n) / 10n = 5000n / 10n = 500n\n // Integer division automatically floors the result\n return (value * numerator) / denominator;\n}\n","import type { ChainId, ChainIdString, DatetimeISO8601, UrlString } from \"enssdk\";\n\nimport type {\n Price,\n PriceDai,\n PriceEth,\n PriceUsdc,\n SerializedPrice,\n SerializedPriceDai,\n SerializedPriceEth,\n SerializedPriceUsdc,\n} from \"./currencies\";\nimport type { Datetime } from \"./types\";\n\n/**\n * Serializes a {@link ChainId} value into its string representation.\n */\nexport function serializeChainId(chainId: ChainId): ChainIdString {\n return chainId.toString();\n}\n\n/**\n * Serializes a {@link Datetime} value into its string representation.\n */\nexport function serializeDatetime(datetime: Datetime): DatetimeISO8601 {\n return datetime.toISOString();\n}\n\n/**\n * Serializes a {@link URL} value into its string representation.\n */\nexport function serializeUrl(url: URL): UrlString {\n return url.toString();\n}\n\n/**\n * Serializes a {@link Price} object.\n */\nexport function serializePrice(price: Price): SerializedPrice {\n return {\n currency: price.currency,\n amount: price.amount.toString(),\n };\n}\n\n/**\n * Serializes a {@link PriceEth} object.\n */\nexport function serializePriceEth(price: PriceEth): SerializedPriceEth {\n return serializePrice(price) as SerializedPriceEth;\n}\n\n/**\n * Serializes a {@link PriceUsdc} object.\n */\nexport function serializePriceUsdc(price: PriceUsdc): SerializedPriceUsdc {\n return serializePrice(price) as SerializedPriceUsdc;\n}\n\n/**\n * Serializes a {@link PriceDai} object.\n */\nexport function serializePriceDai(price: PriceDai): SerializedPriceDai {\n return serializePrice(price) as SerializedPriceDai;\n}\n","import z from \"zod/v4\";\n\nimport {\n makeDurationSchema,\n makeFiniteNonNegativeNumberSchema,\n makeNonNegativeIntegerSchema,\n makeNormalizedAddressSchema,\n makePositiveIntegerSchema,\n makePriceEthSchema,\n makePriceUsdcSchema,\n makeUnixTimestampSchema,\n} from \"@ensnode/ensnode-sdk/internal\";\n\nimport {\n makeBaseReferralProgramEditionSummarySchema,\n makeBaseReferralProgramRulesSchema,\n makeBaseReferrerLeaderboardPageSchema,\n makeReferralProgramStatusSchema,\n} from \"../../shared/api/zod-schemas\";\nimport { ReferrerEditionMetricsTypeIds } from \"../../shared/edition-metrics\";\nimport { ReferralProgramAwardModels } from \"../../shared/rules\";\n\n/**\n * Schema for {@link ReferralProgramRulesPieSplit}.\n */\nexport const makeReferralProgramRulesPieSplitSchema = (\n valueLabel: string = \"ReferralProgramRulesPieSplit\",\n) =>\n makeBaseReferralProgramRulesSchema(valueLabel).safeExtend({\n awardModel: z.literal(ReferralProgramAwardModels.PieSplit),\n awardPool: makePriceUsdcSchema(`${valueLabel}.awardPool`),\n maxQualifiedReferrers: makeNonNegativeIntegerSchema(`${valueLabel}.maxQualifiedReferrers`),\n });\n\n/**\n * Schema for {@link AwardedReferrerMetricsPieSplit} (with numeric rank).\n */\nexport const makeAwardedReferrerMetricsPieSplitSchema = (\n valueLabel: string = \"AwardedReferrerMetricsPieSplit\",\n) =>\n z.object({\n referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`),\n totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),\n totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),\n totalRevenueContribution: makePriceEthSchema(`${valueLabel}.totalRevenueContribution`),\n score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),\n rank: makePositiveIntegerSchema(`${valueLabel}.rank`),\n isQualified: z.boolean(),\n finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(\n 1,\n `${valueLabel}.finalScoreBoost must be <= 1`,\n ),\n finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),\n awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(\n 1,\n `${valueLabel}.awardPoolShare must be <= 1`,\n ),\n awardPoolApproxValue: makePriceUsdcSchema(`${valueLabel}.awardPoolApproxValue`),\n });\n\n/**\n * Schema for {@link UnrankedReferrerMetricsPieSplit} (with null rank).\n */\nexport const makeUnrankedReferrerMetricsPieSplitSchema = (\n valueLabel: string = \"UnrankedReferrerMetricsPieSplit\",\n) =>\n z.object({\n referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`),\n totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),\n totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),\n totalRevenueContribution: makePriceEthSchema(`${valueLabel}.totalRevenueContribution`),\n score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),\n rank: z.null(),\n isQualified: z.literal(false),\n finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(\n 1,\n `${valueLabel}.finalScoreBoost must be <= 1`,\n ),\n finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),\n awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(\n 1,\n `${valueLabel}.awardPoolShare must be <= 1`,\n ),\n awardPoolApproxValue: makePriceUsdcSchema(`${valueLabel}.awardPoolApproxValue`),\n });\n\n/**\n * Schema for {@link AggregatedReferrerMetricsPieSplit}.\n */\nexport const makeAggregatedReferrerMetricsPieSplitSchema = (\n valueLabel: string = \"AggregatedReferrerMetricsPieSplit\",\n) =>\n z.object({\n grandTotalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.grandTotalReferrals`),\n grandTotalIncrementalDuration: makeDurationSchema(\n `${valueLabel}.grandTotalIncrementalDuration`,\n ),\n grandTotalRevenueContribution: makePriceEthSchema(\n `${valueLabel}.grandTotalRevenueContribution`,\n ),\n grandTotalQualifiedReferrersFinalScore: makeFiniteNonNegativeNumberSchema(\n `${valueLabel}.grandTotalQualifiedReferrersFinalScore`,\n ),\n minFinalScoreToQualify: makeFiniteNonNegativeNumberSchema(\n `${valueLabel}.minFinalScoreToQualify`,\n ),\n });\n\n/**\n * Schema for {@link ReferrerEditionMetricsRankedPieSplit}.\n */\nexport const makeReferrerEditionMetricsRankedPieSplitSchema = (\n valueLabel: string = \"ReferrerEditionMetricsRankedPieSplit\",\n) =>\n z\n .object({\n awardModel: z.literal(ReferralProgramAwardModels.PieSplit),\n type: z.literal(ReferrerEditionMetricsTypeIds.Ranked),\n rules: makeReferralProgramRulesPieSplitSchema(`${valueLabel}.rules`),\n referrer: makeAwardedReferrerMetricsPieSplitSchema(`${valueLabel}.referrer`),\n aggregatedMetrics: makeAggregatedReferrerMetricsPieSplitSchema(\n `${valueLabel}.aggregatedMetrics`,\n ),\n status: makeReferralProgramStatusSchema(`${valueLabel}.status`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n })\n .refine((data) => data.awardModel === data.rules.awardModel, {\n message: `${valueLabel}.awardModel must equal ${valueLabel}.rules.awardModel`,\n path: [\"awardModel\"],\n });\n\n/**\n * Schema for {@link ReferrerEditionMetricsUnrankedPieSplit}.\n */\nexport const makeReferrerEditionMetricsUnrankedPieSplitSchema = (\n valueLabel: string = \"ReferrerEditionMetricsUnrankedPieSplit\",\n) =>\n z\n .object({\n awardModel: z.literal(ReferralProgramAwardModels.PieSplit),\n type: z.literal(ReferrerEditionMetricsTypeIds.Unranked),\n rules: makeReferralProgramRulesPieSplitSchema(`${valueLabel}.rules`),\n referrer: makeUnrankedReferrerMetricsPieSplitSchema(`${valueLabel}.referrer`),\n aggregatedMetrics: makeAggregatedReferrerMetricsPieSplitSchema(\n `${valueLabel}.aggregatedMetrics`,\n ),\n status: makeReferralProgramStatusSchema(`${valueLabel}.status`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n })\n .refine((data) => data.awardModel === data.rules.awardModel, {\n message: `${valueLabel}.awardModel must equal ${valueLabel}.rules.awardModel`,\n path: [\"awardModel\"],\n });\n\n/**\n * Schema for all {@link ReferrerEditionMetrics} variants of the pie-split award model\n * (both ranked and unranked).\n */\nexport const makeReferrerEditionMetricsPieSplitSchema = (\n valueLabel: string = \"ReferrerEditionMetricsPieSplit\",\n) =>\n z.discriminatedUnion(\"type\", [\n makeReferrerEditionMetricsRankedPieSplitSchema(valueLabel),\n makeReferrerEditionMetricsUnrankedPieSplitSchema(valueLabel),\n ]);\n\n/**\n * Schema for {@link ReferralProgramEditionSummaryPieSplit}.\n */\nexport const makeReferralProgramEditionSummaryPieSplitSchema = (\n valueLabel: string = \"ReferralProgramEditionSummaryPieSplit\",\n) =>\n makeBaseReferralProgramEditionSummarySchema(valueLabel)\n .safeExtend({\n awardModel: z.literal(ReferralProgramAwardModels.PieSplit),\n rules: makeReferralProgramRulesPieSplitSchema(`${valueLabel}.rules`),\n })\n .refine((data) => data.awardModel === data.rules.awardModel, {\n message: `${valueLabel}.awardModel must equal ${valueLabel}.rules.awardModel`,\n path: [\"awardModel\"],\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPagePieSplit}.\n */\nexport const makeReferrerLeaderboardPagePieSplitSchema = (\n valueLabel: string = \"ReferrerLeaderboardPagePieSplit\",\n) =>\n makeBaseReferrerLeaderboardPageSchema(valueLabel)\n .safeExtend({\n awardModel: z.literal(ReferralProgramAwardModels.PieSplit),\n rules: makeReferralProgramRulesPieSplitSchema(`${valueLabel}.rules`),\n referrers: z.array(\n makeAwardedReferrerMetricsPieSplitSchema(`${valueLabel}.referrers[record]`),\n ),\n aggregatedMetrics: makeAggregatedReferrerMetricsPieSplitSchema(\n `${valueLabel}.aggregatedMetrics`,\n ),\n })\n .refine((data) => data.awardModel === data.rules.awardModel, {\n message: `${valueLabel}.awardModel must equal ${valueLabel}.rules.awardModel`,\n path: [\"awardModel\"],\n });\n","import z from \"zod/v4\";\n\nimport {\n makeAccountIdSchema,\n makeNonNegativeIntegerSchema,\n makePositiveIntegerSchema,\n makeUnixTimestampSchema,\n makeUrlSchema,\n} from \"@ensnode/ensnode-sdk/internal\";\n\nimport { REFERRERS_PER_LEADERBOARD_PAGE_MAX } from \"../leaderboard-page\";\nimport { ReferralProgramEditionStatuses } from \"../status\";\n\n/**\n * Loose base schema for {@link BaseReferralProgramRules}.\n *\n * Accepts any string for `awardModel` to support forward-compatible parsing of unrecognized\n * models. Model-specific schemas override `awardModel` with a literal.\n */\nexport const makeBaseReferralProgramRulesSchema = (valueLabel: string) =>\n z\n .object({\n awardModel: z.string(),\n startTime: makeUnixTimestampSchema(`${valueLabel}.startTime`),\n endTime: makeUnixTimestampSchema(`${valueLabel}.endTime`),\n subregistryId: makeAccountIdSchema(`${valueLabel}.subregistryId`),\n rulesUrl: makeUrlSchema(`${valueLabel}.rulesUrl`),\n areAwardsDistributed: z.boolean(),\n })\n .refine((data) => data.endTime >= data.startTime, {\n message: `${valueLabel}.endTime must be >= ${valueLabel}.startTime`,\n path: [\"endTime\"],\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageContext}.\n */\nexport const makeReferrerLeaderboardPageContextSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageContext\",\n) =>\n z.object({\n page: makePositiveIntegerSchema(`${valueLabel}.page`),\n recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(\n REFERRERS_PER_LEADERBOARD_PAGE_MAX,\n `${valueLabel}.recordsPerPage must not exceed ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}`,\n ),\n totalRecords: makeNonNegativeIntegerSchema(`${valueLabel}.totalRecords`),\n totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),\n hasNext: z.boolean(),\n hasPrev: z.boolean(),\n startIndex: z.optional(makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`)),\n endIndex: z.optional(makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`)),\n });\n\n/**\n * Schema for referral program status field.\n * Validates that the status is one of the values in {@link ReferralProgramEditionStatuses}.\n */\nexport const makeReferralProgramStatusSchema = (_valueLabel: string = \"status\") =>\n z.enum(ReferralProgramEditionStatuses);\n\n/**\n * Loose base schema for {@link BaseReferralProgramEditionSummary}.\n *\n * Accepts any string for `rules.awardModel` to support forward-compatible parsing.\n */\nexport const makeBaseReferralProgramEditionSummarySchema = (valueLabel: string) =>\n z.object({\n awardModel: z.string(),\n slug: z.string().min(1, `${valueLabel}.slug must not be empty`),\n displayName: z.string().min(1, `${valueLabel}.displayName must not be empty`),\n status: makeReferralProgramStatusSchema(`${valueLabel}.status`),\n rules: makeBaseReferralProgramRulesSchema(`${valueLabel}.rules`),\n });\n\n/**\n * Loose base schema for {@link BaseReferrerLeaderboardPage}.\n *\n * Accepts any string for `awardModel` to support forward-compatible parsing of unrecognized\n * models. Model-specific schemas override `awardModel` with a literal.\n */\nexport const makeBaseReferrerLeaderboardPageSchema = (valueLabel: string) =>\n z.object({\n awardModel: z.string(),\n pageContext: makeReferrerLeaderboardPageContextSchema(`${valueLabel}.pageContext`),\n status: makeReferralProgramStatusSchema(`${valueLabel}.status`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n });\n","export const isInteger = (value: number): boolean => {\n return Number.isInteger(value);\n};\n\nexport const isNonNegativeInteger = (value: number): boolean => {\n return value >= 0 && Number.isInteger(value);\n};\n\nexport const isPositiveInteger = (value: number): boolean => {\n return value >= 1 && Number.isInteger(value);\n};\n\nexport const validateNonNegativeInteger = (value: number): void => {\n if (!isNonNegativeInteger(value)) {\n throw new Error(`Invalid non-negative integer: ${value}.`);\n }\n};\n\nexport const isFiniteNonNegativeNumber = (value: number): boolean => {\n return value >= 0 && Number.isFinite(value);\n};\n","import type { NormalizedAddress, UnixTimestamp } from \"enssdk\";\n\nimport type { ReferrerLeaderboard } from \"../../leaderboard\";\nimport { isNonNegativeInteger, isPositiveInteger } from \"../../number\";\nimport type { ReferralProgramAwardModel, ReferralProgramAwardModels } from \"./rules\";\nimport type { ReferralProgramEditionStatusId } from \"./status\";\n\n/**\n * The default number of referrers per leaderboard page.\n */\nexport const REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT = 25;\n\n/**\n * The maximum number of referrers per leaderboard page.\n */\n\nexport const REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;\n\n/**\n * Pagination params for leaderboard queries.\n */\nexport interface ReferrerLeaderboardPageParams {\n /**\n * Requested referrer leaderboard page number (1-indexed)\n * @invariant Must be a positive integer (>= 1)\n * @default 1\n */\n page?: number;\n\n /**\n * Maximum number of referrers to return per leaderboard page\n * @invariant Must be a positive integer (>= 1) and less than or equal to {@link REFERRERS_PER_LEADERBOARD_PAGE_MAX}\n * @default {@link REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT}\n */\n recordsPerPage?: number;\n}\n\nconst validateReferrerLeaderboardPageParams = (params: ReferrerLeaderboardPageParams): void => {\n if (params.page !== undefined && !isPositiveInteger(params.page)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.page}. page must be a positive integer.`,\n );\n }\n if (params.recordsPerPage !== undefined && !isPositiveInteger(params.recordsPerPage)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be a positive integer.`,\n );\n }\n if (\n params.recordsPerPage !== undefined &&\n params.recordsPerPage > REFERRERS_PER_LEADERBOARD_PAGE_MAX\n ) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be less than or equal to ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}.`,\n );\n }\n};\n\nexport const buildReferrerLeaderboardPageParams = (\n params: ReferrerLeaderboardPageParams,\n): Required<ReferrerLeaderboardPageParams> => {\n const result = {\n page: params.page ?? 1,\n recordsPerPage: params.recordsPerPage ?? REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT,\n } satisfies Required<ReferrerLeaderboardPageParams>;\n validateReferrerLeaderboardPageParams(result);\n return result;\n};\n\nexport interface ReferrerLeaderboardPageContext extends Required<ReferrerLeaderboardPageParams> {\n /**\n * Total number of referrers across all leaderboard pages\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n totalRecords: number;\n\n /**\n * Total number of pages in the leaderboard\n * @invariant Guaranteed to be a positive integer (>= 1)\n */\n totalPages: number;\n\n /**\n * Indicates if there is a next page available\n * @invariant true if and only if (`page` * `recordsPerPage` < `totalRecords`)\n */\n hasNext: boolean;\n\n /**\n * Indicates if there is a previous page available\n * @invariant true if and only if (`page` > 1)\n */\n hasPrev: boolean;\n\n /**\n * The start index of the referrers on the page (0-indexed)\n *\n * `undefined` if and only if `totalRecords` is 0.\n *\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n startIndex?: number;\n\n /**\n * The end index of the referrers on the page (0-indexed)\n *\n * `undefined` if and only if `totalRecords` is 0.\n *\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n * @invariant If `totalRecords` is > 0:\n * - Guaranteed to be greater than or equal to `startIndex`.\n * - Guaranteed to be less than `totalRecords`.\n */\n endIndex?: number;\n}\n\nexport const validateReferrerLeaderboardPageContext = (\n context: ReferrerLeaderboardPageContext,\n): void => {\n validateReferrerLeaderboardPageParams(context);\n if (!isNonNegativeInteger(context.totalRecords)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: totalRecords must be a non-negative integer but is ${context.totalRecords}.`,\n );\n }\n\n // Validate totalPages\n if (!isPositiveInteger(context.totalPages)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: totalPages must be a positive integer (>= 1) but is ${context.totalPages}.`,\n );\n }\n\n const expectedTotalPages =\n context.totalRecords === 0 ? 1 : Math.ceil(context.totalRecords / context.recordsPerPage);\n\n if (context.totalPages !== expectedTotalPages) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: totalPages is ${context.totalPages} but expected ${expectedTotalPages} based on totalRecords (${context.totalRecords}) and recordsPerPage (${context.recordsPerPage}).`,\n );\n }\n\n if (context.page > context.totalPages) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: page ${context.page} exceeds totalPages ${context.totalPages}.`,\n );\n }\n\n // Validate startIndex and endIndex\n const expectedStartIndex = (context.page - 1) * context.recordsPerPage;\n const expectedEndIndex = Math.min(\n expectedStartIndex + context.recordsPerPage - 1,\n context.totalRecords - 1,\n );\n\n if (context.totalRecords === 0) {\n if (context.startIndex !== undefined) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: startIndex must be undefined when totalRecords is 0 but is ${context.startIndex}.`,\n );\n }\n if (context.endIndex !== undefined) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: endIndex must be undefined when totalRecords is 0 but is ${context.endIndex}.`,\n );\n }\n } else {\n if (context.startIndex !== expectedStartIndex) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: startIndex is ${context.startIndex} but expected ${expectedStartIndex} based on page (${context.page}) and recordsPerPage (${context.recordsPerPage}).`,\n );\n }\n if (context.endIndex !== expectedEndIndex) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: endIndex is ${context.endIndex} but expected ${expectedEndIndex} based on startIndex (${expectedStartIndex}), recordsPerPage (${context.recordsPerPage}), and totalRecords (${context.totalRecords}).`,\n );\n }\n if (\n typeof context.endIndex !== \"undefined\" &&\n typeof context.startIndex !== \"undefined\" &&\n context.endIndex < context.startIndex\n ) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: endIndex (${context.endIndex}) must be greater than or equal to startIndex (${context.startIndex}).`,\n );\n }\n }\n\n const startIndex = (context.page - 1) * context.recordsPerPage;\n const endIndex = startIndex + context.recordsPerPage;\n\n if (!context.hasNext && endIndex < context.totalRecords) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasNext is false, endIndex (${endIndex}) must be greater than or equal to totalRecords (${context.totalRecords}).`,\n );\n } else if (context.hasNext && context.page * context.recordsPerPage >= context.totalRecords) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasNext is true, endIndex (${endIndex}) must be less than totalRecords (${context.totalRecords}).`,\n );\n }\n if (!context.hasPrev && context.page !== 1) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasPrev is false, page must be the first page (1) but is ${context.page}.`,\n );\n } else if (context.hasPrev && context.page === 1) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasPrev is true, page must not be the first page (1) but is ${context.page}.`,\n );\n }\n};\n\nexport const buildReferrerLeaderboardPageContext = (\n optionalParams: ReferrerLeaderboardPageParams,\n leaderboard: ReferrerLeaderboard,\n): ReferrerLeaderboardPageContext => {\n const materializedParams = buildReferrerLeaderboardPageParams(optionalParams);\n\n const totalRecords = leaderboard.referrers.size;\n\n const totalPages = Math.max(1, Math.ceil(totalRecords / materializedParams.recordsPerPage));\n\n if (materializedParams.page > totalPages) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: page ${materializedParams.page} exceeds total pages ${totalPages}.`,\n );\n }\n\n if (totalRecords === 0) {\n return {\n ...materializedParams,\n totalRecords: 0,\n totalPages: 1,\n hasNext: false,\n hasPrev: false,\n startIndex: undefined,\n endIndex: undefined,\n } satisfies ReferrerLeaderboardPageContext;\n }\n\n const startIndex = (materializedParams.page - 1) * materializedParams.recordsPerPage;\n const maxTheoreticalIndexOnPage = startIndex + (materializedParams.recordsPerPage - 1);\n const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);\n const hasNext = maxTheoreticalIndexOnPage < totalRecords - 1;\n const hasPrev = materializedParams.page > 1;\n\n const result = {\n ...materializedParams,\n totalRecords,\n totalPages,\n hasNext,\n hasPrev,\n startIndex,\n endIndex,\n } satisfies ReferrerLeaderboardPageContext;\n validateReferrerLeaderboardPageContext(result);\n return result;\n};\n\n/**\n * Base fields shared by all leaderboard page variants.\n */\nexport interface BaseReferrerLeaderboardPage {\n /**\n * Discriminant identifying the award model for this leaderboard page.\n */\n awardModel: ReferralProgramAwardModel;\n\n /**\n * The {@link ReferrerLeaderboardPageContext} of this page relative to the overall leaderboard.\n */\n pageContext: ReferrerLeaderboardPageContext;\n\n /**\n * The status of the referral program edition.\n */\n status: ReferralProgramEditionStatusId;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build this page was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\n/**\n * A leaderboard page whose `awardModel` is not recognized by this client version.\n *\n * @remarks\n * This is a **client-side forward-compatibility** type only. It is never serialized or processed\n * by business logic on the backend. When the server introduces a new award model type, older\n * clients preserve the page rather than throwing, and downstream code that encounters this type\n * should handle it gracefully rather than crashing.\n */\nexport interface ReferrerLeaderboardPageUnrecognized extends BaseReferrerLeaderboardPage {\n /**\n * Discriminant — always `\"unrecognized\"`.\n */\n awardModel: typeof ReferralProgramAwardModels.Unrecognized;\n\n /**\n * The original, unrecognized `awardModel` string received from the server.\n *\n * @remarks Preserved for logging and debugging. Never used for business logic.\n */\n originalAwardModel: string;\n}\n\n/**\n * Extracts the referrers for the current page from a fully-ranked Map.\n * Generic over the referrer type so each model variant retains its specific type.\n */\nexport function sliceReferrers<T>(\n referrers: Map<NormalizedAddress, T>,\n pageContext: ReferrerLeaderboardPageContext,\n): T[] {\n // pageContext invariants: startIndex and endIndex are defined iff totalRecords > 0\n if (\n pageContext.totalRecords === 0 ||\n pageContext.startIndex === undefined ||\n pageContext.endIndex === undefined\n ) {\n return [];\n }\n const all = [...referrers.values()];\n return all.slice(pageContext.startIndex, pageContext.endIndex + 1);\n}\n","import type { UnixTimestamp } from \"enssdk\";\n\nimport type { BaseReferralProgramRules } from \"./rules\";\n\n/**\n * The type of referral program edition's status.\n */\nexport const ReferralProgramEditionStatuses = {\n /**\n * Represents a referral program edition that has been announced, but hasn't started yet.\n */\n Scheduled: \"Scheduled\",\n\n /**\n * Represents a currently ongoing referral program edition.\n */\n Active: \"Active\",\n\n /**\n * Represents a referral program edition that is still within its active window\n * but whose award pool has been fully consumed.\n *\n * @note Not all award models may support this status.\n */\n Exhausted: \"Exhausted\",\n\n /**\n * Represents a referral program edition that has passed its end time but whose awards have not yet\n * been distributed. The edition is in a review window before full closure.\n *\n * Transitions to {@link ReferralProgramEditionStatuses.Closed} once `areAwardsDistributed` is set to `true`.\n */\n AwardsReview: \"AwardsReview\",\n\n /**\n * Represents a referral program edition that has already ended and whose awards have been distributed.\n */\n Closed: \"Closed\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferralProgramEditionStatuses}.\n */\nexport type ReferralProgramEditionStatusId =\n (typeof ReferralProgramEditionStatuses)[keyof typeof ReferralProgramEditionStatuses];\n\n/**\n * Calculate the base status of a referral program edition using only its rules and\n * the current time (makes no consideration of the awards possibly being exhausted).\n *\n * @param rules - Related referral program's rules containing program's start/end date and\n * `areAwardsDistributed` flag.\n * @param now - Current date in {@link UnixTimestamp} format.\n */\nexport const calcBaseReferralProgramEditionStatus = (\n rules: BaseReferralProgramRules,\n now: UnixTimestamp,\n): ReferralProgramEditionStatusId => {\n // if the program has not started return \"Scheduled\"\n if (now < rules.startTime) return ReferralProgramEditionStatuses.Scheduled;\n\n // if the program has ended, return \"Closed\" if awards are distributed, else \"AwardsReview\"\n if (now > rules.endTime)\n return rules.areAwardsDistributed\n ? ReferralProgramEditionStatuses.Closed\n : ReferralProgramEditionStatuses.AwardsReview;\n\n // otherwise, return \"Active\"\n return ReferralProgramEditionStatuses.Active;\n};\n","import type { ReferralProgramAwardModels } from \"./rules\";\n\n/**\n * The type of referrer edition metrics data.\n */\nexport const ReferrerEditionMetricsTypeIds = {\n /**\n * Represents a referrer who is ranked on the leaderboard.\n */\n Ranked: \"ranked\",\n\n /**\n * Represents a referrer who is not ranked on the leaderboard.\n */\n Unranked: \"unranked\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerEditionMetricsTypeIds}.\n */\nexport type ReferrerEditionMetricsTypeId =\n (typeof ReferrerEditionMetricsTypeIds)[keyof typeof ReferrerEditionMetricsTypeIds];\n\n/**\n * Referrer edition metrics for an edition whose `awardModel` is not recognized by this client version.\n *\n * @remarks\n * This is a **client-side forward-compatibility** type only. It is never serialized or processed\n * by business logic on the backend. When the server introduces a new award model type, older\n * clients preserve the metrics rather than throwing, and downstream code that encounters this type\n * should handle it gracefully rather than crashing.\n */\nexport interface ReferrerEditionMetricsUnrecognized {\n /**\n * Discriminant — always `\"unrecognized\"`.\n */\n awardModel: typeof ReferralProgramAwardModels.Unrecognized;\n\n /**\n * The original, unrecognized `awardModel` string received from the server.\n *\n * @remarks Preserved for logging and debugging. Never used for business logic.\n */\n originalAwardModel: string;\n}\n","import type { Duration, UnixTimestamp } from \"enssdk\";\n\nimport { isInteger, isNonNegativeInteger } from \"./number\";\n\nexport const validateUnixTimestamp = (timestamp: UnixTimestamp): void => {\n if (!isInteger(timestamp)) {\n throw new Error(`Invalid Unix timestamp: ${timestamp}. Unix timestamp must be an integer.`);\n }\n};\n\n/**\n * The number of seconds in a year.\n *\n * (60 seconds per minute * 60 minutes per hour *\n * 24 hours per day * 365.2425 days on average per year).\n */\nexport const SECONDS_PER_YEAR: Duration = 31556952;\n\nexport function isValidDuration(duration: Duration): boolean {\n return isNonNegativeInteger(duration);\n}\n\nexport function validateDuration(duration: Duration): void {\n if (!isValidDuration(duration)) {\n throw new Error(`Invalid duration: ${duration}. Duration must be a non-negative integer.`);\n }\n}\n","import type { AccountId, UnixTimestamp } from \"enssdk\";\n\nimport { makeAccountIdSchema } from \"@ensnode/ensnode-sdk/internal\";\n\nimport { validateUnixTimestamp } from \"../../time\";\n\n/**\n * Discriminant values for the award model used in a referral program edition.\n *\n * @remarks Clients MUST check `awardModel` before accessing model-specific fields.\n * Editions with unrecognized `awardModel` values are preserved as\n * {@link ReferralProgramRulesUnrecognized} during parsing (see\n * `makeReferralProgramEditionConfigSetArraySchema`). Clients must handle this variant — typically\n * by skipping those editions with a warning log rather than crashing.\n */\nexport const ReferralProgramAwardModels = {\n PieSplit: \"pie-split\",\n RevShareCap: \"rev-share-cap\",\n Unrecognized: \"unrecognized\",\n} as const;\n\nexport type ReferralProgramAwardModel =\n (typeof ReferralProgramAwardModels)[keyof typeof ReferralProgramAwardModels];\n\n/**\n * Base fields shared across all referral program rule types.\n *\n * Both `ReferralProgramRulesPieSplit` and `ReferralProgramRulesRevShareCap` are structurally\n * compatible with this interface, so it can be used wherever only the common fields are needed\n * (e.g., `assertLeaderboardInputs`).\n */\nexport interface BaseReferralProgramRules {\n /**\n * Discriminant: identifies the award model for this edition.\n */\n awardModel: ReferralProgramAwardModel;\n\n /**\n * The start time of the referral program.\n */\n startTime: UnixTimestamp;\n\n /**\n * The end time of the referral program.\n * @invariant Guaranteed to be greater than or equal to `startTime`\n */\n endTime: UnixTimestamp;\n\n /**\n * The account ID of the subregistry for the referral program.\n */\n subregistryId: AccountId;\n\n /**\n * URL to the full rules document for these rules.\n * @example new URL(\"https://ensawards.org/ens-holiday-awards-rules\")\n */\n rulesUrl: URL;\n\n /**\n * Whether the awards for this edition have been distributed.\n *\n * When `true` and `now > endTime`, the status transitions from `AwardsReview` to `Closed`.\n */\n areAwardsDistributed: boolean;\n}\n\n/**\n * Rules for a referral program edition whose `awardModel` is not recognized by this client version.\n *\n * @remarks\n * This is a **client-side forward-compatibility** type only. It is never serialized or processed\n * by business logic on the backend. When the server introduces a new award model type, older\n * clients preserve the edition rather than silently dropping it, and downstream code that\n * encounters this type should skip it with a warning log rather than crashing.\n */\nexport interface ReferralProgramRulesUnrecognized extends BaseReferralProgramRules {\n /**\n * Discriminant — always `\"unrecognized\"`.\n */\n awardModel: typeof ReferralProgramAwardModels.Unrecognized;\n\n /**\n * The original, unrecognized `awardModel` string received from the server.\n *\n * @remarks Preserved for logging and debugging. Never used for business logic.\n */\n originalAwardModel: string;\n}\n\nexport const validateBaseReferralProgramRules = (rules: BaseReferralProgramRules): void => {\n makeAccountIdSchema(\"BaseReferralProgramRules.subregistryId\").parse(rules.subregistryId);\n\n validateUnixTimestamp(rules.startTime);\n validateUnixTimestamp(rules.endTime);\n\n if (!(rules.rulesUrl instanceof URL)) {\n throw new Error(\n `BaseReferralProgramRules: rulesUrl must be a URL instance, got ${typeof rules.rulesUrl}.`,\n );\n }\n\n if (rules.endTime < rules.startTime) {\n throw new Error(\n `BaseReferralProgramRules: startTime: ${rules.startTime} is after endTime: ${rules.endTime}.`,\n );\n }\n};\n","import type { NormalizedAddress } from \"enssdk\";\nimport z from \"zod/v4\";\n\nimport {\n makeDurationSchema,\n makeFiniteNonNegativeNumberSchema,\n makeNonNegativeIntegerSchema,\n makeNormalizedAddressSchema,\n makePositiveIntegerSchema,\n makePriceEthSchema,\n makePriceUsdcSchema,\n makeUnixTimestampSchema,\n} from \"@ensnode/ensnode-sdk/internal\";\n\nimport {\n makeBaseReferralProgramEditionSummarySchema,\n makeBaseReferralProgramRulesSchema,\n makeBaseReferrerLeaderboardPageSchema,\n makeReferralProgramStatusSchema,\n} from \"../../shared/api/zod-schemas\";\nimport { ReferrerEditionMetricsTypeIds } from \"../../shared/edition-metrics\";\nimport { ReferralProgramAwardModels } from \"../../shared/rules\";\nimport { type AdminAction, AdminActionTypes } from \"../rules\";\n\n/**\n * Schema for {@link AdminActionDisqualification}.\n */\nexport const makeAdminActionDisqualificationSchema = (valueLabel = \"AdminActionDisqualification\") =>\n z.object({\n actionType: z.literal(AdminActionTypes.Disqualification),\n referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`),\n reason: z.string().trim().min(1, `${valueLabel}.reason must not be empty`),\n });\n\n/**\n * Schema for {@link AdminActionWarning}.\n */\nexport const makeAdminActionWarningSchema = (valueLabel = \"AdminActionWarning\") =>\n z.object({\n actionType: z.literal(AdminActionTypes.Warning),\n referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`),\n reason: z.string().trim().min(1, `${valueLabel}.reason must not be empty`),\n });\n\n/**\n * Schema for {@link AdminAction}.\n */\nexport const makeAdminActionSchema = (valueLabel = \"AdminAction\") =>\n z.discriminatedUnion(\"actionType\", [\n makeAdminActionDisqualificationSchema(valueLabel),\n makeAdminActionWarningSchema(valueLabel),\n ]);\n\n/**\n * Schema for {@link ReferralProgramRulesRevShareCap}.\n */\nexport const makeReferralProgramRulesRevShareCapSchema = (\n valueLabel: string = \"ReferralProgramRulesRevShareCap\",\n) =>\n makeBaseReferralProgramRulesSchema(valueLabel).safeExtend({\n awardModel: z.literal(ReferralProgramAwardModels.RevShareCap),\n awardPool: makePriceUsdcSchema(`${valueLabel}.awardPool`),\n minBaseRevenueContribution: makePriceUsdcSchema(`${valueLabel}.minBaseRevenueContribution`),\n baseAnnualRevenueContribution: makePriceUsdcSchema(\n `${valueLabel}.baseAnnualRevenueContribution`,\n ),\n maxBaseRevenueShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.maxBaseRevenueShare`).max(\n 1,\n `${valueLabel}.maxBaseRevenueShare must be <= 1`,\n ),\n adminActions: z\n .array(makeAdminActionSchema(`${valueLabel}.adminActions[item]`))\n // NOTE: addresses are already normalized, so string equivalence here is accurate\n .refine(\n (items) => {\n const referrers = items.map((a) => a.referrer);\n return new Set(referrers).size === referrers.length;\n },\n {\n message: `${valueLabel}.adminActions must not contain duplicate referrer addresses`,\n },\n )\n .default([]),\n });\n\n/**\n * Schema for {@link AwardedReferrerMetricsRevShareCap} (with numeric rank).\n */\nexport const makeAwardedReferrerMetricsRevShareCapSchema = (\n valueLabel: string = \"AwardedReferrerMetricsRevShareCap\",\n) =>\n z\n .object({\n referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`),\n totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),\n totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),\n totalRevenueContribution: makePriceEthSchema(`${valueLabel}.totalRevenueContribution`),\n totalBaseRevenueContribution: makePriceUsdcSchema(\n `${valueLabel}.totalBaseRevenueContribution`,\n ),\n rank: makePositiveIntegerSchema(`${valueLabel}.rank`),\n isQualified: z.boolean(),\n uncappedAward: makePriceUsdcSchema(`${valueLabel}.uncappedAward`),\n cappedAward: makePriceUsdcSchema(`${valueLabel}.cappedAward`),\n adminAction: makeAdminActionSchema(`${valueLabel}.adminAction`).nullable(),\n })\n .refine((data) => data.cappedAward.amount <= data.uncappedAward.amount, {\n message: `${valueLabel}.cappedAward must be <= ${valueLabel}.uncappedAward`,\n path: [\"cappedAward\"],\n })\n .refine(\n (data) =>\n data.adminAction?.actionType !== AdminActionTypes.Disqualification ||\n (data.isQualified === false && data.cappedAward.amount === 0n),\n {\n message: `When ${valueLabel}.adminAction.actionType is Disqualification, isQualified must be false and cappedAward.amount must be 0`,\n path: [\"adminAction\"],\n },\n )\n .refine((data) => data.isQualified || data.cappedAward.amount === 0n, {\n message: `${valueLabel}.cappedAward must be 0 when isQualified is false`,\n path: [\"cappedAward\"],\n })\n .refine((data) => data.adminAction === null || data.adminAction.referrer === data.referrer, {\n message: `${valueLabel}.adminAction.referrer must match ${valueLabel}.referrer`,\n path: [\"adminAction\", \"referrer\"],\n });\n\n/**\n * Schema for {@link UnrankedReferrerMetricsRevShareCap} (with null rank).\n */\nexport const makeUnrankedReferrerMetricsRevShareCapSchema = (\n valueLabel: string = \"UnrankedReferrerMetricsRevShareCap\",\n) =>\n z\n .object({\n referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`),\n totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),\n totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),\n totalRevenueContribution: makePriceEthSchema(`${valueLabel}.totalRevenueContribution`),\n totalBaseRevenueContribution: makePriceUsdcSchema(\n `${valueLabel}.totalBaseRevenueContribution`,\n ),\n rank: z.null(),\n isQualified: z.literal(false),\n uncappedAward: makePriceUsdcSchema(`${valueLabel}.uncappedAward`),\n cappedAward: makePriceUsdcSchema(`${valueLabel}.cappedAward`),\n adminAction: makeAdminActionSchema(`${valueLabel}.adminAction`).nullable(),\n })\n .refine((data) => data.totalReferrals === 0, {\n message: `${valueLabel}.totalReferrals must be 0 for unranked referrers`,\n path: [\"totalReferrals\"],\n })\n .refine((data) => data.totalIncrementalDuration === 0, {\n message: `${valueLabel}.totalIncrementalDuration must be 0 for unranked referrers`,\n path: [\"totalIncrementalDuration\"],\n })\n .refine((data) => data.totalRevenueContribution.amount === 0n, {\n message: `${valueLabel}.totalRevenueContribution must be 0 for unranked referrers`,\n path: [\"totalRevenueContribution\"],\n })\n .refine((data) => data.totalBaseRevenueContribution.amount === 0n, {\n message: `${valueLabel}.totalBaseRevenueContribution must be 0 for unranked referrers`,\n path: [\"totalBaseRevenueContribution\"],\n })\n .refine((data) => data.uncappedAward.amount === 0n, {\n message: `${valueLabel}.uncappedAward must be 0 for unranked referrers`,\n path: [\"uncappedAward\"],\n })\n .refine((data) => data.cappedAward.amount === 0n, {\n message: `${valueLabel}.cappedAward must be 0 for unranked referrers`,\n path: [\"cappedAward\"],\n })\n .refine((data) => data.adminAction === null || data.adminAction.referrer === data.referrer, {\n message: `${valueLabel}.adminAction.referrer must match ${valueLabel}.referrer`,\n path: [\"adminAction\", \"referrer\"],\n });\n\n/**\n * Schema for {@link AggregatedReferrerMetricsRevShareCap}.\n */\nexport const makeAggregatedReferrerMetricsRevShareCapSchema = (\n valueLabel: string = \"AggregatedReferrerMetricsRevShareCap\",\n) =>\n z.object({\n grandTotalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.grandTotalReferrals`),\n grandTotalIncrementalDuration: makeDurationSchema(\n `${valueLabel}.grandTotalIncrementalDuration`,\n ),\n grandTotalRevenueContribution: makePriceEthSchema(\n `${valueLabel}.grandTotalRevenueContribution`,\n ),\n awardPoolRemaining: makePriceUsdcSchema(`${valueLabel}.awardPoolRemaining`),\n });\n\n/**\n * Adds {@link z.RefinementCtx} issues when `metricsAdminAction` does not match the entry for\n * `referrer` in `rulesAdminActions`.\n */\nconst addAdminActionConsistencyIssues = (\n ctx: z.RefinementCtx,\n metricsAdminAction: AdminAction | null,\n referrer: NormalizedAddress,\n rulesAdminActions: AdminAction[],\n path: (string | number)[],\n): void => {\n const expected = rulesAdminActions.find((a) => a.referrer === referrer) ?? null;\n\n if (expected === null && metricsAdminAction !== null) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `adminAction expected null, got actionType=\"${metricsAdminAction.actionType}\"`,\n path,\n });\n return;\n }\n\n if (\n expected !== null &&\n (metricsAdminAction === null ||\n metricsAdminAction.actionType !== expected.actionType ||\n metricsAdminAction.referrer !== expected.referrer ||\n metricsAdminAction.reason !== expected.reason)\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `adminAction does not match the corresponding entry in rules.adminActions`,\n path,\n });\n }\n};\n\n/**\n * Schema for {@link ReferrerEditionMetricsRankedRevShareCap}.\n */\nexport const makeReferrerEditionMetricsRankedRevShareCapSchema = (\n valueLabel: string = \"ReferrerEditionMetricsRankedRevShareCap\",\n) =>\n z\n .object({\n awardModel: z.literal(ReferralProgramAwardModels.RevShareCap),\n type: z.literal(ReferrerEditionMetricsTypeIds.Ranked),\n rules: makeReferralProgramRulesRevShareCapSchema(`${valueLabel}.rules`),\n referrer: makeAwardedReferrerMetricsRevShareCapSchema(`${valueLabel}.referrer`),\n aggregatedMetrics: makeAggregatedReferrerMetricsRevShareCapSchema(\n `${valueLabel}.aggregatedMetrics`,\n ),\n status: makeReferralProgramStatusSchema(`${valueLabel}.status`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n })\n .refine((data) => data.awardModel === data.rules.awardModel, {\n message: `${valueLabel}.awardModel must equal ${valueLabel}.rules.awardModel`,\n path: [\"awardModel\"],\n })\n .refine((data) => data.referrer.cappedAward.amount <= data.rules.awardPool.amount, {\n message: `${valueLabel}.referrer.cappedAward must be <= ${valueLabel}.rules.awardPool`,\n path: [\"referrer\", \"cappedAward\", \"amount\"],\n })\n .superRefine((data, ctx) => {\n addAdminActionConsistencyIssues(\n ctx,\n data.referrer.adminAction,\n data.referrer.referrer,\n data.rules.adminActions,\n [\"referrer\", \"adminAction\"],\n );\n });\n\n/**\n * Schema for {@link ReferrerEditionMetricsUnrankedRevShareCap}.\n */\nexport const makeReferrerEditionMetricsUnrankedRevShareCapSchema = (\n valueLabel: string = \"ReferrerEditionMetricsUnrankedRevShareCap\",\n) =>\n z\n .object({\n awardModel: z.literal(ReferralProgramAwardModels.RevShareCap),\n type: z.literal(ReferrerEditionMetricsTypeIds.Unranked),\n rules: makeReferralProgramRulesRevShareCapSchema(`${valueLabel}.rules`),\n referrer: makeUnrankedReferrerMetricsRevShareCapSchema(`${valueLabel}.referrer`),\n aggregatedMetrics: makeAggregatedReferrerMetricsRevShareCapSchema(\n `${valueLabel}.aggregatedMetrics`,\n ),\n status: makeReferralProgramStatusSchema(`${valueLabel}.status`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n })\n .refine((data) => data.awardModel === data.rules.awardModel, {\n message: `${valueLabel}.awardModel must equal ${valueLabel}.rules.awardModel`,\n path: [\"awardModel\"],\n })\n .superRefine((data, ctx) => {\n addAdminActionConsistencyIssues(\n ctx,\n data.referrer.adminAction,\n data.referrer.referrer,\n data.rules.adminActions,\n [\"referrer\", \"adminAction\"],\n );\n });\n\n/**\n * Schema for all {@link ReferrerEditionMetrics} variants of the rev-share-cap award model\n * (both ranked and unranked).\n */\nexport const makeReferrerEditionMetricsRevShareCapSchema = (\n valueLabel: string = \"ReferrerEditionMetricsRevShareCap\",\n) =>\n z.discriminatedUnion(\"type\", [\n makeReferrerEditionMetricsRankedRevShareCapSchema(valueLabel),\n makeReferrerEditionMetricsUnrankedRevShareCapSchema(valueLabel),\n ]);\n\n/**\n * Schema for {@link ReferralProgramEditionSummaryRevShareCap}.\n */\nexport const makeReferralProgramEditionSummaryRevShareCapSchema = (\n valueLabel: string = \"ReferralProgramEditionSummaryRevShareCap\",\n) =>\n makeBaseReferralProgramEditionSummarySchema(valueLabel)\n .safeExtend({\n awardModel: z.literal(ReferralProgramAwardModels.RevShareCap),\n rules: makeReferralProgramRulesRevShareCapSchema(`${valueLabel}.rules`),\n awardPoolRemaining: makePriceUsdcSchema(`${valueLabel}.awardPoolRemaining`),\n })\n .refine((data) => data.awardModel === data.rules.awardModel, {\n message: `${valueLabel}.awardModel must equal ${valueLabel}.rules.awardModel`,\n path: [\"awardModel\"],\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageRevShareCap}.\n */\nexport const makeReferrerLeaderboardPageRevShareCapSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageRevShareCap\",\n) =>\n makeBaseReferrerLeaderboardPageSchema(valueLabel)\n .safeExtend({\n awardModel: z.literal(ReferralProgramAwardModels.RevShareCap),\n rules: makeReferralProgramRulesRevShareCapSchema(`${valueLabel}.rules`),\n referrers: z.array(\n makeAwardedReferrerMetricsRevShareCapSchema(`${valueLabel}.referrers[record]`),\n ),\n aggregatedMetrics: makeAggregatedReferrerMetricsRevShareCapSchema(\n `${valueLabel}.aggregatedMetrics`,\n ),\n })\n .refine((data) => data.awardModel === data.rules.awardModel, {\n message: `${valueLabel}.awardModel must equal ${valueLabel}.rules.awardModel`,\n path: [\"awardModel\"],\n })\n .superRefine((data, ctx) => {\n data.referrers.forEach((referrer, index) => {\n if (referrer.cappedAward.amount > data.rules.awardPool.amount) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${valueLabel}.referrers[${index}].cappedAward must be <= ${valueLabel}.rules.awardPool`,\n path: [\"referrers\", index, \"cappedAward\", \"amount\"],\n });\n }\n addAdminActionConsistencyIssues(\n ctx,\n referrer.adminAction,\n referrer.referrer,\n data.rules.adminActions,\n [\"referrers\", index, \"adminAction\"],\n );\n });\n });\n","import type { AccountId, NormalizedAddress, UnixTimestamp } from \"enssdk\";\n\nimport type { PriceUsdc } from \"@ensnode/ensnode-sdk\";\nimport { makePriceUsdcSchema } from \"@ensnode/ensnode-sdk/internal\";\n\nimport { validateNormalizedAddress } from \"../../address\";\nimport {\n type BaseReferralProgramRules,\n ReferralProgramAwardModels,\n validateBaseReferralProgramRules,\n} from \"../shared/rules\";\n\n/**\n * The types of admin actions that can be taken upon a referrer in a rev-share-cap edition.\n */\nexport const AdminActionTypes = {\n /**\n * The referrer is disqualified for awards.\n */\n Disqualification: \"Disqualification\",\n\n /**\n * The referrer is warned about a potential disqualification but may still be qualified for awards.\n */\n Warning: \"Warning\",\n} as const;\n\nexport type AdminActionType = (typeof AdminActionTypes)[keyof typeof AdminActionTypes];\n\n/**\n * An admin action to disqualify a referrer from receiving awards for an edition.\n */\nexport interface AdminActionDisqualification {\n actionType: typeof AdminActionTypes.Disqualification;\n\n /**\n * The Ethereum address of the affected referrer, as a {@link NormalizedAddress}.\n */\n referrer: NormalizedAddress;\n\n /**\n * A short message explaining the disqualification.\n *\n * @invariant Must be a trimmed, non-empty string.\n */\n reason: string;\n}\n\n/**\n * An admin action to warn a referrer that their eligibility for receiving awards for an edition\n * is at risk unless the referrer takes corrective actions.\n */\nexport interface AdminActionWarning {\n actionType: typeof AdminActionTypes.Warning;\n\n /**\n * The Ethereum address of the affected referrer, as a {@link NormalizedAddress}.\n */\n referrer: NormalizedAddress;\n\n /**\n * A short message explaining the warning.\n *\n * @invariant Must be a trimmed, non-empty string.\n */\n reason: string;\n}\n\n/**\n * A discriminated union of all admin action types.\n */\nexport type AdminAction = AdminActionDisqualification | AdminActionWarning;\n\nexport interface ReferralProgramRulesRevShareCap extends BaseReferralProgramRules {\n /**\n * Discriminant: identifies this as a \"rev-share-cap\" award model edition.\n *\n * In rev-share-cap, each qualified referrer receives a share of their base revenue\n * contribution (base-fee-only: `baseAnnualRevenueContribution` × years of incremental duration),\n * subject to the award pool cap and a minimum qualification threshold.\n */\n awardModel: typeof ReferralProgramAwardModels.RevShareCap;\n\n /**\n * The award pool in USDC (acts as a cap on total payouts).\n */\n awardPool: PriceUsdc;\n\n /**\n * The minimum base revenue contribution required for a referrer to qualify for awards.\n */\n minBaseRevenueContribution: PriceUsdc;\n\n /**\n * Base revenue contribution in USDC per year of incremental duration from referred registrations and renewals.\n *\n * Used in `rev-share-cap` qualification and award calculations:\n * 1 year of incremental duration → this many USDC of base revenue (base-fee-only, excluding premiums).\n */\n baseAnnualRevenueContribution: PriceUsdc;\n\n /**\n * The fraction of the referrer's base revenue contribution that constitutes their max potential award for each referral.\n * This is the max for a referral that ignores the possibility of the referrer not having achieved qualification for awards yet, the referrer being disqualified from awards, or the award pool being exhausted.\n *\n * @invariant Guaranteed to be a number between 0 and 1 (inclusive)\n */\n maxBaseRevenueShare: number;\n\n /**\n * Admin actions for this edition.\n *\n * @invariant No duplicate referrer addresses (a referrer can have at most one admin action).\n */\n adminActions: AdminAction[];\n}\n\nexport const validateReferralProgramRulesRevShareCap = (\n rules: ReferralProgramRulesRevShareCap,\n): void => {\n if (rules.awardModel !== ReferralProgramAwardModels.RevShareCap) {\n throw new Error(\n `ReferralProgramRulesRevShareCap: awardModel must be \"${ReferralProgramAwardModels.RevShareCap}\", got \"${rules.awardModel}\".`,\n );\n }\n\n makePriceUsdcSchema(\"ReferralProgramRulesRevShareCap.awardPool\").parse(rules.awardPool);\n\n makePriceUsdcSchema(\"ReferralProgramRulesRevShareCap.minBaseRevenueContribution\").parse(\n rules.minBaseRevenueContribution,\n );\n\n makePriceUsdcSchema(\"ReferralProgramRulesRevShareCap.baseAnnualRevenueContribution\").parse(\n rules.baseAnnualRevenueContribution,\n );\n\n if (\n !Number.isFinite(rules.maxBaseRevenueShare) ||\n rules.maxBaseRevenueShare < 0 ||\n rules.maxBaseRevenueShare > 1\n ) {\n throw new Error(\n `ReferralProgramRulesRevShareCap: maxBaseRevenueShare must be between 0 and 1 (inclusive), got ${rules.maxBaseRevenueShare}.`,\n );\n }\n\n for (const action of rules.adminActions) {\n validateNormalizedAddress(action.referrer);\n if (action.reason.trim().length === 0 || action.reason !== action.reason.trim()) {\n throw new Error(\n \"ReferralProgramRulesRevShareCap: admin action reason must be a trimmed, non-empty string.\",\n );\n }\n }\n\n const adminActionAddresses = rules.adminActions.map((a) => a.referrer);\n const uniqueAdminActionAddresses = new Set(adminActionAddresses);\n if (uniqueAdminActionAddresses.size !== adminActionAddresses.length) {\n throw new Error(\n \"ReferralProgramRulesRevShareCap: adminActions must not contain duplicate referrer addresses.\",\n );\n }\n\n validateBaseReferralProgramRules(rules);\n};\n\nexport const buildReferralProgramRulesRevShareCap = (\n awardPool: PriceUsdc,\n minBaseRevenueContribution: PriceUsdc,\n baseAnnualRevenueContribution: PriceUsdc,\n maxBaseRevenueShare: number,\n startTime: UnixTimestamp,\n endTime: UnixTimestamp,\n subregistryId: AccountId,\n rulesUrl: URL,\n areAwardsDistributed: boolean,\n adminActions: AdminAction[] = [],\n): ReferralProgramRulesRevShareCap => {\n const result = {\n awardModel: ReferralProgramAwardModels.RevShareCap,\n awardPool,\n minBaseRevenueContribution,\n baseAnnualRevenueContribution,\n maxBaseRevenueShare,\n startTime,\n endTime,\n subregistryId,\n rulesUrl,\n areAwardsDistributed,\n adminActions,\n } satisfies ReferralProgramRulesRevShareCap;\n\n validateReferralProgramRulesRevShareCap(result);\n\n return result;\n};\n\n/**\n * Determine if a referrer is qualified under rev-share-cap rules.\n *\n * A referrer is qualified if they meet the revenue threshold AND are not admin-disqualified.\n *\n * @param referrer - The referrer's address.\n * @param totalBaseRevenueContribution - The referrer's total base revenue contribution.\n * @param rules - The rev-share-cap rules of the referral program.\n */\nexport function isReferrerQualifiedRevShareCap(\n referrer: NormalizedAddress,\n totalBaseRevenueContribution: PriceUsdc,\n rules: ReferralProgramRulesRevShareCap,\n): boolean {\n const isAdminDisqualified = rules.adminActions.some(\n (a) => a.referrer === referrer && a.actionType === AdminActionTypes.Disqualification,\n );\n return (\n totalBaseRevenueContribution.amount >= rules.minBaseRevenueContribution.amount &&\n !isAdminDisqualified\n );\n}\n","import type { Address } from \"enssdk\";\n\nimport type { ReferrerLeaderboardPageParams } from \"../award-models/shared/leaderboard-page\";\nimport type { ReferralProgramEditionSlug } from \"../edition\";\nimport type { ReferrerEditionMetrics } from \"../edition-metrics\";\nimport type { ReferralProgramEditionSummary } from \"../edition-summary\";\nimport type { ReferrerLeaderboardPage } from \"../leaderboard-page\";\n\n/**\n * Request parameters for a referrer leaderboard page query.\n */\nexport interface ReferrerLeaderboardPageRequest extends ReferrerLeaderboardPageParams {\n /** The referral program edition slug */\n edition: ReferralProgramEditionSlug;\n}\n\n/**\n * A status code for a referrer leaderboard page API response.\n */\nexport const ReferrerLeaderboardPageResponseCodes = {\n /**\n * Represents that the requested referrer leaderboard page is available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that the referrer leaderboard data is not available.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerLeaderboardPageResponseCodes}.\n */\nexport type ReferrerLeaderboardPageResponseCode =\n (typeof ReferrerLeaderboardPageResponseCodes)[keyof typeof ReferrerLeaderboardPageResponseCodes];\n\n/**\n * A referrer leaderboard page response when the data is available.\n */\nexport type ReferrerLeaderboardPageResponseOk = {\n responseCode: typeof ReferrerLeaderboardPageResponseCodes.Ok;\n data: ReferrerLeaderboardPage;\n};\n\n/**\n * A referrer leaderboard page response when the data is not available.\n */\nexport type ReferrerLeaderboardPageResponseError = {\n responseCode: typeof ReferrerLeaderboardPageResponseCodes.Error;\n error: string;\n errorMessage: string;\n};\n\n/**\n * A referrer leaderboard page API response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferrerLeaderboardPageResponse =\n | ReferrerLeaderboardPageResponseOk\n | ReferrerLeaderboardPageResponseError;\n\n/**\n * Maximum number of editions that can be requested in a single {@link ReferrerMetricsEditionsRequest}.\n */\nexport const MAX_EDITIONS_PER_REQUEST = 20;\n\n/**\n * Request parameters for referrer metrics query.\n */\nexport interface ReferrerMetricsEditionsRequest {\n /** The Ethereum address of the referrer to query */\n referrer: Address;\n /** Array of edition slugs to query (min 1, max {@link MAX_EDITIONS_PER_REQUEST}, must be distinct) */\n editions: ReferralProgramEditionSlug[];\n}\n\n/**\n * A status code for referrer metrics API responses.\n */\nexport const ReferrerMetricsEditionsResponseCodes = {\n /**\n * Represents that the referrer metrics data for the requested editions is available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that an error occurred while fetching the data.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerMetricsEditionsResponseCodes}.\n */\nexport type ReferrerMetricsEditionsResponseCode =\n (typeof ReferrerMetricsEditionsResponseCodes)[keyof typeof ReferrerMetricsEditionsResponseCodes];\n\n/**\n * Referrer metrics data for requested editions.\n *\n * Maps each requested edition slug to the referrer's metrics for that edition.\n * Uses Partial because TypeScript cannot know at compile time which specific edition\n * slugs are requested. At runtime, when responseCode is Ok, all requested edition slugs\n * are guaranteed to be present in this record.\n */\nexport type ReferrerMetricsEditionsData = Partial<\n Record<ReferralProgramEditionSlug, ReferrerEditionMetrics>\n>;\n\n/**\n * A successful response containing referrer metrics for the requested editions.\n */\nexport type ReferrerMetricsEditionsResponseOk = {\n responseCode: typeof ReferrerMetricsEditionsResponseCodes.Ok;\n data: ReferrerMetricsEditionsData;\n};\n\n/**\n * A referrer metrics editions response when an error occurs.\n */\nexport type ReferrerMetricsEditionsResponseError = {\n responseCode: typeof ReferrerMetricsEditionsResponseCodes.Error;\n error: string;\n errorMessage: string;\n};\n\n/**\n * A referrer metrics editions API response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferrerMetricsEditionsResponse =\n | ReferrerMetricsEditionsResponseOk\n | ReferrerMetricsEditionsResponseError;\n\n/**\n * A status code for referral program edition summaries API responses.\n */\nexport const ReferralProgramEditionSummariesResponseCodes = {\n /**\n * Represents that the edition summaries are available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that the edition summaries are not available.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferralProgramEditionSummariesResponseCodes}.\n */\nexport type ReferralProgramEditionSummariesResponseCode =\n (typeof ReferralProgramEditionSummariesResponseCodes)[keyof typeof ReferralProgramEditionSummariesResponseCodes];\n\n/**\n * The data payload containing edition summaries.\n * Editions are sorted in descending order by start timestamp.\n */\nexport type ReferralProgramEditionSummariesData = {\n editions: ReferralProgramEditionSummary[];\n};\n\n/**\n * A successful response containing edition summaries.\n */\nexport type ReferralProgramEditionSummariesResponseOk = {\n responseCode: typeof ReferralProgramEditionSummariesResponseCodes.Ok;\n data: ReferralProgramEditionSummariesData;\n};\n\n/**\n * An edition summaries response when an error occurs.\n */\nexport type ReferralProgramEditionSummariesResponseError = {\n responseCode: typeof ReferralProgramEditionSummariesResponseCodes.Error;\n error: string;\n errorMessage: string;\n};\n\n/**\n * A referral program edition summaries API response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferralProgramEditionSummariesResponse =\n | ReferralProgramEditionSummariesResponseOk\n | ReferralProgramEditionSummariesResponseError;\n","import { serializePriceEth, serializePriceUsdc } from \"@ensnode/ensnode-sdk\";\n\nimport { ReferrerEditionMetricsTypeIds } from \"../../shared/edition-metrics\";\nimport type { AggregatedReferrerMetricsPieSplit } from \"../aggregations\";\nimport type {\n ReferrerEditionMetricsPieSplit,\n ReferrerEditionMetricsRankedPieSplit,\n ReferrerEditionMetricsUnrankedPieSplit,\n} from \"../edition-metrics\";\nimport type { ReferralProgramEditionSummaryPieSplit } from \"../edition-summary\";\nimport type { ReferrerLeaderboardPagePieSplit } from \"../leaderboard-page\";\nimport type { AwardedReferrerMetricsPieSplit, UnrankedReferrerMetricsPieSplit } from \"../metrics\";\nimport type { ReferralProgramRulesPieSplit } from \"../rules\";\nimport type {\n SerializedAggregatedReferrerMetricsPieSplit,\n SerializedAwardedReferrerMetricsPieSplit,\n SerializedReferralProgramEditionSummaryPieSplit,\n SerializedReferralProgramRulesPieSplit,\n SerializedReferrerEditionMetricsPieSplit,\n SerializedReferrerEditionMetricsRankedPieSplit,\n SerializedReferrerEditionMetricsUnrankedPieSplit,\n SerializedReferrerLeaderboardPagePieSplit,\n SerializedUnrankedReferrerMetricsPieSplit,\n} from \"./serialized-types\";\n\n/**\n * Serializes a {@link ReferralProgramRulesPieSplit} object.\n */\nexport function serializeReferralProgramRulesPieSplit(\n rules: ReferralProgramRulesPieSplit,\n): SerializedReferralProgramRulesPieSplit {\n return {\n awardModel: rules.awardModel,\n awardPool: serializePriceUsdc(rules.awardPool),\n maxQualifiedReferrers: rules.maxQualifiedReferrers,\n startTime: rules.startTime,\n endTime: rules.endTime,\n subregistryId: rules.subregistryId,\n rulesUrl: rules.rulesUrl.toString(),\n areAwardsDistributed: rules.areAwardsDistributed,\n };\n}\n\n/**\n * Serializes a {@link AggregatedReferrerMetricsPieSplit} object.\n */\nexport function serializeAggregatedReferrerMetricsPieSplit(\n metrics: AggregatedReferrerMetricsPieSplit,\n): SerializedAggregatedReferrerMetricsPieSplit {\n return {\n grandTotalReferrals: metrics.grandTotalReferrals,\n grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,\n grandTotalRevenueContribution: serializePriceEth(metrics.grandTotalRevenueContribution),\n grandTotalQualifiedReferrersFinalScore: metrics.grandTotalQualifiedReferrersFinalScore,\n minFinalScoreToQualify: metrics.minFinalScoreToQualify,\n };\n}\n\n/**\n * Serializes a {@link AwardedReferrerMetricsPieSplit} object.\n */\nexport function serializeAwardedReferrerMetricsPieSplit(\n metrics: AwardedReferrerMetricsPieSplit,\n): SerializedAwardedReferrerMetricsPieSplit {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: serializePriceEth(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: serializePriceUsdc(metrics.awardPoolApproxValue),\n };\n}\n\n/**\n * Serializes a {@link UnrankedReferrerMetricsPieSplit} object.\n */\nexport function serializeUnrankedReferrerMetricsPieSplit(\n metrics: UnrankedReferrerMetricsPieSplit,\n): SerializedUnrankedReferrerMetricsPieSplit {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: serializePriceEth(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: serializePriceUsdc(metrics.awardPoolApproxValue),\n };\n}\n\n/**\n * Serializes a {@link ReferrerEditionMetricsRankedPieSplit} object.\n */\nexport function serializeReferrerEditionMetricsRankedPieSplit(\n detail: ReferrerEditionMetricsRankedPieSplit,\n): SerializedReferrerEditionMetricsRankedPieSplit {\n return {\n awardModel: detail.awardModel,\n type: detail.type,\n rules: serializeReferralProgramRulesPieSplit(detail.rules),\n referrer: serializeAwardedReferrerMetricsPieSplit(detail.referrer),\n aggregatedMetrics: serializeAggregatedReferrerMetricsPieSplit(detail.aggregatedMetrics),\n status: detail.status,\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferrerEditionMetricsUnrankedPieSplit} object.\n */\nexport function serializeReferrerEditionMetricsUnrankedPieSplit(\n detail: ReferrerEditionMetricsUnrankedPieSplit,\n): SerializedReferrerEditionMetricsUnrankedPieSplit {\n return {\n awardModel: detail.awardModel,\n type: detail.type,\n rules: serializeReferralProgramRulesPieSplit(detail.rules),\n referrer: serializeUnrankedReferrerMetricsPieSplit(detail.referrer),\n aggregatedMetrics: serializeAggregatedReferrerMetricsPieSplit(detail.aggregatedMetrics),\n status: detail.status,\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferrerEditionMetricsPieSplit} object (ranked or unranked).\n */\nexport function serializeReferrerEditionMetricsPieSplit(\n detail: ReferrerEditionMetricsPieSplit,\n): SerializedReferrerEditionMetricsPieSplit {\n switch (detail.type) {\n case ReferrerEditionMetricsTypeIds.Ranked:\n return serializeReferrerEditionMetricsRankedPieSplit(detail);\n case ReferrerEditionMetricsTypeIds.Unranked:\n return serializeReferrerEditionMetricsUnrankedPieSplit(detail);\n default: {\n const _exhaustiveCheck: never = detail;\n throw new Error(`Unknown type: ${(_exhaustiveCheck as ReferrerEditionMetricsPieSplit).type}`);\n }\n }\n}\n\n/**\n * Serializes a {@link ReferrerLeaderboardPagePieSplit} object.\n */\nexport function serializeReferrerLeaderboardPagePieSplit(\n page: ReferrerLeaderboardPagePieSplit,\n): SerializedReferrerLeaderboardPagePieSplit {\n return {\n awardModel: page.awardModel,\n rules: serializeReferralProgramRulesPieSplit(page.rules),\n referrers: page.referrers.map(serializeAwardedReferrerMetricsPieSplit),\n aggregatedMetrics: serializeAggregatedReferrerMetricsPieSplit(page.aggregatedMetrics),\n pageContext: page.pageContext,\n status: page.status,\n accurateAsOf: page.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferralProgramEditionSummaryPieSplit} object.\n */\nexport function serializeReferralProgramEditionSummaryPieSplit(\n summary: ReferralProgramEditionSummaryPieSplit,\n): SerializedReferralProgramEditionSummaryPieSplit {\n return {\n awardModel: summary.awardModel,\n slug: summary.slug,\n displayName: summary.displayName,\n status: summary.status,\n rules: serializeReferralProgramRulesPieSplit(summary.rules),\n };\n}\n","import { serializePriceEth, serializePriceUsdc } from \"@ensnode/ensnode-sdk\";\n\nimport { ReferrerEditionMetricsTypeIds } from \"../../shared/edition-metrics\";\nimport type { AggregatedReferrerMetricsRevShareCap } from \"../aggregations\";\nimport type {\n ReferrerEditionMetricsRankedRevShareCap,\n ReferrerEditionMetricsRevShareCap,\n ReferrerEditionMetricsUnrankedRevShareCap,\n} from \"../edition-metrics\";\nimport type { ReferralProgramEditionSummaryRevShareCap } from \"../edition-summary\";\nimport type { ReferrerLeaderboardPageRevShareCap } from \"../leaderboard-page\";\nimport type {\n AwardedReferrerMetricsRevShareCap,\n UnrankedReferrerMetricsRevShareCap,\n} from \"../metrics\";\nimport type { ReferralProgramRulesRevShareCap } from \"../rules\";\nimport type {\n SerializedAggregatedReferrerMetricsRevShareCap,\n SerializedAwardedReferrerMetricsRevShareCap,\n SerializedReferralProgramEditionSummaryRevShareCap,\n SerializedReferralProgramRulesRevShareCap,\n SerializedReferrerEditionMetricsRankedRevShareCap,\n SerializedReferrerEditionMetricsRevShareCap,\n SerializedReferrerEditionMetricsUnrankedRevShareCap,\n SerializedReferrerLeaderboardPageRevShareCap,\n SerializedUnrankedReferrerMetricsRevShareCap,\n} from \"./serialized-types\";\n\n/**\n * Serializes a {@link ReferralProgramRulesRevShareCap} object.\n */\nexport function serializeReferralProgramRulesRevShareCap(\n rules: ReferralProgramRulesRevShareCap,\n): SerializedReferralProgramRulesRevShareCap {\n return {\n awardModel: rules.awardModel,\n awardPool: serializePriceUsdc(rules.awardPool),\n minBaseRevenueContribution: serializePriceUsdc(rules.minBaseRevenueContribution),\n baseAnnualRevenueContribution: serializePriceUsdc(rules.baseAnnualRevenueContribution),\n maxBaseRevenueShare: rules.maxBaseRevenueShare,\n startTime: rules.startTime,\n endTime: rules.endTime,\n subregistryId: rules.subregistryId,\n rulesUrl: rules.rulesUrl.toString(),\n areAwardsDistributed: rules.areAwardsDistributed,\n adminActions: rules.adminActions,\n };\n}\n\n/**\n * Serializes a {@link AggregatedReferrerMetricsRevShareCap} object.\n */\nexport function serializeAggregatedReferrerMetricsRevShareCap(\n metrics: AggregatedReferrerMetricsRevShareCap,\n): SerializedAggregatedReferrerMetricsRevShareCap {\n return {\n grandTotalReferrals: metrics.grandTotalReferrals,\n grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,\n grandTotalRevenueContribution: serializePriceEth(metrics.grandTotalRevenueContribution),\n awardPoolRemaining: serializePriceUsdc(metrics.awardPoolRemaining),\n };\n}\n\n/**\n * Serializes a {@link AwardedReferrerMetricsRevShareCap} object.\n */\nexport function serializeAwardedReferrerMetricsRevShareCap(\n metrics: AwardedReferrerMetricsRevShareCap,\n): SerializedAwardedReferrerMetricsRevShareCap {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: serializePriceEth(metrics.totalRevenueContribution),\n totalBaseRevenueContribution: serializePriceUsdc(metrics.totalBaseRevenueContribution),\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n uncappedAward: serializePriceUsdc(metrics.uncappedAward),\n cappedAward: serializePriceUsdc(metrics.cappedAward),\n adminAction: metrics.adminAction,\n };\n}\n\n/**\n * Serializes a {@link UnrankedReferrerMetricsRevShareCap} object.\n */\nexport function serializeUnrankedReferrerMetricsRevShareCap(\n metrics: UnrankedReferrerMetricsRevShareCap,\n): SerializedUnrankedReferrerMetricsRevShareCap {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: serializePriceEth(metrics.totalRevenueContribution),\n totalBaseRevenueContribution: serializePriceUsdc(metrics.totalBaseRevenueContribution),\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n uncappedAward: serializePriceUsdc(metrics.uncappedAward),\n cappedAward: serializePriceUsdc(metrics.cappedAward),\n adminAction: metrics.adminAction,\n };\n}\n\n/**\n * Serializes a {@link ReferrerEditionMetricsRankedRevShareCap} object.\n */\nexport function serializeReferrerEditionMetricsRankedRevShareCap(\n detail: ReferrerEditionMetricsRankedRevShareCap,\n): SerializedReferrerEditionMetricsRankedRevShareCap {\n return {\n awardModel: detail.awardModel,\n type: detail.type,\n rules: serializeReferralProgramRulesRevShareCap(detail.rules),\n referrer: serializeAwardedReferrerMetricsRevShareCap(detail.referrer),\n aggregatedMetrics: serializeAggregatedReferrerMetricsRevShareCap(detail.aggregatedMetrics),\n status: detail.status,\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferrerEditionMetricsUnrankedRevShareCap} object.\n */\nexport function serializeReferrerEditionMetricsUnrankedRevShareCap(\n detail: ReferrerEditionMetricsUnrankedRevShareCap,\n): SerializedReferrerEditionMetricsUnrankedRevShareCap {\n return {\n awardModel: detail.awardModel,\n type: detail.type,\n rules: serializeReferralProgramRulesRevShareCap(detail.rules),\n referrer: serializeUnrankedReferrerMetricsRevShareCap(detail.referrer),\n aggregatedMetrics: serializeAggregatedReferrerMetricsRevShareCap(detail.aggregatedMetrics),\n status: detail.status,\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferrerEditionMetricsRevShareCap} object (ranked or unranked).\n */\nexport function serializeReferrerEditionMetricsRevShareCap(\n detail: ReferrerEditionMetricsRevShareCap,\n): SerializedReferrerEditionMetricsRevShareCap {\n switch (detail.type) {\n case ReferrerEditionMetricsTypeIds.Ranked:\n return serializeReferrerEditionMetricsRankedRevShareCap(detail);\n case ReferrerEditionMetricsTypeIds.Unranked:\n return serializeReferrerEditionMetricsUnrankedRevShareCap(detail);\n default: {\n const _exhaustiveCheck: never = detail;\n throw new Error(\n `Unknown type: ${(_exhaustiveCheck as ReferrerEditionMetricsRevShareCap).type}`,\n );\n }\n }\n}\n\n/**\n * Serializes a {@link ReferrerLeaderboardPageRevShareCap} object.\n */\nexport function serializeReferrerLeaderboardPageRevShareCap(\n page: ReferrerLeaderboardPageRevShareCap,\n): SerializedReferrerLeaderboardPageRevShareCap {\n return {\n awardModel: page.awardModel,\n rules: serializeReferralProgramRulesRevShareCap(page.rules),\n referrers: page.referrers.map(serializeAwardedReferrerMetricsRevShareCap),\n aggregatedMetrics: serializeAggregatedReferrerMetricsRevShareCap(page.aggregatedMetrics),\n pageContext: page.pageContext,\n status: page.status,\n accurateAsOf: page.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferralProgramEditionSummaryRevShareCap} object.\n */\nexport function serializeReferralProgramEditionSummaryRevShareCap(\n summary: ReferralProgramEditionSummaryRevShareCap,\n): SerializedReferralProgramEditionSummaryRevShareCap {\n return {\n awardModel: summary.awardModel,\n slug: summary.slug,\n displayName: summary.displayName,\n status: summary.status,\n rules: serializeReferralProgramRulesRevShareCap(summary.rules),\n awardPoolRemaining: serializePriceUsdc(summary.awardPoolRemaining),\n };\n}\n","import {\n serializeReferralProgramEditionSummaryPieSplit,\n serializeReferralProgramRulesPieSplit,\n serializeReferrerEditionMetricsPieSplit,\n serializeReferrerLeaderboardPagePieSplit,\n} from \"../award-models/pie-split/api/serialize\";\nimport {\n serializeReferralProgramEditionSummaryRevShareCap,\n serializeReferralProgramRulesRevShareCap,\n serializeReferrerEditionMetricsRevShareCap,\n serializeReferrerLeaderboardPageRevShareCap,\n} from \"../award-models/rev-share-cap/api/serialize\";\nimport type { ReferrerEditionMetricsUnrecognized } from \"../award-models/shared/edition-metrics\";\nimport type { ReferralProgramEditionSummaryUnrecognized } from \"../award-models/shared/edition-summary\";\nimport type { ReferrerLeaderboardPageUnrecognized } from \"../award-models/shared/leaderboard-page\";\nimport type { ReferralProgramRulesUnrecognized } from \"../award-models/shared/rules\";\nimport { ReferralProgramAwardModels } from \"../award-models/shared/rules\";\nimport type { ReferrerEditionMetrics } from \"../edition-metrics\";\nimport type { ReferralProgramEditionSummary } from \"../edition-summary\";\nimport type { ReferrerLeaderboardPage } from \"../leaderboard-page\";\nimport type { ReferralProgramRules } from \"../rules\";\nimport type {\n SerializedReferralProgramEditionSummariesResponse,\n SerializedReferralProgramEditionSummary,\n SerializedReferralProgramRules,\n SerializedReferrerEditionMetrics,\n SerializedReferrerLeaderboardPage,\n SerializedReferrerLeaderboardPageResponse,\n SerializedReferrerMetricsEditionsData,\n SerializedReferrerMetricsEditionsResponse,\n} from \"./serialized-types\";\nimport {\n type ReferralProgramEditionSummariesResponse,\n ReferralProgramEditionSummariesResponseCodes,\n type ReferrerLeaderboardPageResponse,\n ReferrerLeaderboardPageResponseCodes,\n type ReferrerMetricsEditionsResponse,\n ReferrerMetricsEditionsResponseCodes,\n} from \"./types\";\n\n/**\n * Serializes a {@link ReferralProgramRules} object.\n *\n * @throws if called with a {@link ReferralProgramRulesUnrecognized} — unrecognized editions are\n * client-side forward-compatibility placeholders and must never be serialized.\n */\nexport function serializeReferralProgramRules(\n rules: ReferralProgramRules,\n): SerializedReferralProgramRules {\n switch (rules.awardModel) {\n case ReferralProgramAwardModels.PieSplit:\n return serializeReferralProgramRulesPieSplit(rules);\n\n case ReferralProgramAwardModels.RevShareCap:\n return serializeReferralProgramRulesRevShareCap(rules);\n\n case ReferralProgramAwardModels.Unrecognized: {\n const unrecognized = rules as ReferralProgramRulesUnrecognized;\n throw new Error(\n `ReferralProgramRulesUnrecognized (originalAwardModel: '${unrecognized.originalAwardModel}') must not be serialized — it is a client-side forward-compatibility placeholder only.`,\n );\n }\n\n default: {\n const _exhaustiveCheck: never = rules;\n throw new Error(\n `Unknown award model: ${(_exhaustiveCheck as ReferralProgramRules).awardModel}`,\n );\n }\n }\n}\n\n/**\n * Serializes a {@link ReferrerLeaderboardPage} object.\n *\n * @throws if called with a {@link ReferrerLeaderboardPageUnrecognized} — unrecognized pages are\n * client-side forward-compatibility placeholders and must never be serialized.\n */\nfunction serializeReferrerLeaderboardPage(\n page: ReferrerLeaderboardPage,\n): SerializedReferrerLeaderboardPage {\n switch (page.awardModel) {\n case ReferralProgramAwardModels.PieSplit:\n return serializeReferrerLeaderboardPagePieSplit(page);\n case ReferralProgramAwardModels.RevShareCap:\n return serializeReferrerLeaderboardPageRevShareCap(page);\n case ReferralProgramAwardModels.Unrecognized: {\n const unrecognized = page as ReferrerLeaderboardPageUnrecognized;\n throw new Error(\n `ReferrerLeaderboardPageUnrecognized (originalAwardModel: '${unrecognized.originalAwardModel}') must not be serialized — it is a client-side forward-compatibility placeholder only.`,\n );\n }\n default: {\n const _exhaustiveCheck: never = page;\n throw new Error(\n `Unknown award model: ${(_exhaustiveCheck as ReferrerLeaderboardPage).awardModel}`,\n );\n }\n }\n}\n\n/**\n * Serializes a {@link ReferrerEditionMetrics} object.\n *\n * @throws if called with a {@link ReferrerEditionMetricsUnrecognized} — unrecognized metrics are\n * client-side forward-compatibility placeholders and must never be serialized.\n */\nfunction serializeReferrerEditionMetrics(\n detail: ReferrerEditionMetrics,\n): SerializedReferrerEditionMetrics {\n switch (detail.awardModel) {\n case ReferralProgramAwardModels.PieSplit:\n return serializeReferrerEditionMetricsPieSplit(detail);\n case ReferralProgramAwardModels.RevShareCap:\n return serializeReferrerEditionMetricsRevShareCap(detail);\n case ReferralProgramAwardModels.Unrecognized: {\n const unrecognized = detail as ReferrerEditionMetricsUnrecognized;\n throw new Error(\n `ReferrerEditionMetricsUnrecognized (originalAwardModel: '${unrecognized.originalAwardModel}') must not be serialized — it is a client-side forward-compatibility placeholder only.`,\n );\n }\n default: {\n const _exhaustiveCheck: never = detail;\n throw new Error(\n `Unknown award model: ${(_exhaustiveCheck as ReferrerEditionMetrics).awardModel}`,\n );\n }\n }\n}\n\n/**\n * Serializes a {@link ReferralProgramEditionSummary} object.\n *\n * @throws if called with a {@link ReferralProgramEditionSummaryUnrecognized} — unrecognized\n * summaries are client-side forward-compatibility placeholders and must never be serialized.\n */\nexport function serializeReferralProgramEditionSummary(\n summary: ReferralProgramEditionSummary,\n): SerializedReferralProgramEditionSummary {\n switch (summary.awardModel) {\n case ReferralProgramAwardModels.PieSplit:\n return serializeReferralProgramEditionSummaryPieSplit(summary);\n\n case ReferralProgramAwardModels.RevShareCap:\n return serializeReferralProgramEditionSummaryRevShareCap(summary);\n\n case ReferralProgramAwardModels.Unrecognized: {\n const unrecognized = summary as ReferralProgramEditionSummaryUnrecognized;\n throw new Error(\n `ReferralProgramEditionSummaryUnrecognized (originalAwardModel: '${unrecognized.rules.originalAwardModel}') must not be serialized — it is a client-side forward-compatibility placeholder only.`,\n );\n }\n\n default: {\n const _exhaustiveCheck: never = summary;\n throw new Error(\n `Unknown award model: ${(_exhaustiveCheck as ReferralProgramEditionSummary).awardModel}`,\n );\n }\n }\n}\n\n/**\n * Serialize a {@link ReferrerLeaderboardPageResponse} object.\n */\nexport function serializeReferrerLeaderboardPageResponse(\n response: ReferrerLeaderboardPageResponse,\n): SerializedReferrerLeaderboardPageResponse {\n switch (response.responseCode) {\n case ReferrerLeaderboardPageResponseCodes.Ok:\n return {\n responseCode: response.responseCode,\n data: serializeReferrerLeaderboardPage(response.data),\n };\n\n case ReferrerLeaderboardPageResponseCodes.Error:\n return response;\n }\n}\n\n/**\n * Serialize a {@link ReferrerMetricsEditionsResponse} object.\n */\nexport function serializeReferrerMetricsEditionsResponse(\n response: ReferrerMetricsEditionsResponse,\n): SerializedReferrerMetricsEditionsResponse {\n switch (response.responseCode) {\n case ReferrerMetricsEditionsResponseCodes.Ok: {\n const serializedData = Object.fromEntries(\n Object.entries(response.data).map(([editionSlug, detail]) => [\n editionSlug,\n serializeReferrerEditionMetrics(detail as ReferrerEditionMetrics),\n ]),\n ) as SerializedReferrerMetricsEditionsData;\n\n return {\n responseCode: response.responseCode,\n data: serializedData,\n };\n }\n\n case ReferrerMetricsEditionsResponseCodes.Error:\n return response;\n\n default: {\n const _exhaustiveCheck: never = response;\n throw new Error(\n `Unknown response code: ${(_exhaustiveCheck as ReferrerMetricsEditionsResponse).responseCode}`,\n );\n }\n }\n}\n\n/**\n * Serialize a {@link ReferralProgramEditionSummariesResponse} object.\n */\nexport function serializeReferralProgramEditionSummariesResponse(\n response: ReferralProgramEditionSummariesResponse,\n): SerializedReferralProgramEditionSummariesResponse {\n switch (response.responseCode) {\n case ReferralProgramEditionSummariesResponseCodes.Ok:\n return {\n responseCode: response.responseCode,\n data: {\n editions: response.data.editions.map(serializeReferralProgramEditionSummary),\n },\n };\n\n case ReferralProgramEditionSummariesResponseCodes.Error:\n return response;\n\n default: {\n const _exhaustiveCheck: never = response;\n throw new Error(\n `Unknown response code: ${(_exhaustiveCheck as ReferralProgramEditionSummariesResponse).responseCode}`,\n );\n }\n }\n}\n","/**\n * The score of a referrer.\n *\n * @invariant Guaranteed to be a finite non-negative number (>= 0)\n */\nexport type ReferrerScore = number;\n\nexport const isValidReferrerScore = (score: ReferrerScore): boolean => {\n return score >= 0 && Number.isFinite(score);\n};\n\nexport const validateReferrerScore = (score: ReferrerScore): void => {\n if (!isValidReferrerScore(score)) {\n throw new Error(\n `Invalid referrer score: ${score}. Referrer score must be a finite non-negative number.`,\n );\n }\n};\n","import type { Duration } from \"enssdk\";\n\nimport { type PriceEth, priceEth } from \"@ensnode/ensnode-sdk\";\nimport { makePriceEthSchema } from \"@ensnode/ensnode-sdk/internal\";\n\nimport { validateNonNegativeInteger } from \"../../number\";\nimport { validateDuration } from \"../../time\";\nimport { type ReferrerScore, validateReferrerScore } from \"../shared/score\";\nimport type { RankedReferrerMetricsPieSplit } from \"./metrics\";\nimport type { ReferralProgramRulesPieSplit } from \"./rules\";\n\n/**\n * Represents aggregated metrics for a list of {@link RankedReferrerMetricsPieSplit}.\n */\nexport interface AggregatedReferrerMetricsPieSplit {\n /**\n * @invariant The sum of `totalReferrals` across all {@link RankedReferrerMetricsPieSplit} in the list.\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n grandTotalReferrals: number;\n\n /**\n * @invariant The sum of `totalIncrementalDuration` across all {@link RankedReferrerMetricsPieSplit} in the list.\n */\n grandTotalIncrementalDuration: Duration;\n\n /**\n * The total revenue contribution in ETH to the ENS DAO from all referrals\n * across all referrers on the leaderboard.\n *\n * This is the sum of `totalRevenueContribution` across all {@link RankedReferrerMetricsPieSplit} in the list.\n *\n * @invariant Guaranteed to be a valid PriceEth with non-negative amount (>= 0n)\n */\n grandTotalRevenueContribution: PriceEth;\n\n /**\n * @invariant The sum of `finalScore` across all {@link RankedReferrerMetricsPieSplit} where `isQualified` is `true`.\n */\n grandTotalQualifiedReferrersFinalScore: ReferrerScore;\n\n /**\n * @invariant Identifies the minimum final score required to become a qualified referrer.\n * @invariant If `rules.maxQualifiedReferrers` is 0, then `minFinalScoreToQualify` is guaranteed to\n * be `Number.MAX_SAFE_INTEGER`.\n * @invariant If `rules.maxQualifiedReferrers` is greater than 0, and there are no current referrers\n * matching the `rules`, then `minFinalScoreToQualify` is guaranteed to be `0`.\n */\n minFinalScoreToQualify: ReferrerScore;\n}\n\nexport const validateAggregatedReferrerMetricsPieSplit = (\n metrics: AggregatedReferrerMetricsPieSplit,\n): void => {\n validateNonNegativeInteger(metrics.grandTotalReferrals);\n validateDuration(metrics.grandTotalIncrementalDuration);\n\n makePriceEthSchema(\"AggregatedReferrerMetricsPieSplit.grandTotalRevenueContribution\").parse(\n metrics.grandTotalRevenueContribution,\n );\n\n validateReferrerScore(metrics.grandTotalQualifiedReferrersFinalScore);\n validateReferrerScore(metrics.minFinalScoreToQualify);\n};\n\n/**\n * Builds aggregated pie-split metrics from a complete, globally ranked list of referrers.\n *\n * **IMPORTANT: This function expects a complete ranking of all referrers.**\n *\n * @param referrers - Must be a complete, globally ranked list of {@link RankedReferrerMetricsPieSplit}\n * where ranks start at 1 and are consecutive.\n * **This must NOT be a paginated or partial slice of the rankings.**\n *\n * @param rules - The {@link ReferralProgramRulesPieSplit} object that define qualification criteria,\n * including `maxQualifiedReferrers` (the maximum number of referrers\n * that can qualify for rewards).\n *\n * @returns Aggregated metrics including totals across all referrers and the minimum\n * score required to qualify.\n *\n * @remarks\n * - If you need to work with paginated data, aggregate the full ranking first before\n * calling this function, or call this function on the complete dataset and then paginate\n * the results.\n * - If `rules.maxQualifiedReferrers === 0`, no referrers can qualify and\n * `minFinalScoreToQualify` will be set to `Number.MAX_SAFE_INTEGER`.\n * - If `referrers` is empty and `rules.maxQualifiedReferrers > 0`,\n * `minFinalScoreToQualify` will be set to `0` (anyone can qualify).\n */\nexport const buildAggregatedReferrerMetricsPieSplit = (\n referrers: RankedReferrerMetricsPieSplit[],\n rules: ReferralProgramRulesPieSplit,\n): AggregatedReferrerMetricsPieSplit => {\n let grandTotalReferrals = 0;\n let grandTotalIncrementalDuration = 0;\n let grandTotalRevenueContributionAmount = 0n;\n let grandTotalQualifiedReferrersFinalScore = 0;\n let minFinalScoreToQualify = Number.MAX_SAFE_INTEGER;\n\n for (const referrer of referrers) {\n grandTotalReferrals += referrer.totalReferrals;\n grandTotalIncrementalDuration += referrer.totalIncrementalDuration;\n grandTotalRevenueContributionAmount += referrer.totalRevenueContribution.amount;\n if (referrer.isQualified) {\n grandTotalQualifiedReferrersFinalScore += referrer.finalScore;\n if (referrer.finalScore < minFinalScoreToQualify) {\n minFinalScoreToQualify = referrer.finalScore;\n }\n }\n }\n\n if (minFinalScoreToQualify === Number.MAX_SAFE_INTEGER) {\n if (rules.maxQualifiedReferrers === 0) {\n // ... because it's impossible to qualify based on the rules\n // therefore keep minFinalScoreToQualify as Number.MAX_SAFE_INTEGER\n } else {\n // ... because there are no referrers at all on the leaderboard\n if (referrers.length !== 0) {\n // invariant sanity check\n throw new Error(\n \"AggregatedReferrerMetricsPieSplit: There are referrers on the leaderboard, and the rules allow for qualified referrers, but no qualified referrers.\",\n );\n }\n\n minFinalScoreToQualify = 0;\n }\n }\n\n const result = {\n grandTotalReferrals,\n grandTotalIncrementalDuration,\n grandTotalRevenueContribution: priceEth(grandTotalRevenueContributionAmount),\n grandTotalQualifiedReferrersFinalScore,\n minFinalScoreToQualify,\n } satisfies AggregatedReferrerMetricsPieSplit;\n\n validateAggregatedReferrerMetricsPieSplit(result);\n\n return result;\n};\n","import type { ReferralProgramRules } from \"./rules\";\n\n/**\n * Referral program edition slug.\n *\n * A URL-safe identifier for a referral program edition. Each edition represents\n * a distinct referral program period with its own rules, leaderboard, and\n * award distribution.\n *\n * @invariant Must contain only lowercase letters (a-z), digits (0-9), and hyphens (-).\n * Must not start or end with a hyphen. Pattern: `^[a-z0-9]+(-[a-z0-9]+)*$`\n *\n * @example \"2025-12\" // December 2025 edition\n * @example \"2026-03\" // March 2026 edition\n * @example \"holiday-special\" // Custom named edition\n */\nexport type ReferralProgramEditionSlug = string;\n\n/**\n * Regex pattern that all {@link ReferralProgramEditionSlug} values must match.\n *\n * Allows lowercase letters (a-z), digits (0-9), and hyphens (-).\n * Must not start or end with a hyphen.\n */\nexport const REFERRAL_PROGRAM_EDITION_SLUG_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;\n\n/**\n * Represents a referral program edition configuration.\n */\nexport interface ReferralProgramEditionConfig {\n /**\n * Unique slug identifier for the edition.\n */\n slug: ReferralProgramEditionSlug;\n\n /**\n * Human-readable display name for the edition.\n * @example \"ENS Holiday Awards\"\n */\n displayName: string;\n\n /**\n * The rules that govern this referral program edition.\n */\n rules: ReferralProgramRules;\n}\n\n/**\n * A map from edition slug to edition configuration.\n *\n * Used to store and look up all configured referral program editions.\n *\n * @invariant For each key-value pair in the map, the key must equal the value's slug property.\n * That is, for all entries: `map.get(key)?.slug === key`\n */\nexport type ReferralProgramEditionConfigSet = Map<\n ReferralProgramEditionSlug,\n ReferralProgramEditionConfig\n>;\n\n/**\n * Validates that a ReferralProgramEditionConfigSet maintains the invariant\n * that each map key equals the corresponding config's slug.\n *\n * @param configSet - The edition config set to validate\n * @throws {Error} If any entry violates the invariant (key !== value.slug)\n */\nexport function validateReferralProgramEditionConfigSet(\n configSet: ReferralProgramEditionConfigSet,\n): void {\n const violation = Array.from(configSet.entries()).find(([key, config]) => key !== config.slug);\n\n if (violation) {\n const [key, config] = violation;\n throw new Error(\n `Edition config set invariant violation: map key \"${key}\" does not match config.slug \"${config.slug}\"`,\n );\n }\n}\n\n/**\n * Builds a new ReferralProgramEditionConfigSet from an array of configs and validates the invariant.\n *\n * @param configs - Array of edition configurations to add to the set\n * @returns A validated edition config set\n * @throws {Error} If duplicate slugs are detected or if any config would violate the invariant\n */\nexport function buildReferralProgramEditionConfigSet(\n configs: ReferralProgramEditionConfig[],\n): ReferralProgramEditionConfigSet {\n // Check for duplicate slugs before creating the Map\n const slugCounts = configs.reduce((counts, config) => {\n counts.set(config.slug, (counts.get(config.slug) || 0) + 1);\n return counts;\n }, new Map<ReferralProgramEditionSlug, number>());\n\n const duplicates = Array.from(slugCounts.entries())\n .filter(([_, count]) => count > 1)\n .map(([slug, count]) => `\"${slug}\" (${count} occurrences)`);\n\n if (duplicates.length > 0) {\n throw new Error(`Duplicate edition config slugs detected: ${duplicates.join(\", \")}`);\n }\n\n const configSet = new Map(configs.map((config) => [config.slug, config]));\n validateReferralProgramEditionConfigSet(configSet);\n return configSet;\n}\n","import {\n REFERRAL_PROGRAM_EDITION_SLUG_PATTERN,\n type ReferralProgramEditionSlug,\n} from \"../../edition\";\nimport type {\n BaseReferralProgramRules,\n ReferralProgramAwardModel,\n ReferralProgramAwardModels,\n ReferralProgramRulesUnrecognized,\n} from \"./rules\";\nimport type { ReferralProgramEditionStatusId } from \"./status\";\n\n/**\n * Base fields shared by all edition summary variants.\n */\nexport interface BaseReferralProgramEditionSummary {\n /**\n * Discriminant: identifies the award model for this edition.\n *\n * @invariant Always equals `rules.awardModel`.\n */\n awardModel: ReferralProgramAwardModel;\n\n /**\n * Unique slug identifier for the edition.\n */\n slug: ReferralProgramEditionSlug;\n\n /**\n * Human-readable display name for the edition.\n */\n displayName: string;\n\n /**\n * The current runtime status of the edition.\n */\n status: ReferralProgramEditionStatusId;\n\n /**\n * The rules for this edition. Per-model subtypes narrow this to their specific rules type.\n */\n rules: BaseReferralProgramRules;\n}\n\n/**\n * Edition summary for an edition whose `awardModel` is not recognized by this client version.\n *\n * @remarks\n * This is a **client-side forward-compatibility** type only. It is never serialized or produced\n * by the server. When the server sends a new award model, older clients preserve the edition\n * summary rather than crashing, and downstream code should handle it gracefully.\n */\nexport interface ReferralProgramEditionSummaryUnrecognized\n extends BaseReferralProgramEditionSummary {\n /**\n * Discriminant — always `\"unrecognized\"`.\n */\n awardModel: typeof ReferralProgramAwardModels.Unrecognized;\n\n /**\n * The unrecognized rules — preserves `originalAwardModel` for logging/debugging.\n */\n rules: ReferralProgramRulesUnrecognized;\n}\n\nexport const validateBaseReferralProgramEditionSummary = (\n summary: BaseReferralProgramEditionSummary,\n): void => {\n if (!REFERRAL_PROGRAM_EDITION_SLUG_PATTERN.test(summary.slug)) {\n throw new Error(\n `BaseReferralProgramEditionSummary: slug \"${summary.slug}\" does not match required pattern ${REFERRAL_PROGRAM_EDITION_SLUG_PATTERN}.`,\n );\n }\n\n if (summary.displayName.length === 0) {\n throw new Error(\"BaseReferralProgramEditionSummary: displayName must not be empty.\");\n }\n\n if (summary.awardModel !== summary.rules.awardModel) {\n throw new Error(\n `BaseReferralProgramEditionSummary: awardModel (${summary.awardModel}) must equal rules.awardModel (${summary.rules.awardModel}).`,\n );\n }\n};\n","import type { AccountId, UnixTimestamp } from \"enssdk\";\n\nimport type { PriceUsdc } from \"@ensnode/ensnode-sdk\";\nimport { makePriceUsdcSchema } from \"@ensnode/ensnode-sdk/internal\";\n\nimport { validateNonNegativeInteger } from \"../../number\";\nimport {\n type BaseReferralProgramRules,\n ReferralProgramAwardModels,\n validateBaseReferralProgramRules,\n} from \"../shared/rules\";\n\nexport interface ReferralProgramRulesPieSplit extends BaseReferralProgramRules {\n /**\n * Discriminant: identifies this as a \"pie-split\" award model edition.\n *\n * In pie-split, the top-N referrers split an award pool proportionally\n * based on their scored duration (with rank-based boost).\n */\n awardModel: typeof ReferralProgramAwardModels.PieSplit;\n\n /**\n * The award pool in USDC.\n *\n * NOTE: Awards will actually be distributed in $ENS tokens.\n */\n awardPool: PriceUsdc;\n\n /**\n * The maximum number of referrers that will qualify to receive a non-zero `awardPoolShare`.\n *\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n maxQualifiedReferrers: number;\n}\n\nexport const validateReferralProgramRulesPieSplit = (rules: ReferralProgramRulesPieSplit): void => {\n makePriceUsdcSchema(\"ReferralProgramRulesPieSplit.awardPool\").parse(rules.awardPool);\n\n validateNonNegativeInteger(rules.maxQualifiedReferrers);\n\n validateBaseReferralProgramRules(rules);\n};\n\nexport const buildReferralProgramRulesPieSplit = (\n awardPool: PriceUsdc,\n maxQualifiedReferrers: number,\n startTime: UnixTimestamp,\n endTime: UnixTimestamp,\n subregistryId: AccountId,\n rulesUrl: URL,\n areAwardsDistributed: boolean,\n): ReferralProgramRulesPieSplit => {\n const result = {\n awardModel: ReferralProgramAwardModels.PieSplit,\n awardPool,\n maxQualifiedReferrers,\n startTime,\n endTime,\n subregistryId,\n rulesUrl,\n areAwardsDistributed,\n } satisfies ReferralProgramRulesPieSplit;\n\n validateReferralProgramRulesPieSplit(result);\n\n return result;\n};\n","import type { UnixTimestamp } from \"enssdk\";\n\nimport {\n calcBaseReferralProgramEditionStatus,\n type ReferralProgramEditionStatusId,\n} from \"../shared/status\";\nimport type { ReferralProgramRulesPieSplit } from \"./rules\";\n\n/**\n * Calculate the status of a `pie-split` referral program.\n *\n * Delegates entirely to {@link calcBaseReferralProgramEditionStatus} — pie-split has no additional\n * runtime conditions that affect status beyond the time-based lifecycle.\n *\n * @param rules - The pie-split rules for the edition.\n * @param now - Current date in {@link UnixTimestamp} format.\n */\nexport const calcReferralProgramEditionStatusPieSplit = (\n rules: ReferralProgramRulesPieSplit,\n now: UnixTimestamp,\n): ReferralProgramEditionStatusId => calcBaseReferralProgramEditionStatus(rules, now);\n","import type { ReferralProgramEditionSlug } from \"../../edition\";\nimport type { BaseReferralProgramEditionSummary } from \"../shared/edition-summary\";\nimport { validateBaseReferralProgramEditionSummary } from \"../shared/edition-summary\";\nimport type { ReferralProgramAwardModels } from \"../shared/rules\";\nimport type { ReferrerLeaderboardPieSplit } from \"./leaderboard\";\nimport type { ReferralProgramRulesPieSplit } from \"./rules\";\nimport { validateReferralProgramRulesPieSplit } from \"./rules\";\nimport { calcReferralProgramEditionStatusPieSplit } from \"./status\";\n\n/**\n * Edition summary for a `pie-split` referral program edition.\n */\nexport interface ReferralProgramEditionSummaryPieSplit extends BaseReferralProgramEditionSummary {\n /**\n * Discriminant — always `\"pie-split\"`.\n *\n * @invariant Always equals `rules.awardModel` ({@link ReferralProgramAwardModels.PieSplit}).\n */\n awardModel: typeof ReferralProgramAwardModels.PieSplit;\n\n /**\n * The pie-split rules for this edition.\n */\n rules: ReferralProgramRulesPieSplit;\n}\n\nexport const validateEditionSummaryPieSplit = (\n summary: ReferralProgramEditionSummaryPieSplit,\n): void => {\n validateReferralProgramRulesPieSplit(summary.rules);\n validateBaseReferralProgramEditionSummary(summary);\n};\n\n/**\n * Build a {@link ReferralProgramEditionSummaryPieSplit} from a pie-split edition config and the\n * edition's leaderboard.\n */\nexport function buildEditionSummaryPieSplit(\n slug: ReferralProgramEditionSlug,\n displayName: string,\n rules: ReferralProgramRulesPieSplit,\n leaderboard: ReferrerLeaderboardPieSplit,\n): ReferralProgramEditionSummaryPieSplit {\n const status = calcReferralProgramEditionStatusPieSplit(rules, leaderboard.accurateAsOf);\n const result = { awardModel: rules.awardModel, slug, displayName, status, rules };\n\n validateEditionSummaryPieSplit(result);\n\n return result;\n}\n","import type { UnixTimestamp } from \"enssdk\";\n\nimport type { ReferrerMetrics } from \"../../referrer-metrics\";\nimport type { BaseReferralProgramRules } from \"./rules\";\n\n/**\n * Asserts invariants that must hold for any leaderboard builder regardless of award model.\n */\nexport const assertLeaderboardInputs = (\n allReferrers: ReferrerMetrics[],\n rules: BaseReferralProgramRules,\n accurateAsOf: UnixTimestamp,\n): void => {\n const uniqueReferrers = new Set(allReferrers.map((r) => r.referrer));\n if (uniqueReferrers.size !== allReferrers.length) {\n throw new Error(\n \"ReferrerLeaderboard: Cannot build a leaderboard containing duplicate referrers\",\n );\n }\n\n if (accurateAsOf < rules.startTime && allReferrers.length > 0) {\n throw new Error(\n `ReferrerLeaderboard: accurateAsOf (${accurateAsOf}) is before startTime (${rules.startTime}) which indicates allReferrers should be empty, but allReferrers is not empty.`,\n );\n }\n};\n","import type { Duration, NormalizedAddress } from \"enssdk\";\n\nimport { isPositiveInteger } from \"../../number\";\nimport type { ReferrerMetrics } from \"../../referrer-metrics\";\n\n/**\n * The rank of a referrer relative to all other referrers, where 1 is the\n * top-ranked referrer.\n *\n * @invariant Guaranteed to be a positive integer (> 0)\n */\nexport type ReferrerRank = number;\n\nexport const validateReferrerRank = (rank: ReferrerRank): void => {\n if (!isPositiveInteger(rank)) {\n throw new Error(`Invalid ReferrerRank: ${rank}. ReferrerRank must be a positive integer.`);\n }\n};\n\nexport interface ReferrerMetricsForComparison {\n /**\n * The total incremental duration (in seconds) of all referrals made by the referrer within\n * the {@link ReferralProgramRules}.\n */\n totalIncrementalDuration: Duration;\n\n /**\n * The Ethereum address of the referrer, as a {@link NormalizedAddress}.\n */\n referrer: NormalizedAddress;\n}\n\nexport const compareReferrerMetrics = (\n a: ReferrerMetricsForComparison,\n b: ReferrerMetricsForComparison,\n): number => {\n // Primary sort: totalIncrementalDuration (descending)\n if (a.totalIncrementalDuration !== b.totalIncrementalDuration) {\n return b.totalIncrementalDuration - a.totalIncrementalDuration;\n }\n\n // Secondary sort: referrer address using lexicographic comparison of ASCII hex strings (descending)\n if (b.referrer > a.referrer) return 1;\n if (b.referrer < a.referrer) return -1;\n return 0;\n};\n\n/**\n * Sorts a list of referrers for leaderboard ranking.\n * Returns a new array — does not mutate the input.\n */\nexport const sortReferrerMetrics = (referrers: ReferrerMetrics[]): ReferrerMetrics[] => {\n return [...referrers].sort(compareReferrerMetrics);\n};\n","import type { Duration, NormalizedAddress } from \"enssdk\";\n\nimport type { PriceEth } from \"@ensnode/ensnode-sdk\";\nimport { makePriceEthSchema } from \"@ensnode/ensnode-sdk/internal\";\n\nimport { validateNormalizedAddress } from \"./address\";\nimport { validateNonNegativeInteger } from \"./number\";\nimport { ReferralProgramRules } from \"./rules\";\nimport { validateDuration } from \"./time\";\n\n/**\n * Metrics for a single referrer, as aggregated from the DB layer.\n * Independent of other referrers and award model; does not carry an `awardModel` discriminant.\n */\nexport interface ReferrerMetrics {\n /**\n * The Ethereum address of the referrer, as a {@link NormalizedAddress}.\n */\n referrer: NormalizedAddress;\n\n /**\n * The total number of referrals made by the referrer within the {@link ReferralProgramRules}.\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n totalReferrals: number;\n\n /**\n * The total incremental duration (in seconds) of all referrals made by the referrer within\n * the {@link ReferralProgramRules}.\n */\n totalIncrementalDuration: Duration;\n\n /**\n * The total revenue contribution in ETH made to the ENS DAO by all referrals\n * from this referrer.\n *\n * This is the sum of the total cost paid by registrants for all registrar actions\n * where this address was the referrer.\n *\n * @invariant Never null (records with null `total` in the database are treated as 0 when summing)\n */\n totalRevenueContribution: PriceEth;\n}\n\nexport const buildReferrerMetrics = (\n referrer: NormalizedAddress,\n totalReferrals: number,\n totalIncrementalDuration: Duration,\n totalRevenueContribution: PriceEth,\n): ReferrerMetrics => {\n const result = {\n referrer,\n totalReferrals,\n totalIncrementalDuration,\n totalRevenueContribution,\n } satisfies ReferrerMetrics;\n\n validateReferrerMetrics(result);\n return result;\n};\n\nexport const validateReferrerMetrics = (metrics: ReferrerMetrics): void => {\n validateNormalizedAddress(metrics.referrer);\n validateNonNegativeInteger(metrics.totalReferrals);\n validateDuration(metrics.totalIncrementalDuration);\n\n makePriceEthSchema(\"ReferrerMetrics.totalRevenueContribution\").parse(\n metrics.totalRevenueContribution,\n );\n};\n","import type { Duration } from \"enssdk\";\n\nimport { SECONDS_PER_YEAR } from \"../../time\";\nimport type { ReferrerScore } from \"../shared/score\";\n\n/**\n * Calculate the score of a referrer based on the total incremental duration\n * (in seconds) of registrations and renewals for direct subnames of .eth\n * referred by the referrer within the referral program edition.\n *\n * Used exclusively in the pie-split award model pipeline.\n *\n * @param totalIncrementalDuration - The total incremental duration (in seconds)\n * of referrals made by a referrer within the {@link ReferralProgramRulesPieSplit}.\n */\nexport const calcReferrerScorePieSplit = (totalIncrementalDuration: Duration): ReferrerScore => {\n return totalIncrementalDuration / SECONDS_PER_YEAR;\n};\n","import type { Duration } from \"enssdk\";\n\nimport type { ReferrerRank } from \"../shared/rank\";\nimport type { ReferrerScore } from \"../shared/score\";\nimport type { ReferralProgramRulesPieSplit } from \"./rules\";\nimport { calcReferrerScorePieSplit } from \"./score\";\n\n/**\n * Determine if a referrer with the given `rank` is qualified to receive a non-zero\n * `awardPoolShare` under pie-split rules.\n *\n * @param rank - The rank of the referrer relative to all other referrers on a leaderboard.\n * @param rules - The pie-split rules of the referral program.\n */\nexport function isReferrerQualifiedPieSplit(\n rank: ReferrerRank,\n rules: ReferralProgramRulesPieSplit,\n): boolean {\n return rank <= rules.maxQualifiedReferrers;\n}\n\n/**\n * Calculate the final score boost of a referrer based on their rank (pie-split only).\n *\n * @param rank - The rank of the referrer relative to all other referrers, where 1 is the\n * top-ranked referrer.\n * @returns The final score boost of the referrer as a number between 0 and 1 (inclusive).\n */\nexport function calcReferrerFinalScoreBoostPieSplit(\n rank: ReferrerRank,\n rules: ReferralProgramRulesPieSplit,\n): number {\n if (!isReferrerQualifiedPieSplit(rank, rules)) return 0;\n\n // Avoid division by zero when only a single referrer is qualified.\n // In this case, that single referrer (rank 1) should receive the maximum boost.\n if (rules.maxQualifiedReferrers === 1) return 1;\n\n return 1 - (rank - 1) / (rules.maxQualifiedReferrers - 1);\n}\n\n/**\n * Calculate the final score multiplier of a referrer based on their rank (pie-split only).\n *\n * @param rank - The rank of the referrer relative to all other referrers, where 1 is the\n * top-ranked referrer.\n * @returns The final score multiplier of the referrer as a number between 1 and 2 (inclusive).\n */\nexport function calcReferrerFinalScoreMultiplierPieSplit(\n rank: ReferrerRank,\n rules: ReferralProgramRulesPieSplit,\n): number {\n return 1 + calcReferrerFinalScoreBoostPieSplit(rank, rules);\n}\n\n/**\n * Calculate the final score of a referrer based on their score and final score boost (pie-split only).\n *\n * @param rank - The rank of the referrer relative to all other referrers.\n * @param totalIncrementalDuration - The total incremental duration (in seconds)\n * of referrals made by the referrer within the `rules`.\n * @param rules - The pie-split rules of the referral program.\n */\nexport function calcReferrerFinalScorePieSplit(\n rank: ReferrerRank,\n totalIncrementalDuration: Duration,\n rules: ReferralProgramRulesPieSplit,\n): ReferrerScore {\n return (\n calcReferrerScorePieSplit(totalIncrementalDuration) *\n calcReferrerFinalScoreMultiplierPieSplit(rank, rules)\n );\n}\n","import type { NormalizedAddress } from \"enssdk\";\n\nimport { type PriceUsdc, priceEth, priceUsdc, scalePrice } from \"@ensnode/ensnode-sdk\";\nimport { makePriceEthSchema, makePriceUsdcSchema } from \"@ensnode/ensnode-sdk/internal\";\n\nimport type { ReferrerMetrics } from \"../../referrer-metrics\";\nimport { buildReferrerMetrics, validateReferrerMetrics } from \"../../referrer-metrics\";\nimport type { ReferrerRank } from \"../shared/rank\";\nimport { validateReferrerRank } from \"../shared/rank\";\nimport { type ReferrerScore, validateReferrerScore } from \"../shared/score\";\nimport type { AggregatedReferrerMetricsPieSplit } from \"./aggregations\";\nimport {\n calcReferrerFinalScoreBoostPieSplit,\n calcReferrerFinalScorePieSplit,\n isReferrerQualifiedPieSplit,\n} from \"./rank\";\nimport type { ReferralProgramRulesPieSplit } from \"./rules\";\nimport { calcReferrerScorePieSplit } from \"./score\";\n\n/**\n * Represents metrics for a single referrer independent of other referrers,\n * including a calculation of the referrer's score.\n */\nexport interface ScoredReferrerMetricsPieSplit extends ReferrerMetrics {\n /**\n * The referrer's score.\n *\n * @invariant Guaranteed to be `calcReferrerScorePieSplit(totalIncrementalDuration)`\n */\n score: ReferrerScore;\n}\n\nexport const buildScoredReferrerMetricsPieSplit = (\n referrer: ReferrerMetrics,\n): ScoredReferrerMetricsPieSplit => {\n const result = {\n ...referrer,\n score: calcReferrerScorePieSplit(referrer.totalIncrementalDuration),\n } satisfies ScoredReferrerMetricsPieSplit;\n\n validateScoredReferrerMetricsPieSplit(result);\n return result;\n};\n\nexport const validateScoredReferrerMetricsPieSplit = (\n metrics: ScoredReferrerMetricsPieSplit,\n): void => {\n validateReferrerMetrics(metrics);\n validateReferrerScore(metrics.score);\n\n const expectedScore = calcReferrerScorePieSplit(metrics.totalIncrementalDuration);\n if (metrics.score !== expectedScore) {\n throw new Error(`Referrer: Invalid score: ${metrics.score}, expected: ${expectedScore}.`);\n }\n};\n\n/**\n * Extends {@link ScoredReferrerMetricsPieSplit} to include additional metrics relative to all\n * other referrers on a {@link ReferrerLeaderboardPieSplit} and {@link ReferralProgramRulesPieSplit}.\n */\nexport interface RankedReferrerMetricsPieSplit extends ScoredReferrerMetricsPieSplit {\n /**\n * The referrer's rank on the {@link ReferrerLeaderboardPieSplit} relative to all other referrers.\n */\n rank: ReferrerRank;\n\n /**\n * Identifies if the referrer meets the qualifications of the {@link ReferralProgramRulesPieSplit} to receive a non-zero `awardPoolShare`.\n *\n * @invariant true if and only if `rank` is less than or equal to {@link ReferralProgramRulesPieSplit.maxQualifiedReferrers}\n */\n isQualified: boolean;\n\n /**\n * The referrer's final score boost.\n *\n * @invariant Guaranteed to be a number between 0 and 1 (inclusive)\n * @invariant Calculated as: `1-((rank-1)/({@link ReferralProgramRulesPieSplit.maxQualifiedReferrers}-1))` if `isQualified` is `true`, else `0`\n */\n finalScoreBoost: number;\n\n /**\n * The referrer's final score.\n *\n * @invariant Calculated as: `score * (1 + finalScoreBoost)`\n */\n finalScore: ReferrerScore;\n}\n\nexport const validateRankedReferrerMetricsPieSplit = (\n metrics: RankedReferrerMetricsPieSplit,\n rules: ReferralProgramRulesPieSplit,\n): void => {\n validateScoredReferrerMetricsPieSplit(metrics);\n validateReferrerRank(metrics.rank);\n\n if (metrics.finalScoreBoost < 0 || metrics.finalScoreBoost > 1) {\n throw new Error(\n `Invalid RankedReferrerMetricsPieSplit: Invalid finalScoreBoost: ${metrics.finalScoreBoost}. finalScoreBoost must be between 0 and 1 (inclusive).`,\n );\n }\n\n validateReferrerScore(metrics.finalScore);\n\n const expectedIsQualified = isReferrerQualifiedPieSplit(metrics.rank, rules);\n if (metrics.isQualified !== expectedIsQualified) {\n throw new Error(\n `RankedReferrerMetricsPieSplit: Invalid isQualified: ${metrics.isQualified}, expected: ${expectedIsQualified}.`,\n );\n }\n\n const expectedFinalScoreBoost = calcReferrerFinalScoreBoostPieSplit(metrics.rank, rules);\n if (metrics.finalScoreBoost !== expectedFinalScoreBoost) {\n throw new Error(\n `RankedReferrerMetricsPieSplit: Invalid finalScoreBoost: ${metrics.finalScoreBoost}, expected: ${expectedFinalScoreBoost}.`,\n );\n }\n\n const expectedFinalScore = calcReferrerFinalScorePieSplit(\n metrics.rank,\n metrics.totalIncrementalDuration,\n rules,\n );\n if (metrics.finalScore !== expectedFinalScore) {\n throw new Error(\n `RankedReferrerMetricsPieSplit: Invalid finalScore: ${metrics.finalScore}, expected: ${expectedFinalScore}.`,\n );\n }\n};\n\nexport const buildRankedReferrerMetricsPieSplit = (\n referrer: ScoredReferrerMetricsPieSplit,\n rank: ReferrerRank,\n rules: ReferralProgramRulesPieSplit,\n): RankedReferrerMetricsPieSplit => {\n const result = {\n ...referrer,\n rank,\n isQualified: isReferrerQualifiedPieSplit(rank, rules),\n finalScoreBoost: calcReferrerFinalScoreBoostPieSplit(rank, rules),\n finalScore: calcReferrerFinalScorePieSplit(rank, referrer.totalIncrementalDuration, rules),\n } satisfies RankedReferrerMetricsPieSplit;\n validateRankedReferrerMetricsPieSplit(result, rules);\n return result;\n};\n\n/**\n * Calculate the share of the award pool for a referrer.\n * @param referrer - The referrer to calculate the award pool share for.\n * @param aggregatedMetrics - Aggregated metrics for all referrers.\n * @returns The referrer's share of the award pool as a number between 0 and 1 (inclusive).\n */\nexport const calcReferrerAwardPoolSharePieSplit = (\n referrer: RankedReferrerMetricsPieSplit,\n aggregatedMetrics: AggregatedReferrerMetricsPieSplit,\n): number => {\n if (!referrer.isQualified) return 0;\n if (aggregatedMetrics.grandTotalQualifiedReferrersFinalScore === 0) return 0;\n\n return referrer.finalScore / aggregatedMetrics.grandTotalQualifiedReferrersFinalScore;\n};\n\n/**\n * Extends {@link RankedReferrerMetricsPieSplit} to include additional metrics\n * relative to {@link AggregatedReferrerMetricsPieSplit}.\n */\nexport interface AwardedReferrerMetricsPieSplit extends RankedReferrerMetricsPieSplit {\n /**\n * The referrer's share of the award pool.\n *\n * @invariant Guaranteed to be a number between 0 and 1 (inclusive)\n * @invariant Calculated as: `finalScore / {@link AggregatedReferrerMetricsPieSplit.grandTotalQualifiedReferrersFinalScore}` if `isQualified` is `true`, else `0`\n */\n awardPoolShare: number;\n\n /**\n * The approximate USDC value of the referrer's share of the {@link ReferralProgramRulesPieSplit.awardPool}.\n *\n * @invariant Guaranteed to be a valid PriceUsdc with amount between 0 and {@link ReferralProgramRulesPieSplit.awardPool.amount} (inclusive)\n * @invariant Calculated as: `awardPoolShare` * {@link ReferralProgramRulesPieSplit.awardPool.amount}\n */\n awardPoolApproxValue: PriceUsdc;\n}\n\nexport const validateAwardedReferrerMetricsPieSplit = (\n referrer: AwardedReferrerMetricsPieSplit,\n rules: ReferralProgramRulesPieSplit,\n): void => {\n validateRankedReferrerMetricsPieSplit(referrer, rules);\n if (referrer.awardPoolShare < 0 || referrer.awardPoolShare > 1) {\n throw new Error(\n `Invalid AwardedReferrerMetricsPieSplit: ${referrer.awardPoolShare}. awardPoolShare must be between 0 and 1 (inclusive).`,\n );\n }\n\n makePriceUsdcSchema(\"AwardedReferrerMetricsPieSplit.awardPoolApproxValue\").parse(\n referrer.awardPoolApproxValue,\n );\n\n if (referrer.awardPoolApproxValue.amount > rules.awardPool.amount) {\n throw new Error(\n `AwardedReferrerMetricsPieSplit: awardPoolApproxValue.amount ${referrer.awardPoolApproxValue.amount.toString()} exceeds awardPool.amount ${rules.awardPool.amount.toString()}.`,\n );\n }\n};\n\nexport const buildAwardedReferrerMetricsPieSplit = (\n referrer: RankedReferrerMetricsPieSplit,\n aggregatedMetrics: AggregatedReferrerMetricsPieSplit,\n rules: ReferralProgramRulesPieSplit,\n): AwardedReferrerMetricsPieSplit => {\n const awardPoolShare = calcReferrerAwardPoolSharePieSplit(referrer, aggregatedMetrics);\n\n // Calculate the approximate USDC value by multiplying the share by the award pool\n const awardPoolApproxValue = scalePrice(rules.awardPool, awardPoolShare);\n\n const result = {\n ...referrer,\n awardPoolShare,\n awardPoolApproxValue,\n } satisfies AwardedReferrerMetricsPieSplit;\n validateAwardedReferrerMetricsPieSplit(result, rules);\n return result;\n};\n\n/**\n * Extends {@link AwardedReferrerMetricsPieSplit} but with rank set to null to represent\n * a referrer who is not on the leaderboard (has zero referrals within the rules associated with the leaderboard).\n */\nexport interface UnrankedReferrerMetricsPieSplit\n extends Omit<AwardedReferrerMetricsPieSplit, \"rank\" | \"isQualified\"> {\n /**\n * The referrer is not on the leaderboard and therefore has no rank.\n */\n rank: null;\n\n /**\n * Always false for unranked referrers.\n */\n isQualified: false;\n}\n\nexport const validateUnrankedReferrerMetricsPieSplit = (\n metrics: UnrankedReferrerMetricsPieSplit,\n): void => {\n validateScoredReferrerMetricsPieSplit(metrics);\n\n if (metrics.rank !== null) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsPieSplit: rank must be null, got: ${metrics.rank}.`,\n );\n }\n if (metrics.isQualified !== false) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsPieSplit: isQualified must be false, got: ${metrics.isQualified}.`,\n );\n }\n if (metrics.totalReferrals !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsPieSplit: totalReferrals must be 0, got: ${metrics.totalReferrals}.`,\n );\n }\n if (metrics.totalIncrementalDuration !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsPieSplit: totalIncrementalDuration must be 0, got: ${metrics.totalIncrementalDuration}.`,\n );\n }\n\n makePriceEthSchema(\"UnrankedReferrerMetricsPieSplit.totalRevenueContribution\").parse(\n metrics.totalRevenueContribution,\n );\n if (metrics.totalRevenueContribution.amount !== 0n) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsPieSplit: totalRevenueContribution.amount must be 0n, got: ${metrics.totalRevenueContribution.amount.toString()}.`,\n );\n }\n\n if (metrics.score !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsPieSplit: score must be 0, got: ${metrics.score}.`,\n );\n }\n if (metrics.finalScoreBoost !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsPieSplit: finalScoreBoost must be 0, got: ${metrics.finalScoreBoost}.`,\n );\n }\n if (metrics.finalScore !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsPieSplit: finalScore must be 0, got: ${metrics.finalScore}.`,\n );\n }\n if (metrics.awardPoolShare !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsPieSplit: awardPoolShare must be 0, got: ${metrics.awardPoolShare}.`,\n );\n }\n\n makePriceUsdcSchema(\"UnrankedReferrerMetricsPieSplit.awardPoolApproxValue\").parse(\n metrics.awardPoolApproxValue,\n );\n if (metrics.awardPoolApproxValue.amount !== 0n) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsPieSplit: awardPoolApproxValue must be 0n, got: ${metrics.awardPoolApproxValue.amount.toString()}.`,\n );\n }\n};\n\n/**\n * Build an unranked zero-score referrer record for a referrer address that is not in the leaderboard.\n *\n * This is useful when you want to return a referrer record for an address that has no referrals\n * and is not qualified for the leaderboard.\n *\n * @param referrer - The referrer address\n * @returns An {@link UnrankedReferrerMetricsPieSplit} with zero values for all metrics and null rank\n */\nexport const buildUnrankedReferrerMetricsPieSplit = (\n referrer: NormalizedAddress,\n): UnrankedReferrerMetricsPieSplit => {\n const metrics = buildReferrerMetrics(referrer, 0, 0, priceEth(0n));\n const scoredMetrics = buildScoredReferrerMetricsPieSplit(metrics);\n\n const result = {\n ...scoredMetrics,\n rank: null,\n isQualified: false,\n finalScoreBoost: 0,\n finalScore: 0,\n awardPoolShare: 0,\n awardPoolApproxValue: priceUsdc(0n),\n } satisfies UnrankedReferrerMetricsPieSplit;\n\n validateUnrankedReferrerMetricsPieSplit(result);\n return result;\n};\n","import type { NormalizedAddress, UnixTimestamp } from \"enssdk\";\n\nimport type { ReferrerMetrics } from \"../../referrer-metrics\";\nimport { assertLeaderboardInputs } from \"../shared/leaderboard-guards\";\nimport { sortReferrerMetrics } from \"../shared/rank\";\nimport type { ReferralProgramAwardModels } from \"../shared/rules\";\nimport type { AggregatedReferrerMetricsPieSplit } from \"./aggregations\";\nimport { buildAggregatedReferrerMetricsPieSplit } from \"./aggregations\";\nimport type { AwardedReferrerMetricsPieSplit } from \"./metrics\";\nimport {\n buildAwardedReferrerMetricsPieSplit,\n buildRankedReferrerMetricsPieSplit,\n buildScoredReferrerMetricsPieSplit,\n} from \"./metrics\";\nimport type { ReferralProgramRulesPieSplit } from \"./rules\";\n\n/**\n * Represents a leaderboard with the pie-split award model for any number of referrers.\n */\nexport interface ReferrerLeaderboardPieSplit {\n /**\n * Discriminant identifying this as a pie-split leaderboard.\n *\n * @invariant Always equals `rules.awardModel` ({@link ReferralProgramAwardModels.PieSplit}).\n */\n awardModel: typeof ReferralProgramAwardModels.PieSplit;\n\n /**\n * The rules of the referral program that generated the {@link ReferrerLeaderboardPieSplit}.\n */\n rules: ReferralProgramRulesPieSplit;\n\n /**\n * The {@link AggregatedReferrerMetricsPieSplit} for all {@link RankedReferrerMetricsPieSplit} values in `referrers`.\n */\n aggregatedMetrics: AggregatedReferrerMetricsPieSplit;\n\n /**\n * Ordered map containing `AwardedReferrerMetricsPieSplit` for all referrers with 1 or more\n * `totalReferrals` within the `rules` as of `accurateAsOf`.\n *\n * @invariant Map entries are ordered by `rank` (ascending).\n * @invariant Map is empty if there are no referrers with 1 or more `totalReferrals`\n * within the `rules` as of `accurateAsOf`.\n * @invariant If a `NormalizedAddress` is not a key in this map then that `NormalizedAddress` had\n * 0 `totalReferrals`, `totalIncrementalDuration`, and `score` within the\n * `rules` as of `accurateAsOf`.\n * @invariant Each value in this map is guaranteed to have a non-zero\n * `totalReferrals`, `totalIncrementalDuration`, and `score`.\n */\n referrers: Map<NormalizedAddress, AwardedReferrerMetricsPieSplit>;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link ReferrerLeaderboardPieSplit} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\nexport const buildReferrerLeaderboardPieSplit = (\n allReferrers: ReferrerMetrics[],\n rules: ReferralProgramRulesPieSplit,\n accurateAsOf: UnixTimestamp,\n): ReferrerLeaderboardPieSplit => {\n assertLeaderboardInputs(allReferrers, rules, accurateAsOf);\n\n const sortedReferrers = sortReferrerMetrics(allReferrers);\n\n const scoredReferrers = sortedReferrers.map((r) => buildScoredReferrerMetricsPieSplit(r));\n\n const rankedReferrers = scoredReferrers.map((r, index) =>\n buildRankedReferrerMetricsPieSplit(r, index + 1, rules),\n );\n\n const aggregatedMetrics = buildAggregatedReferrerMetricsPieSplit(rankedReferrers, rules);\n\n const awardedReferrers = rankedReferrers.map((r) =>\n buildAwardedReferrerMetricsPieSplit(r, aggregatedMetrics, rules),\n );\n\n const referrers = new Map(awardedReferrers.map((r) => [r.referrer, r]));\n\n return { awardModel: rules.awardModel, rules, aggregatedMetrics, referrers, accurateAsOf };\n};\n","import {\n type BaseReferrerLeaderboardPage,\n type ReferrerLeaderboardPageContext,\n sliceReferrers,\n} from \"../shared/leaderboard-page\";\nimport type { ReferralProgramAwardModels } from \"../shared/rules\";\nimport type { AggregatedReferrerMetricsPieSplit } from \"./aggregations\";\nimport type { ReferrerLeaderboardPieSplit } from \"./leaderboard\";\nimport type { AwardedReferrerMetricsPieSplit } from \"./metrics\";\nimport type { ReferralProgramRulesPieSplit } from \"./rules\";\nimport { calcReferralProgramEditionStatusPieSplit } from \"./status\";\n\n/**\n * A page of referrers from the pie-split referrer leaderboard.\n */\nexport interface ReferrerLeaderboardPagePieSplit extends BaseReferrerLeaderboardPage {\n /**\n * Discriminant identifying this as a page from a pie-split leaderboard.\n *\n * @invariant Always equals `rules.awardModel` ({@link ReferralProgramAwardModels.PieSplit}).\n */\n awardModel: typeof ReferralProgramAwardModels.PieSplit;\n\n /**\n * The {@link ReferralProgramRulesPieSplit} used to generate the {@link ReferrerLeaderboardPieSplit}\n * that this {@link ReferrerLeaderboardPagePieSplit} comes from.\n */\n rules: ReferralProgramRulesPieSplit;\n\n /**\n * Ordered list of {@link AwardedReferrerMetricsPieSplit} for the {@link ReferrerLeaderboardPagePieSplit}\n * described by {@link pageContext} within the related {@link ReferrerLeaderboardPieSplit}.\n *\n * @invariant Array will be empty if `pageContext.totalRecords` is 0.\n * @invariant Array entries are ordered by `rank` (ascending).\n */\n referrers: AwardedReferrerMetricsPieSplit[];\n\n /**\n * The aggregated metrics for all referrers on the leaderboard.\n */\n aggregatedMetrics: AggregatedReferrerMetricsPieSplit;\n}\n\nexport function buildLeaderboardPagePieSplit(\n pageContext: ReferrerLeaderboardPageContext,\n leaderboard: ReferrerLeaderboardPieSplit,\n): ReferrerLeaderboardPagePieSplit {\n const status = calcReferralProgramEditionStatusPieSplit(\n leaderboard.rules,\n leaderboard.accurateAsOf,\n );\n return {\n awardModel: leaderboard.awardModel,\n rules: leaderboard.rules,\n referrers: sliceReferrers(leaderboard.referrers, pageContext),\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n pageContext,\n status,\n accurateAsOf: leaderboard.accurateAsOf,\n };\n}\n","import type { Duration } from \"enssdk\";\n\nimport { type PriceEth, type PriceUsdc, priceEth } from \"@ensnode/ensnode-sdk\";\nimport { makePriceEthSchema, makePriceUsdcSchema } from \"@ensnode/ensnode-sdk/internal\";\n\nimport { validateNonNegativeInteger } from \"../../number\";\nimport { validateDuration } from \"../../time\";\nimport type { AwardedReferrerMetricsRevShareCap } from \"./metrics\";\n\n/**\n * Represents aggregated metrics for a list of referrers on a rev-share-cap leaderboard.\n */\nexport interface AggregatedReferrerMetricsRevShareCap {\n /**\n * @invariant The sum of `totalReferrals` across all referrers in the list.\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n grandTotalReferrals: number;\n\n /**\n * @invariant The sum of `totalIncrementalDuration` across all referrers in the list.\n */\n grandTotalIncrementalDuration: Duration;\n\n /**\n * The total revenue contribution in ETH to the ENS DAO from all referrals\n * across all referrers on the leaderboard.\n *\n * This is the sum of `totalRevenueContribution` across all referrers in the list.\n *\n * @invariant Guaranteed to be a valid PriceEth with non-negative amount (>= 0n)\n */\n grandTotalRevenueContribution: PriceEth;\n\n /**\n * The remaining amount in the award pool after subtracting all capped awards\n * claimed during the sequential race processing.\n *\n * @invariant Guaranteed to be a valid PriceUsdc with non-negative amount (>= 0n)\n */\n awardPoolRemaining: PriceUsdc;\n}\n\nexport const validateAggregatedReferrerMetricsRevShareCap = (\n metrics: AggregatedReferrerMetricsRevShareCap,\n): void => {\n validateNonNegativeInteger(metrics.grandTotalReferrals);\n validateDuration(metrics.grandTotalIncrementalDuration);\n\n makePriceEthSchema(\"AggregatedReferrerMetricsRevShareCap.grandTotalRevenueContribution\").parse(\n metrics.grandTotalRevenueContribution,\n );\n\n makePriceUsdcSchema(\"AggregatedReferrerMetricsRevShareCap.awardPoolRemaining\").parse(\n metrics.awardPoolRemaining,\n );\n};\n\n/**\n * Builds aggregated rev-share-cap metrics from a complete list of referrers and\n * the award pool remaining after sequential race processing.\n *\n * **IMPORTANT: This function expects a complete list of all referrers.**\n *\n * @param referrers - Must be a complete list of referrers with their totals.\n * **This must NOT be a paginated or partial slice.**\n *\n * @param awardPoolRemaining - The amount remaining in the award pool after the sequential\n * race algorithm has processed all events.\n *\n * @returns Aggregated metrics including totals across all referrers and the award pool remaining.\n */\nexport const buildAggregatedReferrerMetricsRevShareCap = (\n referrers: AwardedReferrerMetricsRevShareCap[],\n awardPoolRemaining: PriceUsdc,\n): AggregatedReferrerMetricsRevShareCap => {\n let grandTotalReferrals = 0;\n let grandTotalIncrementalDuration = 0;\n let grandTotalRevenueContributionAmount = 0n;\n\n for (const referrer of referrers) {\n grandTotalReferrals += referrer.totalReferrals;\n grandTotalIncrementalDuration += referrer.totalIncrementalDuration;\n grandTotalRevenueContributionAmount += referrer.totalRevenueContribution.amount;\n }\n\n const aggregatedMetrics = {\n grandTotalReferrals,\n grandTotalIncrementalDuration,\n grandTotalRevenueContribution: priceEth(grandTotalRevenueContributionAmount),\n awardPoolRemaining,\n } satisfies AggregatedReferrerMetricsRevShareCap;\n\n validateAggregatedReferrerMetricsRevShareCap(aggregatedMetrics);\n\n return aggregatedMetrics;\n};\n","import type { UnixTimestamp } from \"enssdk\";\n\nimport {\n calcBaseReferralProgramEditionStatus,\n ReferralProgramEditionStatuses,\n type ReferralProgramEditionStatusId,\n} from \"../shared/status\";\nimport type { AggregatedReferrerMetricsRevShareCap } from \"./aggregations\";\nimport type { ReferralProgramRulesRevShareCap } from \"./rules\";\n\n/**\n * Calculate the status of a `rev-share-cap` referral program.\n *\n * Returns `Exhausted` when the program is `Active` but its award pool has been fully consumed\n * (`awardPoolRemaining.amount === 0n`). Otherwise delegates to {@link calcBaseReferralProgramEditionStatus}.\n *\n * @param rules - The rev-share-cap rules for the edition.\n * @param now - Current date in {@link UnixTimestamp} format.\n * @param aggregatedMetrics - The aggregated leaderboard metrics, used to check `awardPoolRemaining`.\n */\nexport const calcReferralProgramEditionStatusRevShareCap = (\n rules: ReferralProgramRulesRevShareCap,\n now: UnixTimestamp,\n aggregatedMetrics: AggregatedReferrerMetricsRevShareCap,\n): ReferralProgramEditionStatusId => {\n const base = calcBaseReferralProgramEditionStatus(rules, now);\n if (\n base === ReferralProgramEditionStatuses.Active &&\n aggregatedMetrics.awardPoolRemaining.amount === 0n\n ) {\n return ReferralProgramEditionStatuses.Exhausted;\n }\n return base;\n};\n","import type { PriceUsdc } from \"@ensnode/ensnode-sdk\";\nimport { makePriceUsdcSchema } from \"@ensnode/ensnode-sdk/internal\";\n\nimport type { ReferralProgramEditionSlug } from \"../../edition\";\nimport type { BaseReferralProgramEditionSummary } from \"../shared/edition-summary\";\nimport { validateBaseReferralProgramEditionSummary } from \"../shared/edition-summary\";\nimport type { ReferralProgramAwardModels } from \"../shared/rules\";\nimport type { ReferrerLeaderboardRevShareCap } from \"./leaderboard\";\nimport type { ReferralProgramRulesRevShareCap } from \"./rules\";\nimport { validateReferralProgramRulesRevShareCap } from \"./rules\";\nimport { calcReferralProgramEditionStatusRevShareCap } from \"./status\";\n\n/**\n * Edition summary for a `rev-share-cap` referral program edition.\n *\n * Includes `awardPoolRemaining` so consumers can display pool exhaustion state\n * without needing to fetch the full leaderboard.\n */\nexport interface ReferralProgramEditionSummaryRevShareCap\n extends BaseReferralProgramEditionSummary {\n /**\n * Discriminant — always `\"rev-share-cap\"`.\n *\n * @invariant Always equals `rules.awardModel` ({@link ReferralProgramAwardModels.RevShareCap}).\n */\n awardModel: typeof ReferralProgramAwardModels.RevShareCap;\n\n /**\n * The rev-share-cap rules for this edition.\n */\n rules: ReferralProgramRulesRevShareCap;\n\n /**\n * The remaining award pool after sequential race processing.\n *\n * When `0n`, the edition's status will be {@link ReferralProgramEditionStatuses.Exhausted}\n * if the edition is still within its active window.\n */\n awardPoolRemaining: PriceUsdc;\n}\n\nexport const validateEditionSummaryRevShareCap = (\n summary: ReferralProgramEditionSummaryRevShareCap,\n): void => {\n validateReferralProgramRulesRevShareCap(summary.rules);\n\n makePriceUsdcSchema(\"ReferralProgramEditionSummaryRevShareCap.awardPoolRemaining\").parse(\n summary.awardPoolRemaining,\n );\n\n validateBaseReferralProgramEditionSummary(summary);\n};\n\n/**\n * Build a {@link ReferralProgramEditionSummaryRevShareCap} from a rev-share-cap edition\n * config and the edition's leaderboard.\n */\nexport function buildEditionSummaryRevShareCap(\n slug: ReferralProgramEditionSlug,\n displayName: string,\n rules: ReferralProgramRulesRevShareCap,\n leaderboard: ReferrerLeaderboardRevShareCap,\n): ReferralProgramEditionSummaryRevShareCap {\n const status = calcReferralProgramEditionStatusRevShareCap(\n rules,\n leaderboard.accurateAsOf,\n leaderboard.aggregatedMetrics,\n );\n const result = {\n awardModel: rules.awardModel,\n slug,\n displayName,\n status,\n rules,\n awardPoolRemaining: leaderboard.aggregatedMetrics.awardPoolRemaining,\n };\n\n validateEditionSummaryRevShareCap(result);\n\n return result;\n}\n","import type { NormalizedAddress } from \"enssdk\";\n\nimport { type PriceUsdc, priceEth, priceUsdc } from \"@ensnode/ensnode-sdk\";\nimport { makePriceEthSchema, makePriceUsdcSchema } from \"@ensnode/ensnode-sdk/internal\";\n\nimport type { ReferrerMetrics } from \"../../referrer-metrics\";\nimport { buildReferrerMetrics, validateReferrerMetrics } from \"../../referrer-metrics\";\nimport { SECONDS_PER_YEAR } from \"../../time\";\nimport type { ReferrerRank } from \"../shared/rank\";\nimport { validateReferrerRank } from \"../shared/rank\";\nimport {\n type AdminAction,\n AdminActionTypes,\n isReferrerQualifiedRevShareCap,\n type ReferralProgramRulesRevShareCap,\n} from \"./rules\";\n\n/**\n * Extends {@link ReferrerMetrics} with computed base revenue contribution.\n */\nexport interface ReferrerMetricsRevShareCap extends ReferrerMetrics {\n /**\n * The referrer's base revenue contribution\n * (`rules.baseAnnualRevenueContribution` × years of incremental duration).\n * Used for qualification and award calculation in the rev-share-cap model.\n *\n * @invariant Guaranteed to be `priceUsdc(rules.baseAnnualRevenueContribution.amount * BigInt(totalIncrementalDuration) / BigInt(SECONDS_PER_YEAR))`\n */\n totalBaseRevenueContribution: PriceUsdc;\n}\n\nexport const validateReferrerMetricsRevShareCap = (\n metrics: ReferrerMetricsRevShareCap,\n rules: ReferralProgramRulesRevShareCap,\n): void => {\n validateReferrerMetrics(metrics);\n\n makePriceUsdcSchema(\"ReferrerMetricsRevShareCap.totalBaseRevenueContribution\").parse(\n metrics.totalBaseRevenueContribution,\n );\n\n const expectedTotalBaseRevenueContribution = priceUsdc(\n (rules.baseAnnualRevenueContribution.amount * BigInt(metrics.totalIncrementalDuration)) /\n BigInt(SECONDS_PER_YEAR),\n );\n if (metrics.totalBaseRevenueContribution.amount !== expectedTotalBaseRevenueContribution.amount) {\n throw new Error(\n `ReferrerMetricsRevShareCap: Invalid totalBaseRevenueContribution: ${metrics.totalBaseRevenueContribution.amount.toString()}, expected: ${expectedTotalBaseRevenueContribution.amount.toString()}.`,\n );\n }\n};\n\nexport const buildReferrerMetricsRevShareCap = (\n metrics: ReferrerMetrics,\n rules: ReferralProgramRulesRevShareCap,\n): ReferrerMetricsRevShareCap => {\n const totalBaseRevenueContribution = priceUsdc(\n (rules.baseAnnualRevenueContribution.amount * BigInt(metrics.totalIncrementalDuration)) /\n BigInt(SECONDS_PER_YEAR),\n );\n\n const result = {\n ...metrics,\n totalBaseRevenueContribution,\n } satisfies ReferrerMetricsRevShareCap;\n\n validateReferrerMetricsRevShareCap(result, rules);\n return result;\n};\n\n/**\n * Extends {@link ReferrerMetricsRevShareCap} with rank, qualification status, and admin disqualification.\n */\nexport interface RankedReferrerMetricsRevShareCap extends ReferrerMetricsRevShareCap {\n /**\n * The referrer's rank on the {@link ReferrerLeaderboardRevShareCap} relative to all other referrers.\n */\n rank: ReferrerRank;\n\n /**\n * Identifies if the referrer is eligible for an award under the {@link ReferralProgramRulesRevShareCap}.\n *\n * Note: this is a purely rule-based eligibility predicate and does NOT guarantee\n * `cappedAward.amount > 0n` — a qualified referrer may still receive $0 if the\n * capped award pool is already exhausted by earlier referrers in the race.\n *\n * @invariant true if and only if `totalBaseRevenueContribution` is greater than or equal to\n * {@link ReferralProgramRulesRevShareCap.minBaseRevenueContribution} AND\n * {@link adminAction} does not have `actionType` of {@link AdminActionTypes.Disqualification}.\n */\n isQualified: boolean;\n\n /**\n * The admin action taken on this referrer, or null if no admin action has been taken.\n *\n * @invariant null when no admin action has been taken on this referrer.\n * @invariant Must match the corresponding entry in {@link ReferralProgramRulesRevShareCap.adminActions}.\n */\n adminAction: AdminAction | null;\n}\n\n/**\n * Validates that `metricsAdminAction` matches the admin action (or absence thereof) recorded for\n * `referrer` in `rules.adminActions`. Errors are prefixed with `context` so callers can preserve\n * their existing message format.\n */\nconst validateAdminActionConsistency = (\n metricsAdminAction: AdminAction | null,\n referrer: NormalizedAddress,\n rules: ReferralProgramRulesRevShareCap,\n context: string,\n): void => {\n const expected = rules.adminActions.find((a) => a.referrer === referrer) ?? null;\n\n if (expected === null && metricsAdminAction !== null) {\n throw new Error(\n `${context}: expected null, got actionType=\"${metricsAdminAction.actionType}\".`,\n );\n }\n\n if (expected !== null) {\n if (\n metricsAdminAction === null ||\n metricsAdminAction.actionType !== expected.actionType ||\n metricsAdminAction.referrer !== expected.referrer ||\n metricsAdminAction.reason !== expected.reason\n ) {\n throw new Error(`${context}: does not match expected action from rules.`);\n }\n }\n};\n\nexport const validateRankedReferrerMetricsRevShareCap = (\n metrics: RankedReferrerMetricsRevShareCap,\n rules: ReferralProgramRulesRevShareCap,\n): void => {\n validateReferrerMetricsRevShareCap(metrics, rules);\n validateReferrerRank(metrics.rank);\n\n const expectedIsQualified = isReferrerQualifiedRevShareCap(\n metrics.referrer,\n metrics.totalBaseRevenueContribution,\n rules,\n );\n if (metrics.isQualified !== expectedIsQualified) {\n throw new Error(\n `RankedReferrerMetricsRevShareCap: Invalid isQualified: ${metrics.isQualified}, expected: ${expectedIsQualified}.`,\n );\n }\n\n validateAdminActionConsistency(\n metrics.adminAction,\n metrics.referrer,\n rules,\n \"RankedReferrerMetricsRevShareCap: Invalid adminAction\",\n );\n};\n\nexport const buildRankedReferrerMetricsRevShareCap = (\n referrer: ReferrerMetricsRevShareCap,\n rank: ReferrerRank,\n rules: ReferralProgramRulesRevShareCap,\n): RankedReferrerMetricsRevShareCap => {\n const adminAction = rules.adminActions.find((a) => a.referrer === referrer.referrer) ?? null;\n\n const result = {\n ...referrer,\n rank,\n isQualified: isReferrerQualifiedRevShareCap(\n referrer.referrer,\n referrer.totalBaseRevenueContribution,\n rules,\n ),\n adminAction,\n } satisfies RankedReferrerMetricsRevShareCap;\n\n validateRankedReferrerMetricsRevShareCap(result, rules);\n return result;\n};\n\n/**\n * Extends {@link RankedReferrerMetricsRevShareCap} with the referrer's uncapped and capped awards.\n */\nexport interface AwardedReferrerMetricsRevShareCap extends RankedReferrerMetricsRevShareCap {\n /**\n * The uncapped USDC award for this referrer, computed as\n * `maxBaseRevenueShare × totalBaseRevenueContribution`.\n *\n * Represents what the referrer would receive if the pool were uncapped and the referrer were qualified.\n * Independent of the pool state, qualification status, and admin disqualification status.\n */\n uncappedAward: PriceUsdc;\n\n /**\n * The referrer's (tentative) capped USDC award.\n *\n * This is the amount (tentatively) claimed from the award pool by this referrer, capped by\n * the remaining award pool at the time of their qualifying referrals.\n *\n * @invariant Guaranteed to be a valid PriceUsdc with amount between 0 and {@link ReferralProgramRulesRevShareCap.awardPool.amount} (inclusive)\n * @invariant Always <= uncappedAward.amount\n * @invariant Amount equal to 0 when {@link adminAction} has `actionType` of {@link AdminActionTypes.Disqualification}.\n * @invariant Amount equal to 0 when {@link isQualified} is false.\n */\n cappedAward: PriceUsdc;\n}\n\nexport const validateAwardedReferrerMetricsRevShareCap = (\n metrics: AwardedReferrerMetricsRevShareCap,\n rules: ReferralProgramRulesRevShareCap,\n): void => {\n validateRankedReferrerMetricsRevShareCap(metrics, rules);\n\n makePriceUsdcSchema(\"AwardedReferrerMetricsRevShareCap.uncappedAward\").parse(\n metrics.uncappedAward,\n );\n\n makePriceUsdcSchema(\"AwardedReferrerMetricsRevShareCap.cappedAward\").parse(metrics.cappedAward);\n\n if (\n metrics.adminAction?.actionType === AdminActionTypes.Disqualification &&\n metrics.cappedAward.amount !== 0n\n ) {\n throw new Error(\n `AwardedReferrerMetricsRevShareCap: cappedAward.amount must be 0n for admin-disqualified referrers, got ${metrics.cappedAward.amount.toString()}.`,\n );\n }\n\n if (!metrics.isQualified && metrics.cappedAward.amount !== 0n) {\n throw new Error(\n `AwardedReferrerMetricsRevShareCap: cappedAward.amount must be 0n for unqualified referrers, got ${metrics.cappedAward.amount.toString()}.`,\n );\n }\n\n if (metrics.cappedAward.amount > rules.awardPool.amount) {\n throw new Error(\n `AwardedReferrerMetricsRevShareCap: cappedAward.amount ${metrics.cappedAward.amount.toString()} exceeds awardPool.amount ${rules.awardPool.amount.toString()}.`,\n );\n }\n\n if (metrics.cappedAward.amount > metrics.uncappedAward.amount) {\n throw new Error(\n `AwardedReferrerMetricsRevShareCap: cappedAward.amount ${metrics.cappedAward.amount.toString()} exceeds uncappedAward.amount ${metrics.uncappedAward.amount.toString()}.`,\n );\n }\n};\n\nexport const buildAwardedReferrerMetricsRevShareCap = (\n referrer: RankedReferrerMetricsRevShareCap,\n uncappedAward: PriceUsdc,\n cappedAward: PriceUsdc,\n rules: ReferralProgramRulesRevShareCap,\n): AwardedReferrerMetricsRevShareCap => {\n const result = {\n ...referrer,\n uncappedAward,\n cappedAward,\n } satisfies AwardedReferrerMetricsRevShareCap;\n\n validateAwardedReferrerMetricsRevShareCap(result, rules);\n return result;\n};\n\n/**\n * Extends {@link AwardedReferrerMetricsRevShareCap} but with rank set to null to represent\n * a referrer who is not on the leaderboard (has zero referrals within the rules associated with the leaderboard).\n */\nexport interface UnrankedReferrerMetricsRevShareCap\n extends Omit<AwardedReferrerMetricsRevShareCap, \"rank\" | \"isQualified\"> {\n /**\n * The referrer is not on the leaderboard and therefore has no rank.\n */\n rank: null;\n\n /**\n * Always false for unranked referrers.\n */\n isQualified: false;\n}\n\nexport const validateUnrankedReferrerMetricsRevShareCap = (\n metrics: UnrankedReferrerMetricsRevShareCap,\n rules: ReferralProgramRulesRevShareCap,\n): void => {\n validateReferrerMetrics(metrics);\n\n if (metrics.rank !== null) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsRevShareCap: rank must be null, got: ${metrics.rank}.`,\n );\n }\n if (metrics.isQualified !== false) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsRevShareCap: isQualified must be false, got: ${metrics.isQualified}.`,\n );\n }\n\n validateAdminActionConsistency(\n metrics.adminAction,\n metrics.referrer,\n rules,\n \"Invalid UnrankedReferrerMetricsRevShareCap: adminAction\",\n );\n\n if (metrics.totalReferrals !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsRevShareCap: totalReferrals must be 0, got: ${metrics.totalReferrals}.`,\n );\n }\n if (metrics.totalIncrementalDuration !== 0) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsRevShareCap: totalIncrementalDuration must be 0, got: ${metrics.totalIncrementalDuration}.`,\n );\n }\n\n makePriceEthSchema(\"UnrankedReferrerMetricsRevShareCap.totalRevenueContribution\").parse(\n metrics.totalRevenueContribution,\n );\n if (metrics.totalRevenueContribution.amount !== 0n) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsRevShareCap: totalRevenueContribution.amount must be 0n, got: ${metrics.totalRevenueContribution.amount.toString()}.`,\n );\n }\n\n makePriceUsdcSchema(\"UnrankedReferrerMetricsRevShareCap.totalBaseRevenueContribution\").parse(\n metrics.totalBaseRevenueContribution,\n );\n if (metrics.totalBaseRevenueContribution.amount !== 0n) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsRevShareCap: totalBaseRevenueContribution.amount must be 0n, got: ${metrics.totalBaseRevenueContribution.amount.toString()}.`,\n );\n }\n\n makePriceUsdcSchema(\"UnrankedReferrerMetricsRevShareCap.uncappedAward\").parse(\n metrics.uncappedAward,\n );\n if (metrics.uncappedAward.amount !== 0n) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsRevShareCap: uncappedAward.amount must be 0n, got: ${metrics.uncappedAward.amount.toString()}.`,\n );\n }\n\n makePriceUsdcSchema(\"UnrankedReferrerMetricsRevShareCap.cappedAward\").parse(metrics.cappedAward);\n if (metrics.cappedAward.amount !== 0n) {\n throw new Error(\n `Invalid UnrankedReferrerMetricsRevShareCap: cappedAward.amount must be 0n, got: ${metrics.cappedAward.amount.toString()}.`,\n );\n }\n};\n\n/**\n * Build an unranked zero-metrics rev-share-cap referrer record for an address not on the leaderboard.\n */\nexport const buildUnrankedReferrerMetricsRevShareCap = (\n referrer: NormalizedAddress,\n rules: ReferralProgramRulesRevShareCap,\n): UnrankedReferrerMetricsRevShareCap => {\n const metrics = buildReferrerMetrics(referrer, 0, 0, priceEth(0n));\n\n const adminAction = rules.adminActions.find((a) => a.referrer === metrics.referrer) ?? null;\n\n const result = {\n ...metrics,\n totalBaseRevenueContribution: priceUsdc(0n),\n rank: null,\n isQualified: false,\n uncappedAward: priceUsdc(0n),\n cappedAward: priceUsdc(0n),\n adminAction,\n } satisfies UnrankedReferrerMetricsRevShareCap;\n\n validateUnrankedReferrerMetricsRevShareCap(result, rules);\n return result;\n};\n","import type { ReferralEvent } from \"./referral-event\";\n\n/**\n * Sorts referral events into the chronological order in which each registrar action\n * was executed onchain.\n */\nexport function sortReferralEvents(events: ReferralEvent[]): ReferralEvent[] {\n return [...events].sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));\n}\n","import type { Duration, NormalizedAddress, UnixTimestamp } from \"enssdk\";\n\nimport { priceEth, priceUsdc, scalePrice } from \"@ensnode/ensnode-sdk\";\n\nimport { buildReferrerMetrics } from \"../../referrer-metrics\";\nimport { SECONDS_PER_YEAR } from \"../../time\";\nimport type { ReferralProgramAwardModels } from \"../shared/rules\";\nimport type { AggregatedReferrerMetricsRevShareCap } from \"./aggregations\";\nimport { buildAggregatedReferrerMetricsRevShareCap } from \"./aggregations\";\nimport type { AwardedReferrerMetricsRevShareCap } from \"./metrics\";\nimport {\n buildAwardedReferrerMetricsRevShareCap,\n buildRankedReferrerMetricsRevShareCap,\n buildReferrerMetricsRevShareCap,\n} from \"./metrics\";\nimport type { ReferralEvent } from \"./referral-event\";\nimport { isReferrerQualifiedRevShareCap, type ReferralProgramRulesRevShareCap } from \"./rules\";\nimport { sortReferralEvents } from \"./sort-referral-events\";\n\nconst bigintMin = (a: bigint, b: bigint): bigint => (a < b ? a : b);\n\n/**\n * Represents a leaderboard with the rev-share-cap award model for any number of referrers.\n */\nexport interface ReferrerLeaderboardRevShareCap {\n /**\n * Discriminant identifying this as a rev-share-cap leaderboard.\n *\n * @invariant Always equals `rules.awardModel` ({@link ReferralProgramAwardModels.RevShareCap}).\n */\n awardModel: typeof ReferralProgramAwardModels.RevShareCap;\n\n /**\n * The rules of the referral program that generated the {@link ReferrerLeaderboardRevShareCap}.\n */\n rules: ReferralProgramRulesRevShareCap;\n\n /**\n * The {@link AggregatedReferrerMetricsRevShareCap} for all {@link AwardedReferrerMetricsRevShareCap} values in `referrers`.\n */\n aggregatedMetrics: AggregatedReferrerMetricsRevShareCap;\n\n /**\n * Ordered map containing {@link AwardedReferrerMetricsRevShareCap} for all referrers with 1 or more\n * `totalReferrals` within the `rules` as of `accurateAsOf`.\n *\n * @invariant Map entries are ordered by `rank` (ascending).\n * @invariant Map is empty if there are no referrers with 1 or more `totalReferrals`\n * within the `rules` as of `accurateAsOf`.\n * @invariant If a `NormalizedAddress` is not a key in this map then that `NormalizedAddress` had\n * 0 `totalReferrals`, `totalIncrementalDuration`, and `totalRevenueContribution` within the\n * `rules` as of `accurateAsOf`.\n * @invariant Each value in this map is guaranteed to have a non-zero\n * `totalReferrals` and `totalIncrementalDuration`.\n */\n referrers: Map<NormalizedAddress, AwardedReferrerMetricsRevShareCap>;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link ReferrerLeaderboardRevShareCap} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\n/**\n * Per-referrer mutable state used during sequential race processing.\n */\ninterface ReferrerRaceState {\n totalReferrals: number;\n totalIncrementalDuration: Duration;\n totalRevenueContributionAmount: bigint;\n /** Whether this referrer has ever crossed the qualification threshold. */\n wasQualified: boolean;\n /** Amount actually claimed from the award pool (the capped award). */\n cappedAwardAmount: bigint;\n}\n\n/**\n * Builds a {@link ReferrerLeaderboardRevShareCap} using a sequential \"first-come, first-served\"\n * race algorithm over individual referral events.\n *\n * Events are processed in chronological order. When a referrer first crosses the qualification\n * threshold, they claim ALL accumulated uncapped awards at once (capped by remaining award pool).\n * After qualifying, each referrer's subsequent referrals claim that event's incremental capped award.\n * Once the award pool is exhausted, no further awards are issued to anyone.\n *\n * @param events - Raw referral events from ENSDb (unsorted; will be sorted internally).\n * @param rules - The {@link ReferralProgramRulesRevShareCap} defining the program parameters.\n * @param accurateAsOf - Timestamp indicating data freshness.\n */\nexport const buildReferrerLeaderboardRevShareCap = (\n events: ReferralEvent[],\n rules: ReferralProgramRulesRevShareCap,\n accurateAsOf: UnixTimestamp,\n): ReferrerLeaderboardRevShareCap => {\n // 1. Sort events into chronological order by onchain execution order.\n const sortedEvents = sortReferralEvents(events);\n\n // 2. Process events sequentially to run the race.\n const referrerStates = new Map<NormalizedAddress, ReferrerRaceState>();\n let awardPoolRemaining = rules.awardPool.amount;\n\n for (const event of sortedEvents) {\n const referrer = event.referrer;\n\n let state = referrerStates.get(referrer);\n if (!state) {\n state = {\n totalReferrals: 0,\n totalIncrementalDuration: 0,\n totalRevenueContributionAmount: 0n,\n wasQualified: false,\n cappedAwardAmount: 0n,\n };\n referrerStates.set(referrer, state);\n }\n\n // Update raw totals.\n state.totalReferrals += 1;\n state.totalIncrementalDuration += event.incrementalDuration;\n state.totalRevenueContributionAmount += event.incrementalRevenueContribution.amount;\n\n // Compute totalBaseRevenue from aggregated duration (single division — avoids per-event\n // truncation that would compound into a sum lower than the correct aggregated value).\n const totalBaseRevenueAmount =\n (rules.baseAnnualRevenueContribution.amount * BigInt(state.totalIncrementalDuration)) /\n BigInt(SECONDS_PER_YEAR);\n\n // Determine if newly qualifying or already qualified.\n const isNowQualified = isReferrerQualifiedRevShareCap(\n referrer,\n priceUsdc(totalBaseRevenueAmount),\n rules,\n );\n\n if (isNowQualified && !state.wasQualified) {\n // First time crossing the qualification threshold: claim all accumulated uncapped award.\n // Compute from aggregated totals to match the single-division used in final output.\n const accumulatedUncappedAward = scalePrice(\n priceUsdc(totalBaseRevenueAmount),\n rules.maxBaseRevenueShare,\n ).amount;\n const incrementalCappedAward = bigintMin(accumulatedUncappedAward, awardPoolRemaining);\n state.cappedAwardAmount += incrementalCappedAward;\n awardPoolRemaining -= incrementalCappedAward;\n state.wasQualified = true;\n } else if (state.wasQualified) {\n // Already qualified: claim this event's incremental uncapped award.\n const incrementalBaseRevenueAmount =\n (rules.baseAnnualRevenueContribution.amount * BigInt(event.incrementalDuration)) /\n BigInt(SECONDS_PER_YEAR);\n const incrementalUncappedAward = scalePrice(\n priceUsdc(incrementalBaseRevenueAmount),\n rules.maxBaseRevenueShare,\n ).amount;\n const incrementalCappedAward = bigintMin(incrementalUncappedAward, awardPoolRemaining);\n state.cappedAwardAmount += incrementalCappedAward;\n awardPoolRemaining -= incrementalCappedAward;\n }\n // If not yet qualified, nothing is claimed from the pool.\n }\n\n // 3. Sort referrers to assign ranks:\n // 1. cappedAward desc — actual pool claims, race winners first\n // 2. totalIncrementalDuration desc — tie-break for pool-depleted referrers\n // 3. referrer address desc — deterministic tie-break\n const sortedEntries = [...referrerStates.entries()].sort(([a, stateA], [b, stateB]) => {\n // Primary: cappedAward desc (bigint comparison)\n if (stateB.cappedAwardAmount !== stateA.cappedAwardAmount) {\n return stateB.cappedAwardAmount > stateA.cappedAwardAmount ? 1 : -1;\n }\n\n // Secondary: totalIncrementalDuration desc (used directly as the tie-breaker).\n if (stateB.totalIncrementalDuration !== stateA.totalIncrementalDuration) {\n return stateB.totalIncrementalDuration - stateA.totalIncrementalDuration;\n }\n\n // Tertiary: referrer address desc (lexicographic)\n if (b > a) return 1;\n if (b < a) return -1;\n return 0;\n });\n\n // 4. Build AwardedReferrerMetricsRevShareCap for each referrer.\n const awardedReferrers: AwardedReferrerMetricsRevShareCap[] = sortedEntries.map(\n ([referrerAddr, state], index) => {\n const baseMetrics = buildReferrerMetrics(\n referrerAddr,\n state.totalReferrals,\n state.totalIncrementalDuration,\n priceEth(state.totalRevenueContributionAmount),\n );\n\n const revShareMetrics = buildReferrerMetricsRevShareCap(baseMetrics, rules);\n\n const rankedMetrics = buildRankedReferrerMetricsRevShareCap(\n revShareMetrics,\n index + 1,\n rules,\n );\n\n const uncappedAward = scalePrice(\n revShareMetrics.totalBaseRevenueContribution,\n rules.maxBaseRevenueShare,\n );\n\n return buildAwardedReferrerMetricsRevShareCap(\n rankedMetrics,\n uncappedAward,\n priceUsdc(state.cappedAwardAmount),\n rules,\n );\n },\n );\n\n const aggregatedMetrics = buildAggregatedReferrerMetricsRevShareCap(\n awardedReferrers,\n priceUsdc(awardPoolRemaining),\n );\n\n const referrers = new Map(awardedReferrers.map((r) => [r.referrer, r]));\n\n return { awardModel: rules.awardModel, rules, aggregatedMetrics, referrers, accurateAsOf };\n};\n","import {\n type BaseReferrerLeaderboardPage,\n type ReferrerLeaderboardPageContext,\n sliceReferrers,\n} from \"../shared/leaderboard-page\";\nimport type { ReferralProgramAwardModels } from \"../shared/rules\";\nimport type { AggregatedReferrerMetricsRevShareCap } from \"./aggregations\";\nimport type { ReferrerLeaderboardRevShareCap } from \"./leaderboard\";\nimport type { AwardedReferrerMetricsRevShareCap } from \"./metrics\";\nimport type { ReferralProgramRulesRevShareCap } from \"./rules\";\nimport { calcReferralProgramEditionStatusRevShareCap } from \"./status\";\n\n/**\n * A page of referrers from the rev-share-cap referrer leaderboard.\n */\nexport interface ReferrerLeaderboardPageRevShareCap extends BaseReferrerLeaderboardPage {\n /**\n * Discriminant identifying this as a page from a rev-share-cap leaderboard.\n *\n * @invariant Always equals `rules.awardModel` ({@link ReferralProgramAwardModels.RevShareCap}).\n */\n awardModel: typeof ReferralProgramAwardModels.RevShareCap;\n\n /**\n * The {@link ReferralProgramRulesRevShareCap} used to generate the {@link ReferrerLeaderboardRevShareCap}\n * that this {@link ReferrerLeaderboardPageRevShareCap} comes from.\n */\n rules: ReferralProgramRulesRevShareCap;\n\n /**\n * Ordered list of {@link AwardedReferrerMetricsRevShareCap} for the {@link ReferrerLeaderboardPageRevShareCap}\n * described by {@link pageContext} within the related {@link ReferrerLeaderboard}.\n *\n * @invariant Array will be empty if `pageContext.totalRecords` is 0.\n * @invariant Array entries are ordered by `rank` (ascending).\n */\n referrers: AwardedReferrerMetricsRevShareCap[];\n\n /**\n * The aggregated metrics for all referrers on the leaderboard.\n */\n aggregatedMetrics: AggregatedReferrerMetricsRevShareCap;\n}\n\nexport function buildLeaderboardPageRevShareCap(\n pageContext: ReferrerLeaderboardPageContext,\n leaderboard: ReferrerLeaderboardRevShareCap,\n): ReferrerLeaderboardPageRevShareCap {\n const status = calcReferralProgramEditionStatusRevShareCap(\n leaderboard.rules,\n leaderboard.accurateAsOf,\n leaderboard.aggregatedMetrics,\n );\n return {\n awardModel: leaderboard.awardModel,\n rules: leaderboard.rules,\n referrers: sliceReferrers(leaderboard.referrers, pageContext),\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n pageContext,\n status,\n accurateAsOf: leaderboard.accurateAsOf,\n };\n}\n","import {\n deserializeReferralProgramEditionConfigSetArray,\n deserializeReferralProgramEditionSummariesResponse,\n deserializeReferrerLeaderboardPageResponse,\n deserializeReferrerMetricsEditionsResponse,\n type ReferralProgramEditionSummariesResponse,\n type ReferrerLeaderboardPageRequest,\n type ReferrerLeaderboardPageResponse,\n type ReferrerMetricsEditionsRequest,\n type ReferrerMetricsEditionsResponse,\n type SerializedReferralProgramEditionSummariesResponse,\n type SerializedReferrerLeaderboardPageResponse,\n type SerializedReferrerMetricsEditionsResponse,\n} from \"./api\";\nimport {\n buildReferralProgramEditionConfigSet,\n type ReferralProgramEditionConfigSet,\n} from \"./edition\";\n\n/**\n * Default ENSNode endpoint URL\n */\nexport const DEFAULT_ENSNODE_API_URL = \"https://api.alpha.ensnode.io\" as const;\n\n/**\n * Configuration options for an ENS Referrals client\n */\nexport interface ClientOptions {\n /** The ENSNode URL */\n url: URL;\n}\n\n/**\n * ENS Referrals Client\n *\n * Provides access to ENS Referrals data and leaderboard information.\n *\n * @example\n * ```typescript\n * // Create client with default options\n * const client = new ENSReferralsClient();\n *\n * // Get referrer leaderboard for December 2025 edition\n * const leaderboardPage = await client.getReferrerLeaderboardPage({\n * edition: \"2025-12\",\n * page: 1,\n * recordsPerPage: 25\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Custom configuration\n * const client = new ENSReferralsClient({\n * url: new URL(\"https://my-ensnode-instance.com\"),\n * });\n * ```\n */\nexport class ENSReferralsClient {\n private readonly options: ClientOptions;\n\n static defaultOptions(): ClientOptions {\n return {\n url: new URL(DEFAULT_ENSNODE_API_URL),\n };\n }\n\n constructor(options: Partial<ClientOptions> = {}) {\n this.options = {\n ...ENSReferralsClient.defaultOptions(),\n ...options,\n };\n }\n\n getOptions(): Readonly<ClientOptions> {\n return Object.freeze({\n url: new URL(this.options.url.href),\n });\n }\n\n /**\n * Get Referral Program Edition Config Set\n *\n * Fetches and deserializes a referral program edition config set from a remote URL.\n *\n * @param url - The URL to fetch the edition config set from\n * @returns A ReferralProgramEditionConfigSet (Map of edition slugs to edition configurations)\n *\n * @remarks Editions whose `rules.awardModel` is not recognized by this client version are\n * preserved as {@link ReferralProgramRulesUnrecognized}. The returned map includes all\n * editions — recognized and unrecognized alike. Callers should check `editionConfig.rules.awardModel`\n * and skip editions with `\"unrecognized\"` as appropriate. The returned map may be empty.\n *\n * @throws if the fetch fails\n * @throws if the response is not valid JSON\n * @throws if the data doesn't match the expected schema\n *\n * @example\n * ```typescript\n * const url = new URL(\"https://example.com/editions.json\");\n * const editionConfigSet = await ENSReferralsClient.getReferralProgramEditionConfigSet(url);\n * console.log(`Loaded ${editionConfigSet.size} editions`);\n * ```\n */\n static async getReferralProgramEditionConfigSet(\n url: URL,\n ): Promise<ReferralProgramEditionConfigSet> {\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n let json: unknown;\n try {\n json = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n const editionConfigs = deserializeReferralProgramEditionConfigSetArray(json);\n\n return buildReferralProgramEditionConfigSet(editionConfigs);\n }\n\n /**\n * Fetch Referrer Leaderboard Page\n *\n * Retrieves a paginated list of referrer leaderboard metrics for a specific referral program edition.\n *\n * @param request - Request parameters including edition and pagination\n * @param request.edition - The referral program edition slug (e.g., \"2025-12\", \"2026-03\", or any other configured edition slug)\n * @param request.page - The page number to retrieve (1-indexed, default: 1)\n * @param request.recordsPerPage - Number of records per page (default: 25, max: 100)\n * @returns {ReferrerLeaderboardPageResponse}\n *\n * @remarks If the server returns a leaderboard page whose `awardModel` is not recognized by\n * this client version, it is preserved as {@link ReferrerLeaderboardPageUnrecognized}. Callers\n * should check `response.data.awardModel` and handle the `\"unrecognized\"` case accordingly.\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n *\n * @example\n * ```typescript\n * // Get first page of 2025-12 leaderboard with default page size (25 records)\n * const editionSlug = \"2025-12\";\n * const response = await client.getReferrerLeaderboardPage({ edition: editionSlug });\n * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Ok) {\n * const { awardModel, pageContext, accurateAsOf } = response.data;\n * if (awardModel === ReferralProgramAwardModels.Unrecognized) {\n * console.log(`Unrecognized award model: ${response.data.originalAwardModel} — skipping`);\n * } else {\n * const { aggregatedMetrics, referrers, rules } = response.data;\n * console.log(`Edition: ${editionSlug}`);\n * console.log(`Subregistry: ${rules.subregistryId}`);\n * console.log(`Total Referrers: ${pageContext.totalRecords}`);\n * console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Get second page of 2026-03 with 50 records per page\n * const response = await client.getReferrerLeaderboardPage({\n * edition: \"2026-03\",\n * page: 2,\n * recordsPerPage: 50\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Handle error response (e.g., unknown edition or data not available)\n * const response = await client.getReferrerLeaderboardPage({ edition: \"2025-12\" });\n *\n * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Error) {\n * console.error(response.error);\n * console.error(response.errorMessage);\n * }\n * ```\n */\n async getReferrerLeaderboardPage(\n request: ReferrerLeaderboardPageRequest,\n ): Promise<ReferrerLeaderboardPageResponse> {\n const url = new URL(`/v1/ensanalytics/referral-leaderboard`, this.options.url);\n\n url.searchParams.set(\"edition\", request.edition);\n if (request.page !== undefined) url.searchParams.set(\"page\", request.page.toString());\n if (request.recordsPerPage !== undefined)\n url.searchParams.set(\"recordsPerPage\", request.recordsPerPage.toString());\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // The API can return errors with various status codes, but they're still in the\n // ReferrerLeaderboardPageResponse format with responseCode: 'error'\n // So we don't need to check response.ok here, just deserialize and let\n // the caller handle the responseCode\n\n return deserializeReferrerLeaderboardPageResponse(\n responseData as SerializedReferrerLeaderboardPageResponse,\n );\n }\n\n /**\n * Fetch Referrer Metrics for Specific Editions\n *\n * Retrieves detailed information about a specific referrer for the requested\n * referral program editions. Returns a record mapping each requested edition slug\n * to the referrer's metrics for that edition.\n *\n * The response data maps edition slugs to referrer metrics. Each edition's entry is a\n * {@link ReferrerEditionMetrics} discriminated union. Narrow on `awardModel` first to\n * exclude unrecognized models, then on `type` to distinguish ranked from unranked:\n *\n * - `awardModel: \"unrecognized\"` ({@link ReferrerEditionMetricsUnrecognized}): the server\n * returned an award model this client does not recognize. Only `originalAwardModel` is\n * available; no model-specific fields are present.\n * - `type: \"ranked\"` ({@link ReferrerEditionMetricsTypeIds.Ranked}): the referrer appears on\n * the leaderboard. `referrer` contains rank, qualification status, and award share.\n * - `type: \"unranked\"` ({@link ReferrerEditionMetricsTypeIds.Unranked}): the referrer has no\n * activity in this edition. `referrer` contains zero-value placeholders.\n *\n * **Note:** This endpoint does not allow partial success. When `responseCode === Ok`,\n * all requested editions are guaranteed to be present in the response data. If any\n * requested edition cannot be returned, the entire request fails with an error.\n *\n * @see {@link https://www.npmjs.com/package/@namehash/ens-referrals|@namehash/ens-referrals} for calculation details\n *\n * @param request The referrer address and edition slugs to query\n * @returns {ReferrerMetricsEditionsResponse} Returns the referrer metrics for requested editions\n *\n * @remarks If the server returns metrics for an edition whose `awardModel` is not recognized by\n * this client version, that edition's entry in `response.data` is preserved as\n * {@link ReferrerEditionMetricsUnrecognized}. Callers should check each edition's `awardModel`\n * and handle the `\"unrecognized\"` case accordingly.\n *\n * @throws if the ENSNode request fails\n * @throws if the response data is malformed\n *\n * @example\n * ```typescript\n * // Get referrer metrics for specific editions\n * const response = await client.getReferrerMetricsEditions({\n * referrer: \"0x1234567890123456789012345678901234567890\",\n * editions: [\"2025-12\", \"2026-01\"]\n * });\n * if (response.responseCode === ReferrerMetricsEditionsResponseCodes.Ok) {\n * // All requested editions are present in response.data\n * for (const [editionSlug, detail] of Object.entries(response.data)) {\n * console.log(`Edition: ${editionSlug}`);\n * if (detail.awardModel === ReferralProgramAwardModels.Unrecognized) {\n * console.log(`Unrecognized award model: ${detail.originalAwardModel} — skipping`);\n * continue;\n * }\n * console.log(`Type: ${detail.type}`);\n * if (detail.type === ReferrerEditionMetricsTypeIds.Ranked) {\n * console.log(`Rank: ${detail.referrer.rank}`);\n * console.log(`Award Share: ${detail.referrer.awardPoolShare * 100}%`);\n * }\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Access specific edition data directly (edition is guaranteed to exist when OK)\n * const response = await client.getReferrerMetricsEditions({\n * referrer: \"0x1234567890123456789012345678901234567890\",\n * editions: [\"2025-12\"]\n * });\n * if (response.responseCode === ReferrerMetricsEditionsResponseCodes.Ok) {\n * const detail = response.data[\"2025-12\"];\n * if (detail && detail.awardModel === ReferralProgramAwardModels.Unrecognized) {\n * console.log(`Unrecognized award model: ${detail.originalAwardModel} — skipping`);\n * } else if (detail && detail.type === ReferrerEditionMetricsTypeIds.Ranked) {\n * console.log(`Edition 2025-12 Rank: ${detail.referrer.rank}`);\n * } else if (detail) {\n * console.log(\"Referrer is not on the leaderboard for 2025-12\");\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Handle error response (e.g., unknown edition or data not available)\n * const response = await client.getReferrerMetricsEditions({\n * referrer: \"0x1234567890123456789012345678901234567890\",\n * editions: [\"2025-12\", \"invalid-edition\"]\n * });\n *\n * if (response.responseCode === ReferrerMetricsEditionsResponseCodes.Error) {\n * console.error(response.error);\n * console.error(response.errorMessage);\n * }\n * ```\n */\n async getReferrerMetricsEditions(\n request: ReferrerMetricsEditionsRequest,\n ): Promise<ReferrerMetricsEditionsResponse> {\n const url = new URL(\n `/v1/ensanalytics/referrer/${encodeURIComponent(request.referrer)}`,\n this.options.url,\n );\n\n // Add editions as comma-separated query parameter\n url.searchParams.set(\"editions\", request.editions.join(\",\"));\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // The API can return errors with various status codes, but they're still in the\n // ReferrerMetricsEditionsResponse format with responseCode: 'error'\n // So we don't need to check response.ok here, just deserialize and let\n // the caller handle the responseCode\n\n return deserializeReferrerMetricsEditionsResponse(\n responseData as SerializedReferrerMetricsEditionsResponse,\n );\n }\n\n /**\n * Get the currently configured referral program edition summaries.\n * Editions are sorted in descending order by start timestamp (most recent first).\n *\n * @returns A response containing edition summaries, or an error response if unavailable.\n *\n * @remarks Editions whose `rules.awardModel` is not recognized by this client version are\n * preserved as {@link ReferralProgramEditionSummaryUnrecognized}. The returned response includes all\n * editions — recognized and unrecognized alike. Callers should check `edition.awardModel`\n * and skip editions with `\"unrecognized\"` as appropriate. The returned editions list may be empty.\n *\n * @example\n * ```typescript\n * const response = await client.getEditionSummaries();\n *\n * if (response.responseCode === ReferralProgramEditionSummariesResponseCodes.Ok) {\n * console.log(`Found ${response.data.editions.length} editions`);\n * for (const edition of response.data.editions) {\n * console.log(`${edition.slug}: ${edition.displayName}`);\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Handle error response\n * const response = await client.getEditionSummaries();\n *\n * if (response.responseCode === ReferralProgramEditionSummariesResponseCodes.Error) {\n * console.error(response.error);\n * console.error(response.errorMessage);\n * }\n * ```\n */\n async getEditionSummaries(): Promise<ReferralProgramEditionSummariesResponse> {\n const url = new URL(`/v1/ensanalytics/editions`, this.options.url);\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // The API can return errors with various status codes, but they're still in the\n // ReferralProgramEditionSummariesResponse format with responseCode: 'error'\n // So we don't need to check response.ok here, just deserialize and let\n // the caller handle the responseCode\n\n return deserializeReferralProgramEditionSummariesResponse(\n responseData as SerializedReferralProgramEditionSummariesResponse,\n );\n }\n}\n","import type { NormalizedAddress } from \"enssdk\";\n\nimport type {\n ReferrerEditionMetricsPieSplit,\n ReferrerEditionMetricsRankedPieSplit,\n ReferrerEditionMetricsUnrankedPieSplit,\n} from \"./award-models/pie-split/edition-metrics\";\nimport { buildUnrankedReferrerMetricsPieSplit } from \"./award-models/pie-split/metrics\";\nimport { calcReferralProgramEditionStatusPieSplit } from \"./award-models/pie-split/status\";\nimport type {\n ReferrerEditionMetricsRankedRevShareCap,\n ReferrerEditionMetricsRevShareCap,\n ReferrerEditionMetricsUnrankedRevShareCap,\n} from \"./award-models/rev-share-cap/edition-metrics\";\nimport { buildUnrankedReferrerMetricsRevShareCap } from \"./award-models/rev-share-cap/metrics\";\nimport { calcReferralProgramEditionStatusRevShareCap } from \"./award-models/rev-share-cap/status\";\nimport {\n ReferrerEditionMetricsTypeIds,\n type ReferrerEditionMetricsUnrecognized,\n} from \"./award-models/shared/edition-metrics\";\nimport { ReferralProgramAwardModels } from \"./award-models/shared/rules\";\nimport type { ReferrerLeaderboard } from \"./leaderboard\";\n\n/**\n * Referrer edition metrics data for a specific referrer address.\n *\n * Use `awardModel` to narrow the award model variant, then `type` to narrow ranked vs unranked.\n * When `awardModel` is `\"unrecognized\"`, the data was produced by a server running a newer\n * version — use {@link ReferrerEditionMetricsUnrecognized} to access `originalAwardModel`.\n */\nexport type ReferrerEditionMetrics =\n | ReferrerEditionMetricsPieSplit\n | ReferrerEditionMetricsRevShareCap\n | ReferrerEditionMetricsUnrecognized;\n\n/**\n * Get the edition metrics for a specific referrer from the leaderboard.\n *\n * Returns a {@link ReferrerEditionMetricsPieSplit} or {@link ReferrerEditionMetricsRevShareCap}\n * with `type: \"ranked\"` if the referrer is on the leaderboard, or `type: \"unranked\"` otherwise.\n *\n * @param referrer - The referrer address to look up\n * @param leaderboard - The referrer leaderboard to query\n */\nexport const getReferrerEditionMetrics = (\n referrer: NormalizedAddress,\n leaderboard: ReferrerLeaderboard,\n): ReferrerEditionMetrics => {\n switch (leaderboard.awardModel) {\n case ReferralProgramAwardModels.PieSplit: {\n const status = calcReferralProgramEditionStatusPieSplit(\n leaderboard.rules,\n leaderboard.accurateAsOf,\n );\n const awardedReferrerMetrics = leaderboard.referrers.get(referrer);\n if (awardedReferrerMetrics) {\n return {\n awardModel: leaderboard.awardModel,\n type: ReferrerEditionMetricsTypeIds.Ranked,\n rules: leaderboard.rules,\n referrer: awardedReferrerMetrics,\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n status,\n accurateAsOf: leaderboard.accurateAsOf,\n } satisfies ReferrerEditionMetricsRankedPieSplit;\n }\n return {\n awardModel: leaderboard.awardModel,\n type: ReferrerEditionMetricsTypeIds.Unranked,\n rules: leaderboard.rules,\n referrer: buildUnrankedReferrerMetricsPieSplit(referrer),\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n status,\n accurateAsOf: leaderboard.accurateAsOf,\n } satisfies ReferrerEditionMetricsUnrankedPieSplit;\n }\n\n case ReferralProgramAwardModels.RevShareCap: {\n const status = calcReferralProgramEditionStatusRevShareCap(\n leaderboard.rules,\n leaderboard.accurateAsOf,\n leaderboard.aggregatedMetrics,\n );\n const awardedReferrerMetrics = leaderboard.referrers.get(referrer);\n if (awardedReferrerMetrics) {\n return {\n awardModel: leaderboard.awardModel,\n type: ReferrerEditionMetricsTypeIds.Ranked,\n rules: leaderboard.rules,\n referrer: awardedReferrerMetrics,\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n status,\n accurateAsOf: leaderboard.accurateAsOf,\n } satisfies ReferrerEditionMetricsRankedRevShareCap;\n }\n return {\n awardModel: leaderboard.awardModel,\n type: ReferrerEditionMetricsTypeIds.Unranked,\n rules: leaderboard.rules,\n referrer: buildUnrankedReferrerMetricsRevShareCap(referrer, leaderboard.rules),\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n status,\n accurateAsOf: leaderboard.accurateAsOf,\n } satisfies ReferrerEditionMetricsUnrankedRevShareCap;\n }\n\n default: {\n const _exhaustiveCheck: never = leaderboard;\n throw new Error(\n `Unknown award model: ${(_exhaustiveCheck as ReferrerLeaderboard).awardModel}`,\n );\n }\n }\n};\n","import {\n buildEditionSummaryPieSplit,\n type ReferralProgramEditionSummaryPieSplit,\n} from \"./award-models/pie-split/edition-summary\";\nimport {\n buildEditionSummaryRevShareCap,\n type ReferralProgramEditionSummaryRevShareCap,\n} from \"./award-models/rev-share-cap/edition-summary\";\nimport type { ReferralProgramEditionSummaryUnrecognized } from \"./award-models/shared/edition-summary\";\nimport { ReferralProgramAwardModels } from \"./award-models/shared/rules\";\nimport type { ReferralProgramEditionConfig } from \"./edition\";\nimport type { ReferrerLeaderboard } from \"./leaderboard\";\n\n/**\n * Runtime summary of a referral program edition, enriched with current status and pool data.\n *\n * Use `awardModel` to discriminate between variants at runtime.\n */\nexport type ReferralProgramEditionSummary =\n | ReferralProgramEditionSummaryPieSplit\n | ReferralProgramEditionSummaryRevShareCap\n | ReferralProgramEditionSummaryUnrecognized;\n\n/**\n * Build a runtime edition summary from an edition config and the edition's leaderboard.\n * Dispatches to the appropriate per-model builder based on `leaderboard.awardModel`.\n *\n * @param config - The edition configuration (provides `slug` and `displayName`).\n * @param leaderboard - The resolved leaderboard for this edition.\n */\nexport function buildEditionSummary(\n config: ReferralProgramEditionConfig,\n leaderboard: ReferrerLeaderboard,\n): ReferralProgramEditionSummary {\n const { slug, displayName } = config;\n\n switch (leaderboard.awardModel) {\n case ReferralProgramAwardModels.PieSplit:\n return buildEditionSummaryPieSplit(slug, displayName, leaderboard.rules, leaderboard);\n\n case ReferralProgramAwardModels.RevShareCap:\n return buildEditionSummaryRevShareCap(slug, displayName, leaderboard.rules, leaderboard);\n\n default: {\n const _exhaustiveCheck: never = leaderboard;\n throw new Error(\n `Unknown award model: ${(_exhaustiveCheck as ReferrerLeaderboard).awardModel}`,\n );\n }\n }\n}\n","import {\n buildLeaderboardPagePieSplit,\n type ReferrerLeaderboardPagePieSplit,\n} from \"./award-models/pie-split/leaderboard-page\";\nimport {\n buildLeaderboardPageRevShareCap,\n type ReferrerLeaderboardPageRevShareCap,\n} from \"./award-models/rev-share-cap/leaderboard-page\";\nimport {\n buildReferrerLeaderboardPageContext,\n type ReferrerLeaderboardPageParams,\n type ReferrerLeaderboardPageUnrecognized,\n} from \"./award-models/shared/leaderboard-page\";\nimport { ReferralProgramAwardModels } from \"./award-models/shared/rules\";\nimport type { ReferrerLeaderboard } from \"./leaderboard\";\n\n/**\n * A page of referrers from the referrer leaderboard.\n *\n * Use `awardModel` to narrow the specific variant at runtime. Within each variant,\n * `rules`, `referrers`, and `aggregatedMetrics` are all guaranteed to be from the same model.\n * When `awardModel` is `\"unrecognized\"`, the page was produced by a server running a newer\n * version — use {@link ReferrerLeaderboardPageUnrecognized} to access `originalAwardModel`.\n */\nexport type ReferrerLeaderboardPage =\n | ReferrerLeaderboardPagePieSplit\n | ReferrerLeaderboardPageRevShareCap\n | ReferrerLeaderboardPageUnrecognized;\n\nexport const getReferrerLeaderboardPage = (\n pageParams: ReferrerLeaderboardPageParams,\n leaderboard: ReferrerLeaderboard,\n): ReferrerLeaderboardPage => {\n const pageContext = buildReferrerLeaderboardPageContext(pageParams, leaderboard);\n\n switch (leaderboard.awardModel) {\n case ReferralProgramAwardModels.PieSplit:\n return buildLeaderboardPagePieSplit(pageContext, leaderboard);\n case ReferralProgramAwardModels.RevShareCap:\n return buildLeaderboardPageRevShareCap(pageContext, leaderboard);\n\n default: {\n const _exhaustiveCheck: never = leaderboard;\n throw new Error(\n `Unknown award model: ${(_exhaustiveCheck as ReferrerLeaderboard).awardModel}`,\n );\n }\n }\n};\n","import type { Address } from \"enssdk\";\nimport { getAddress } from \"viem\";\n\n/**\n * Build a URL to the official ENS manager app\n * where the given {@link Address} is set as the referrer.\n */\nexport function buildEnsReferralUrl(address: Address): URL {\n const ensAppUrl = new URL(\"https://app.ens.domains\");\n\n ensAppUrl.searchParams.set(\"referrer\", getAddress(address));\n\n return ensAppUrl;\n}\n"],"mappings":"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","names":["z","CAIP2","name","regex","parameters","delimiter","values","CAIP10","AssetName","CAIP19AssetType","CAIP19AssetId","CAIP","assetName","assetType","assetId","splitParams","id","spec","split","getParams","arr","params","forEach","value","index","joinParams","Object","map","parameter","param","join","isValidId","RegExp","test","length","keys","matches","filter","x","ChainId","parse","namespace","reference","Error","toJSON","format","toString","AccountId","chainId","address","AssetType","AssetId","tokenId","z","z","z","z","z","z","z","parsed","z","parsed"]}
|