@namehash/ens-referrals 1.5.1 → 1.7.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 CHANGED
@@ -20,22 +20,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- ENCODED_REFERRER_BYTE_LENGTH: () => ENCODED_REFERRER_BYTE_LENGTH,
24
- ENCODED_REFERRER_BYTE_OFFSET: () => ENCODED_REFERRER_BYTE_OFFSET,
23
+ DEFAULT_ENSNODE_API_URL: () => DEFAULT_ENSNODE_API_URL,
24
+ ENSReferralsClient: () => ENSReferralsClient,
25
25
  ENS_HOLIDAY_AWARDS_END_DATE: () => ENS_HOLIDAY_AWARDS_END_DATE,
26
26
  ENS_HOLIDAY_AWARDS_MAX_QUALIFIED_REFERRERS: () => ENS_HOLIDAY_AWARDS_MAX_QUALIFIED_REFERRERS,
27
27
  ENS_HOLIDAY_AWARDS_START_DATE: () => ENS_HOLIDAY_AWARDS_START_DATE,
28
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
29
  REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT: () => REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT,
31
30
  REFERRERS_PER_LEADERBOARD_PAGE_MAX: () => REFERRERS_PER_LEADERBOARD_PAGE_MAX,
32
31
  ReferralProgramStatuses: () => ReferralProgramStatuses,
32
+ ReferrerDetailResponseCodes: () => ReferrerDetailResponseCodes,
33
33
  ReferrerDetailTypeIds: () => ReferrerDetailTypeIds,
34
+ ReferrerLeaderboardPageResponseCodes: () => ReferrerLeaderboardPageResponseCodes,
34
35
  SECONDS_PER_YEAR: () => SECONDS_PER_YEAR,
35
- ZERO_ENCODED_REFERRER: () => ZERO_ENCODED_REFERRER,
36
36
  buildAggregatedReferrerMetrics: () => buildAggregatedReferrerMetrics,
37
37
  buildAwardedReferrerMetrics: () => buildAwardedReferrerMetrics,
38
- buildEncodedReferrer: () => buildEncodedReferrer,
39
38
  buildEnsReferralUrl: () => buildEnsReferralUrl,
40
39
  buildRankedReferrerMetrics: () => buildRankedReferrerMetrics,
41
40
  buildReferralProgramRules: () => buildReferralProgramRules,
