@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.js
CHANGED
|
@@ -353,7 +353,8 @@ function scaleBigintByNumber(value, scaleFactor) {
|
|
|
353
353
|
var CurrencyIds = {
|
|
354
354
|
ETH: "ETH",
|
|
355
355
|
USDC: "USDC",
|
|
356
|
-
DAI: "DAI"
|
|
356
|
+
DAI: "DAI",
|
|
357
|
+
ENSTokens: "ENSTokens"
|
|
357
358
|
};
|
|
358
359
|
var currencyInfo = {
|
|
359
360
|
[CurrencyIds.ETH]: {
|
|
@@ -370,6 +371,11 @@ var currencyInfo = {
|
|
|
370
371
|
id: CurrencyIds.DAI,
|
|
371
372
|
name: "Dai Stablecoin",
|
|
372
373
|
decimals: 18
|
|
374
|
+
},
|
|
375
|
+
[CurrencyIds.ENSTokens]: {
|
|
376
|
+
id: CurrencyIds.ENSTokens,
|
|
377
|
+
name: "$ENS Tokens",
|
|
378
|
+
decimals: 18
|
|
373
379
|
}
|
|
374
380
|
};
|
|
375
381
|
function priceEth(amount) {
|
|
@@ -384,6 +390,45 @@ function priceUsdc(amount) {
|
|
|
384
390
|
currency: CurrencyIds.USDC
|
|
385
391
|
};
|
|
386
392
|
}
|
|
393
|
+
function isPriceCurrencyEqual(priceA, priceB) {
|
|
394
|
+
return priceA.currency === priceB.currency;
|
|
395
|
+
}
|
|
396
|
+
function addPrices(...prices) {
|
|
397
|
+
const firstPrice = prices[0];
|
|
398
|
+
const allPricesInSameCurrency = prices.every((price) => isPriceCurrencyEqual(firstPrice, price));
|
|
399
|
+
if (allPricesInSameCurrency === false) {
|
|
400
|
+
throw new Error("All prices must have the same currency to be added together.");
|
|
401
|
+
}
|
|
402
|
+
const { currency } = firstPrice;
|
|
403
|
+
return prices.reduce(
|
|
404
|
+
(acc, price) => ({
|
|
405
|
+
amount: acc.amount + price.amount,
|
|
406
|
+
currency
|
|
407
|
+
}),
|
|
408
|
+
{
|
|
409
|
+
amount: 0n,
|
|
410
|
+
currency: firstPrice.currency
|
|
411
|
+
}
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
function subtractPrice(a, b) {
|
|
415
|
+
if (!isPriceCurrencyEqual(a, b)) {
|
|
416
|
+
throw new Error("All prices must have the same currency to be subtracted.");
|
|
417
|
+
}
|
|
418
|
+
const resultAmount = a.amount - b.amount;
|
|
419
|
+
if (resultAmount < 0n) {
|
|
420
|
+
throw new Error("subtractPrice result must be non-negative.");
|
|
421
|
+
}
|
|
422
|
+
return { amount: resultAmount, currency: a.currency };
|
|
423
|
+
}
|
|
424
|
+
function minPrice(...prices) {
|
|
425
|
+
const firstPrice = prices[0];
|
|
426
|
+
const allPricesInSameCurrency = prices.every((price) => isPriceCurrencyEqual(firstPrice, price));
|
|
427
|
+
if (allPricesInSameCurrency === false) {
|
|
428
|
+
throw new Error("All prices must have the same currency to be compared.");
|
|
429
|
+
}
|
|
430
|
+
return prices.reduce((acc, price) => price.amount < acc.amount ? price : acc);
|
|
431
|
+
}
|
|
387
432
|
function scalePrice(price, scaleFactor) {
|
|
388
433
|
const scaledAmount = scaleBigintByNumber(price.amount, scaleFactor);
|
|
389
434
|
return {
|
|
@@ -465,6 +510,62 @@ import z3 from "zod/v4";
|
|
|
465
510
|
// src/award-models/shared/api/zod-schemas.ts
|
|
466
511
|
import z2 from "zod/v4";
|
|
467
512
|
|
|
513
|
+
// src/edition.ts
|
|
514
|
+
var REFERRAL_PROGRAM_EDITION_SLUG_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
515
|
+
function validateReferralProgramEditionConfigSet(configSet) {
|
|
516
|
+
const violation = Array.from(configSet.entries()).find(([key, config]) => key !== config.slug);
|
|
517
|
+
if (violation) {
|
|
518
|
+
const [key, config] = violation;
|
|
519
|
+
throw new Error(
|
|
520
|
+
`Edition config set invariant violation: map key "${key}" does not match config.slug "${config.slug}"`
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
const overlap = findOverlappingEditionPair(Array.from(configSet.values()));
|
|
524
|
+
if (overlap) {
|
|
525
|
+
const [a, b] = overlap;
|
|
526
|
+
throw new Error(
|
|
527
|
+
`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)`
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
function findOverlappingEditionPair(editions) {
|
|
532
|
+
const byRegistry = /* @__PURE__ */ new Map();
|
|
533
|
+
for (const edition of editions) {
|
|
534
|
+
const key = `${edition.rules.subregistryId.chainId}:${edition.rules.subregistryId.address}`;
|
|
535
|
+
const group = byRegistry.get(key);
|
|
536
|
+
if (group) {
|
|
537
|
+
group.push(edition);
|
|
538
|
+
} else {
|
|
539
|
+
byRegistry.set(key, [edition]);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
for (const group of byRegistry.values()) {
|
|
543
|
+
if (group.length < 2) continue;
|
|
544
|
+
group.sort((a, b) => a.rules.startTime - b.rules.startTime);
|
|
545
|
+
for (let i = 1; i < group.length; i++) {
|
|
546
|
+
const prev = group[i - 1];
|
|
547
|
+
const curr = group[i];
|
|
548
|
+
if (curr.rules.startTime <= prev.rules.endTime) {
|
|
549
|
+
return [prev, curr];
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return null;
|
|
554
|
+
}
|
|
555
|
+
function buildReferralProgramEditionConfigSet(configs) {
|
|
556
|
+
const slugCounts = configs.reduce((counts, config) => {
|
|
557
|
+
counts.set(config.slug, (counts.get(config.slug) || 0) + 1);
|
|
558
|
+
return counts;
|
|
559
|
+
}, /* @__PURE__ */ new Map());
|
|
560
|
+
const duplicates = Array.from(slugCounts.entries()).filter(([_, count]) => count > 1).map(([slug, count]) => `"${slug}" (${count} occurrences)`);
|
|
561
|
+
if (duplicates.length > 0) {
|
|
562
|
+
throw new Error(`Duplicate edition config slugs detected: ${duplicates.join(", ")}`);
|
|
563
|
+
}
|
|
564
|
+
const configSet = new Map(configs.map((config) => [config.slug, config]));
|
|
565
|
+
validateReferralProgramEditionConfigSet(configSet);
|
|
566
|
+
return configSet;
|
|
567
|
+
}
|
|
568
|
+
|
|
468
569
|
// src/number.ts
|
|
469
570
|
var isInteger = (value) => {
|
|
470
571
|
return Number.isInteger(value);
|
|
@@ -671,6 +772,15 @@ var calcBaseReferralProgramEditionStatus = (rules, now) => {
|
|
|
671
772
|
};
|
|
672
773
|
|
|
673
774
|
// src/award-models/shared/api/zod-schemas.ts
|
|
775
|
+
var makeReferralProgramEditionSlugSchema = (valueLabel = "ReferralProgramEditionSlug") => z2.string().min(1, `${valueLabel} must not be empty`).regex(
|
|
776
|
+
REFERRAL_PROGRAM_EDITION_SLUG_PATTERN,
|
|
777
|
+
`${valueLabel} must contain only lowercase letters, digits, and hyphens. Must not start or end with a hyphen.`
|
|
778
|
+
);
|
|
779
|
+
var makeBaseReferralProgramEditionConfigSchema = (valueLabel = "BaseReferralProgramEditionConfig") => z2.object({
|
|
780
|
+
slug: makeReferralProgramEditionSlugSchema(`${valueLabel}.slug`),
|
|
781
|
+
displayName: z2.string().min(1, `${valueLabel}.displayName must not be empty`),
|
|
782
|
+
rules: makeBaseReferralProgramRulesSchema(`${valueLabel}.rules`)
|
|
783
|
+
});
|
|
674
784
|
var makeBaseReferralProgramRulesSchema = (valueLabel) => z2.object({
|
|
675
785
|
awardModel: z2.string(),
|
|
676
786
|
startTime: makeUnixTimestampSchema(`${valueLabel}.startTime`),
|
|
@@ -696,12 +806,9 @@ var makeReferrerLeaderboardPageContextSchema = (valueLabel = "ReferrerLeaderboar
|
|
|
696
806
|
endIndex: z2.optional(makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`))
|
|
697
807
|
});
|
|
698
808
|
var makeReferralProgramStatusSchema = (_valueLabel = "status") => z2.enum(ReferralProgramEditionStatuses);
|
|
699
|
-
var makeBaseReferralProgramEditionSummarySchema = (valueLabel) =>
|
|
809
|
+
var makeBaseReferralProgramEditionSummarySchema = (valueLabel) => makeBaseReferralProgramEditionConfigSchema(valueLabel).safeExtend({
|
|
700
810
|
awardModel: z2.string(),
|
|
701
|
-
|
|
702
|
-
displayName: z2.string().min(1, `${valueLabel}.displayName must not be empty`),
|
|
703
|
-
status: makeReferralProgramStatusSchema(`${valueLabel}.status`),
|
|
704
|
-
rules: makeBaseReferralProgramRulesSchema(`${valueLabel}.rules`)
|
|
811
|
+
status: makeReferralProgramStatusSchema(`${valueLabel}.status`)
|
|
705
812
|
});
|
|
706
813
|
var makeBaseReferrerLeaderboardPageSchema = (valueLabel) => z2.object({
|
|
707
814
|
awardModel: z2.string(),
|
|
@@ -938,6 +1045,11 @@ var buildReferralProgramRulesRevShareCap = (awardPool, minBaseRevenueContributio
|
|
|
938
1045
|
validateReferralProgramRulesRevShareCap(result);
|
|
939
1046
|
return result;
|
|
940
1047
|
};
|
|
1048
|
+
function calcBaseRevenueContribution(rules, duration) {
|
|
1049
|
+
return priceUsdc(
|
|
1050
|
+
rules.baseAnnualRevenueContribution.amount * BigInt(duration) / BigInt(SECONDS_PER_YEAR)
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
941
1053
|
function isReferrerQualifiedRevShareCap(referrer, totalBaseRevenueContribution, rules) {
|
|
942
1054
|
const isAdminDisqualified = rules.adminActions.some(
|
|
943
1055
|
(a) => a.referrer === referrer && a.actionType === AdminActionTypes.Disqualification
|
|
@@ -1277,10 +1389,6 @@ var makeReferrerEditionMetricsSchema = (valueLabel = "ReferrerEditionMetrics") =
|
|
|
1277
1389
|
};
|
|
1278
1390
|
});
|
|
1279
1391
|
};
|
|
1280
|
-
var makeReferralProgramEditionSlugSchema = (valueLabel = "ReferralProgramEditionSlug") => z5.string().min(1, `${valueLabel} must not be empty`).regex(
|
|
1281
|
-
/^[a-z0-9]+(-[a-z0-9]+)*$/,
|
|
1282
|
-
`${valueLabel} must contain only lowercase letters, digits, and hyphens. Must not start or end with a hyphen.`
|
|
1283
|
-
);
|
|
1284
1392
|
var makeReferrerMetricsEditionsResponseOkSchema = (valueLabel = "ReferrerMetricsEditionsResponseOk") => z5.object({
|
|
1285
1393
|
responseCode: z5.literal(ReferrerMetricsEditionsResponseCodes.Ok),
|
|
1286
1394
|
data: z5.record(
|
|
@@ -1297,12 +1405,7 @@ var makeReferrerMetricsEditionsResponseSchema = (valueLabel = "ReferrerMetricsEd
|
|
|
1297
1405
|
makeReferrerMetricsEditionsResponseOkSchema(valueLabel),
|
|
1298
1406
|
makeReferrerMetricsEditionsResponseErrorSchema(valueLabel)
|
|
1299
1407
|
]);
|
|
1300
|
-
var
|
|
1301
|
-
slug: makeReferralProgramEditionSlugSchema(`${valueLabel}.slug`),
|
|
1302
|
-
displayName: z5.string().min(1, `${valueLabel}.displayName must not be empty`),
|
|
1303
|
-
rules: makeBaseReferralProgramRulesSchema(`${valueLabel}.rules`)
|
|
1304
|
-
});
|
|
1305
|
-
var makeReferralProgramEditionConfigSchema = (valueLabel = "ReferralProgramEditionConfig") => makeReferralProgramEditionConfigBaseSchema(valueLabel).safeExtend({
|
|
1408
|
+
var makeReferralProgramEditionConfigSchema = (valueLabel = "ReferralProgramEditionConfig") => makeBaseReferralProgramEditionConfigSchema(valueLabel).safeExtend({
|
|
1306
1409
|
rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`)
|
|
1307
1410
|
});
|
|
1308
1411
|
var makeReferralProgramEditionConfigSetArraySchema = (valueLabel = "ReferralProgramEditionConfigSetArray") => {
|
|
@@ -1313,7 +1416,7 @@ var makeReferralProgramEditionConfigSetArraySchema = (valueLabel = "ReferralProg
|
|
|
1313
1416
|
const looseItemSchema = z5.looseObject({
|
|
1314
1417
|
rules: z5.looseObject({ awardModel: z5.string() })
|
|
1315
1418
|
});
|
|
1316
|
-
const unrecognizedBaseSchema =
|
|
1419
|
+
const unrecognizedBaseSchema = makeBaseReferralProgramEditionConfigSchema(
|
|
1317
1420
|
`${valueLabel}[edition]`
|
|
1318
1421
|
);
|
|
1319
1422
|
return z5.array(looseItemSchema).transform((items, ctx) => {
|
|
@@ -1354,6 +1457,15 @@ var makeReferralProgramEditionConfigSetArraySchema = (valueLabel = "ReferralProg
|
|
|
1354
1457
|
}
|
|
1355
1458
|
slugs.add(edition.slug);
|
|
1356
1459
|
}
|
|
1460
|
+
const overlap = findOverlappingEditionPair(result);
|
|
1461
|
+
if (overlap) {
|
|
1462
|
+
const [a, b] = overlap;
|
|
1463
|
+
ctx.addIssue({
|
|
1464
|
+
code: "custom",
|
|
1465
|
+
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)`
|
|
1466
|
+
});
|
|
1467
|
+
return [];
|
|
1468
|
+
}
|
|
1357
1469
|
return result;
|
|
1358
1470
|
});
|
|
1359
1471
|
};
|
|
@@ -1394,6 +1506,15 @@ var makeReferralProgramEditionSummarySchema = (valueLabel = "ReferralProgramEdit
|
|
|
1394
1506
|
};
|
|
1395
1507
|
var makeReferralProgramEditionSummariesDataSchema = (valueLabel = "ReferralProgramEditionSummariesData") => z5.object({
|
|
1396
1508
|
editions: z5.array(makeReferralProgramEditionSummarySchema(`${valueLabel}.editions[edition]`))
|
|
1509
|
+
}).superRefine((data, ctx) => {
|
|
1510
|
+
const overlap = findOverlappingEditionPair(data.editions);
|
|
1511
|
+
if (!overlap) return;
|
|
1512
|
+
const [a, b] = overlap;
|
|
1513
|
+
ctx.addIssue({
|
|
1514
|
+
code: "custom",
|
|
1515
|
+
path: ["editions"],
|
|
1516
|
+
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)`
|
|
1517
|
+
});
|
|
1397
1518
|
});
|
|
1398
1519
|
var makeReferralProgramEditionSummariesResponseOkSchema = (valueLabel = "ReferralProgramEditionSummariesResponseOk") => z5.object({
|
|
1399
1520
|
responseCode: z5.literal(ReferralProgramEditionSummariesResponseCodes.Ok),
|
|
@@ -1873,31 +1994,6 @@ var buildAggregatedReferrerMetricsPieSplit = (referrers, rules) => {
|
|
|
1873
1994
|
return result;
|
|
1874
1995
|
};
|
|
1875
1996
|
|
|
1876
|
-
// src/edition.ts
|
|
1877
|
-
var REFERRAL_PROGRAM_EDITION_SLUG_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
1878
|
-
function validateReferralProgramEditionConfigSet(configSet) {
|
|
1879
|
-
const violation = Array.from(configSet.entries()).find(([key, config]) => key !== config.slug);
|
|
1880
|
-
if (violation) {
|
|
1881
|
-
const [key, config] = violation;
|
|
1882
|
-
throw new Error(
|
|
1883
|
-
`Edition config set invariant violation: map key "${key}" does not match config.slug "${config.slug}"`
|
|
1884
|
-
);
|
|
1885
|
-
}
|
|
1886
|
-
}
|
|
1887
|
-
function buildReferralProgramEditionConfigSet(configs) {
|
|
1888
|
-
const slugCounts = configs.reduce((counts, config) => {
|
|
1889
|
-
counts.set(config.slug, (counts.get(config.slug) || 0) + 1);
|
|
1890
|
-
return counts;
|
|
1891
|
-
}, /* @__PURE__ */ new Map());
|
|
1892
|
-
const duplicates = Array.from(slugCounts.entries()).filter(([_, count]) => count > 1).map(([slug, count]) => `"${slug}" (${count} occurrences)`);
|
|
1893
|
-
if (duplicates.length > 0) {
|
|
1894
|
-
throw new Error(`Duplicate edition config slugs detected: ${duplicates.join(", ")}`);
|
|
1895
|
-
}
|
|
1896
|
-
const configSet = new Map(configs.map((config) => [config.slug, config]));
|
|
1897
|
-
validateReferralProgramEditionConfigSet(configSet);
|
|
1898
|
-
return configSet;
|
|
1899
|
-
}
|
|
1900
|
-
|
|
1901
1997
|
// src/award-models/shared/edition-summary.ts
|
|
1902
1998
|
var validateBaseReferralProgramEditionSummary = (summary) => {
|
|
1903
1999
|
if (!REFERRAL_PROGRAM_EDITION_SLUG_PATTERN.test(summary.slug)) {
|
|
@@ -2296,8 +2392,9 @@ var validateReferrerMetricsRevShareCap = (metrics, rules) => {
|
|
|
2296
2392
|
makePriceUsdcSchema("ReferrerMetricsRevShareCap.totalBaseRevenueContribution").parse(
|
|
2297
2393
|
metrics.totalBaseRevenueContribution
|
|
2298
2394
|
);
|
|
2299
|
-
const expectedTotalBaseRevenueContribution =
|
|
2300
|
-
rules
|
|
2395
|
+
const expectedTotalBaseRevenueContribution = calcBaseRevenueContribution(
|
|
2396
|
+
rules,
|
|
2397
|
+
metrics.totalIncrementalDuration
|
|
2301
2398
|
);
|
|
2302
2399
|
if (metrics.totalBaseRevenueContribution.amount !== expectedTotalBaseRevenueContribution.amount) {
|
|
2303
2400
|
throw new Error(
|
|
@@ -2306,8 +2403,9 @@ var validateReferrerMetricsRevShareCap = (metrics, rules) => {
|
|
|
2306
2403
|
}
|
|
2307
2404
|
};
|
|
2308
2405
|
var buildReferrerMetricsRevShareCap = (metrics, rules) => {
|
|
2309
|
-
const totalBaseRevenueContribution =
|
|
2310
|
-
rules
|
|
2406
|
+
const totalBaseRevenueContribution = calcBaseRevenueContribution(
|
|
2407
|
+
rules,
|
|
2408
|
+
metrics.totalIncrementalDuration
|
|
2311
2409
|
);
|
|
2312
2410
|
const result = {
|
|
2313
2411
|
...metrics,
|
|
@@ -2481,71 +2579,71 @@ function sortReferralEvents(events) {
|
|
|
2481
2579
|
}
|
|
2482
2580
|
|
|
2483
2581
|
// src/award-models/rev-share-cap/leaderboard.ts
|
|
2484
|
-
var bigintMin = (a, b) => a < b ? a : b;
|
|
2485
2582
|
var buildReferrerLeaderboardRevShareCap = (events, rules, accurateAsOf) => {
|
|
2486
2583
|
const sortedEvents = sortReferralEvents(events);
|
|
2487
2584
|
const referrerStates = /* @__PURE__ */ new Map();
|
|
2488
|
-
let awardPoolRemaining = rules.awardPool
|
|
2585
|
+
let awardPoolRemaining = rules.awardPool;
|
|
2489
2586
|
for (const event of sortedEvents) {
|
|
2490
|
-
const
|
|
2491
|
-
let
|
|
2492
|
-
if (!
|
|
2493
|
-
|
|
2587
|
+
const referrerId = event.referrer;
|
|
2588
|
+
let referrerState = referrerStates.get(referrerId);
|
|
2589
|
+
if (!referrerState) {
|
|
2590
|
+
referrerState = {
|
|
2494
2591
|
totalReferrals: 0,
|
|
2495
2592
|
totalIncrementalDuration: 0,
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2593
|
+
totalRevenueContribution: priceEth(0n),
|
|
2594
|
+
hasQualified: false,
|
|
2595
|
+
cappedAward: priceUsdc(0n)
|
|
2499
2596
|
};
|
|
2500
|
-
referrerStates.set(
|
|
2501
|
-
}
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
rules
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
)
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
const incrementalBaseRevenueAmount = rules.baseAnnualRevenueContribution.amount * BigInt(event.incrementalDuration) / BigInt(SECONDS_PER_YEAR);
|
|
2597
|
+
referrerStates.set(referrerId, referrerState);
|
|
2598
|
+
}
|
|
2599
|
+
referrerState.totalReferrals += 1;
|
|
2600
|
+
referrerState.totalIncrementalDuration += event.incrementalDuration;
|
|
2601
|
+
referrerState.totalRevenueContribution = addPrices(
|
|
2602
|
+
referrerState.totalRevenueContribution,
|
|
2603
|
+
event.incrementalRevenueContribution
|
|
2604
|
+
);
|
|
2605
|
+
const totalBaseRevenue = calcBaseRevenueContribution(
|
|
2606
|
+
rules,
|
|
2607
|
+
referrerState.totalIncrementalDuration
|
|
2608
|
+
);
|
|
2609
|
+
const isNowQualified = isReferrerQualifiedRevShareCap(referrerId, totalBaseRevenue, rules);
|
|
2610
|
+
if (isNowQualified && !referrerState.hasQualified) {
|
|
2611
|
+
const accumulatedUncappedAward = scalePrice(totalBaseRevenue, rules.maxBaseRevenueShare);
|
|
2612
|
+
const incrementalCappedAward = minPrice(accumulatedUncappedAward, awardPoolRemaining);
|
|
2613
|
+
referrerState.cappedAward = addPrices(referrerState.cappedAward, incrementalCappedAward);
|
|
2614
|
+
awardPoolRemaining = subtractPrice(awardPoolRemaining, incrementalCappedAward);
|
|
2615
|
+
referrerState.hasQualified = true;
|
|
2616
|
+
} else if (referrerState.hasQualified) {
|
|
2617
|
+
const incrementalBaseRevenue = calcBaseRevenueContribution(rules, event.incrementalDuration);
|
|
2522
2618
|
const incrementalUncappedAward = scalePrice(
|
|
2523
|
-
|
|
2619
|
+
incrementalBaseRevenue,
|
|
2524
2620
|
rules.maxBaseRevenueShare
|
|
2525
|
-
)
|
|
2526
|
-
const incrementalCappedAward =
|
|
2527
|
-
|
|
2528
|
-
awardPoolRemaining
|
|
2621
|
+
);
|
|
2622
|
+
const incrementalCappedAward = minPrice(incrementalUncappedAward, awardPoolRemaining);
|
|
2623
|
+
referrerState.cappedAward = addPrices(referrerState.cappedAward, incrementalCappedAward);
|
|
2624
|
+
awardPoolRemaining = subtractPrice(awardPoolRemaining, incrementalCappedAward);
|
|
2529
2625
|
}
|
|
2530
2626
|
}
|
|
2531
|
-
const sortedEntries = [...referrerStates.entries()].sort(
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2627
|
+
const sortedEntries = [...referrerStates.entries()].sort(
|
|
2628
|
+
([referrerIdA, referrerStateA], [referrerIdB, referrerStateB]) => {
|
|
2629
|
+
if (referrerStateB.cappedAward.amount !== referrerStateA.cappedAward.amount) {
|
|
2630
|
+
return referrerStateB.cappedAward.amount > referrerStateA.cappedAward.amount ? 1 : -1;
|
|
2631
|
+
}
|
|
2632
|
+
if (referrerStateB.totalIncrementalDuration !== referrerStateA.totalIncrementalDuration) {
|
|
2633
|
+
return referrerStateB.totalIncrementalDuration - referrerStateA.totalIncrementalDuration;
|
|
2634
|
+
}
|
|
2635
|
+
if (referrerIdB > referrerIdA) return 1;
|
|
2636
|
+
if (referrerIdB < referrerIdA) return -1;
|
|
2637
|
+
return 0;
|
|
2537
2638
|
}
|
|
2538
|
-
|
|
2539
|
-
if (b < a) return -1;
|
|
2540
|
-
return 0;
|
|
2541
|
-
});
|
|
2639
|
+
);
|
|
2542
2640
|
const awardedReferrers = sortedEntries.map(
|
|
2543
|
-
([
|
|
2641
|
+
([referrerId, referrerState], index) => {
|
|
2544
2642
|
const baseMetrics = buildReferrerMetrics(
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2643
|
+
referrerId,
|
|
2644
|
+
referrerState.totalReferrals,
|
|
2645
|
+
referrerState.totalIncrementalDuration,
|
|
2646
|
+
referrerState.totalRevenueContribution
|
|
2549
2647
|
);
|
|
2550
2648
|
const revShareMetrics = buildReferrerMetricsRevShareCap(baseMetrics, rules);
|
|
2551
2649
|
const rankedMetrics = buildRankedReferrerMetricsRevShareCap(
|
|
@@ -2560,14 +2658,14 @@ var buildReferrerLeaderboardRevShareCap = (events, rules, accurateAsOf) => {
|
|
|
2560
2658
|
return buildAwardedReferrerMetricsRevShareCap(
|
|
2561
2659
|
rankedMetrics,
|
|
2562
2660
|
uncappedAward,
|
|
2563
|
-
|
|
2661
|
+
referrerState.cappedAward,
|
|
2564
2662
|
rules
|
|
2565
2663
|
);
|
|
2566
2664
|
}
|
|
2567
2665
|
);
|
|
2568
2666
|
const aggregatedMetrics = buildAggregatedReferrerMetricsRevShareCap(
|
|
2569
2667
|
awardedReferrers,
|
|
2570
|
-
|
|
2668
|
+
awardPoolRemaining
|
|
2571
2669
|
);
|
|
2572
2670
|
const referrers = new Map(awardedReferrers.map((r) => [r.referrer, r]));
|
|
2573
2671
|
return { awardModel: rules.awardModel, rules, aggregatedMetrics, referrers, accurateAsOf };
|
|
@@ -3032,6 +3130,7 @@ export {
|
|
|
3032
3130
|
buildUnrankedReferrerMetricsPieSplit,
|
|
3033
3131
|
buildUnrankedReferrerMetricsRevShareCap,
|
|
3034
3132
|
calcBaseReferralProgramEditionStatus,
|
|
3133
|
+
calcBaseRevenueContribution,
|
|
3035
3134
|
calcReferralProgramEditionStatusPieSplit,
|
|
3036
3135
|
calcReferralProgramEditionStatusRevShareCap,
|
|
3037
3136
|
calcReferrerAwardPoolSharePieSplit,
|
|
@@ -3041,6 +3140,7 @@ export {
|
|
|
3041
3140
|
deserializeReferralProgramEditionSummariesResponse,
|
|
3042
3141
|
deserializeReferrerLeaderboardPageResponse,
|
|
3043
3142
|
deserializeReferrerMetricsEditionsResponse,
|
|
3143
|
+
findOverlappingEditionPair,
|
|
3044
3144
|
getReferrerEditionMetrics,
|
|
3045
3145
|
getReferrerLeaderboardPage,
|
|
3046
3146
|
isFiniteNonNegativeNumber,
|