@namehash/ens-referrals 1.0.0 → 1.1.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 +492 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +437 -7
- package/dist/index.d.ts +437 -7
- package/dist/index.js +485 -10
- package/dist/index.js.map +1 -1
- package/package.json +10 -5
package/dist/index.cjs
CHANGED
|
@@ -23,55 +23,530 @@ __export(index_exports, {
|
|
|
23
23
|
ENCODED_REFERRER_BYTE_LENGTH: () => ENCODED_REFERRER_BYTE_LENGTH,
|
|
24
24
|
ENCODED_REFERRER_BYTE_OFFSET: () => ENCODED_REFERRER_BYTE_OFFSET,
|
|
25
25
|
ENS_HOLIDAY_AWARDS_END_DATE: () => ENS_HOLIDAY_AWARDS_END_DATE,
|
|
26
|
+
ENS_HOLIDAY_AWARDS_MAX_QUALIFIED_REFERRERS: () => ENS_HOLIDAY_AWARDS_MAX_QUALIFIED_REFERRERS,
|
|
26
27
|
ENS_HOLIDAY_AWARDS_START_DATE: () => ENS_HOLIDAY_AWARDS_START_DATE,
|
|
28
|
+
ENS_HOLIDAY_AWARDS_TOTAL_AWARD_POOL_VALUE: () => ENS_HOLIDAY_AWARDS_TOTAL_AWARD_POOL_VALUE,
|
|
29
|
+
EXPECTED_ENCODED_REFERRER_PADDING: () => EXPECTED_ENCODED_REFERRER_PADDING,
|
|
30
|
+
REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT: () => REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT,
|
|
31
|
+
REFERRERS_PER_LEADERBOARD_PAGE_MAX: () => REFERRERS_PER_LEADERBOARD_PAGE_MAX,
|
|
32
|
+
SECONDS_PER_YEAR: () => SECONDS_PER_YEAR,
|
|
33
|
+
ZERO_ENCODED_REFERRER: () => ZERO_ENCODED_REFERRER,
|
|
34
|
+
buildAggregatedReferrerMetrics: () => buildAggregatedReferrerMetrics,
|
|
35
|
+
buildAwardedReferrerMetrics: () => buildAwardedReferrerMetrics,
|
|
27
36
|
buildEncodedReferrer: () => buildEncodedReferrer,
|
|
28
37
|
buildEnsReferralUrl: () => buildEnsReferralUrl,
|
|
38
|
+
buildRankedReferrerMetrics: () => buildRankedReferrerMetrics,
|
|
39
|
+
buildReferralProgramRules: () => buildReferralProgramRules,
|
|
40
|
+
buildReferrerLeaderboard: () => buildReferrerLeaderboard,
|
|
41
|
+
buildReferrerLeaderboardPaginationContext: () => buildReferrerLeaderboardPaginationContext,
|
|
42
|
+
buildReferrerLeaderboardPaginationParams: () => buildReferrerLeaderboardPaginationParams,
|
|
43
|
+
buildReferrerMetrics: () => buildReferrerMetrics,
|
|
44
|
+
buildScoredReferrerMetrics: () => buildScoredReferrerMetrics,
|
|
45
|
+
calcReferrerAwardPoolShare: () => calcReferrerAwardPoolShare,
|
|
46
|
+
calcReferrerFinalScore: () => calcReferrerFinalScore,
|
|
47
|
+
calcReferrerFinalScoreBoost: () => calcReferrerFinalScoreBoost,
|
|
48
|
+
calcReferrerFinalScoreMultiplier: () => calcReferrerFinalScoreMultiplier,
|
|
49
|
+
calcReferrerScore: () => calcReferrerScore,
|
|
50
|
+
compareReferrerMetrics: () => compareReferrerMetrics,
|
|
29
51
|
decodeEncodedReferrer: () => decodeEncodedReferrer,
|
|
30
|
-
|
|
31
|
-
|
|
52
|
+
getReferrerLeaderboardPage: () => getReferrerLeaderboardPage,
|
|
53
|
+
isFiniteNonNegativeNumber: () => isFiniteNonNegativeNumber,
|
|
54
|
+
isInteger: () => isInteger,
|
|
55
|
+
isNonNegativeInteger: () => isNonNegativeInteger,
|
|
56
|
+
isPositiveInteger: () => isPositiveInteger,
|
|
57
|
+
isReferrerQualified: () => isReferrerQualified,
|
|
58
|
+
isValidDuration: () => isValidDuration,
|
|
59
|
+
isValidReferrerScore: () => isValidReferrerScore,
|
|
60
|
+
isValidUSDQuantity: () => isValidUSDQuantity,
|
|
61
|
+
normalizeAddress: () => normalizeAddress,
|
|
62
|
+
sortReferrerMetrics: () => sortReferrerMetrics,
|
|
63
|
+
validateAggregatedReferrerMetrics: () => validateAggregatedReferrerMetrics,
|
|
64
|
+
validateAwardedReferrerMetrics: () => validateAwardedReferrerMetrics,
|
|
65
|
+
validateDuration: () => validateDuration,
|
|
66
|
+
validateLowercaseAddress: () => validateLowercaseAddress,
|
|
67
|
+
validateNonNegativeInteger: () => validateNonNegativeInteger,
|
|
68
|
+
validateRankedReferrerMetrics: () => validateRankedReferrerMetrics,
|
|
69
|
+
validateReferralProgramRules: () => validateReferralProgramRules,
|
|
70
|
+
validateReferrerLeaderboardPaginationContext: () => validateReferrerLeaderboardPaginationContext,
|
|
71
|
+
validateReferrerMetrics: () => validateReferrerMetrics,
|
|
72
|
+
validateReferrerRank: () => validateReferrerRank,
|
|
73
|
+
validateReferrerScore: () => validateReferrerScore,
|
|
74
|
+
validateScoredReferrerMetrics: () => validateScoredReferrerMetrics,
|
|
75
|
+
validateUSDQuantity: () => validateUSDQuantity,
|
|
76
|
+
validateUnixTimestamp: () => validateUnixTimestamp
|
|
32
77
|
});
|
|
33
78
|
module.exports = __toCommonJS(index_exports);
|
|
34
79
|
|
|
35
|
-
// src/
|
|
36
|
-
var ENS_HOLIDAY_AWARDS_START_DATE = 1764547200;
|
|
37
|
-
var ENS_HOLIDAY_AWARDS_END_DATE = 1767225599;
|
|
38
|
-
|
|
39
|
-
// src/referrer.ts
|
|
80
|
+
// src/address.ts
|
|
40
81
|
var import_viem = require("viem");
|
|
82
|
+
var validateLowercaseAddress = (address) => {
|
|
83
|
+
if (!(0, import_viem.isAddress)(address, { strict: false })) {
|
|
84
|
+
throw new Error(`Invalid address: ${address}. Address must be a valid EVM address.`);
|
|
85
|
+
}
|
|
86
|
+
if (address !== address.toLowerCase()) {
|
|
87
|
+
throw new Error(`Invalid address: ${address}. Address must be in lowercase format.`);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
var normalizeAddress = (address) => {
|
|
91
|
+
return address.toLowerCase();
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// src/number.ts
|
|
95
|
+
var isInteger = (value) => {
|
|
96
|
+
return Number.isInteger(value);
|
|
97
|
+
};
|
|
98
|
+
var isNonNegativeInteger = (value) => {
|
|
99
|
+
return value >= 0 && Number.isInteger(value);
|
|
100
|
+
};
|
|
101
|
+
var isPositiveInteger = (value) => {
|
|
102
|
+
return value >= 1 && Number.isInteger(value);
|
|
103
|
+
};
|
|
104
|
+
var validateNonNegativeInteger = (value) => {
|
|
105
|
+
if (!isNonNegativeInteger(value)) {
|
|
106
|
+
throw new Error(`Invalid non-negative integer: ${value}.`);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var isFiniteNonNegativeNumber = (value) => {
|
|
110
|
+
return value >= 0 && Number.isFinite(value);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// src/time.ts
|
|
114
|
+
var validateUnixTimestamp = (timestamp) => {
|
|
115
|
+
if (!isInteger(timestamp)) {
|
|
116
|
+
throw new Error(`Invalid Unix timestamp: ${timestamp}. Unix timestamp must be an integer.`);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
var SECONDS_PER_YEAR = 31556952;
|
|
120
|
+
function isValidDuration(duration) {
|
|
121
|
+
return isNonNegativeInteger(duration);
|
|
122
|
+
}
|
|
123
|
+
function validateDuration(duration) {
|
|
124
|
+
if (!isValidDuration(duration)) {
|
|
125
|
+
throw new Error(`Invalid duration: ${duration}. Duration must be a non-negative integer.`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// src/score.ts
|
|
130
|
+
var isValidReferrerScore = (score) => {
|
|
131
|
+
return score >= 0 && Number.isFinite(score);
|
|
132
|
+
};
|
|
133
|
+
var validateReferrerScore = (score) => {
|
|
134
|
+
if (!isValidReferrerScore(score)) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`Invalid referrer score: ${score}. Referrer score must be a finite non-negative number.`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var calcReferrerScore = (totalIncrementalDuration) => {
|
|
141
|
+
return totalIncrementalDuration / SECONDS_PER_YEAR;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// src/aggregations.ts
|
|
145
|
+
var validateAggregatedReferrerMetrics = (metrics) => {
|
|
146
|
+
validateNonNegativeInteger(metrics.grandTotalReferrals);
|
|
147
|
+
validateDuration(metrics.grandTotalIncrementalDuration);
|
|
148
|
+
validateReferrerScore(metrics.grandTotalQualifiedReferrersFinalScore);
|
|
149
|
+
validateReferrerScore(metrics.minFinalScoreToQualify);
|
|
150
|
+
};
|
|
151
|
+
var buildAggregatedReferrerMetrics = (referrers, rules) => {
|
|
152
|
+
let grandTotalReferrals = 0;
|
|
153
|
+
let grandTotalIncrementalDuration = 0;
|
|
154
|
+
let grandTotalQualifiedReferrersFinalScore = 0;
|
|
155
|
+
let minFinalScoreToQualify = Number.MAX_SAFE_INTEGER;
|
|
156
|
+
for (const referrer of referrers) {
|
|
157
|
+
grandTotalReferrals += referrer.totalReferrals;
|
|
158
|
+
grandTotalIncrementalDuration += referrer.totalIncrementalDuration;
|
|
159
|
+
if (referrer.isQualified) {
|
|
160
|
+
grandTotalQualifiedReferrersFinalScore += referrer.finalScore;
|
|
161
|
+
if (referrer.finalScore < minFinalScoreToQualify) {
|
|
162
|
+
minFinalScoreToQualify = referrer.finalScore;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (minFinalScoreToQualify === Number.MAX_SAFE_INTEGER) {
|
|
167
|
+
if (rules.maxQualifiedReferrers === 0) {
|
|
168
|
+
} else {
|
|
169
|
+
if (referrers.length !== 0) {
|
|
170
|
+
throw new Error(
|
|
171
|
+
"AggregatedReferrerMetrics: There are referrers on the leaderboard, and the rules allow for qualified referrers, but no qualified referrers."
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
minFinalScoreToQualify = 0;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const result = {
|
|
178
|
+
grandTotalReferrals,
|
|
179
|
+
grandTotalIncrementalDuration,
|
|
180
|
+
grandTotalQualifiedReferrersFinalScore,
|
|
181
|
+
minFinalScoreToQualify
|
|
182
|
+
};
|
|
183
|
+
validateAggregatedReferrerMetrics(result);
|
|
184
|
+
return result;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// src/currency.ts
|
|
188
|
+
function isValidUSDQuantity(value) {
|
|
189
|
+
return isFiniteNonNegativeNumber(value);
|
|
190
|
+
}
|
|
191
|
+
function validateUSDQuantity(value) {
|
|
192
|
+
if (!isValidUSDQuantity(value)) {
|
|
193
|
+
throw new Error(`Invalid USD quantity: ${value}.`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// src/encoding.ts
|
|
198
|
+
var import_viem2 = require("viem");
|
|
41
199
|
var ENCODED_REFERRER_BYTE_OFFSET = 12;
|
|
42
200
|
var ENCODED_REFERRER_BYTE_LENGTH = 32;
|
|
43
|
-
var
|
|
201
|
+
var EXPECTED_ENCODED_REFERRER_PADDING = (0, import_viem2.pad)("0x", {
|
|
44
202
|
size: ENCODED_REFERRER_BYTE_OFFSET,
|
|
45
203
|
dir: "left"
|
|
46
204
|
});
|
|
47
|
-
var
|
|
205
|
+
var ZERO_ENCODED_REFERRER = (0, import_viem2.pad)("0x", {
|
|
48
206
|
size: ENCODED_REFERRER_BYTE_LENGTH,
|
|
49
207
|
dir: "left"
|
|
50
208
|
});
|
|
51
209
|
function buildEncodedReferrer(address) {
|
|
52
210
|
const lowercaseAddress = address.toLowerCase();
|
|
53
|
-
return (0,
|
|
211
|
+
return (0, import_viem2.pad)(lowercaseAddress, { size: ENCODED_REFERRER_BYTE_LENGTH, dir: "left" });
|
|
54
212
|
}
|
|
55
213
|
function decodeEncodedReferrer(encodedReferrer) {
|
|
56
|
-
if ((0,
|
|
214
|
+
if ((0, import_viem2.size)(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) {
|
|
57
215
|
throw new Error(
|
|
58
216
|
`Encoded referrer value must be represented by ${ENCODED_REFERRER_BYTE_LENGTH} bytes.`
|
|
59
217
|
);
|
|
60
218
|
}
|
|
61
|
-
const padding = (0,
|
|
62
|
-
if (padding !==
|
|
63
|
-
return
|
|
219
|
+
const padding = (0, import_viem2.slice)(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET);
|
|
220
|
+
if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) {
|
|
221
|
+
return import_viem2.zeroAddress;
|
|
64
222
|
}
|
|
65
|
-
const decodedReferrer = (0,
|
|
223
|
+
const decodedReferrer = (0, import_viem2.slice)(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET);
|
|
66
224
|
try {
|
|
67
|
-
return (0,
|
|
225
|
+
return (0, import_viem2.getAddress)(decodedReferrer);
|
|
68
226
|
} catch {
|
|
69
227
|
throw new Error(`Decoded referrer value must be a valid EVM address.`);
|
|
70
228
|
}
|
|
71
229
|
}
|
|
230
|
+
|
|
231
|
+
// src/rank.ts
|
|
232
|
+
var validateReferrerRank = (rank) => {
|
|
233
|
+
if (!isPositiveInteger(rank)) {
|
|
234
|
+
throw new Error(`Invalid ReferrerRank: ${rank}. ReferrerRank must be a positive integer.`);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
function isReferrerQualified(rank, rules) {
|
|
238
|
+
return rank <= rules.maxQualifiedReferrers;
|
|
239
|
+
}
|
|
240
|
+
function calcReferrerFinalScoreBoost(rank, rules) {
|
|
241
|
+
if (!isReferrerQualified(rank, rules)) return 0;
|
|
242
|
+
return 1 - (rank - 1) / (rules.maxQualifiedReferrers - 1);
|
|
243
|
+
}
|
|
244
|
+
function calcReferrerFinalScoreMultiplier(rank, rules) {
|
|
245
|
+
return 1 + calcReferrerFinalScoreBoost(rank, rules);
|
|
246
|
+
}
|
|
247
|
+
function calcReferrerFinalScore(rank, totalIncrementalDuration, rules) {
|
|
248
|
+
return calcReferrerScore(totalIncrementalDuration) * calcReferrerFinalScoreMultiplier(rank, rules);
|
|
249
|
+
}
|
|
250
|
+
var compareReferrerMetrics = (a, b) => {
|
|
251
|
+
if (a.totalIncrementalDuration !== b.totalIncrementalDuration) {
|
|
252
|
+
return b.totalIncrementalDuration - a.totalIncrementalDuration;
|
|
253
|
+
}
|
|
254
|
+
if (b.referrer > a.referrer) return 1;
|
|
255
|
+
if (b.referrer < a.referrer) return -1;
|
|
256
|
+
return 0;
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
// src/referrer-metrics.ts
|
|
260
|
+
var buildReferrerMetrics = (referrer, totalReferrals, totalIncrementalDuration) => {
|
|
261
|
+
const result = {
|
|
262
|
+
referrer: normalizeAddress(referrer),
|
|
263
|
+
totalReferrals,
|
|
264
|
+
totalIncrementalDuration
|
|
265
|
+
};
|
|
266
|
+
validateReferrerMetrics(result);
|
|
267
|
+
return result;
|
|
268
|
+
};
|
|
269
|
+
var validateReferrerMetrics = (metrics) => {
|
|
270
|
+
validateLowercaseAddress(metrics.referrer);
|
|
271
|
+
validateNonNegativeInteger(metrics.totalReferrals);
|
|
272
|
+
validateDuration(metrics.totalIncrementalDuration);
|
|
273
|
+
};
|
|
274
|
+
var sortReferrerMetrics = (referrers) => {
|
|
275
|
+
return [...referrers].sort(compareReferrerMetrics);
|
|
276
|
+
};
|
|
277
|
+
var buildScoredReferrerMetrics = (referrer) => {
|
|
278
|
+
const result = {
|
|
279
|
+
...referrer,
|
|
280
|
+
score: calcReferrerScore(referrer.totalIncrementalDuration)
|
|
281
|
+
};
|
|
282
|
+
validateScoredReferrerMetrics(result);
|
|
283
|
+
return result;
|
|
284
|
+
};
|
|
285
|
+
var validateScoredReferrerMetrics = (metrics) => {
|
|
286
|
+
validateReferrerMetrics(metrics);
|
|
287
|
+
validateReferrerScore(metrics.score);
|
|
288
|
+
const expectedScore = calcReferrerScore(metrics.totalIncrementalDuration);
|
|
289
|
+
if (metrics.score !== expectedScore) {
|
|
290
|
+
throw new Error(`Referrer: Invalid score: ${metrics.score}, expected: ${expectedScore}.`);
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
var validateRankedReferrerMetrics = (metrics, rules) => {
|
|
294
|
+
validateScoredReferrerMetrics(metrics);
|
|
295
|
+
validateReferrerRank(metrics.rank);
|
|
296
|
+
if (metrics.finalScoreBoost < 0 || metrics.finalScoreBoost > 1) {
|
|
297
|
+
throw new Error(
|
|
298
|
+
`Invalid RankedReferrerMetrics: Invalid finalScoreBoost: ${metrics.finalScoreBoost}. finalScoreBoost must be between 0 and 1 (inclusive).`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
validateReferrerScore(metrics.finalScore);
|
|
302
|
+
const expectedIsQualified = isReferrerQualified(metrics.rank, rules);
|
|
303
|
+
if (metrics.isQualified !== expectedIsQualified) {
|
|
304
|
+
throw new Error(
|
|
305
|
+
`RankedReferrerMetrics: Invalid isQualified: ${metrics.isQualified}, expected: ${expectedIsQualified}.`
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
const expectedFinalScoreBoost = calcReferrerFinalScoreBoost(metrics.rank, rules);
|
|
309
|
+
if (metrics.finalScoreBoost !== expectedFinalScoreBoost) {
|
|
310
|
+
throw new Error(
|
|
311
|
+
`RankedReferrerMetrics: Invalid finalScoreBoost: ${metrics.finalScoreBoost}, expected: ${expectedFinalScoreBoost}.`
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
const expectedFinalScore = calcReferrerFinalScore(
|
|
315
|
+
metrics.rank,
|
|
316
|
+
metrics.totalIncrementalDuration,
|
|
317
|
+
rules
|
|
318
|
+
);
|
|
319
|
+
if (metrics.finalScore !== expectedFinalScore) {
|
|
320
|
+
throw new Error(
|
|
321
|
+
`RankedReferrerMetrics: Invalid finalScore: ${metrics.finalScore}, expected: ${expectedFinalScore}.`
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
var buildRankedReferrerMetrics = (referrer, rank, rules) => {
|
|
326
|
+
const result = {
|
|
327
|
+
...referrer,
|
|
328
|
+
rank,
|
|
329
|
+
isQualified: isReferrerQualified(rank, rules),
|
|
330
|
+
finalScoreBoost: calcReferrerFinalScoreBoost(rank, rules),
|
|
331
|
+
finalScore: calcReferrerFinalScore(rank, referrer.totalIncrementalDuration, rules)
|
|
332
|
+
};
|
|
333
|
+
validateRankedReferrerMetrics(result, rules);
|
|
334
|
+
return result;
|
|
335
|
+
};
|
|
336
|
+
var calcReferrerAwardPoolShare = (referrer, aggregatedMetrics, rules) => {
|
|
337
|
+
if (!isReferrerQualified(referrer.rank, rules)) return 0;
|
|
338
|
+
if (aggregatedMetrics.grandTotalQualifiedReferrersFinalScore === 0) return 0;
|
|
339
|
+
return calcReferrerFinalScore(referrer.rank, referrer.totalIncrementalDuration, rules) / aggregatedMetrics.grandTotalQualifiedReferrersFinalScore;
|
|
340
|
+
};
|
|
341
|
+
var validateAwardedReferrerMetrics = (referrer, rules) => {
|
|
342
|
+
validateRankedReferrerMetrics(referrer, rules);
|
|
343
|
+
if (referrer.awardPoolShare < 0 || referrer.awardPoolShare > 1) {
|
|
344
|
+
throw new Error(
|
|
345
|
+
`Invalid AwardedReferrerMetrics: ${referrer.awardPoolShare}. awardPoolShare must be between 0 and 1 (inclusive).`
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
if (referrer.awardPoolApproxValue < 0 || referrer.awardPoolApproxValue > rules.totalAwardPoolValue) {
|
|
349
|
+
throw new Error(
|
|
350
|
+
`Invalid AwardedReferrerMetrics: ${referrer.awardPoolApproxValue}. awardPoolApproxValue must be between 0 and ${rules.totalAwardPoolValue} (inclusive).`
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
var buildAwardedReferrerMetrics = (referrer, aggregatedMetrics, rules) => {
|
|
355
|
+
const awardPoolShare = calcReferrerAwardPoolShare(referrer, aggregatedMetrics, rules);
|
|
356
|
+
const result = {
|
|
357
|
+
...referrer,
|
|
358
|
+
awardPoolShare,
|
|
359
|
+
awardPoolApproxValue: awardPoolShare * rules.totalAwardPoolValue
|
|
360
|
+
};
|
|
361
|
+
validateAwardedReferrerMetrics(result, rules);
|
|
362
|
+
return result;
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
// src/leaderboard.ts
|
|
366
|
+
var buildReferrerLeaderboard = (allReferrers, rules, accurateAsOf) => {
|
|
367
|
+
const uniqueReferrers = allReferrers.map((referrer) => referrer.referrer);
|
|
368
|
+
if (uniqueReferrers.length !== allReferrers.length) {
|
|
369
|
+
throw new Error(
|
|
370
|
+
"ReferrerLeaderboard: Cannot buildReferrerLeaderboard containing duplicate referrers"
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
if (accurateAsOf < rules.startTime && allReferrers.length > 0) {
|
|
374
|
+
throw new Error(
|
|
375
|
+
`ReferrerLeaderboard: accurateAsOf (${accurateAsOf}) is before startTime (${rules.startTime}) which indicates allReferrers should be empty, but allReferrers is not empty.`
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
const sortedReferrers = sortReferrerMetrics(allReferrers);
|
|
379
|
+
const scoredReferrers = sortedReferrers.map((referrer) => buildScoredReferrerMetrics(referrer));
|
|
380
|
+
const rankedReferrers = scoredReferrers.map((referrer, index) => {
|
|
381
|
+
return buildRankedReferrerMetrics(referrer, index + 1, rules);
|
|
382
|
+
});
|
|
383
|
+
const aggregatedMetrics = buildAggregatedReferrerMetrics(rankedReferrers, rules);
|
|
384
|
+
const awardedReferrers = rankedReferrers.map((referrer) => {
|
|
385
|
+
return buildAwardedReferrerMetrics(referrer, aggregatedMetrics, rules);
|
|
386
|
+
});
|
|
387
|
+
const referrers = new Map(
|
|
388
|
+
awardedReferrers.map((referrer) => {
|
|
389
|
+
return [referrer.referrer, referrer];
|
|
390
|
+
})
|
|
391
|
+
);
|
|
392
|
+
return {
|
|
393
|
+
rules,
|
|
394
|
+
aggregatedMetrics,
|
|
395
|
+
referrers,
|
|
396
|
+
accurateAsOf
|
|
397
|
+
};
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
// src/leaderboard-page.ts
|
|
401
|
+
var REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT = 25;
|
|
402
|
+
var REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;
|
|
403
|
+
var validateReferrerLeaderboardPaginationParams = (params) => {
|
|
404
|
+
if (params.page !== void 0 && !isPositiveInteger(params.page)) {
|
|
405
|
+
throw new Error(
|
|
406
|
+
`Invalid ReferrerLeaderboardPaginationParams: ${params.page}. page must be a positive integer.`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
if (params.itemsPerPage !== void 0 && !isPositiveInteger(params.itemsPerPage)) {
|
|
410
|
+
throw new Error(
|
|
411
|
+
`Invalid ReferrerLeaderboardPaginationParams: ${params.itemsPerPage}. itemsPerPage must be a positive integer.`
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
if (params.itemsPerPage !== void 0 && params.itemsPerPage > REFERRERS_PER_LEADERBOARD_PAGE_MAX) {
|
|
415
|
+
throw new Error(
|
|
416
|
+
`Invalid ReferrerLeaderboardPaginationParams: ${params.itemsPerPage}. itemsPerPage must be less than or equal to ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}.`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
var buildReferrerLeaderboardPaginationParams = (params) => {
|
|
421
|
+
const result = {
|
|
422
|
+
page: params.page ?? 1,
|
|
423
|
+
itemsPerPage: params.itemsPerPage ?? REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT
|
|
424
|
+
};
|
|
425
|
+
validateReferrerLeaderboardPaginationParams(result);
|
|
426
|
+
return result;
|
|
427
|
+
};
|
|
428
|
+
var validateReferrerLeaderboardPaginationContext = (context) => {
|
|
429
|
+
validateReferrerLeaderboardPaginationParams(context);
|
|
430
|
+
if (!isNonNegativeInteger(context.totalRecords)) {
|
|
431
|
+
throw new Error(
|
|
432
|
+
`Invalid ReferrerLeaderboardPaginationContext: total must be a non-negative integer but is ${context.totalRecords}.`
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
const startIndex = (context.page - 1) * context.itemsPerPage;
|
|
436
|
+
const endIndex = startIndex + context.itemsPerPage;
|
|
437
|
+
if (!context.hasNext && endIndex < context.totalRecords) {
|
|
438
|
+
throw new Error(
|
|
439
|
+
`Invalid ReferrerLeaderboardPaginationContext: if hasNext is false, endIndex (${endIndex}) must be greater than or equal to total (${context.totalRecords}).`
|
|
440
|
+
);
|
|
441
|
+
} else if (context.hasNext && context.page * context.itemsPerPage >= context.totalRecords) {
|
|
442
|
+
throw new Error(
|
|
443
|
+
`Invalid ReferrerLeaderboardPaginationContext: if hasNext is true, endIndex (${endIndex}) must be less than total (${context.totalRecords}).`
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
if (!context.hasPrev && context.page !== 1) {
|
|
447
|
+
throw new Error(
|
|
448
|
+
`Invalid ReferrerLeaderboardPaginationContext: if hasPrev is false, page must be the first page (1) but is ${context.page}.`
|
|
449
|
+
);
|
|
450
|
+
} else if (context.hasPrev && context.page === 1) {
|
|
451
|
+
throw new Error(
|
|
452
|
+
`Invalid ReferrerLeaderboardPaginationContext: if hasPrev is true, page must not be the first page (1) but is ${context.page}.`
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
var buildReferrerLeaderboardPaginationContext = (optionalParams, leaderboard) => {
|
|
457
|
+
const materializedParams = buildReferrerLeaderboardPaginationParams(optionalParams);
|
|
458
|
+
const totalRecords = leaderboard.referrers.size;
|
|
459
|
+
const totalPages = Math.max(1, Math.ceil(totalRecords / materializedParams.itemsPerPage));
|
|
460
|
+
if (materializedParams.page > totalPages) {
|
|
461
|
+
throw new Error(
|
|
462
|
+
`Invalid ReferrerLeaderboardPaginationContext: page ${materializedParams.page} exceeds total pages ${totalPages}.`
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
if (totalRecords === 0) {
|
|
466
|
+
return {
|
|
467
|
+
...materializedParams,
|
|
468
|
+
totalRecords: 0,
|
|
469
|
+
totalPages: 1,
|
|
470
|
+
hasNext: false,
|
|
471
|
+
hasPrev: false,
|
|
472
|
+
startIndex: void 0,
|
|
473
|
+
endIndex: void 0
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
const startIndex = (materializedParams.page - 1) * materializedParams.itemsPerPage;
|
|
477
|
+
const maxTheoreticalIndexOnPage = startIndex + (materializedParams.itemsPerPage - 1);
|
|
478
|
+
const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);
|
|
479
|
+
const hasNext = maxTheoreticalIndexOnPage < totalRecords;
|
|
480
|
+
const hasPrev = materializedParams.page > 1;
|
|
481
|
+
const result = {
|
|
482
|
+
...materializedParams,
|
|
483
|
+
totalRecords,
|
|
484
|
+
totalPages,
|
|
485
|
+
hasNext,
|
|
486
|
+
hasPrev,
|
|
487
|
+
startIndex,
|
|
488
|
+
endIndex
|
|
489
|
+
};
|
|
490
|
+
validateReferrerLeaderboardPaginationContext(result);
|
|
491
|
+
return result;
|
|
492
|
+
};
|
|
493
|
+
var getReferrerLeaderboardPage = (paginationParams, leaderboard) => {
|
|
494
|
+
const paginationContext = buildReferrerLeaderboardPaginationContext(
|
|
495
|
+
paginationParams,
|
|
496
|
+
leaderboard
|
|
497
|
+
);
|
|
498
|
+
let referrers;
|
|
499
|
+
if (paginationContext.totalRecords > 0 && typeof paginationContext.startIndex !== "undefined" && typeof paginationContext.endIndex !== "undefined") {
|
|
500
|
+
referrers = Array.from(leaderboard.referrers.values()).slice(
|
|
501
|
+
paginationContext.startIndex,
|
|
502
|
+
paginationContext.endIndex + 1
|
|
503
|
+
// For `slice`, this is exclusive of the element at the index 'end'. We need it to be inclusive, hence plus one.
|
|
504
|
+
);
|
|
505
|
+
} else {
|
|
506
|
+
referrers = [];
|
|
507
|
+
}
|
|
508
|
+
return {
|
|
509
|
+
rules: leaderboard.rules,
|
|
510
|
+
referrers,
|
|
511
|
+
aggregatedMetrics: leaderboard.aggregatedMetrics,
|
|
512
|
+
paginationContext,
|
|
513
|
+
accurateAsOf: leaderboard.accurateAsOf
|
|
514
|
+
};
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
// src/link.ts
|
|
518
|
+
var import_viem3 = require("viem");
|
|
72
519
|
function buildEnsReferralUrl(address) {
|
|
73
520
|
const ensAppUrl = new URL("https://app.ens.domains");
|
|
74
|
-
ensAppUrl.searchParams.set("referrer", (0,
|
|
521
|
+
ensAppUrl.searchParams.set("referrer", (0, import_viem3.getAddress)(address));
|
|
75
522
|
return ensAppUrl;
|
|
76
523
|
}
|
|
524
|
+
|
|
525
|
+
// src/rules.ts
|
|
526
|
+
var ENS_HOLIDAY_AWARDS_START_DATE = 1764547200;
|
|
527
|
+
var ENS_HOLIDAY_AWARDS_END_DATE = 1767225599;
|
|
528
|
+
var ENS_HOLIDAY_AWARDS_MAX_QUALIFIED_REFERRERS = 10;
|
|
529
|
+
var ENS_HOLIDAY_AWARDS_TOTAL_AWARD_POOL_VALUE = 1e4;
|
|
530
|
+
var validateReferralProgramRules = (rules) => {
|
|
531
|
+
validateUSDQuantity(rules.totalAwardPoolValue);
|
|
532
|
+
validateNonNegativeInteger(rules.maxQualifiedReferrers);
|
|
533
|
+
validateUnixTimestamp(rules.startTime);
|
|
534
|
+
validateUnixTimestamp(rules.endTime);
|
|
535
|
+
if (rules.endTime < rules.startTime) {
|
|
536
|
+
throw new Error(
|
|
537
|
+
`ReferralProgramRules: startTime: ${rules.startTime} is after endTime: ${rules.endTime}.`
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
var buildReferralProgramRules = (totalAwardPoolValue, maxQualifiedReferrers, startTime, endTime, subregistryId) => {
|
|
542
|
+
const result = {
|
|
543
|
+
totalAwardPoolValue,
|
|
544
|
+
maxQualifiedReferrers,
|
|
545
|
+
startTime,
|
|
546
|
+
endTime,
|
|
547
|
+
subregistryId
|
|
548
|
+
};
|
|
549
|
+
validateReferralProgramRules(result);
|
|
550
|
+
return result;
|
|
551
|
+
};
|
|
77
552
|
//# sourceMappingURL=index.cjs.map
|