@@ -52,7 +51,8 @@ __export(index_exports, {
52
51
  calcReferrerFinalScoreMultiplier: () => calcReferrerFinalScoreMultiplier,
53
52
  calcReferrerScore: () => calcReferrerScore,
54
53
  compareReferrerMetrics: () => compareReferrerMetrics,
55
- decodeEncodedReferrer: () => decodeEncodedReferrer,
54
+ deserializeReferrerDetailResponse: () => deserializeReferrerDetailResponse,
55
+ deserializeReferrerLeaderboardPageResponse: () => deserializeReferrerLeaderboardPageResponse,
56
56
  getReferrerDetail: () => getReferrerDetail,
57
57
  getReferrerLeaderboardPage: () => getReferrerLeaderboardPage,
58
58
  isFiniteNonNegativeNumber: () => isFiniteNonNegativeNumber,
@@ -65,6 +65,8 @@ __export(index_exports, {
65
65
  isValidRevenueContribution: () => isValidRevenueContribution,
66
66
  isValidUSDQuantity: () => isValidUSDQuantity,
67
67
  normalizeAddress: () => normalizeAddress,
68
+ serializeReferrerDetailResponse: () => serializeReferrerDetailResponse,
69
+ serializeReferrerLeaderboardPageResponse: () => serializeReferrerLeaderboardPageResponse,
68
70
  sortReferrerMetrics: () => sortReferrerMetrics,
69
71
  validateAggregatedReferrerMetrics: () => validateAggregatedReferrerMetrics,
70
72
  validateAwardedReferrerMetrics: () => validateAwardedReferrerMetrics,
@@ -209,49 +211,469 @@ var buildAggregatedReferrerMetrics = (referrers, rules) => {
209
211
  return result;
210
212
  };
211
213
 
212
- // src/currency.ts
213
- function isValidUSDQuantity(value) {
214
- return isFiniteNonNegativeNumber(value);
214
+ // src/api/deserialize.ts
215
+ var import_v43 = require("zod/v4");
216
+
217
+ // src/api/zod-schemas.ts
218
+ var import_v42 = require("zod/v4");
219
+
220
+ // ../../node_modules/.pnpm/caip@1.1.1/node_modules/caip/dist/index.mjs
221
+ function _extends() {
222
+ _extends = Object.assign || function(target) {
223
+ for (var i = 1; i < arguments.length; i++) {
224
+ var source = arguments[i];
225
+ for (var key in source) {
226
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
227
+ target[key] = source[key];
228
+ }
229
+ }
230
+ }
231
+ return target;
232
+ };
233
+ return _extends.apply(this, arguments);
215
234
  }
216
- function validateUSDQuantity(value) {
217
- if (!isValidUSDQuantity(value)) {
218
- throw new Error(`Invalid USD quantity: ${value}.`);
235
+ var CAIP2 = {
236
+ name: "chainId",
237
+ regex: "[-:a-zA-Z0-9]{5,41}",
238
+ parameters: {
239
+ delimiter: ":",
240
+ values: {
241
+ 0: {
242
+ name: "namespace",
243
+ regex: "[-a-z0-9]{3,8}"
244
+ },
245
+ 1: {
246
+ name: "reference",
247
+ regex: "[-a-zA-Z0-9]{1,32}"
248
+ }
249
+ }
219
250
  }
251
+ };
252
+ var CAIP10 = {
253
+ name: "accountId",
254
+ regex: "[-:a-zA-Z0-9]{7,106}",
255
+ parameters: {
256
+ delimiter: ":",
257
+ values: {
258
+ 0: {
259
+ name: "namespace",
260
+ regex: "[-a-z0-9]{3,8}"
261
+ },
262
+ 1: {
263
+ name: "reference",
264
+ regex: "[-a-zA-Z0-9]{1,32}"
265
+ },
266
+ 2: {
267
+ name: "address",
268
+ regex: "[a-zA-Z0-9]{1,64}"
269
+ }
270
+ }
271
+ }
272
+ };
273
+ var AssetName$1 = {
274
+ name: "assetName",
275
+ regex: "[-:a-zA-Z0-9]{5,73}",
276
+ parameters: {
277
+ delimiter: ":",
278
+ values: {
279
+ 0: {
280
+ name: "namespace",
281
+ regex: "[-a-z0-9]{3,8}"
282
+ },
283
+ 1: {
284
+ name: "reference",
285
+ regex: "[-a-zA-Z0-9]{1,64}"
286
+ }
287
+ }
288
+ }
289
+ };
290
+ var CAIP19AssetType = {
291
+ name: "assetType",
292
+ regex: "[-:a-zA-Z0-9]{11,115}",
293
+ parameters: {
294
+ delimiter: "/",
295
+ values: {
296
+ 0: CAIP2,
297
+ 1: AssetName$1
298
+ }
299
+ }
300
+ };
301
+ var CAIP19AssetId = {
302
+ name: "assetId",
303
+ regex: "[-:a-zA-Z0-9]{13,148}",
304
+ parameters: {
305
+ delimiter: "/",
306
+ values: {
307
+ 0: CAIP2,
308
+ 1: AssetName$1,
309
+ 2: {
310
+ name: "tokenId",
311
+ regex: "[-a-zA-Z0-9]{1,32}"
312
+ }
313
+ }
314
+ }
315
+ };
316
+ var CAIP = {
317
+ "2": CAIP2,
318
+ "10": CAIP10,
319
+ "19": {
320
+ assetName: AssetName$1,
321
+ assetType: CAIP19AssetType,
322
+ assetId: CAIP19AssetId
323
+ }
324
+ };
325
+ function splitParams(id, spec) {
326
+ return id.split(spec.parameters.delimiter);
220
327
  }
328
+ function getParams(id, spec) {
329
+ var arr = splitParams(id, spec);
330
+ var params = {};
331
+ arr.forEach(function(value, index) {
332
+ params[spec.parameters.values[index].name] = value;
333
+ });
334
+ return params;
335
+ }
336
+ function joinParams(params, spec) {
337
+ return Object.values(spec.parameters.values).map(function(parameter) {
338
+ var param = params[parameter.name];
339
+ return typeof param === "string" ? param : joinParams(param, parameter);
340
+ }).join(spec.parameters.delimiter);
341
+ }
342
+ function isValidId(id, spec) {
343
+ if (!new RegExp(spec.regex).test(id)) return false;
344
+ var params = splitParams(id, spec);
345
+ if (params.length !== Object.keys(spec.parameters.values).length) return false;
346
+ var matches = params.map(function(param, index) {
347
+ return new RegExp(spec.parameters.values[index].regex).test(param);
348
+ }).filter(function(x) {
349
+ return !!x;
350
+ });
351
+ if (matches.length !== params.length) return false;
352
+ return true;
353
+ }
354
+ var ChainId = /* @__PURE__ */ (function() {
355
+ function ChainId2(params) {
356
+ if (typeof params === "string") {
357
+ params = ChainId2.parse(params);
358
+ }
359
+ this.namespace = params.namespace;
360
+ this.reference = params.reference;
361
+ }
362
+ ChainId2.parse = function parse(id) {
363
+ if (!isValidId(id, this.spec)) {
364
+ throw new Error("Invalid " + this.spec.name + " provided: " + id);
365
+ }
366
+ return new ChainId2(getParams(id, this.spec)).toJSON();
367
+ };
368
+ ChainId2.format = function format(params) {
369
+ return joinParams(params, this.spec);
370
+ };
371
+ var _proto = ChainId2.prototype;
372
+ _proto.toString = function toString() {
373
+ return ChainId2.format(this.toJSON());
374
+ };
375
+ _proto.toJSON = function toJSON() {
376
+ return {
377
+ namespace: this.namespace,
378
+ reference: this.reference
379
+ };
380
+ };
381
+ return ChainId2;
382
+ })();
383
+ ChainId.spec = CAIP["2"];
384
+ var AccountId = /* @__PURE__ */ (function() {
385
+ function AccountId2(params) {
386
+ if (typeof params === "string") {
387
+ params = AccountId2.parse(params);
388
+ }
389
+ this.chainId = new ChainId(params.chainId);
390
+ this.address = params.address;
391
+ }
392
+ AccountId2.parse = function parse(id) {
393
+ if (!isValidId(id, this.spec)) {
394
+ throw new Error("Invalid " + this.spec.name + " provided: " + id);
395
+ }
396
+ var _getParams = getParams(id, this.spec), namespace = _getParams.namespace, reference = _getParams.reference, address = _getParams.address;
397
+ var chainId = new ChainId({
398
+ namespace,
399
+ reference
400
+ });
401
+ return new AccountId2({
402
+ chainId,
403
+ address
404
+ }).toJSON();
405
+ };
406
+ AccountId2.format = function format(params) {
407
+ var chainId = new ChainId(params.chainId);
408
+ var splitParams2 = _extends({}, chainId.toJSON(), {
409
+ address: params.address
410
+ });
411
+ return joinParams(splitParams2, this.spec);
412
+ };
413
+ var _proto = AccountId2.prototype;
414
+ _proto.toString = function toString() {
415
+ return AccountId2.format(this.toJSON());
416
+ };
417
+ _proto.toJSON = function toJSON() {
418
+ return {
419
+ chainId: this.chainId.toJSON(),
420
+ address: this.address
421
+ };
422
+ };
423
+ return AccountId2;
424
+ })();
425
+ AccountId.spec = CAIP["10"];
426
+ var AssetName = /* @__PURE__ */ (function() {
427
+ function AssetName2(params) {
428
+ if (typeof params === "string") {
429
+ params = AssetName2.parse(params);
430
+ }
431
+ this.namespace = params.namespace;
432
+ this.reference = params.reference;
433
+ }
434
+ AssetName2.parse = function parse(id) {
435
+ if (!isValidId(id, this.spec)) {
436
+ throw new Error("Invalid " + this.spec.name + " provided: " + id);
437
+ }
438
+ return new AssetName2(getParams(id, this.spec)).toJSON();
439
+ };
440
+ AssetName2.format = function format(params) {
441
+ return joinParams(params, this.spec);
442
+ };
443
+ var _proto = AssetName2.prototype;
444
+ _proto.toString = function toString() {
445
+ return AssetName2.format(this.toJSON());
446
+ };
447
+ _proto.toJSON = function toJSON() {
448
+ return {
449
+ namespace: this.namespace,
450
+ reference: this.reference
451
+ };
452
+ };
453
+ return AssetName2;
454
+ })();
455
+ AssetName.spec = CAIP["19"].assetName;
456
+ var AssetType = /* @__PURE__ */ (function() {
457
+ function AssetType2(params) {
458
+ if (typeof params === "string") {
459
+ params = AssetType2.parse(params);
460
+ }
461
+ this.chainId = new ChainId(params.chainId);
462
+ this.assetName = new AssetName(params.assetName);
463
+ }
464
+ AssetType2.parse = function parse(id) {
465
+ if (!isValidId(id, this.spec)) {
466
+ throw new Error("Invalid " + this.spec.name + " provided: " + id);
467
+ }
468
+ return new AssetType2(getParams(id, this.spec)).toJSON();
469
+ };
470
+ AssetType2.format = function format(params) {
471
+ return joinParams(params, this.spec);
472
+ };
473
+ var _proto = AssetType2.prototype;
474
+ _proto.toString = function toString() {
475
+ return AssetType2.format(this.toJSON());
476
+ };
477
+ _proto.toJSON = function toJSON() {
478
+ return {
479
+ chainId: this.chainId.toJSON(),
480
+ assetName: this.assetName
481
+ };
482
+ };
483
+ return AssetType2;
484
+ })();
485
+ AssetType.spec = CAIP["19"].assetType;
486
+ var AssetId = /* @__PURE__ */ (function() {
487
+ function AssetId2(params) {
488
+ if (typeof params === "string") {
489
+ params = AssetId2.parse(params);
490
+ }
491
+ this.chainId = new ChainId(params.chainId);
492
+ this.assetName = new AssetName(params.assetName);
493
+ this.tokenId = params.tokenId;
494
+ }
495
+ AssetId2.parse = function parse(id) {
496
+ if (!isValidId(id, this.spec)) {
497
+ throw new Error("Invalid " + this.spec.name + " provided: " + id);
498
+ }
499
+ return new AssetId2(getParams(id, this.spec)).toJSON();
500
+ };
501
+ AssetId2.format = function format(params) {
502
+ return joinParams(params, this.spec);
503
+ };
504
+ var _proto = AssetId2.prototype;
505
+ _proto.toString = function toString() {
506
+ return AssetId2.format(this.toJSON());
507
+ };
508
+ _proto.toJSON = function toJSON() {
509
+ return {
510
+ chainId: this.chainId.toJSON(),
511
+ assetName: this.assetName.toJSON(),
512
+ tokenId: this.tokenId
513
+ };
514
+ };
515
+ return AssetId2;
516
+ })();
517
+ AssetId.spec = CAIP["19"].assetId;
221
518
 
222
- // src/encoding.ts
519
+ // ../ensnode-sdk/src/shared/zod-schemas.ts
223
520
  var import_viem2 = require("viem");
224
- var ENCODED_REFERRER_BYTE_OFFSET = 12;
225
- var ENCODED_REFERRER_BYTE_LENGTH = 32;
226
- var EXPECTED_ENCODED_REFERRER_PADDING = (0, import_viem2.pad)("0x", {
227
- size: ENCODED_REFERRER_BYTE_OFFSET,
228
- dir: "left"
521
+ var import_v4 = require("zod/v4");
522
+
523
+ // ../ensnode-sdk/src/shared/address.ts
524
+ function asLowerCaseAddress(address) {
525
+ return address.toLowerCase();
526
+ }
527
+
528
+ // ../ensnode-sdk/src/shared/zod-schemas.ts
529
+ var makeFiniteNonNegativeNumberSchema = (valueLabel = "Value") => import_v4.z.number({
530
+ // NOTE: Zod's implementation of `number` automatically rejects NaN and Infinity values.
531
+ // and therefore the finite check is implicit.
532
+ error: `${valueLabel} must be a finite number.`
533
+ }).nonnegative({
534
+ error: `${valueLabel} must be a non-negative number (>=0).`
229
535
  });
230
- var ZERO_ENCODED_REFERRER = (0, import_viem2.pad)("0x", {
231
- size: ENCODED_REFERRER_BYTE_LENGTH,
232
- dir: "left"
536
+ var makeIntegerSchema = (valueLabel = "Value") => import_v4.z.int({
537
+ error: `${valueLabel} must be an integer.`
233
538
  });
234
- function buildEncodedReferrer(address) {
235
- const lowercaseAddress = address.toLowerCase();
236
- return (0, import_viem2.pad)(lowercaseAddress, { size: ENCODED_REFERRER_BYTE_LENGTH, dir: "left" });
237
- }
238
- function decodeEncodedReferrer(encodedReferrer) {
239
- if ((0, import_viem2.size)(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) {
539
+ var makePositiveIntegerSchema = (valueLabel = "Value") => makeIntegerSchema(valueLabel).positive({
540
+ error: `${valueLabel} must be a positive integer (>0).`
541
+ });
542
+ var makeNonNegativeIntegerSchema = (valueLabel = "Value") => makeIntegerSchema(valueLabel).nonnegative({
543
+ error: `${valueLabel} must be a non-negative integer (>=0).`
544
+ });
545
+ var makeDurationSchema = (valueLabel = "Value") => import_v4.z.number({
546
+ error: `${valueLabel} must be a number.`
547
+ }).pipe(makeNonNegativeIntegerSchema(valueLabel));
548
+ var makeChainIdSchema = (valueLabel = "Chain ID") => makePositiveIntegerSchema(valueLabel).transform((val) => val);
549
+ var makeLowercaseAddressSchema = (valueLabel = "EVM address") => import_v4.z.string().check((ctx) => {
550
+ if (!(0, import_viem2.isAddress)(ctx.value)) {
551
+ ctx.issues.push({
552
+ code: "custom",
553
+ message: `${valueLabel} must be a valid EVM address`,
554
+ input: ctx.value
555
+ });
556
+ }
557
+ }).transform((val) => asLowerCaseAddress(val));
558
+ var makeUnixTimestampSchema = (valueLabel = "Timestamp") => makeIntegerSchema(valueLabel);
559
+ var makeAccountIdSchema = (valueLabel = "AccountId") => import_v4.z.strictObject({
560
+ chainId: makeChainIdSchema(`${valueLabel} chain ID`),
561
+ address: makeLowercaseAddressSchema(`${valueLabel} address`)
562
+ });
563
+
564
+ // src/leaderboard-page.ts
565
+ var REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT = 25;
566
+ var REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;
567
+ var validateReferrerLeaderboardPageParams = (params) => {
568
+ if (params.page !== void 0 && !isPositiveInteger(params.page)) {
240
569
  throw new Error(
241
- `Encoded referrer value must be represented by ${ENCODED_REFERRER_BYTE_LENGTH} bytes.`
570
+ `Invalid ReferrerLeaderboardPageParams: ${params.page}. page must be a positive integer.`
242
571
  );
243
572
  }
244
- const padding = (0, import_viem2.slice)(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET);
245
- if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) {
246
- return import_viem2.zeroAddress;
573
+ if (params.recordsPerPage !== void 0 && !isPositiveInteger(params.recordsPerPage)) {
574
+ throw new Error(
575
+ `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be a positive integer.`
576
+ );
247
577
  }
248
- const decodedReferrer = (0, import_viem2.slice)(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET);
249
- try {
250
- return (0, import_viem2.getAddress)(decodedReferrer);
251
- } catch {
252
- throw new Error(`Decoded referrer value must be a valid EVM address.`);
578
+ if (params.recordsPerPage !== void 0 && params.recordsPerPage > REFERRERS_PER_LEADERBOARD_PAGE_MAX) {
579
+ throw new Error(
580
+ `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be less than or equal to ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}.`
581
+ );
253
582
  }
254
- }
583
+ };
584
+ var buildReferrerLeaderboardPageParams = (params) => {
585
+ const result = {
586
+ page: params.page ?? 1,
587
+ recordsPerPage: params.recordsPerPage ?? REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT
588
+ };
589
+ validateReferrerLeaderboardPageParams(result);
590
+ return result;
591
+ };
592
+ var validateReferrerLeaderboardPageContext = (context) => {
593
+ validateReferrerLeaderboardPageParams(context);
594
+ if (!isNonNegativeInteger(context.totalRecords)) {
595
+ throw new Error(
596
+ `Invalid ReferrerLeaderboardPageContext: total must be a non-negative integer but is ${context.totalRecords}.`
597
+ );
598
+ }
599
+ const startIndex = (context.page - 1) * context.recordsPerPage;
600
+ const endIndex = startIndex + context.recordsPerPage;
601
+ if (!context.hasNext && endIndex < context.totalRecords) {
602
+ throw new Error(
603
+ `Invalid ReferrerLeaderboardPageContext: if hasNext is false, endIndex (${endIndex}) must be greater than or equal to total (${context.totalRecords}).`
604
+ );
605
+ } else if (context.hasNext && context.page * context.recordsPerPage >= context.totalRecords) {
606
+ throw new Error(
607
+ `Invalid ReferrerLeaderboardPageContext: if hasNext is true, endIndex (${endIndex}) must be less than total (${context.totalRecords}).`
608
+ );
609
+ }
610
+ if (!context.hasPrev && context.page !== 1) {
611
+ throw new Error(
612
+ `Invalid ReferrerLeaderboardPageContext: if hasPrev is false, page must be the first page (1) but is ${context.page}.`
613
+ );
614
+ } else if (context.hasPrev && context.page === 1) {
615
+ throw new Error(
616
+ `Invalid ReferrerLeaderboardPageContext: if hasPrev is true, page must not be the first page (1) but is ${context.page}.`
617
+ );
618
+ }
619
+ };
620
+ var buildReferrerLeaderboardPageContext = (optionalParams, leaderboard) => {
621
+ const materializedParams = buildReferrerLeaderboardPageParams(optionalParams);
622
+ const totalRecords = leaderboard.referrers.size;
623
+ const totalPages = Math.max(1, Math.ceil(totalRecords / materializedParams.recordsPerPage));
624
+ if (materializedParams.page > totalPages) {
625
+ throw new Error(
626
+ `Invalid ReferrerLeaderboardPageContext: page ${materializedParams.page} exceeds total pages ${totalPages}.`
627
+ );
628
+ }
629
+ if (totalRecords === 0) {
630
+ return {
631
+ ...materializedParams,
632
+ totalRecords: 0,
633
+ totalPages: 1,
634
+ hasNext: false,
635
+ hasPrev: false,
636
+ startIndex: void 0,
637
+ endIndex: void 0
638
+ };
639
+ }
640
+ const startIndex = (materializedParams.page - 1) * materializedParams.recordsPerPage;
641
+ const maxTheoreticalIndexOnPage = startIndex + (materializedParams.recordsPerPage - 1);
642
+ const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);
643
+ const hasNext = maxTheoreticalIndexOnPage < totalRecords - 1;
644
+ const hasPrev = materializedParams.page > 1;
645
+ const result = {
646
+ ...materializedParams,
647
+ totalRecords,
648
+ totalPages,
649
+ hasNext,
650
+ hasPrev,
651
+ startIndex,
652
+ endIndex
653
+ };
654
+ validateReferrerLeaderboardPageContext(result);
655
+ return result;
656
+ };
657
+ var getReferrerLeaderboardPage = (pageParams, leaderboard) => {
658
+ const pageContext = buildReferrerLeaderboardPageContext(pageParams, leaderboard);
659
+ let referrers;
660
+ if (pageContext.totalRecords > 0 && typeof pageContext.startIndex !== "undefined" && typeof pageContext.endIndex !== "undefined") {
661
+ referrers = Array.from(leaderboard.referrers.values()).slice(
662
+ pageContext.startIndex,
663
+ pageContext.endIndex + 1
664
+ // For `slice`, this is exclusive of the element at the index 'end'. We need it to be inclusive, hence plus one.
665
+ );
666
+ } else {
667
+ referrers = [];
668
+ }
669
+ return {
670
+ rules: leaderboard.rules,
671
+ referrers,
672
+ aggregatedMetrics: leaderboard.aggregatedMetrics,
673
+ pageContext,
674
+ accurateAsOf: leaderboard.accurateAsOf
675
+ };
676
+ };
255
677
 
256
678
  // src/rank.ts
257
679
  var validateReferrerRank = (rank) => {
@@ -453,6 +875,624 @@ var buildUnrankedReferrerMetrics = (referrer) => {
453
875
  return result;
454
876
  };
455
877
 
878
+ // src/referrer-detail.ts
879
+ var ReferrerDetailTypeIds = {
880
+ /**
881
+ * Represents a referrer who is ranked on the leaderboard.
882
+ */
883
+ Ranked: "ranked",
884
+ /**
885
+ * Represents a referrer who is not ranked on the leaderboard.
886
+ */
887
+ Unranked: "unranked"
888
+ };
889
+ var getReferrerDetail = (referrer, leaderboard) => {
890
+ const awardedReferrerMetrics = leaderboard.referrers.get(referrer);
891
+ if (awardedReferrerMetrics) {
892
+ return {
893
+ type: ReferrerDetailTypeIds.Ranked,
894
+ rules: leaderboard.rules,
895
+ referrer: awardedReferrerMetrics,
896
+ aggregatedMetrics: leaderboard.aggregatedMetrics,
897
+ accurateAsOf: leaderboard.accurateAsOf
898
+ };
899
+ }
900
+ return {
901
+ type: ReferrerDetailTypeIds.Unranked,
902
+ rules: leaderboard.rules,
903
+ referrer: buildUnrankedReferrerMetrics(referrer),
904
+ aggregatedMetrics: leaderboard.aggregatedMetrics,
905
+ accurateAsOf: leaderboard.accurateAsOf
906
+ };
907
+ };
908
+
909
+ // src/api/types.ts
910
+ var ReferrerLeaderboardPageResponseCodes = {
911
+ /**
912
+ * Represents that the requested referrer leaderboard page is available.
913
+ */
914
+ Ok: "ok",
915
+ /**
916
+ * Represents that the referrer leaderboard data is not available.
917
+ */
918
+ Error: "error"
919
+ };
920
+ var ReferrerDetailResponseCodes = {
921
+ /**
922
+ * Represents that the referrer detail data is available.
923
+ */
924
+ Ok: "ok",
925
+ /**
926
+ * Represents that an error occurred while fetching the data.
927
+ */
928
+ Error: "error"
929
+ };
930
+
931
+ // src/api/zod-schemas.ts
932
+ var makeRevenueContributionSchema = (valueLabel = "RevenueContribution") => import_v42.z.coerce.bigint({
933
+ error: `${valueLabel} must represent a bigint.`
934
+ }).nonnegative({
935
+ error: `${valueLabel} must not be negative.`
936
+ });
937
+ var makeReferralProgramRulesSchema = (valueLabel = "ReferralProgramRules") => import_v42.z.object({
938
+ totalAwardPoolValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.totalAwardPoolValue`),
939
+ maxQualifiedReferrers: makeNonNegativeIntegerSchema(`${valueLabel}.maxQualifiedReferrers`),
940
+ startTime: makeUnixTimestampSchema(`${valueLabel}.startTime`),
941
+ endTime: makeUnixTimestampSchema(`${valueLabel}.endTime`),
942
+ subregistryId: makeAccountIdSchema(`${valueLabel}.subregistryId`)
943
+ });
944
+ var makeAwardedReferrerMetricsSchema = (valueLabel = "AwardedReferrerMetrics") => import_v42.z.object({
945
+ referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),
946
+ totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),
947
+ totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),
948
+ totalRevenueContribution: makeRevenueContributionSchema(
949
+ `${valueLabel}.totalRevenueContribution`
950
+ ),
951
+ score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),
952
+ rank: makePositiveIntegerSchema(`${valueLabel}.rank`),
953
+ isQualified: import_v42.z.boolean(),
954
+ finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(
955
+ 1,
956
+ `${valueLabel}.finalScoreBoost must be <= 1`
957
+ ),
958
+ finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),
959
+ awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(
960
+ 1,
961
+ `${valueLabel}.awardPoolShare must be <= 1`
962
+ ),
963
+ awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`)
964
+ });
965
+ var makeUnrankedReferrerMetricsSchema = (valueLabel = "UnrankedReferrerMetrics") => import_v42.z.object({
966
+ referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),
967
+ totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),
968
+ totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),
969
+ totalRevenueContribution: makeRevenueContributionSchema(
970
+ `${valueLabel}.totalRevenueContribution`
971
+ ),
972
+ score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),
973
+ rank: import_v42.z.null(),
974
+ isQualified: import_v42.z.literal(false),
975
+ finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(
976
+ 1,
977
+ `${valueLabel}.finalScoreBoost must be <= 1`
978
+ ),
979
+ finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),
980
+ awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(
981
+ 1,
982
+ `${valueLabel}.awardPoolShare must be <= 1`
983
+ ),
984
+ awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`)
985
+ });
986
+ var makeAggregatedReferrerMetricsSchema = (valueLabel = "AggregatedReferrerMetrics") => import_v42.z.object({
987
+ grandTotalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.grandTotalReferrals`),
988
+ grandTotalIncrementalDuration: makeDurationSchema(
989
+ `${valueLabel}.grandTotalIncrementalDuration`
990
+ ),
991
+ grandTotalRevenueContribution: makeRevenueContributionSchema(
992
+ `${valueLabel}.grandTotalRevenueContribution`
993
+ ),
994
+ grandTotalQualifiedReferrersFinalScore: makeFiniteNonNegativeNumberSchema(
995
+ `${valueLabel}.grandTotalQualifiedReferrersFinalScore`
996
+ ),
997
+ minFinalScoreToQualify: makeFiniteNonNegativeNumberSchema(
998
+ `${valueLabel}.minFinalScoreToQualify`
999
+ )
1000
+ });
1001
+ var makeReferrerLeaderboardPageContextSchema = (valueLabel = "ReferrerLeaderboardPageContext") => import_v42.z.object({
1002
+ page: makePositiveIntegerSchema(`${valueLabel}.page`),
1003
+ recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(
1004
+ REFERRERS_PER_LEADERBOARD_PAGE_MAX,
1005
+ `${valueLabel}.recordsPerPage must not exceed ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}`
1006
+ ),
1007
+ totalRecords: makeNonNegativeIntegerSchema(`${valueLabel}.totalRecords`),
1008
+ totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),
1009
+ hasNext: import_v42.z.boolean(),
1010
+ hasPrev: import_v42.z.boolean(),
1011
+ startIndex: import_v42.z.optional(makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`)),
1012
+ endIndex: import_v42.z.optional(makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`))
1013
+ });
1014
+ var makeReferrerLeaderboardPageSchema = (valueLabel = "ReferrerLeaderboardPage") => import_v42.z.object({
1015
+ rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
1016
+ referrers: import_v42.z.array(makeAwardedReferrerMetricsSchema(`${valueLabel}.referrers[record]`)),
1017
+ aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
1018
+ pageContext: makeReferrerLeaderboardPageContextSchema(`${valueLabel}.pageContext`),
1019
+ accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
1020
+ });
1021
+ var makeReferrerLeaderboardPageResponseOkSchema = (valueLabel = "ReferrerLeaderboardPageResponseOk") => import_v42.z.object({
1022
+ responseCode: import_v42.z.literal(ReferrerLeaderboardPageResponseCodes.Ok),
1023
+ data: makeReferrerLeaderboardPageSchema(`${valueLabel}.data`)
1024
+ });
1025
+ var makeReferrerLeaderboardPageResponseErrorSchema = (_valueLabel = "ReferrerLeaderboardPageResponseError") => import_v42.z.object({
1026
+ responseCode: import_v42.z.literal(ReferrerLeaderboardPageResponseCodes.Error),
1027
+ error: import_v42.z.string(),
1028
+ errorMessage: import_v42.z.string()
1029
+ });
1030
+ var makeReferrerLeaderboardPageResponseSchema = (valueLabel = "ReferrerLeaderboardPageResponse") => import_v42.z.union([
1031
+ makeReferrerLeaderboardPageResponseOkSchema(valueLabel),
1032
+ makeReferrerLeaderboardPageResponseErrorSchema(valueLabel)
1033
+ ]);
1034
+ var makeReferrerDetailRankedSchema = (valueLabel = "ReferrerDetailRanked") => import_v42.z.object({
1035
+ type: import_v42.z.literal(ReferrerDetailTypeIds.Ranked),
1036
+ rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
1037
+ referrer: makeAwardedReferrerMetricsSchema(`${valueLabel}.referrer`),
1038
+ aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
1039
+ accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
1040
+ });
1041
+ var makeReferrerDetailUnrankedSchema = (valueLabel = "ReferrerDetailUnranked") => import_v42.z.object({
1042
+ type: import_v42.z.literal(ReferrerDetailTypeIds.Unranked),
1043
+ rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
1044
+ referrer: makeUnrankedReferrerMetricsSchema(`${valueLabel}.referrer`),
1045
+ aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
1046
+ accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
1047
+ });
1048
+ var makeReferrerDetailResponseOkSchema = (valueLabel = "ReferrerDetailResponse") => import_v42.z.object({
1049
+ responseCode: import_v42.z.literal(ReferrerDetailResponseCodes.Ok),
1050
+ data: import_v42.z.union([
1051
+ makeReferrerDetailRankedSchema(`${valueLabel}.data`),
1052
+ makeReferrerDetailUnrankedSchema(`${valueLabel}.data`)
1053
+ ])
1054
+ });
1055
+ var makeReferrerDetailResponseErrorSchema = (_valueLabel = "ReferrerDetailResponse") => import_v42.z.object({
1056
+ responseCode: import_v42.z.literal(ReferrerDetailResponseCodes.Error),
1057
+ error: import_v42.z.string(),
1058
+ errorMessage: import_v42.z.string()
1059
+ });
1060
+ var makeReferrerDetailResponseSchema = (valueLabel = "ReferrerDetailResponse") => import_v42.z.union([
1061
+ makeReferrerDetailResponseOkSchema(valueLabel),
1062
+ makeReferrerDetailResponseErrorSchema(valueLabel)
1063
+ ]);
1064
+
1065
+ // src/api/deserialize.ts
1066
+ function deserializeRevenueContribution(value) {
1067
+ return BigInt(value);
1068
+ }
1069
+ function deserializeReferralProgramRules(rules) {
1070
+ return rules;
1071
+ }
1072
+ function deserializeAwardedReferrerMetrics(metrics) {
1073
+ return {
1074
+ referrer: metrics.referrer,
1075
+ totalReferrals: metrics.totalReferrals,
1076
+ totalIncrementalDuration: metrics.totalIncrementalDuration,
1077
+ totalRevenueContribution: deserializeRevenueContribution(metrics.totalRevenueContribution),
1078
+ score: metrics.score,
1079
+ rank: metrics.rank,
1080
+ isQualified: metrics.isQualified,
1081
+ finalScoreBoost: metrics.finalScoreBoost,
1082
+ finalScore: metrics.finalScore,
1083
+ awardPoolShare: metrics.awardPoolShare,
1084
+ awardPoolApproxValue: metrics.awardPoolApproxValue
1085
+ };
1086
+ }
1087
+ function deserializeUnrankedReferrerMetrics(metrics) {
1088
+ return {
1089
+ referrer: metrics.referrer,
1090
+ totalReferrals: metrics.totalReferrals,
1091
+ totalIncrementalDuration: metrics.totalIncrementalDuration,
1092
+ totalRevenueContribution: deserializeRevenueContribution(metrics.totalRevenueContribution),
1093
+ score: metrics.score,
1094
+ rank: metrics.rank,
1095
+ isQualified: metrics.isQualified,
1096
+ finalScoreBoost: metrics.finalScoreBoost,
1097
+ finalScore: metrics.finalScore,
1098
+ awardPoolShare: metrics.awardPoolShare,
1099
+ awardPoolApproxValue: metrics.awardPoolApproxValue
1100
+ };
1101
+ }
1102
+ function deserializeAggregatedReferrerMetrics(metrics) {
1103
+ return {
1104
+ grandTotalReferrals: metrics.grandTotalReferrals,
1105
+ grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,
1106
+ grandTotalRevenueContribution: deserializeRevenueContribution(
1107
+ metrics.grandTotalRevenueContribution
1108
+ ),
1109
+ grandTotalQualifiedReferrersFinalScore: metrics.grandTotalQualifiedReferrersFinalScore,
1110
+ minFinalScoreToQualify: metrics.minFinalScoreToQualify
1111
+ };
1112
+ }
1113
+ function deserializeReferrerLeaderboardPage(page) {
1114
+ return {
1115
+ rules: deserializeReferralProgramRules(page.rules),
1116
+ referrers: page.referrers.map(deserializeAwardedReferrerMetrics),
1117
+ aggregatedMetrics: deserializeAggregatedReferrerMetrics(page.aggregatedMetrics),
1118
+ pageContext: page.pageContext,
1119
+ accurateAsOf: page.accurateAsOf
1120
+ };
1121
+ }
1122
+ function deserializeReferrerDetailRanked(detail) {
1123
+ return {
1124
+ type: detail.type,
1125
+ rules: deserializeReferralProgramRules(detail.rules),
1126
+ referrer: deserializeAwardedReferrerMetrics(detail.referrer),
1127
+ aggregatedMetrics: deserializeAggregatedReferrerMetrics(detail.aggregatedMetrics),
1128
+ accurateAsOf: detail.accurateAsOf
1129
+ };
1130
+ }
1131
+ function deserializeReferrerDetailUnranked(detail) {
1132
+ return {
1133
+ type: detail.type,
1134
+ rules: deserializeReferralProgramRules(detail.rules),
1135
+ referrer: deserializeUnrankedReferrerMetrics(detail.referrer),
1136
+ aggregatedMetrics: deserializeAggregatedReferrerMetrics(detail.aggregatedMetrics),
1137
+ accurateAsOf: detail.accurateAsOf
1138
+ };
1139
+ }
1140
+ function deserializeReferrerLeaderboardPageResponse(maybeResponse, valueLabel) {
1141
+ let deserialized;
1142
+ switch (maybeResponse.responseCode) {
1143
+ case "ok": {
1144
+ deserialized = {
1145
+ responseCode: maybeResponse.responseCode,
1146
+ data: deserializeReferrerLeaderboardPage(maybeResponse.data)
1147
+ };
1148
+ break;
1149
+ }
1150
+ case "error":
1151
+ deserialized = maybeResponse;
1152
+ break;
1153
+ }
1154
+ const schema = makeReferrerLeaderboardPageResponseSchema(valueLabel);
1155
+ const parsed = schema.safeParse(deserialized);
1156
+ if (parsed.error) {
1157
+ throw new Error(
1158
+ `Cannot deserialize SerializedReferrerLeaderboardPageResponse:
1159
+ ${(0, import_v43.prettifyError)(parsed.error)}
1160
+ `
1161
+ );
1162
+ }
1163
+ return parsed.data;
1164
+ }
1165
+ function deserializeReferrerDetailResponse(maybeResponse, valueLabel) {
1166
+ let deserialized;
1167
+ switch (maybeResponse.responseCode) {
1168
+ case "ok": {
1169
+ switch (maybeResponse.data.type) {
1170
+ case "ranked":
1171
+ deserialized = {
1172
+ responseCode: maybeResponse.responseCode,
1173
+ data: deserializeReferrerDetailRanked(maybeResponse.data)
1174
+ };
1175
+ break;
1176
+ case "unranked":
1177
+ deserialized = {
1178
+ responseCode: maybeResponse.responseCode,
1179
+ data: deserializeReferrerDetailUnranked(maybeResponse.data)
1180
+ };
1181
+ break;
1182
+ }
1183
+ break;
1184
+ }
1185
+ case "error":
1186
+ deserialized = maybeResponse;
1187
+ break;
1188
+ }
1189
+ const schema = makeReferrerDetailResponseSchema(valueLabel);
1190
+ const parsed = schema.safeParse(deserialized);
1191
+ if (parsed.error) {
1192
+ throw new Error(`Cannot deserialize ReferrerDetailResponse:
1193
+ ${(0, import_v43.prettifyError)(parsed.error)}
1194
+ `);
1195
+ }
1196
+ return parsed.data;
1197
+ }
1198
+
1199
+ // src/api/serialize.ts
1200
+ function serializeRevenueContribution(revenueContribution) {
1201
+ return revenueContribution.toString();
1202
+ }
1203
+ function serializeReferralProgramRules(rules) {
1204
+ return rules;
1205
+ }
1206
+ function serializeAwardedReferrerMetrics(metrics) {
1207
+ return {
1208
+ referrer: metrics.referrer,
1209
+ totalReferrals: metrics.totalReferrals,
1210
+ totalIncrementalDuration: metrics.totalIncrementalDuration,
1211
+ totalRevenueContribution: serializeRevenueContribution(metrics.totalRevenueContribution),
1212
+ score: metrics.score,
1213
+ rank: metrics.rank,
1214
+ isQualified: metrics.isQualified,
1215
+ finalScoreBoost: metrics.finalScoreBoost,
1216
+ finalScore: metrics.finalScore,
1217
+ awardPoolShare: metrics.awardPoolShare,
1218
+ awardPoolApproxValue: metrics.awardPoolApproxValue
1219
+ };
1220
+ }
1221
+ function serializeUnrankedReferrerMetrics(metrics) {
1222
+ return {
1223
+ referrer: metrics.referrer,
1224
+ totalReferrals: metrics.totalReferrals,
1225
+ totalIncrementalDuration: metrics.totalIncrementalDuration,
1226
+ totalRevenueContribution: serializeRevenueContribution(metrics.totalRevenueContribution),
1227
+ score: metrics.score,
1228
+ rank: metrics.rank,
1229
+ isQualified: metrics.isQualified,
1230
+ finalScoreBoost: metrics.finalScoreBoost,
1231
+ finalScore: metrics.finalScore,
1232
+ awardPoolShare: metrics.awardPoolShare,
1233
+ awardPoolApproxValue: metrics.awardPoolApproxValue
1234
+ };
1235
+ }
1236
+ function serializeAggregatedReferrerMetrics(metrics) {
1237
+ return {
1238
+ grandTotalReferrals: metrics.grandTotalReferrals,
1239
+ grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,
1240
+ grandTotalRevenueContribution: serializeRevenueContribution(
1241
+ metrics.grandTotalRevenueContribution
1242
+ ),
1243
+ grandTotalQualifiedReferrersFinalScore: metrics.grandTotalQualifiedReferrersFinalScore,
1244
+ minFinalScoreToQualify: metrics.minFinalScoreToQualify
1245
+ };
1246
+ }
1247
+ function serializeReferrerLeaderboardPage(page) {
1248
+ return {
1249
+ rules: serializeReferralProgramRules(page.rules),
1250
+ referrers: page.referrers.map(serializeAwardedReferrerMetrics),
1251
+ aggregatedMetrics: serializeAggregatedReferrerMetrics(page.aggregatedMetrics),
1252
+ pageContext: page.pageContext,
1253
+ accurateAsOf: page.accurateAsOf
1254
+ };
1255
+ }
1256
+ function serializeReferrerDetailRanked(detail) {
1257
+ return {
1258
+ type: detail.type,
1259
+ rules: serializeReferralProgramRules(detail.rules),
1260
+ referrer: serializeAwardedReferrerMetrics(detail.referrer),
1261
+ aggregatedMetrics: serializeAggregatedReferrerMetrics(detail.aggregatedMetrics),
1262
+ accurateAsOf: detail.accurateAsOf
1263
+ };
1264
+ }
1265
+ function serializeReferrerDetailUnranked(detail) {
1266
+ return {
1267
+ type: detail.type,
1268
+ rules: serializeReferralProgramRules(detail.rules),
1269
+ referrer: serializeUnrankedReferrerMetrics(detail.referrer),
1270
+ aggregatedMetrics: serializeAggregatedReferrerMetrics(detail.aggregatedMetrics),
1271
+ accurateAsOf: detail.accurateAsOf
1272
+ };
1273
+ }
1274
+ function serializeReferrerLeaderboardPageResponse(response) {
1275
+ switch (response.responseCode) {
1276
+ case ReferrerLeaderboardPageResponseCodes.Ok:
1277
+ return {
1278
+ responseCode: response.responseCode,
1279
+ data: serializeReferrerLeaderboardPage(response.data)
1280
+ };
1281
+ case ReferrerLeaderboardPageResponseCodes.Error:
1282
+ return response;
1283
+ }
1284
+ }
1285
+ function serializeReferrerDetailResponse(response) {
1286
+ switch (response.responseCode) {
1287
+ case ReferrerDetailResponseCodes.Ok:
1288
+ switch (response.data.type) {
1289
+ case "ranked":
1290
+ return {
1291
+ responseCode: response.responseCode,
1292
+ data: serializeReferrerDetailRanked(response.data)
1293
+ };
1294
+ case "unranked":
1295
+ return {
1296
+ responseCode: response.responseCode,
1297
+ data: serializeReferrerDetailUnranked(response.data)
1298
+ };
1299
+ }
1300
+ break;
1301
+ case ReferrerDetailResponseCodes.Error:
1302
+ return response;
1303
+ }
1304
+ }
1305
+
1306
+ // src/client.ts
1307
+ var DEFAULT_ENSNODE_API_URL = "https://api.alpha.ensnode.io";
1308
+ var ENSReferralsClient = class _ENSReferralsClient {
1309
+ options;
1310
+ static defaultOptions() {
1311
+ return {
1312
+ url: new URL(DEFAULT_ENSNODE_API_URL)
1313
+ };
1314
+ }
1315
+ constructor(options = {}) {
1316
+ this.options = {
1317
+ ..._ENSReferralsClient.defaultOptions(),
1318
+ ...options
1319
+ };
1320
+ }
1321
+ getOptions() {
1322
+ return Object.freeze({
1323
+ url: new URL(this.options.url.href)
1324
+ });
1325
+ }
1326
+ /**
1327
+ * Fetch Referrer Leaderboard Page
1328
+ *
1329
+ * Retrieves a paginated list of referrer leaderboard metrics with contribution percentages.
1330
+ * Each referrer's contribution is calculated as a percentage of the grand totals across all referrers.
1331
+ *
1332
+ * @param request - Pagination parameters
1333
+ * @param request.page - The page number to retrieve (1-indexed, default: 1)
1334
+ * @param request.recordsPerPage - Number of records per page (default: 25, max: 100)
1335
+ * @returns {ReferrerLeaderboardPageResponse}
1336
+ *
1337
+ * @throws if the ENSNode request fails
1338
+ * @throws if the ENSNode API returns an error response
1339
+ * @throws if the ENSNode response breaks required invariants
1340
+ *
1341
+ * @example
1342
+ * ```typescript
1343
+ * // Get first page with default page size (25 records)
1344
+ * const response = await client.getReferrerLeaderboardPage();
1345
+ * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Ok) {
1346
+ * const {
1347
+ * aggregatedMetrics,
1348
+ * referrers,
1349
+ * rules,
1350
+ * pageContext,
1351
+ * updatedAt
1352
+ * } = response.data;
1353
+ * console.log(aggregatedMetrics);
1354
+ * console.log(referrers);
1355
+ * console.log(rules);
1356
+ * console.log(updatedAt);
1357
+ * console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);
1358
+ * }
1359
+ * ```
1360
+ *
1361
+ * @example
1362
+ * ```typescript
1363
+ * // Get second page with 50 records per page
1364
+ * const response = await client.getReferrerLeaderboardPage({ page: 2, recordsPerPage: 50 });
1365
+ * ```
1366
+ *
1367
+ * @example
1368
+ * ```typescript
1369
+ * // Handle error response, ie. when Referrer Leaderboard is not currently available.
1370
+ * const response = await client.getReferrerLeaderboardPage();
1371
+ *
1372
+ * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Error) {
1373
+ * console.error(response.error);
1374
+ * console.error(response.errorMessage);
1375
+ * }
1376
+ * ```
1377
+ */
1378
+ async getReferrerLeaderboardPage(request) {
1379
+ const url = new URL(`/ensanalytics/referrers`, this.options.url);
1380
+ if (request?.page) url.searchParams.set("page", request.page.toString());
1381
+ if (request?.recordsPerPage)
1382
+ url.searchParams.set("recordsPerPage", request.recordsPerPage.toString());
1383
+ const response = await fetch(url);
1384
+ let responseData;
1385
+ try {
1386
+ responseData = await response.json();
1387
+ } catch {
1388
+ throw new Error("Malformed response data: invalid JSON");
1389
+ }
1390
+ return deserializeReferrerLeaderboardPageResponse(
1391
+ responseData
1392
+ );
1393
+ }
1394
+ /**
1395
+ * Fetch Referrer Detail
1396
+ *
1397
+ * Retrieves detailed information about a specific referrer, whether they are on the
1398
+ * leaderboard or not.
1399
+ *
1400
+ * The response data is a discriminated union type with a `type` field:
1401
+ *
1402
+ * **For referrers on the leaderboard** (`ReferrerDetailRanked`):
1403
+ * - `type`: {@link ReferrerDetailTypeIds.Ranked}
1404
+ * - `referrer`: The `AwardedReferrerMetrics` from @namehash/ens-referrals
1405
+ * - `rules`: The referral program rules
1406
+ * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard
1407
+ * - `accurateAsOf`: Unix timestamp indicating when the data was last updated
1408
+ *
1409
+ * **For referrers NOT on the leaderboard** (`ReferrerDetailUnranked`):
1410
+ * - `type`: {@link ReferrerDetailTypeIds.Unranked}
1411
+ * - `referrer`: The `UnrankedReferrerMetrics` from @namehash/ens-referrals
1412
+ * - `rules`: The referral program rules
1413
+ * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard
1414
+ * - `accurateAsOf`: Unix timestamp indicating when the data was last updated
1415
+ *
1416
+ * @see {@link https://www.npmjs.com/package/@namehash/ens-referrals|@namehash/ens-referrals} for calculation details
1417
+ *
1418
+ * @param request The referrer address to query
1419
+ * @returns {ReferrerDetailResponse} Returns the referrer detail response
1420
+ *
1421
+ * @throws if the ENSNode request fails
1422
+ * @throws if the response data is malformed
1423
+ *
1424
+ * @example
1425
+ * ```typescript
1426
+ * // Get referrer detail for a specific address
1427
+ * const response = await client.getReferrerDetail({
1428
+ * referrer: "0x1234567890123456789012345678901234567890"
1429
+ * });
1430
+ * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {
1431
+ * const { type, referrer, rules, aggregatedMetrics, accurateAsOf } = response.data;
1432
+ * console.log(type); // ReferrerDetailTypeIds.Ranked or ReferrerDetailTypeIds.Unranked
1433
+ * console.log(referrer);
1434
+ * console.log(accurateAsOf);
1435
+ * }
1436
+ * ```
1437
+ *
1438
+ * @example
1439
+ * ```typescript
1440
+ * // Use discriminated union to check if referrer is ranked
1441
+ * const response = await client.getReferrerDetail({
1442
+ * referrer: "0x1234567890123456789012345678901234567890"
1443
+ * });
1444
+ * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {
1445
+ * if (response.data.type === ReferrerDetailTypeIds.Ranked) {
1446
+ * // TypeScript knows this is ReferrerDetailRanked
1447
+ * console.log(`Rank: ${response.data.referrer.rank}`);
1448
+ * console.log(`Qualified: ${response.data.referrer.isQualified}`);
1449
+ * console.log(`Award Pool Share: ${response.data.referrer.awardPoolShare * 100}%`);
1450
+ * } else {
1451
+ * // TypeScript knows this is ReferrerDetailUnranked
1452
+ * console.log("Referrer is not on the leaderboard (no referrals yet)");
1453
+ * }
1454
+ * }
1455
+ * ```
1456
+ *
1457
+ * @example
1458
+ * ```typescript
1459
+ * // Handle error response, ie. when Referrer Detail is not currently available.
1460
+ * const response = await client.getReferrerDetail({
1461
+ * referrer: "0x1234567890123456789012345678901234567890"
1462
+ * });
1463
+ *
1464
+ * if (response.responseCode === ReferrerDetailResponseCodes.Error) {
1465
+ * console.error(response.error);
1466
+ * console.error(response.errorMessage);
1467
+ * }
1468
+ * ```
1469
+ */
1470
+ async getReferrerDetail(request) {
1471
+ const url = new URL(
1472
+ `/ensanalytics/referrers/${encodeURIComponent(request.referrer)}`,
1473
+ this.options.url
1474
+ );
1475
+ const response = await fetch(url);
1476
+ let responseData;
1477
+ try {
1478
+ responseData = await response.json();
1479
+ } catch {
1480
+ throw new Error("Malformed response data: invalid JSON");
1481
+ }
1482
+ return deserializeReferrerDetailResponse(responseData);
1483
+ }
1484
+ };
1485
+
1486
+ // src/currency.ts
1487
+ function isValidUSDQuantity(value) {
1488
+ return isFiniteNonNegativeNumber(value);
1489
+ }
1490
+ function validateUSDQuantity(value) {
1491
+ if (!isValidUSDQuantity(value)) {
1492
+ throw new Error(`Invalid USD quantity: ${value}.`);
1493
+ }
1494
+ }
1495
+
456
1496
  // src/leaderboard.ts
457
1497
  var buildReferrerLeaderboard = (allReferrers, rules, accurateAsOf) => {
458
1498
  const uniqueReferrers = allReferrers.map((referrer) => referrer.referrer);
@@ -488,120 +1528,6 @@ var buildReferrerLeaderboard = (allReferrers, rules, accurateAsOf) => {
488
1528
  };
489
1529
  };
490
1530
 
491
- // src/leaderboard-page.ts
492
- var REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT = 25;
493
- var REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;
494
- var validateReferrerLeaderboardPageParams = (params) => {
495
- if (params.page !== void 0 && !isPositiveInteger(params.page)) {
496
- throw new Error(
497
- `Invalid ReferrerLeaderboardPageParams: ${params.page}. page must be a positive integer.`
498
- );
499
- }
500
- if (params.recordsPerPage !== void 0 && !isPositiveInteger(params.recordsPerPage)) {
501
- throw new Error(
502
- `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be a positive integer.`
503
- );
504
- }
505
- if (params.recordsPerPage !== void 0 && params.recordsPerPage > REFERRERS_PER_LEADERBOARD_PAGE_MAX) {
506
- throw new Error(
507
- `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be less than or equal to ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}.`
508
- );
509
- }
510
- };
511
- var buildReferrerLeaderboardPageParams = (params) => {
512
- const result = {
513
- page: params.page ?? 1,
514
- recordsPerPage: params.recordsPerPage ?? REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT
515
- };
516
- validateReferrerLeaderboardPageParams(result);
517
- return result;
518
- };
519
- var validateReferrerLeaderboardPageContext = (context) => {
520
- validateReferrerLeaderboardPageParams(context);
521
- if (!isNonNegativeInteger(context.totalRecords)) {
522
- throw new Error(
523
- `Invalid ReferrerLeaderboardPageContext: total must be a non-negative integer but is ${context.totalRecords}.`
524
- );
525
- }
526
- const startIndex = (context.page - 1) * context.recordsPerPage;
527
- const endIndex = startIndex + context.recordsPerPage;
528
- if (!context.hasNext && endIndex < context.totalRecords) {
529
- throw new Error(
530
- `Invalid ReferrerLeaderboardPageContext: if hasNext is false, endIndex (${endIndex}) must be greater than or equal to total (${context.totalRecords}).`
531
- );
532
- } else if (context.hasNext && context.page * context.recordsPerPage >= context.totalRecords) {
533
- throw new Error(
534
- `Invalid ReferrerLeaderboardPageContext: if hasNext is true, endIndex (${endIndex}) must be less than total (${context.totalRecords}).`
535
- );
536
- }
537
- if (!context.hasPrev && context.page !== 1) {
538
- throw new Error(
539
- `Invalid ReferrerLeaderboardPageContext: if hasPrev is false, page must be the first page (1) but is ${context.page}.`
540
- );
541
- } else if (context.hasPrev && context.page === 1) {
542
- throw new Error(
543
- `Invalid ReferrerLeaderboardPageContext: if hasPrev is true, page must not be the first page (1) but is ${context.page}.`
544
- );
545
- }
546
- };
547
- var buildReferrerLeaderboardPageContext = (optionalParams, leaderboard) => {
548
- const materializedParams = buildReferrerLeaderboardPageParams(optionalParams);
549
- const totalRecords = leaderboard.referrers.size;
550
- const totalPages = Math.max(1, Math.ceil(totalRecords / materializedParams.recordsPerPage));
551
- if (materializedParams.page > totalPages) {
552
- throw new Error(
553
- `Invalid ReferrerLeaderboardPageContext: page ${materializedParams.page} exceeds total pages ${totalPages}.`
554
- );
555
- }
556
- if (totalRecords === 0) {
557
- return {
558
- ...materializedParams,
559
- totalRecords: 0,
560
- totalPages: 1,
561
- hasNext: false,
562
- hasPrev: false,
563
- startIndex: void 0,
564
- endIndex: void 0
565
- };
566
- }
567
- const startIndex = (materializedParams.page - 1) * materializedParams.recordsPerPage;
568
- const maxTheoreticalIndexOnPage = startIndex + (materializedParams.recordsPerPage - 1);
569
- const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);
570
- const hasNext = maxTheoreticalIndexOnPage < totalRecords - 1;
571
- const hasPrev = materializedParams.page > 1;
572
- const result = {
573
- ...materializedParams,
574
- totalRecords,
575
- totalPages,
576
- hasNext,
577
- hasPrev,
578
- startIndex,
579
- endIndex
580
- };
581
- validateReferrerLeaderboardPageContext(result);
582
- return result;
583
- };
584
- var getReferrerLeaderboardPage = (pageParams, leaderboard) => {
585
- const pageContext = buildReferrerLeaderboardPageContext(pageParams, leaderboard);
586
- let referrers;
587
- if (pageContext.totalRecords > 0 && typeof pageContext.startIndex !== "undefined" && typeof pageContext.endIndex !== "undefined") {
588
- referrers = Array.from(leaderboard.referrers.values()).slice(
589
- pageContext.startIndex,
590
- pageContext.endIndex + 1
591
- // For `slice`, this is exclusive of the element at the index 'end'. We need it to be inclusive, hence plus one.
592
- );
593
- } else {
594
- referrers = [];
595
- }
596
- return {
597
- rules: leaderboard.rules,
598
- referrers,
599
- aggregatedMetrics: leaderboard.aggregatedMetrics,
600
- pageContext,
601
- accurateAsOf: leaderboard.accurateAsOf
602
- };
603
- };
604
-
605
1531
  // src/link.ts
606
1532
  var import_viem3 = require("viem");
607
1533
  function buildEnsReferralUrl(address) {
@@ -610,37 +1536,6 @@ function buildEnsReferralUrl(address) {
610
1536
  return ensAppUrl;
611
1537
  }
612
1538
 
613
- // src/referrer-detail.ts
614
- var ReferrerDetailTypeIds = {
615
- /**
616
- * Represents a referrer who is ranked on the leaderboard.
617
- */
618
- Ranked: "ranked",
619
- /**
620
- * Represents a referrer who is not ranked on the leaderboard.
621
- */
622
- Unranked: "unranked"
623
- };
624
- var getReferrerDetail = (referrer, leaderboard) => {
625
- const awardedReferrerMetrics = leaderboard.referrers.get(referrer);
626
- if (awardedReferrerMetrics) {
627
- return {
628
- type: ReferrerDetailTypeIds.Ranked,
629
- rules: leaderboard.rules,
630
- referrer: awardedReferrerMetrics,
631
- aggregatedMetrics: leaderboard.aggregatedMetrics,
632
- accurateAsOf: leaderboard.accurateAsOf
633
- };
634
- }
635
- return {
636
- type: ReferrerDetailTypeIds.Unranked,
637
- rules: leaderboard.rules,
638
- referrer: buildUnrankedReferrerMetrics(referrer),
639
- aggregatedMetrics: leaderboard.aggregatedMetrics,
640
- accurateAsOf: leaderboard.accurateAsOf
641
- };
642
- };
643
-
644
1539
  // src/rules.ts
645
1540
  var ENS_HOLIDAY_AWARDS_START_DATE = 1764547200;
646
1541
  var ENS_HOLIDAY_AWARDS_END_DATE = 1767225599;