Skip to content
Merged
5 changes: 5 additions & 0 deletions .changeset/bright-foxes-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@namehash/ens-referrals": minor
---

Rename rev-share-limit API fields for clarity: `minQualifiedRevenueContribution` → `minBaseRevenueContribution`, `qualifiedRevenueShare` → `maxBaseRevenueShare`, `standardAwardValue` → `uncappedAward`, `awardPoolApproxValue` → `cappedAward`. Rename `totalAwardPoolValue` → `awardPool` for both rev-share-limit and pie-split rules. Extract the previously hardcoded `BASE_REVENUE_CONTRIBUTION_PER_YEAR` constant into a per-edition `baseAnnualRevenueContribution` rule field.
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ export const emptyReferralLeaderboard: ReferrerLeaderboardPieSplit = {
awardModel: ReferralProgramAwardModels.PieSplit,
rules: {
awardModel: ReferralProgramAwardModels.PieSplit,
totalAwardPoolValue: parseUsdc("10000"),
awardPool: parseUsdc("10000"),
maxQualifiedReferrers: 10,
startTime: 1735689600,
endTime: 1767225599,
Expand All @@ -205,7 +205,7 @@ export const populatedReferrerLeaderboard: ReferrerLeaderboardPieSplit = {
awardModel: ReferralProgramAwardModels.PieSplit,
rules: {
awardModel: ReferralProgramAwardModels.PieSplit,
totalAwardPoolValue: parseUsdc("10000"),
awardPool: parseUsdc("10000"),
maxQualifiedReferrers: 10,
startTime: 1735689600,
endTime: 1767225599,
Expand Down Expand Up @@ -698,7 +698,7 @@ export const referrerLeaderboardPageResponseOk = {
awardModel: ReferralProgramAwardModels.PieSplit,
rules: {
awardModel: ReferralProgramAwardModels.PieSplit,
totalAwardPoolValue: parseUsdc("10000"),
awardPool: parseUsdc("10000"),
maxQualifiedReferrers: 10,
startTime: 1735689600,
endTime: 1767225599,
Expand Down
8 changes: 4 additions & 4 deletions packages/ens-referrals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Ok) {

if (leaderboardPage.awardModel === ReferralProgramAwardModels.RevShareLimit) {
console.log(
`Min Qualified Revenue Contribution: ${leaderboardPage.rules.minQualifiedRevenueContribution}`,
`Min Base Revenue Contribution: ${leaderboardPage.rules.minBaseRevenueContribution}`,
);
console.log(`Qualified Revenue Share: ${leaderboardPage.rules.qualifiedRevenueShare}`);
console.log(`Max Base Revenue Share: ${leaderboardPage.rules.maxBaseRevenueShare}`);
console.log(
`Tentative award for the best referrer: ${firstReferrer !== null ? firstReferrer.awardPoolApproxValue : noReferrersFallback}`,
`Tentative award for the top ranked referrer: ${firstReferrer !== null ? firstReferrer.cappedAward : noReferrersFallback}`,
);
}
}
Expand Down Expand Up @@ -146,7 +146,7 @@ if (response.responseCode === ReferrerMetricsEditionsResponseCodes.Ok) {
console.log(
`Referrer's total base revenue contribution: ${detail.referrer.totalBaseRevenueContribution}`,
);
console.log(`Referrer's standard award value: ${detail.referrer.standardAwardValue}`);
console.log(`Referrer's uncapped award value: ${detail.referrer.uncappedAward}`);
}
}
}
Expand Down
58 changes: 32 additions & 26 deletions packages/ens-referrals/src/v1/api/zod-schemas.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe("makeReferralProgramEditionConfigSetArraySchema", () => {
displayName: "December 2025",
rules: {
awardModel: ReferralProgramAwardModels.PieSplit,
totalAwardPoolValue: parseUsdc("1000"),
awardPool: parseUsdc("1000"),
maxQualifiedReferrers: 100,
startTime: 1000000,
endTime: 2000000,
Expand All @@ -43,9 +43,10 @@ describe("makeReferralProgramEditionConfigSetArraySchema", () => {
displayName: "January 2026",
rules: {
awardModel: ReferralProgramAwardModels.RevShareLimit,
totalAwardPoolValue: parseUsdc("500"),
minQualifiedRevenueContribution: parseUsdc("10"),
qualifiedRevenueShare: 0.5,
awardPool: parseUsdc("500"),
minBaseRevenueContribution: parseUsdc("10"),
baseAnnualRevenueContribution: parseUsdc("5"),
maxBaseRevenueShare: 0.5,
startTime: 1000000,
endTime: 2000000,
subregistryId,
Expand Down Expand Up @@ -92,14 +93,16 @@ describe("makeReferralProgramEditionConfigSetArraySchema", () => {

const rules = revShareLimit!.rules as {
awardModel: typeof ReferralProgramAwardModels.RevShareLimit;
totalAwardPoolValue: { amount: bigint; currency: string };
minQualifiedRevenueContribution: { amount: bigint; currency: string };
qualifiedRevenueShare: number;
awardPool: { amount: bigint; currency: string };
minBaseRevenueContribution: { amount: bigint; currency: string };
baseAnnualRevenueContribution: { amount: bigint; currency: string };
maxBaseRevenueShare: number;
};
expect(rules.totalAwardPoolValue).toBeDefined();
expect(rules.minQualifiedRevenueContribution).toBeDefined();
expect(typeof rules.qualifiedRevenueShare).toBe("number");
expect(rules.qualifiedRevenueShare).toBe(0.5);
expect(rules.awardPool).toBeDefined();
expect(rules.minBaseRevenueContribution).toBeDefined();
expect(rules.baseAnnualRevenueContribution).toBeDefined();
expect(typeof rules.maxBaseRevenueShare).toBe("number");
expect(rules.maxBaseRevenueShare).toBe(0.5);
expect(revShareLimit!.rules.areAwardsDistributed).toBe(
revShareLimitEdition.rules.areAwardsDistributed,
);
Expand Down Expand Up @@ -189,7 +192,7 @@ describe("makeReferrerLeaderboardPageSchema", () => {
awardModel: ReferralProgramAwardModels.PieSplit,
rules: {
awardModel: ReferralProgramAwardModels.PieSplit,
totalAwardPoolValue: parseUsdc("1000"),
awardPool: parseUsdc("1000"),
maxQualifiedReferrers: 100,
startTime: 1000000,
endTime: 2000000,
Expand All @@ -214,9 +217,10 @@ describe("makeReferrerLeaderboardPageSchema", () => {
awardModel: ReferralProgramAwardModels.RevShareLimit,
rules: {
awardModel: ReferralProgramAwardModels.RevShareLimit,
totalAwardPoolValue: parseUsdc("2000"),
minQualifiedRevenueContribution: parseUsdc("10"),
qualifiedRevenueShare: 0.5,
awardPool: parseUsdc("2000"),
minBaseRevenueContribution: parseUsdc("10"),
baseAnnualRevenueContribution: parseUsdc("5"),
maxBaseRevenueShare: 0.5,
startTime: 1000000,
endTime: 2000000,
subregistryId,
Expand Down Expand Up @@ -275,7 +279,7 @@ describe("makeReferrerLeaderboardPageSchema", () => {
...pieSplitLeaderboardPage,
rules: {
...pieSplitLeaderboardPage.rules,
totalAwardPoolValue: { amount: "not-a-number", currency: CurrencyIds.USDC },
awardPool: { amount: "not-a-number", currency: CurrencyIds.USDC },
},
};

Expand Down Expand Up @@ -307,7 +311,7 @@ describe("makeReferralProgramEditionSummarySchema", () => {
status: ReferralProgramEditionStatuses.Active,
rules: {
awardModel: ReferralProgramAwardModels.PieSplit,
totalAwardPoolValue: parseUsdc("1000"),
awardPool: parseUsdc("1000"),
maxQualifiedReferrers: 100,
startTime: 1000000,
endTime: 2000000,
Expand All @@ -324,9 +328,10 @@ describe("makeReferralProgramEditionSummarySchema", () => {
status: ReferralProgramEditionStatuses.Active,
rules: {
awardModel: ReferralProgramAwardModels.RevShareLimit,
totalAwardPoolValue: parseUsdc("2000"),
minQualifiedRevenueContribution: parseUsdc("10"),
qualifiedRevenueShare: 0.5,
awardPool: parseUsdc("2000"),
minBaseRevenueContribution: parseUsdc("10"),
baseAnnualRevenueContribution: parseUsdc("5"),
maxBaseRevenueShare: 0.5,
startTime: 1000000,
endTime: 2000000,
subregistryId,
Expand Down Expand Up @@ -423,7 +428,7 @@ describe("makeReferrerEditionMetricsSchema", () => {

const pieSplitRules = {
awardModel: ReferralProgramAwardModels.PieSplit,
totalAwardPoolValue: parseUsdc("1000"),
awardPool: parseUsdc("1000"),
maxQualifiedReferrers: 100,
startTime: 1000000,
endTime: 2000000,
Expand Down Expand Up @@ -506,9 +511,10 @@ describe("makeReferrerEditionMetricsSchema", () => {
type: ReferrerEditionMetricsTypeIds.Ranked,
rules: {
awardModel: ReferralProgramAwardModels.RevShareLimit,
totalAwardPoolValue: parseUsdc("2000"),
minQualifiedRevenueContribution: parseUsdc("10"),
qualifiedRevenueShare: 0.5,
awardPool: parseUsdc("2000"),
minBaseRevenueContribution: parseUsdc("10"),
baseAnnualRevenueContribution: parseUsdc("5"),
maxBaseRevenueShare: 0.5,
startTime: 1000000,
endTime: 2000000,
subregistryId,
Expand All @@ -523,8 +529,8 @@ describe("makeReferrerEditionMetricsSchema", () => {
totalBaseRevenueContribution: parseUsdc("150"),
rank: 1,
isQualified: true,
standardAwardValue: parseUsdc("200"),
awardPoolApproxValue: parseUsdc("200"),
uncappedAward: parseUsdc("200"),
cappedAward: parseUsdc("200"),
isAdminDisqualified: false,
adminDisqualificationReason: null,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function serializeReferralProgramRulesPieSplit(
): SerializedReferralProgramRulesPieSplit {
return {
awardModel: rules.awardModel,
totalAwardPoolValue: serializePriceUsdc(rules.totalAwardPoolValue),
awardPool: serializePriceUsdc(rules.awardPool),
maxQualifiedReferrers: rules.maxQualifiedReferrers,
startTime: rules.startTime,
endTime: rules.endTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import type { ReferralProgramRulesPieSplit } from "../rules";
* Serialized representation of {@link ReferralProgramRulesPieSplit}.
*/
export interface SerializedReferralProgramRulesPieSplit
extends Omit<ReferralProgramRulesPieSplit, "totalAwardPoolValue" | "rulesUrl"> {
totalAwardPoolValue: SerializedPriceUsdc;
extends Omit<ReferralProgramRulesPieSplit, "awardPool" | "rulesUrl"> {
awardPool: SerializedPriceUsdc;
rulesUrl: string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const makeReferralProgramRulesPieSplitSchema = (
) =>
makeBaseReferralProgramRulesSchema(valueLabel).safeExtend({
awardModel: z.literal(ReferralProgramAwardModels.PieSplit),
totalAwardPoolValue: makePriceUsdcSchema(`${valueLabel}.totalAwardPoolValue`),
awardPool: makePriceUsdcSchema(`${valueLabel}.awardPool`),
maxQualifiedReferrers: makeNonNegativeIntegerSchema(`${valueLabel}.maxQualifiedReferrers`),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,10 @@ export interface AwardedReferrerMetricsPieSplit extends RankedReferrerMetricsPie
awardPoolShare: number;

/**
* The approximate USDC value of the referrer's share of the {@link ReferralProgramRulesPieSplit.totalAwardPoolValue}.
* The approximate USDC value of the referrer's share of the {@link ReferralProgramRulesPieSplit.awardPool}.
*
* @invariant Guaranteed to be a valid PriceUsdc with amount between 0 and {@link ReferralProgramRulesPieSplit.totalAwardPoolValue.amount} (inclusive)
* @invariant Calculated as: `awardPoolShare` * {@link ReferralProgramRulesPieSplit.totalAwardPoolValue.amount}
* @invariant Guaranteed to be a valid PriceUsdc with amount between 0 and {@link ReferralProgramRulesPieSplit.awardPool.amount} (inclusive)
* @invariant Calculated as: `awardPoolShare` * {@link ReferralProgramRulesPieSplit.awardPool.amount}
*/
awardPoolApproxValue: PriceUsdc;
}
Expand All @@ -197,9 +197,9 @@ export const validateAwardedReferrerMetricsPieSplit = (
referrer.awardPoolApproxValue,
);

if (referrer.awardPoolApproxValue.amount > rules.totalAwardPoolValue.amount) {
if (referrer.awardPoolApproxValue.amount > rules.awardPool.amount) {
throw new Error(
`AwardedReferrerMetricsPieSplit: awardPoolApproxValue.amount ${referrer.awardPoolApproxValue.amount.toString()} exceeds totalAwardPoolValue.amount ${rules.totalAwardPoolValue.amount.toString()}.`,
`AwardedReferrerMetricsPieSplit: awardPoolApproxValue.amount ${referrer.awardPoolApproxValue.amount.toString()} exceeds awardPool.amount ${rules.awardPool.amount.toString()}.`,
);
}
};
Expand All @@ -211,8 +211,8 @@ export const buildAwardedReferrerMetricsPieSplit = (
): AwardedReferrerMetricsPieSplit => {
const awardPoolShare = calcReferrerAwardPoolSharePieSplit(referrer, aggregatedMetrics);

// Calculate the approximate USDC value by multiplying the share by the total award pool value
const awardPoolApproxValue = scalePrice(rules.totalAwardPoolValue, awardPoolShare);
// Calculate the approximate USDC value by multiplying the share by the award pool
const awardPoolApproxValue = scalePrice(rules.awardPool, awardPoolShare);

const result = {
...referrer,
Expand Down
12 changes: 5 additions & 7 deletions packages/ens-referrals/src/v1/award-models/pie-split/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ export interface ReferralProgramRulesPieSplit extends BaseReferralProgramRules {
awardModel: typeof ReferralProgramAwardModels.PieSplit;

/**
* The total value of the award pool in USDC.
* The award pool in USDC.
*
* NOTE: Awards will actually be distributed in $ENS tokens.
*/
totalAwardPoolValue: PriceUsdc;
awardPool: PriceUsdc;

/**
* The maximum number of referrers that will qualify to receive a non-zero `awardPoolShare`.
Expand All @@ -35,17 +35,15 @@ export interface ReferralProgramRulesPieSplit extends BaseReferralProgramRules {
}

export const validateReferralProgramRulesPieSplit = (rules: ReferralProgramRulesPieSplit): void => {
makePriceUsdcSchema("ReferralProgramRulesPieSplit.totalAwardPoolValue").parse(
rules.totalAwardPoolValue,
);
makePriceUsdcSchema("ReferralProgramRulesPieSplit.awardPool").parse(rules.awardPool);

validateNonNegativeInteger(rules.maxQualifiedReferrers);

validateBaseReferralProgramRules(rules);
};

export const buildReferralProgramRulesPieSplit = (
totalAwardPoolValue: PriceUsdc,
awardPool: PriceUsdc,
maxQualifiedReferrers: number,
startTime: UnixTimestamp,
endTime: UnixTimestamp,
Expand All @@ -55,7 +53,7 @@ export const buildReferralProgramRulesPieSplit = (
): ReferralProgramRulesPieSplit => {
const result = {
awardModel: ReferralProgramAwardModels.PieSplit,
totalAwardPoolValue,
awardPool,
maxQualifiedReferrers,
startTime,
endTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export interface AggregatedReferrerMetricsRevShareLimit {
grandTotalRevenueContribution: PriceEth;

/**
* The remaining amount in the award pool after subtracting all qualified awards
* The remaining amount in the award pool after subtracting all capped awards
* claimed during the sequential race processing.
*
* @invariant Guaranteed to be a valid PriceUsdc with non-negative amount (>= 0n)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ export function serializeReferralProgramRulesRevShareLimit(
): SerializedReferralProgramRulesRevShareLimit {
return {
awardModel: rules.awardModel,
totalAwardPoolValue: serializePriceUsdc(rules.totalAwardPoolValue),
minQualifiedRevenueContribution: serializePriceUsdc(rules.minQualifiedRevenueContribution),
qualifiedRevenueShare: rules.qualifiedRevenueShare,
awardPool: serializePriceUsdc(rules.awardPool),
minBaseRevenueContribution: serializePriceUsdc(rules.minBaseRevenueContribution),
baseAnnualRevenueContribution: serializePriceUsdc(rules.baseAnnualRevenueContribution),
maxBaseRevenueShare: rules.maxBaseRevenueShare,
startTime: rules.startTime,
endTime: rules.endTime,
subregistryId: rules.subregistryId,
Expand Down Expand Up @@ -74,8 +75,8 @@ export function serializeAwardedReferrerMetricsRevShareLimit(
totalBaseRevenueContribution: serializePriceUsdc(metrics.totalBaseRevenueContribution),
rank: metrics.rank,
isQualified: metrics.isQualified,
standardAwardValue: serializePriceUsdc(metrics.standardAwardValue),
awardPoolApproxValue: serializePriceUsdc(metrics.awardPoolApproxValue),
uncappedAward: serializePriceUsdc(metrics.uncappedAward),
cappedAward: serializePriceUsdc(metrics.cappedAward),
isAdminDisqualified: metrics.isAdminDisqualified,
adminDisqualificationReason: metrics.adminDisqualificationReason,
};
Expand All @@ -95,8 +96,8 @@ export function serializeUnrankedReferrerMetricsRevShareLimit(
totalBaseRevenueContribution: serializePriceUsdc(metrics.totalBaseRevenueContribution),
rank: metrics.rank,
isQualified: metrics.isQualified,
standardAwardValue: serializePriceUsdc(metrics.standardAwardValue),
awardPoolApproxValue: serializePriceUsdc(metrics.awardPoolApproxValue),
uncappedAward: serializePriceUsdc(metrics.uncappedAward),
cappedAward: serializePriceUsdc(metrics.cappedAward),
isAdminDisqualified: metrics.isAdminDisqualified,
adminDisqualificationReason: metrics.adminDisqualificationReason,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ import type { ReferralProgramRulesRevShareLimit } from "../rules";
export interface SerializedReferralProgramRulesRevShareLimit
extends Omit<
ReferralProgramRulesRevShareLimit,
"totalAwardPoolValue" | "minQualifiedRevenueContribution" | "rulesUrl"
"awardPool" | "minBaseRevenueContribution" | "baseAnnualRevenueContribution" | "rulesUrl"
> {
totalAwardPoolValue: SerializedPriceUsdc;
minQualifiedRevenueContribution: SerializedPriceUsdc;
awardPool: SerializedPriceUsdc;
minBaseRevenueContribution: SerializedPriceUsdc;
baseAnnualRevenueContribution: SerializedPriceUsdc;
rulesUrl: string;
}

Expand All @@ -45,15 +46,12 @@ export interface SerializedAggregatedReferrerMetricsRevShareLimit
export interface SerializedAwardedReferrerMetricsRevShareLimit
extends Omit<
AwardedReferrerMetricsRevShareLimit,
| "totalRevenueContribution"
| "totalBaseRevenueContribution"
| "standardAwardValue"
| "awardPoolApproxValue"
"totalRevenueContribution" | "totalBaseRevenueContribution" | "uncappedAward" | "cappedAward"
> {
totalRevenueContribution: SerializedPriceEth;
totalBaseRevenueContribution: SerializedPriceUsdc;
standardAwardValue: SerializedPriceUsdc;
awardPoolApproxValue: SerializedPriceUsdc;
uncappedAward: SerializedPriceUsdc;
cappedAward: SerializedPriceUsdc;
}

/**
Expand All @@ -62,15 +60,12 @@ export interface SerializedAwardedReferrerMetricsRevShareLimit
export interface SerializedUnrankedReferrerMetricsRevShareLimit
extends Omit<
UnrankedReferrerMetricsRevShareLimit,
| "totalRevenueContribution"
| "totalBaseRevenueContribution"
| "standardAwardValue"
| "awardPoolApproxValue"
"totalRevenueContribution" | "totalBaseRevenueContribution" | "uncappedAward" | "cappedAward"
> {
totalRevenueContribution: SerializedPriceEth;
totalBaseRevenueContribution: SerializedPriceUsdc;
standardAwardValue: SerializedPriceUsdc;
awardPoolApproxValue: SerializedPriceUsdc;
uncappedAward: SerializedPriceUsdc;
cappedAward: SerializedPriceUsdc;
}

/**
Expand Down
Loading
Loading