@namehash/ens-referrals 1.10.0 → 1.10.1

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 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,
@@ -508,6 +509,45 @@ function priceUsdc(amount) {
508
509
  currency: CurrencyIds.USDC
509
510
  };
510
511
  }
512
+ function isPriceCurrencyEqual(priceA, priceB) {
513
+ return priceA.currency === priceB.currency;
514
+ }
515
+ function addPrices(...prices) {
516
+ const firstPrice = prices[0];
517
+ const allPricesInSameCurrency = prices.every((price) => isPriceCurrencyEqual(firstPrice, price));
518
+ if (allPricesInSameCurrency === false) {
519
+ throw new Error("All prices must have the same currency to be added together.");
520
+ }
521
+ const { currency } = firstPrice;
522
+ return prices.reduce(
523
+ (acc, price) => ({
524
+ amount: acc.amount + price.amount,
525
+ currency
526
+ }),
527
+ {
528
+ amount: 0n,
529
+ currency: firstPrice.currency
530
+ }
531
+ );
532
+ }
533
+ function subtractPrice(a, b) {
534
+ if (!isPriceCurrencyEqual(a, b)) {
535
+ throw new Error("All prices must have the same currency to be subtracted.");
536
+ }
537
+ const resultAmount = a.amount - b.amount;
538
+ if (resultAmount < 0n) {
539
+ throw new Error("subtractPrice result must be non-negative.");
540
+ }
541
+ return { amount: resultAmount, currency: a.currency };
542
+ }
543
+ function minPrice(...prices) {
544
+ const firstPrice = prices[0];
545
+ const allPricesInSameCurrency = prices.every((price) => isPriceCurrencyEqual(firstPrice, price));
546
+ if (allPricesInSameCurrency === false) {
547
+ throw new Error("All prices must have the same currency to be compared.");
548
+ }
549
+ return prices.reduce((acc, price) => price.amount < acc.amount ? price : acc);
550
+ }
511
551
  function scalePrice(price, scaleFactor) {
512
552
  const scaledAmount = scaleBigintByNumber(price.amount, scaleFactor);
513
553
  return {
@@ -1062,6 +1102,11 @@ var buildReferralProgramRulesRevShareCap = (awardPool, minBaseRevenueContributio
1062
1102
  validateReferralProgramRulesRevShareCap(result);
1063
1103
  return result;
1064
1104
  };
1105
+ function calcBaseRevenueContribution(rules, duration) {
1106
+ return priceUsdc(
1107
+ rules.baseAnnualRevenueContribution.amount * BigInt(duration) / BigInt(SECONDS_PER_YEAR)
1108
+ );
1109
+ }
1065
1110
  function isReferrerQualifiedRevShareCap(referrer, totalBaseRevenueContribution, rules) {
1066
1111
  const isAdminDisqualified = rules.adminActions.some(
1067
1112
  (a) => a.referrer === referrer && a.actionType === AdminActionTypes.Disqualification
@@ -2420,8 +2465,9 @@ var validateReferrerMetricsRevShareCap = (metrics, rules) => {
2420
2465
  makePriceUsdcSchema("ReferrerMetricsRevShareCap.totalBaseRevenueContribution").parse(
2421
2466
  metrics.totalBaseRevenueContribution
2422
2467
  );
2423
- const expectedTotalBaseRevenueContribution = priceUsdc(
2424
- rules.baseAnnualRevenueContribution.amount * BigInt(metrics.totalIncrementalDuration) / BigInt(SECONDS_PER_YEAR)
2468
+ const expectedTotalBaseRevenueContribution = calcBaseRevenueContribution(
2469
+ rules,
2470
+ metrics.totalIncrementalDuration
2425
2471
  );
2426
2472
  if (metrics.totalBaseRevenueContribution.amount !== expectedTotalBaseRevenueContribution.amount) {
2427
2473
  throw new Error(
@@ -2430,8 +2476,9 @@ var validateReferrerMetricsRevShareCap = (metrics, rules) => {
2430
2476
  }
2431
2477
  };
2432
2478
  var buildReferrerMetricsRevShareCap = (metrics, rules) => {
2433
- const totalBaseRevenueContribution = priceUsdc(
2434
- rules.baseAnnualRevenueContribution.amount * BigInt(metrics.totalIncrementalDuration) / BigInt(SECONDS_PER_YEAR)
2479
+ const totalBaseRevenueContribution = calcBaseRevenueContribution(
2480
+ rules,
2481
+ metrics.totalIncrementalDuration
2435
2482
  );
2436
2483
  const result = {
2437
2484
  ...metrics,
@@ -2605,71 +2652,71 @@ function sortReferralEvents(events) {
2605
2652
  }
2606
2653
 
2607
2654
  // src/award-models/rev-share-cap/leaderboard.ts
2608
- var bigintMin = (a, b) => a < b ? a : b;
2609
2655
  var buildReferrerLeaderboardRevShareCap = (events, rules, accurateAsOf) => {
2610
2656
  const sortedEvents = sortReferralEvents(events);
2611
2657
  const referrerStates = /* @__PURE__ */ new Map();
2612
- let awardPoolRemaining = rules.awardPool.amount;
2658
+ let awardPoolRemaining = rules.awardPool;
2613
2659
  for (const event of sortedEvents) {
2614
- const referrer = event.referrer;
2615
- let state = referrerStates.get(referrer);
2616
- if (!state) {
2617
- state = {
2660
+ const referrerId = event.referrer;
2661
+ let referrerState = referrerStates.get(referrerId);
2662
+ if (!referrerState) {
2663
+ referrerState = {
2618
2664
  totalReferrals: 0,
2619
2665
  totalIncrementalDuration: 0,
2620
- totalRevenueContributionAmount: 0n,
2621
- wasQualified: false,
2622
- cappedAwardAmount: 0n
2666
+ totalRevenueContribution: priceEth(0n),
2667
+ hasQualified: false,
2668
+ cappedAward: priceUsdc(0n)
2623
2669
  };
2624
- referrerStates.set(referrer, state);
2670
+ referrerStates.set(referrerId, referrerState);
2625
2671
  }
2626
- state.totalReferrals += 1;
2627
- state.totalIncrementalDuration += event.incrementalDuration;
2628
- state.totalRevenueContributionAmount += event.incrementalRevenueContribution.amount;
2629
- const totalBaseRevenueAmount = rules.baseAnnualRevenueContribution.amount * BigInt(state.totalIncrementalDuration) / BigInt(SECONDS_PER_YEAR);
2630
- const isNowQualified = isReferrerQualifiedRevShareCap(
2631
- referrer,
2632
- priceUsdc(totalBaseRevenueAmount),
2633
- rules
2634
- );
2635
- if (isNowQualified && !state.wasQualified) {
2636
- const accumulatedUncappedAward = scalePrice(
2637
- priceUsdc(totalBaseRevenueAmount),
2638
- rules.maxBaseRevenueShare
2639
- ).amount;
2640
- const incrementalCappedAward = bigintMin(accumulatedUncappedAward, awardPoolRemaining);
2641
- state.cappedAwardAmount += incrementalCappedAward;
2642
- awardPoolRemaining -= incrementalCappedAward;
2643
- state.wasQualified = true;
2644
- } else if (state.wasQualified) {
2645
- const incrementalBaseRevenueAmount = rules.baseAnnualRevenueContribution.amount * BigInt(event.incrementalDuration) / BigInt(SECONDS_PER_YEAR);
2672
+ referrerState.totalReferrals += 1;
2673
+ referrerState.totalIncrementalDuration += event.incrementalDuration;
2674
+ referrerState.totalRevenueContribution = addPrices(
2675
+ referrerState.totalRevenueContribution,
2676
+ event.incrementalRevenueContribution
2677
+ );
2678
+ const totalBaseRevenue = calcBaseRevenueContribution(
2679
+ rules,
2680
+ referrerState.totalIncrementalDuration
2681
+ );
2682
+ const isNowQualified = isReferrerQualifiedRevShareCap(referrerId, totalBaseRevenue, rules);
2683
+ if (isNowQualified && !referrerState.hasQualified) {
2684
+ const accumulatedUncappedAward = scalePrice(totalBaseRevenue, rules.maxBaseRevenueShare);
2685
+ const incrementalCappedAward = minPrice(accumulatedUncappedAward, awardPoolRemaining);
2686
+ referrerState.cappedAward = addPrices(referrerState.cappedAward, incrementalCappedAward);
2687
+ awardPoolRemaining = subtractPrice(awardPoolRemaining, incrementalCappedAward);
2688
+ referrerState.hasQualified = true;
2689
+ } else if (referrerState.hasQualified) {
2690
+ const incrementalBaseRevenue = calcBaseRevenueContribution(rules, event.incrementalDuration);
2646
2691
  const incrementalUncappedAward = scalePrice(
2647
- priceUsdc(incrementalBaseRevenueAmount),
2692
+ incrementalBaseRevenue,
2648
2693
  rules.maxBaseRevenueShare
2649
- ).amount;
2650
- const incrementalCappedAward = bigintMin(incrementalUncappedAward, awardPoolRemaining);
2651
- state.cappedAwardAmount += incrementalCappedAward;
2652
- awardPoolRemaining -= incrementalCappedAward;
2694
+ );
2695
+ const incrementalCappedAward = minPrice(incrementalUncappedAward, awardPoolRemaining);
2696
+ referrerState.cappedAward = addPrices(referrerState.cappedAward, incrementalCappedAward);
2697
+ awardPoolRemaining = subtractPrice(awardPoolRemaining, incrementalCappedAward);
2653
2698
  }
2654
2699
  }
2655
- const sortedEntries = [...referrerStates.entries()].sort(([a, stateA], [b, stateB]) => {
2656
- if (stateB.cappedAwardAmount !== stateA.cappedAwardAmount) {
2657
- return stateB.cappedAwardAmount > stateA.cappedAwardAmount ? 1 : -1;
2658
- }
2659
- if (stateB.totalIncrementalDuration !== stateA.totalIncrementalDuration) {
2660
- return stateB.totalIncrementalDuration - stateA.totalIncrementalDuration;
2700
+ const sortedEntries = [...referrerStates.entries()].sort(
2701
+ ([referrerIdA, referrerStateA], [referrerIdB, referrerStateB]) => {
2702
+ if (referrerStateB.cappedAward.amount !== referrerStateA.cappedAward.amount) {
2703
+ return referrerStateB.cappedAward.amount > referrerStateA.cappedAward.amount ? 1 : -1;
2704
+ }
2705
+ if (referrerStateB.totalIncrementalDuration !== referrerStateA.totalIncrementalDuration) {
2706
+ return referrerStateB.totalIncrementalDuration - referrerStateA.totalIncrementalDuration;
2707
+ }
2708
+ if (referrerIdB > referrerIdA) return 1;
2709
+ if (referrerIdB < referrerIdA) return -1;
2710
+ return 0;
2661
2711
  }
2662
- if (b > a) return 1;
2663
- if (b < a) return -1;
2664
- return 0;
2665
- });
2712
+ );
2666
2713
  const awardedReferrers = sortedEntries.map(
2667
- ([referrerAddr, state], index) => {
2714
+ ([referrerId, referrerState], index) => {
2668
2715
  const baseMetrics = buildReferrerMetrics(
2669
- referrerAddr,
2670
- state.totalReferrals,
2671
- state.totalIncrementalDuration,
2672
- priceEth(state.totalRevenueContributionAmount)
2716
+ referrerId,
2717
+ referrerState.totalReferrals,
2718
+ referrerState.totalIncrementalDuration,
2719
+ referrerState.totalRevenueContribution
2673
2720
  );
2674
2721
  const revShareMetrics = buildReferrerMetricsRevShareCap(baseMetrics, rules);
2675
2722
  const rankedMetrics = buildRankedReferrerMetricsRevShareCap(
@@ -2684,14 +2731,14 @@ var buildReferrerLeaderboardRevShareCap = (events, rules, accurateAsOf) => {
2684
2731
  return buildAwardedReferrerMetricsRevShareCap(
2685
2732
  rankedMetrics,
2686
2733
  uncappedAward,
2687
- priceUsdc(state.cappedAwardAmount),
2734
+ referrerState.cappedAward,
2688
2735
  rules
2689
2736
  );
2690
2737
  }
2691
2738
  );
2692
2739
  const aggregatedMetrics = buildAggregatedReferrerMetricsRevShareCap(
2693
2740
  awardedReferrers,
2694
- priceUsdc(awardPoolRemaining)
2741
+ awardPoolRemaining
2695
2742
  );
2696
2743
  const referrers = new Map(awardedReferrers.map((r) => [r.referrer, r]));
2697
2744
  return { awardModel: rules.awardModel, rules, aggregatedMetrics, referrers, accurateAsOf };