@namehash/ens-referrals 1.10.0 → 1.11.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/dist/index.cjs +199 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -20
- package/dist/index.d.ts +39 -20
- package/dist/index.js +199 -99
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -69,6 +69,7 @@ __export(index_exports, {
|
|
|
69
69
|
buildUnrankedReferrerMetricsPieSplit: () => buildUnrankedReferrerMetricsPieSplit,
|
|
70
70
|
buildUnrankedReferrerMetricsRevShareCap: () => buildUnrankedReferrerMetricsRevShareCap,
|
|
71
71
|
calcBaseReferralProgramEditionStatus: () => calcBaseReferralProgramEditionStatus,
|
|
72
|
+
calcBaseRevenueContribution: () => calcBaseRevenueContribution,
|
|
72
73
|
calcReferralProgramEditionStatusPieSplit: () => calcReferralProgramEditionStatusPieSplit,
|
|
73
74
|
calcReferralProgramEditionStatusRevShareCap: () => calcReferralProgramEditionStatusRevShareCap,
|
|
74
75
|
calcReferrerAwardPoolSharePieSplit: () => calcReferrerAwardPoolSharePieSplit,
|
|
@@ -78,6 +79,7 @@ __export(index_exports, {
|
|
|
78
79
|
deserializeReferralProgramEditionSummariesResponse: () => deserializeReferralProgramEditionSummariesResponse,
|
|
79
80
|
deserializeReferrerLeaderboardPageResponse: () => deserializeReferrerLeaderboardPageResponse,
|
|
80
81
|
deserializeReferrerMetricsEditionsResponse: () => deserializeReferrerMetricsEditionsResponse,
|
|
82
|
+
findOverlappingEditionPair: () => findOverlappingEditionPair,
|
|
81
83
|
getReferrerEditionMetrics: () => getReferrerEditionMetrics,
|
|
82
84
|
getReferrerLeaderboardPage: () => getReferrerLeaderboardPage,
|
|
83
85
|
isFiniteNonNegativeNumber: () => isFiniteNonNegativeNumber,
|
|
@@ -477,7 +479,8 @@ function scaleBigintByNumber(value, scaleFactor) {
|
|
|
477
479
|
var CurrencyIds = {
|
|
478
480
|
ETH: "ETH",
|
|
479
481
|
USDC: "USDC",
|
|
480
|
-
DAI: "DAI"
|
|
482
|
+
DAI: "DAI",
|
|
483
|
+
ENSTokens: "ENSTokens"
|
|
481
484
|
};
|
|
482
485
|
var currencyInfo = {
|
|
483
486
|
[CurrencyIds.ETH]: {
|
|
@@ -494,6 +497,11 @@ var currencyInfo = {
|
|
|
494
497
|
id: CurrencyIds.DAI,
|
|
495
498
|
name: "Dai Stablecoin",
|
|
496
499
|
decimals: 18
|
|
500
|
+
},
|
|
501
|
+
[CurrencyIds.ENSTokens]: {
|
|
502
|
+
id: CurrencyIds.ENSTokens,
|
|
503
|
+
name: "$ENS Tokens",
|
|
504
|
+
decimals: 18
|
|
497
505
|
}
|
|
498
506
|
};
|
|
499
507
|
function priceEth(amount) {
|
|
@@ -508,6 +516,45 @@ function priceUsdc(amount) {
|
|
|
508
516
|
currency: CurrencyIds.USDC
|
|
509
517
|
};
|
|
510
518
|
}
|
|
519
|
+
function isPriceCurrencyEqual(priceA, priceB) {
|
|
520
|
+
return priceA.currency === priceB.currency;
|
|
521
|
+
}
|
|
522
|
+
function addPrices(...prices) {
|
|
523
|
+
const firstPrice = prices[0];
|
|
524
|
+
const allPricesInSameCurrency = prices.every((price) => isPriceCurrencyEqual(firstPrice, price));
|
|
525
|
+
if (allPricesInSameCurrency === false) {
|
|
526
|
+
throw new Error("All prices must have the same currency to be added together.");
|
|
527
|
+
}
|
|
528
|
+
const { currency } = firstPrice;
|
|
529
|
+
return prices.reduce(
|
|
530
|
+
(acc, price) => ({
|
|
531
|
+
amount: acc.amount + price.amount,
|
|
532
|
+
currency
|
|
533
|
+
}),
|
|
534
|
+
{
|
|
535
|
+
amount: 0n,
|
|
536
|
+
currency: firstPrice.currency
|
|
537
|
+
}
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
function subtractPrice(a, b) {
|
|
541
|
+
if (!isPriceCurrencyEqual(a, b)) {
|
|
542
|
+
throw new Error("All prices must have the same currency to be subtracted.");
|
|
543
|
+
}
|
|
544
|
+
const resultAmount = a.amount - b.amount;
|
|
545
|
+
if (resultAmount < 0n) {
|
|
546
|
+
throw new Error("subtractPrice result must be non-negative.");
|
|
547
|
+
}
|
|
548
|
+
return { amount: resultAmount, currency: a.currency };
|
|
549
|
+
}
|
|
550
|
+
function minPrice(...prices) {
|
|
551
|
+
const firstPrice = prices[0];
|
|
552
|
+
const allPricesInSameCurrency = prices.every((price) => isPriceCurrencyEqual(firstPrice, price));
|
|
553
|
+
if (allPricesInSameCurrency === false) {
|
|
554
|
+
throw new Error("All prices must have the same currency to be compared.");
|
|
555
|
+
}
|
|
556
|
+
return prices.reduce((acc, price) => price.amount < acc.amount ? price : acc);
|
|
557
|
+
}
|
|
511
558
|
function scalePrice(price, scaleFactor) {
|
|
512
559
|
const scaledAmount = scaleBigintByNumber(price.amount, scaleFactor);
|
|
513
560
|
return {
|
|
@@ -589,6 +636,62 @@ var import_v43 = __toESM(require("zod/v4"), 1);
|
|
|
589
636
|
// src/award-models/shared/api/zod-schemas.ts
|
|
590
637
|
var import_v42 = __toESM(require("zod/v4"), 1);
|
|
591
638
|
|
|
639
|
+
// src/edition.ts
|
|
640
|
+
var REFERRAL_PROGRAM_EDITION_SLUG_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
641
|
+
function validateReferralProgramEditionConfigSet(configSet) {
|
|
642
|
+
const violation = Array.from(configSet.entries()).find(([key, config]) => key !== config.slug);
|
|
643
|
+
if (violation) {
|
|
644
|
+
const [key, config] = violation;
|
|
645
|
+
throw new Error(
|
|
646
|
+
`Edition config set invariant violation: map key "${key}" does not match config.slug "${config.slug}"`
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
const overlap = findOverlappingEditionPair(Array.from(configSet.values()));
|
|
650
|
+
if (overlap) {
|
|
651
|
+
const [a, b] = overlap;
|
|
652
|
+
throw new Error(
|
|
653
|
+
`Edition config set invariant violation: editions "${a.slug}" and "${b.slug}" have overlapping time ranges for subregistryId ${a.rules.subregistryId.chainId}:${a.rules.subregistryId.address} (startTime and endTime are inclusive)`
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
function findOverlappingEditionPair(editions) {
|
|
658
|
+
const byRegistry = /* @__PURE__ */ new Map();
|
|
659
|
+
for (const edition of editions) {
|
|
660
|
+
const key = `${edition.rules.subregistryId.chainId}:${edition.rules.subregistryId.address}`;
|
|
661
|
+
const group = byRegistry.get(key);
|
|
662
|
+
if (group) {
|
|
663
|
+
group.push(edition);
|
|
664
|
+
} else {
|
|
665
|
+
byRegistry.set(key, [edition]);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
for (const group of byRegistry.values()) {
|
|
669
|
+
if (group.length < 2) continue;
|
|
670
|
+
group.sort((a, b) => a.rules.startTime - b.rules.startTime);
|
|
671
|
+
for (let i = 1; i < group.length; i++) {
|
|
672
|
+
const prev = group[i - 1];
|
|
673
|
+
const curr = group[i];
|
|
674
|
+
if (curr.rules.startTime <= prev.rules.endTime) {
|
|
675
|
+
return [prev, curr];
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
return null;
|
|
680
|
+
}
|
|
681
|
+
function buildReferralProgramEditionConfigSet(configs) {
|
|
682
|
+
const slugCounts = configs.reduce((counts, config) => {
|
|
683
|
+
counts.set(config.slug, (counts.get(config.slug) || 0) + 1);
|
|
684
|
+
return counts;
|
|
685
|
+
}, /* @__PURE__ */ new Map());
|
|
686
|
+
const duplicates = Array.from(slugCounts.entries()).filter(([_, count]) => count > 1).map(([slug, count]) => `"${slug}" (${count} occurrences)`);
|
|
687
|
+
if (duplicates.length > 0) {
|
|
688
|
+
throw new Error(`Duplicate edition config slugs detected: ${duplicates.join(", ")}`);
|
|
689
|
+
}
|
|
690
|
+
const configSet = new Map(configs.map((config) => [config.slug, config]));
|
|
691
|
+
validateReferralProgramEditionConfigSet(configSet);
|
|
692
|
+
return configSet;
|
|
693
|
+
}
|
|
694
|
+
|
|
592
695
|
// src/number.ts
|
|
593
696
|
var isInteger = (value) => {
|
|
594
697
|
return Number.isInteger(value);
|
|
@@ -795,6 +898,15 @@ var calcBaseReferralProgramEditionStatus = (rules, now) => {
|
|
|
795
898
|
};
|
|
796
899
|
|
|
797
900
|
// src/award-models/shared/api/zod-schemas.ts
|
|
901
|
+
var makeReferralProgramEditionSlugSchema = (valueLabel = "ReferralProgramEditionSlug") => import_v42.default.string().min(1, `${valueLabel} must not be empty`).regex(
|
|
902
|
+
REFERRAL_PROGRAM_EDITION_SLUG_PATTERN,
|
|
903
|
+
`${valueLabel} must contain only lowercase letters, digits, and hyphens. Must not start or end with a hyphen.`
|
|
904
|
+
);
|
|
905
|
+
var makeBaseReferralProgramEditionConfigSchema = (valueLabel = "BaseReferralProgramEditionConfig") => import_v42.default.object({
|
|
906
|
+
slug: makeReferralProgramEditionSlugSchema(`${valueLabel}.slug`),
|
|
907
|
+
displayName: import_v42.default.string().min(1, `${valueLabel}.displayName must not be empty`),
|
|
908
|
+
rules: makeBaseReferralProgramRulesSchema(`${valueLabel}.rules`)
|
|
909
|
+
});
|
|
798
910
|
var makeBaseReferralProgramRulesSchema = (valueLabel) => import_v42.default.object({
|
|
799
911
|
awardModel: import_v42.default.string(),
|
|
800
912
|
startTime: makeUnixTimestampSchema(`${valueLabel}.startTime`),
|
|
@@ -820,12 +932,9 @@ var makeReferrerLeaderboardPageContextSchema = (valueLabel = "ReferrerLeaderboar
|
|
|
820
932
|
endIndex: import_v42.default.optional(makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`))
|
|
821
933
|
});
|
|
822
934
|
var makeReferralProgramStatusSchema = (_valueLabel = "status") => import_v42.default.enum(ReferralProgramEditionStatuses);
|
|
823
|
-
var makeBaseReferralProgramEditionSummarySchema = (valueLabel) =>
|
|
935
|
+
var makeBaseReferralProgramEditionSummarySchema = (valueLabel) => makeBaseReferralProgramEditionConfigSchema(valueLabel).safeExtend({
|
|
824
936
|
awardModel: import_v42.default.string(),
|
|
825
|
-
|
|
826
|
-
displayName: import_v42.default.string().min(1, `${valueLabel}.displayName must not be empty`),
|
|
827
|
-
status: makeReferralProgramStatusSchema(`${valueLabel}.status`),
|
|
828
|
-
rules: makeBaseReferralProgramRulesSchema(`${valueLabel}.rules`)
|
|
937
|
+
status: makeReferralProgramStatusSchema(`${valueLabel}.status`)
|
|
829
938
|
});
|
|
830
939
|
var makeBaseReferrerLeaderboardPageSchema = (valueLabel) => import_v42.default.object({
|
|
831
940
|
awardModel: import_v42.default.string(),
|
|
@@ -1062,6 +1171,11 @@ var buildReferralProgramRulesRevShareCap = (awardPool, minBaseRevenueContributio
|
|
|
1062
1171
|
validateReferralProgramRulesRevShareCap(result);
|
|
1063
1172
|
return result;
|
|
1064
1173
|
};
|
|
1174
|
+
function calcBaseRevenueContribution(rules, duration) {
|
|
1175
|
+
return priceUsdc(
|
|
1176
|
+
rules.baseAnnualRevenueContribution.amount * BigInt(duration) / BigInt(SECONDS_PER_YEAR)
|
|
1177
|
+
);
|
|
1178
|
+
}
|
|
1065
1179
|
function isReferrerQualifiedRevShareCap(referrer, totalBaseRevenueContribution, rules) {
|
|
1066
1180
|
const isAdminDisqualified = rules.adminActions.some(
|
|
1067
1181
|
(a) => a.referrer === referrer && a.actionType === AdminActionTypes.Disqualification
|
|
@@ -1401,10 +1515,6 @@ var makeReferrerEditionMetricsSchema = (valueLabel = "ReferrerEditionMetrics") =
|
|
|
1401
1515
|
};
|
|
1402
1516
|
});
|
|
1403
1517
|
};
|
|
1404
|
-
var makeReferralProgramEditionSlugSchema = (valueLabel = "ReferralProgramEditionSlug") => import_v45.default.string().min(1, `${valueLabel} must not be empty`).regex(
|
|
1405
|
-
/^[a-z0-9]+(-[a-z0-9]+)*$/,
|
|
1406
|
-
`${valueLabel} must contain only lowercase letters, digits, and hyphens. Must not start or end with a hyphen.`
|
|
1407
|
-
);
|
|
1408
1518
|
var makeReferrerMetricsEditionsResponseOkSchema = (valueLabel = "ReferrerMetricsEditionsResponseOk") => import_v45.default.object({
|
|
1409
1519
|
responseCode: import_v45.default.literal(ReferrerMetricsEditionsResponseCodes.Ok),
|
|
1410
1520
|
data: import_v45.default.record(
|
|
@@ -1421,12 +1531,7 @@ var makeReferrerMetricsEditionsResponseSchema = (valueLabel = "ReferrerMetricsEd
|
|
|
1421
1531
|
makeReferrerMetricsEditionsResponseOkSchema(valueLabel),
|
|
1422
1532
|
makeReferrerMetricsEditionsResponseErrorSchema(valueLabel)
|
|
1423
1533
|
]);
|
|
1424
|
-
var
|
|
1425
|
-
slug: makeReferralProgramEditionSlugSchema(`${valueLabel}.slug`),
|
|
1426
|
-
displayName: import_v45.default.string().min(1, `${valueLabel}.displayName must not be empty`),
|
|
1427
|
-
rules: makeBaseReferralProgramRulesSchema(`${valueLabel}.rules`)
|
|
1428
|
-
});
|
|
1429
|
-
var makeReferralProgramEditionConfigSchema = (valueLabel = "ReferralProgramEditionConfig") => makeReferralProgramEditionConfigBaseSchema(valueLabel).safeExtend({
|
|
1534
|
+
var makeReferralProgramEditionConfigSchema = (valueLabel = "ReferralProgramEditionConfig") => makeBaseReferralProgramEditionConfigSchema(valueLabel).safeExtend({
|
|
1430
1535
|
rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`)
|
|
1431
1536
|
});
|
|
1432
1537
|
var makeReferralProgramEditionConfigSetArraySchema = (valueLabel = "ReferralProgramEditionConfigSetArray") => {
|
|
@@ -1437,7 +1542,7 @@ var makeReferralProgramEditionConfigSetArraySchema = (valueLabel = "ReferralProg
|
|
|
1437
1542
|
const looseItemSchema = import_v45.default.looseObject({
|
|
1438
1543
|
rules: import_v45.default.looseObject({ awardModel: import_v45.default.string() })
|
|
1439
1544
|
});
|
|
1440
|
-
const unrecognizedBaseSchema =
|
|
1545
|
+
const unrecognizedBaseSchema = makeBaseReferralProgramEditionConfigSchema(
|
|
1441
1546
|
`${valueLabel}[edition]`
|
|
1442
1547
|
);
|
|
1443
1548
|
return import_v45.default.array(looseItemSchema).transform((items, ctx) => {
|
|
@@ -1478,6 +1583,15 @@ var makeReferralProgramEditionConfigSetArraySchema = (valueLabel = "ReferralProg
|
|
|
1478
1583
|
}
|
|
1479
1584
|
slugs.add(edition.slug);
|
|
1480
1585
|
}
|
|
1586
|
+
const overlap = findOverlappingEditionPair(result);
|
|
1587
|
+
if (overlap) {
|
|
1588
|
+
const [a, b] = overlap;
|
|
1589
|
+
ctx.addIssue({
|
|
1590
|
+
code: "custom",
|
|
1591
|
+
message: `${valueLabel}: editions "${a.slug}" and "${b.slug}" have overlapping time ranges for subregistryId ${a.rules.subregistryId.chainId}:${a.rules.subregistryId.address} (startTime and endTime are inclusive)`
|
|
1592
|
+
});
|
|
1593
|
+
return [];
|
|
1594
|
+
}
|
|
1481
1595
|
return result;
|
|
1482
1596
|
});
|
|
1483
1597
|
};
|
|
@@ -1518,6 +1632,15 @@ var makeReferralProgramEditionSummarySchema = (valueLabel = "ReferralProgramEdit
|
|
|
1518
1632
|
};
|
|
1519
1633
|
var makeReferralProgramEditionSummariesDataSchema = (valueLabel = "ReferralProgramEditionSummariesData") => import_v45.default.object({
|
|
1520
1634
|
editions: import_v45.default.array(makeReferralProgramEditionSummarySchema(`${valueLabel}.editions[edition]`))
|
|
1635
|
+
}).superRefine((data, ctx) => {
|
|
1636
|
+
const overlap = findOverlappingEditionPair(data.editions);
|
|
1637
|
+
if (!overlap) return;
|
|
1638
|
+
const [a, b] = overlap;
|
|
1639
|
+
ctx.addIssue({
|
|
1640
|
+
code: "custom",
|
|
1641
|
+
path: ["editions"],
|
|
1642
|
+
message: `${valueLabel}: editions "${a.slug}" and "${b.slug}" have overlapping time ranges for subregistryId ${a.rules.subregistryId.chainId}:${a.rules.subregistryId.address} (startTime and endTime are inclusive)`
|
|
1643
|
+
});
|
|
1521
1644
|
});
|
|
1522
1645
|
var makeReferralProgramEditionSummariesResponseOkSchema = (valueLabel = "ReferralProgramEditionSummariesResponseOk") => import_v45.default.object({
|
|
1523
1646
|
responseCode: import_v45.default.literal(ReferralProgramEditionSummariesResponseCodes.Ok),
|
|
@@ -1997,31 +2120,6 @@ var buildAggregatedReferrerMetricsPieSplit = (referrers, rules) => {
|
|
|
1997
2120
|
return result;
|
|
1998
2121
|
};
|
|
1999
2122
|
|
|
2000
|
-
// src/edition.ts
|
|
2001
|
-
var REFERRAL_PROGRAM_EDITION_SLUG_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
2002
|
-
function validateReferralProgramEditionConfigSet(configSet) {
|
|
2003
|
-
const violation = Array.from(configSet.entries()).find(([key, config]) => key !== config.slug);
|
|
2004
|
-
if (violation) {
|
|
2005
|
-
const [key, config] = violation;
|
|
2006
|
-
throw new Error(
|
|
2007
|
-
`Edition config set invariant violation: map key "${key}" does not match config.slug "${config.slug}"`
|
|
2008
|
-
);
|
|
2009
|
-
}
|
|
2010
|
-
}
|
|
2011
|
-
function buildReferralProgramEditionConfigSet(configs) {
|
|
2012
|
-
const slugCounts = configs.reduce((counts, config) => {
|
|
2013
|
-
counts.set(config.slug, (counts.get(config.slug) || 0) + 1);
|
|
2014
|
-
return counts;
|
|
2015
|
-
}, /* @__PURE__ */ new Map());
|
|
2016
|
-
const duplicates = Array.from(slugCounts.entries()).filter(([_, count]) => count > 1).map(([slug, count]) => `"${slug}" (${count} occurrences)`);
|
|
2017
|
-
if (duplicates.length > 0) {
|
|
2018
|
-
throw new Error(`Duplicate edition config slugs detected: ${duplicates.join(", ")}`);
|
|
2019
|
-
}
|
|
2020
|
-
const configSet = new Map(configs.map((config) => [config.slug, config]));
|
|
2021
|
-
validateReferralProgramEditionConfigSet(configSet);
|
|
2022
|
-
return configSet;
|
|
2023
|
-
}
|
|
2024
|
-
|
|
2025
2123
|
// src/award-models/shared/edition-summary.ts
|
|
2026
2124
|
var validateBaseReferralProgramEditionSummary = (summary) => {
|
|
2027
2125
|
if (!REFERRAL_PROGRAM_EDITION_SLUG_PATTERN.test(summary.slug)) {
|
|
@@ -2420,8 +2518,9 @@ var validateReferrerMetricsRevShareCap = (metrics, rules) => {
|
|
|
2420
2518
|
makePriceUsdcSchema("ReferrerMetricsRevShareCap.totalBaseRevenueContribution").parse(
|
|
2421
2519
|
metrics.totalBaseRevenueContribution
|
|
2422
2520
|
);
|
|
2423
|
-
const expectedTotalBaseRevenueContribution =
|
|
2424
|
-
rules
|
|
2521
|
+
const expectedTotalBaseRevenueContribution = calcBaseRevenueContribution(
|
|
2522
|
+
rules,
|
|
2523
|
+
metrics.totalIncrementalDuration
|
|
2425
2524
|
);
|
|
2426
2525
|
if (metrics.totalBaseRevenueContribution.amount !== expectedTotalBaseRevenueContribution.amount) {
|
|
2427
2526
|
throw new Error(
|
|
@@ -2430,8 +2529,9 @@ var validateReferrerMetricsRevShareCap = (metrics, rules) => {
|
|
|
2430
2529
|
}
|
|
2431
2530
|
};
|
|
2432
2531
|
var buildReferrerMetricsRevShareCap = (metrics, rules) => {
|
|
2433
|
-
const totalBaseRevenueContribution =
|
|
2434
|
-
rules
|
|
2532
|
+
const totalBaseRevenueContribution = calcBaseRevenueContribution(
|
|
2533
|
+
rules,
|
|
2534
|
+
metrics.totalIncrementalDuration
|
|
2435
2535
|
);
|
|
2436
2536
|
const result = {
|
|
2437
2537
|
...metrics,
|
|
@@ -2605,71 +2705,71 @@ function sortReferralEvents(events) {
|
|
|
2605
2705
|
}
|
|
2606
2706
|
|
|
2607
2707
|
// src/award-models/rev-share-cap/leaderboard.ts
|
|
2608
|
-
var bigintMin = (a, b) => a < b ? a : b;
|
|
2609
2708
|
var buildReferrerLeaderboardRevShareCap = (events, rules, accurateAsOf) => {
|
|
2610
2709
|
const sortedEvents = sortReferralEvents(events);
|
|
2611
2710
|
const referrerStates = /* @__PURE__ */ new Map();
|
|
2612
|
-
let awardPoolRemaining = rules.awardPool
|
|
2711
|
+
let awardPoolRemaining = rules.awardPool;
|
|
2613
2712
|
for (const event of sortedEvents) {
|
|
2614
|
-
const
|
|
2615
|
-
let
|
|
2616
|
-
if (!
|
|
2617
|
-
|
|
2713
|
+
const referrerId = event.referrer;
|
|
2714
|
+
let referrerState = referrerStates.get(referrerId);
|
|
2715
|
+
if (!referrerState) {
|
|
2716
|
+
referrerState = {
|
|
2618
2717
|
totalReferrals: 0,
|
|
2619
2718
|
totalIncrementalDuration: 0,
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2719
|
+
totalRevenueContribution: priceEth(0n),
|
|
2720
|
+
hasQualified: false,
|
|
2721
|
+
cappedAward: priceUsdc(0n)
|
|
2623
2722
|
};
|
|
2624
|
-
referrerStates.set(
|
|
2625
|
-
}
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
rules
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
)
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
const incrementalBaseRevenueAmount = rules.baseAnnualRevenueContribution.amount * BigInt(event.incrementalDuration) / BigInt(SECONDS_PER_YEAR);
|
|
2723
|
+
referrerStates.set(referrerId, referrerState);
|
|
2724
|
+
}
|
|
2725
|
+
referrerState.totalReferrals += 1;
|
|
2726
|
+
referrerState.totalIncrementalDuration += event.incrementalDuration;
|
|
2727
|
+
referrerState.totalRevenueContribution = addPrices(
|
|
2728
|
+
referrerState.totalRevenueContribution,
|
|
2729
|
+
event.incrementalRevenueContribution
|
|
2730
|
+
);
|
|
2731
|
+
const totalBaseRevenue = calcBaseRevenueContribution(
|
|
2732
|
+
rules,
|
|
2733
|
+
referrerState.totalIncrementalDuration
|
|
2734
|
+
);
|
|
2735
|
+
const isNowQualified = isReferrerQualifiedRevShareCap(referrerId, totalBaseRevenue, rules);
|
|
2736
|
+
if (isNowQualified && !referrerState.hasQualified) {
|
|
2737
|
+
const accumulatedUncappedAward = scalePrice(totalBaseRevenue, rules.maxBaseRevenueShare);
|
|
2738
|
+
const incrementalCappedAward = minPrice(accumulatedUncappedAward, awardPoolRemaining);
|
|
2739
|
+
referrerState.cappedAward = addPrices(referrerState.cappedAward, incrementalCappedAward);
|
|
2740
|
+
awardPoolRemaining = subtractPrice(awardPoolRemaining, incrementalCappedAward);
|
|
2741
|
+
referrerState.hasQualified = true;
|
|
2742
|
+
} else if (referrerState.hasQualified) {
|
|
2743
|
+
const incrementalBaseRevenue = calcBaseRevenueContribution(rules, event.incrementalDuration);
|
|
2646
2744
|
const incrementalUncappedAward = scalePrice(
|
|
2647
|
-
|
|
2745
|
+
incrementalBaseRevenue,
|
|
2648
2746
|
rules.maxBaseRevenueShare
|
|
2649
|
-
)
|
|
2650
|
-
const incrementalCappedAward =
|
|
2651
|
-
|
|
2652
|
-
awardPoolRemaining
|
|
2747
|
+
);
|
|
2748
|
+
const incrementalCappedAward = minPrice(incrementalUncappedAward, awardPoolRemaining);
|
|
2749
|
+
referrerState.cappedAward = addPrices(referrerState.cappedAward, incrementalCappedAward);
|
|
2750
|
+
awardPoolRemaining = subtractPrice(awardPoolRemaining, incrementalCappedAward);
|
|
2653
2751
|
}
|
|
2654
2752
|
}
|
|
2655
|
-
const sortedEntries = [...referrerStates.entries()].sort(
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2753
|
+
const sortedEntries = [...referrerStates.entries()].sort(
|
|
2754
|
+
([referrerIdA, referrerStateA], [referrerIdB, referrerStateB]) => {
|
|
2755
|
+
if (referrerStateB.cappedAward.amount !== referrerStateA.cappedAward.amount) {
|
|
2756
|
+
return referrerStateB.cappedAward.amount > referrerStateA.cappedAward.amount ? 1 : -1;
|
|
2757
|
+
}
|
|
2758
|
+
if (referrerStateB.totalIncrementalDuration !== referrerStateA.totalIncrementalDuration) {
|
|
2759
|
+
return referrerStateB.totalIncrementalDuration - referrerStateA.totalIncrementalDuration;
|
|
2760
|
+
}
|
|
2761
|
+
if (referrerIdB > referrerIdA) return 1;
|
|
2762
|
+
if (referrerIdB < referrerIdA) return -1;
|
|
2763
|
+
return 0;
|
|
2661
2764
|
}
|
|
2662
|
-
|
|
2663
|
-
if (b < a) return -1;
|
|
2664
|
-
return 0;
|
|
2665
|
-
});
|
|
2765
|
+
);
|
|
2666
2766
|
const awardedReferrers = sortedEntries.map(
|
|
2667
|
-
([
|
|
2767
|
+
([referrerId, referrerState], index) => {
|
|
2668
2768
|
const baseMetrics = buildReferrerMetrics(
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2769
|
+
referrerId,
|
|
2770
|
+
referrerState.totalReferrals,
|
|
2771
|
+
referrerState.totalIncrementalDuration,
|
|
2772
|
+
referrerState.totalRevenueContribution
|
|
2673
2773
|
);
|
|
2674
2774
|
const revShareMetrics = buildReferrerMetricsRevShareCap(baseMetrics, rules);
|
|
2675
2775
|
const rankedMetrics = buildRankedReferrerMetricsRevShareCap(
|
|
@@ -2684,14 +2784,14 @@ var buildReferrerLeaderboardRevShareCap = (events, rules, accurateAsOf) => {
|
|
|
2684
2784
|
return buildAwardedReferrerMetricsRevShareCap(
|
|
2685
2785
|
rankedMetrics,
|
|
2686
2786
|
uncappedAward,
|
|
2687
|
-
|
|
2787
|
+
referrerState.cappedAward,
|
|
2688
2788
|
rules
|
|
2689
2789
|
);
|
|
2690
2790
|
}
|
|
2691
2791
|
);
|
|
2692
2792
|
const aggregatedMetrics = buildAggregatedReferrerMetricsRevShareCap(
|
|
2693
2793
|
awardedReferrers,
|
|
2694
|
-
|
|
2794
|
+
awardPoolRemaining
|
|
2695
2795
|
);
|
|
2696
2796
|
const referrers = new Map(awardedReferrers.map((r) => [r.referrer, r]));
|
|
2697
2797
|
return { awardModel: rules.awardModel, rules, aggregatedMetrics, referrers, accurateAsOf };
|