@merkl/api 0.19.35 → 0.19.36
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/src/eden/index.d.ts +438 -25
- package/dist/src/index.d.ts +122 -5
- package/dist/src/modules/v4/campaign/campaign.controller.d.ts +14 -6
- package/dist/src/modules/v4/campaign/campaign.controller.js +13 -6
- package/dist/src/modules/v4/opportunity/opportunity.repository.js +2 -2
- package/dist/src/modules/v4/opportunity/opportunity.service.js +2 -2
- package/dist/src/modules/v4/reward/reward.controller.d.ts +123 -1
- package/dist/src/modules/v4/reward/reward.controller.js +14 -2
- package/dist/src/modules/v4/reward/reward.model.d.ts +7 -0
- package/dist/src/modules/v4/reward/reward.model.js +6 -0
- package/dist/src/modules/v4/reward/reward.repository.d.ts +9 -1
- package/dist/src/modules/v4/reward/reward.repository.js +27 -0
- package/dist/src/modules/v4/reward/reward.service.d.ts +165 -0
- package/dist/src/modules/v4/reward/reward.service.js +50 -0
- package/dist/src/modules/v4/router.d.ts +122 -5
- package/dist/src/modules/v4/token/token.service.js +9 -0
- package/dist/tsconfig.package.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/src/index.d.ts
CHANGED
@@ -1752,7 +1752,9 @@ declare const app: Elysia<"", false, {
|
|
1752
1752
|
withOpportunity?: boolean | undefined;
|
1753
1753
|
createdAfter?: Date | null | undefined;
|
1754
1754
|
};
|
1755
|
-
headers:
|
1755
|
+
headers: {
|
1756
|
+
authorization: string;
|
1757
|
+
};
|
1756
1758
|
response: {
|
1757
1759
|
200: {
|
1758
1760
|
[x: string]: number;
|
@@ -1764,7 +1766,7 @@ declare const app: Elysia<"", false, {
|
|
1764
1766
|
} & {
|
1765
1767
|
campaigns: {
|
1766
1768
|
count: {
|
1767
|
-
"by-
|
1769
|
+
"by-types": {
|
1768
1770
|
get: {
|
1769
1771
|
body: unknown;
|
1770
1772
|
params: {};
|
@@ -1792,7 +1794,9 @@ declare const app: Elysia<"", false, {
|
|
1792
1794
|
withOpportunity?: boolean | undefined;
|
1793
1795
|
createdAfter?: Date | null | undefined;
|
1794
1796
|
};
|
1795
|
-
headers:
|
1797
|
+
headers: {
|
1798
|
+
authorization: string;
|
1799
|
+
};
|
1796
1800
|
response: {
|
1797
1801
|
200: {
|
1798
1802
|
[x: string]: number;
|
@@ -1805,7 +1809,7 @@ declare const app: Elysia<"", false, {
|
|
1805
1809
|
} & {
|
1806
1810
|
campaigns: {
|
1807
1811
|
count: {
|
1808
|
-
"by-
|
1812
|
+
"by-protocols": {
|
1809
1813
|
get: {
|
1810
1814
|
body: unknown;
|
1811
1815
|
params: {};
|
@@ -1833,7 +1837,9 @@ declare const app: Elysia<"", false, {
|
|
1833
1837
|
withOpportunity?: boolean | undefined;
|
1834
1838
|
createdAfter?: Date | null | undefined;
|
1835
1839
|
};
|
1836
|
-
headers:
|
1840
|
+
headers: {
|
1841
|
+
authorization: string;
|
1842
|
+
};
|
1837
1843
|
response: {
|
1838
1844
|
200: {
|
1839
1845
|
[x: string]: number;
|
@@ -2661,6 +2667,117 @@ declare const app: Elysia<"", false, {
|
|
2661
2667
|
};
|
2662
2668
|
};
|
2663
2669
|
};
|
2670
|
+
} & {
|
2671
|
+
rewards: {
|
2672
|
+
total: {
|
2673
|
+
distributed: {
|
2674
|
+
get: {
|
2675
|
+
body: unknown;
|
2676
|
+
params: {};
|
2677
|
+
query: {
|
2678
|
+
since: Date;
|
2679
|
+
};
|
2680
|
+
headers: {
|
2681
|
+
authorization: string;
|
2682
|
+
};
|
2683
|
+
response: {
|
2684
|
+
200: number;
|
2685
|
+
};
|
2686
|
+
};
|
2687
|
+
};
|
2688
|
+
};
|
2689
|
+
};
|
2690
|
+
} & {
|
2691
|
+
rewards: {
|
2692
|
+
total: {
|
2693
|
+
distributed: {
|
2694
|
+
"by-opportunities": {
|
2695
|
+
get: {
|
2696
|
+
body: unknown;
|
2697
|
+
params: {};
|
2698
|
+
query: {
|
2699
|
+
since: Date;
|
2700
|
+
};
|
2701
|
+
headers: {
|
2702
|
+
authorization: string;
|
2703
|
+
};
|
2704
|
+
response: {
|
2705
|
+
200: string;
|
2706
|
+
};
|
2707
|
+
};
|
2708
|
+
};
|
2709
|
+
};
|
2710
|
+
};
|
2711
|
+
};
|
2712
|
+
} & {
|
2713
|
+
rewards: {
|
2714
|
+
total: {
|
2715
|
+
distributed: {
|
2716
|
+
"by-chains": {
|
2717
|
+
get: {
|
2718
|
+
body: unknown;
|
2719
|
+
params: {};
|
2720
|
+
query: {
|
2721
|
+
since: Date;
|
2722
|
+
};
|
2723
|
+
headers: {
|
2724
|
+
authorization: string;
|
2725
|
+
};
|
2726
|
+
response: {
|
2727
|
+
[x: string]: any;
|
2728
|
+
200: any;
|
2729
|
+
};
|
2730
|
+
};
|
2731
|
+
};
|
2732
|
+
};
|
2733
|
+
};
|
2734
|
+
};
|
2735
|
+
} & {
|
2736
|
+
rewards: {
|
2737
|
+
total: {
|
2738
|
+
distributed: {
|
2739
|
+
"by-types": {
|
2740
|
+
get: {
|
2741
|
+
body: unknown;
|
2742
|
+
params: {};
|
2743
|
+
query: {
|
2744
|
+
since: Date;
|
2745
|
+
};
|
2746
|
+
headers: {
|
2747
|
+
authorization: string;
|
2748
|
+
};
|
2749
|
+
response: {
|
2750
|
+
[x: string]: any;
|
2751
|
+
200: any;
|
2752
|
+
};
|
2753
|
+
};
|
2754
|
+
};
|
2755
|
+
};
|
2756
|
+
};
|
2757
|
+
};
|
2758
|
+
} & {
|
2759
|
+
rewards: {
|
2760
|
+
total: {
|
2761
|
+
distributed: {
|
2762
|
+
"by-protocols": {
|
2763
|
+
get: {
|
2764
|
+
body: unknown;
|
2765
|
+
params: {};
|
2766
|
+
query: {
|
2767
|
+
since: Date;
|
2768
|
+
};
|
2769
|
+
headers: {
|
2770
|
+
authorization: string;
|
2771
|
+
};
|
2772
|
+
response: {
|
2773
|
+
[x: string]: any;
|
2774
|
+
200: any;
|
2775
|
+
};
|
2776
|
+
};
|
2777
|
+
};
|
2778
|
+
};
|
2779
|
+
};
|
2780
|
+
};
|
2664
2781
|
};
|
2665
2782
|
} & {
|
2666
2783
|
v4: {
|
@@ -664,7 +664,9 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
|
|
664
664
|
withOpportunity?: boolean | undefined;
|
665
665
|
createdAfter?: Date | null | undefined;
|
666
666
|
};
|
667
|
-
headers:
|
667
|
+
headers: {
|
668
|
+
authorization: string;
|
669
|
+
};
|
668
670
|
response: {
|
669
671
|
200: {
|
670
672
|
[x: string]: number;
|
@@ -676,7 +678,7 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
|
|
676
678
|
} & {
|
677
679
|
campaigns: {
|
678
680
|
count: {
|
679
|
-
"by-
|
681
|
+
"by-types": {
|
680
682
|
get: {
|
681
683
|
body: unknown;
|
682
684
|
params: {};
|
@@ -704,7 +706,9 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
|
|
704
706
|
withOpportunity?: boolean | undefined;
|
705
707
|
createdAfter?: Date | null | undefined;
|
706
708
|
};
|
707
|
-
headers:
|
709
|
+
headers: {
|
710
|
+
authorization: string;
|
711
|
+
};
|
708
712
|
response: {
|
709
713
|
200: {
|
710
714
|
[x: string]: number;
|
@@ -717,7 +721,7 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
|
|
717
721
|
} & {
|
718
722
|
campaigns: {
|
719
723
|
count: {
|
720
|
-
"by-
|
724
|
+
"by-protocols": {
|
721
725
|
get: {
|
722
726
|
body: unknown;
|
723
727
|
params: {};
|
@@ -745,7 +749,9 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
|
|
745
749
|
withOpportunity?: boolean | undefined;
|
746
750
|
createdAfter?: Date | null | undefined;
|
747
751
|
};
|
748
|
-
headers:
|
752
|
+
headers: {
|
753
|
+
authorization: string;
|
754
|
+
};
|
749
755
|
response: {
|
750
756
|
200: {
|
751
757
|
[x: string]: number;
|
@@ -764,7 +770,9 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
|
|
764
770
|
resolve: {};
|
765
771
|
schema: {
|
766
772
|
body: unknown;
|
767
|
-
headers:
|
773
|
+
headers: {
|
774
|
+
authorization: string;
|
775
|
+
};
|
768
776
|
query: {
|
769
777
|
type?: string | undefined;
|
770
778
|
status?: "NONE" | "PAST" | "LIVE" | "SOON" | undefined;
|
@@ -58,7 +58,7 @@ export const CampaignController = new Elysia({ prefix: "/campaigns", detail: { t
|
|
58
58
|
.group("/dry-run", app => app
|
59
59
|
// ─── Test Dynamic data computation given a campaignId ───────────────────────
|
60
60
|
.get("/:campaignId/dynamic-data", async ({ params }) => {
|
61
|
-
const id = (await CampaignService.findMany({ campaignId: params.campaignId, test: true }))[0]
|
61
|
+
const id = (await CampaignService.findMany({ campaignId: params.campaignId, test: true }))?.[0]?.id;
|
62
62
|
if (!id)
|
63
63
|
throw new NotFoundError();
|
64
64
|
const campaign = await CampaignService.findUniqueOrThrow(id, true);
|
@@ -68,13 +68,15 @@ export const CampaignController = new Elysia({ prefix: "/campaigns", detail: { t
|
|
68
68
|
// ─── Test Opportunity creation through a campaign Id and a chain ───────────────────────
|
69
69
|
// @dev Starts from the engine db to debug opportunity creation failing and preventing the api db to be filled
|
70
70
|
.get("/metadata", async ({ query }) => {
|
71
|
-
const
|
71
|
+
const engineCampaigns = await CampaignService.findEngineCampaigns([
|
72
72
|
{
|
73
73
|
distributionChain: query.distributionChain,
|
74
74
|
campaignId: query.campaignId,
|
75
75
|
},
|
76
76
|
]);
|
77
|
-
|
77
|
+
if (!engineCampaigns.length)
|
78
|
+
throw new NotFoundError("Campaign not found in engine db");
|
79
|
+
return await OpportunityService.createFromCampaign(engineCampaigns[0], false, false);
|
78
80
|
}, {
|
79
81
|
beforeHandle: BackOfficeGuard,
|
80
82
|
headers: AuthorizationHeadersDto,
|
@@ -171,7 +173,12 @@ export const CampaignController = new Elysia({ prefix: "/campaigns", detail: { t
|
|
171
173
|
<p>This endpoint enables you to count campaigns corresponding to filters specified in the query params.</p>`,
|
172
174
|
},
|
173
175
|
})
|
174
|
-
.guard({
|
176
|
+
.guard({
|
177
|
+
response: t.Record(t.String(), t.Number()),
|
178
|
+
headers: AuthorizationHeadersDto,
|
179
|
+
beforeHandle: BackOfficeGuard,
|
180
|
+
detail: { hide: true },
|
181
|
+
})
|
175
182
|
.get("count/by-chains", async ({ query }) => await CampaignService.countByChains(query))
|
176
|
-
.get("/count/by-
|
177
|
-
.get("/count/by-
|
183
|
+
.get("/count/by-types", async ({ query }) => await CampaignService.countByType(query))
|
184
|
+
.get("/count/by-protocols", async ({ query }) => await CampaignService.countByProtocol(query));
|
@@ -313,13 +313,13 @@ export class OpportunityRepository {
|
|
313
313
|
// pagination by offset; might have to change to cursor based for performance
|
314
314
|
const { page: _page, items: _items } = query;
|
315
315
|
const page = _page ? _page : 0;
|
316
|
-
const items = _items ? _items : 20;
|
316
|
+
const items = _items !== undefined ? _items : 20;
|
317
317
|
const withTest = query.test ?? false;
|
318
318
|
const withPoints = query.point ?? false;
|
319
319
|
const withCampaigns = query.campaigns ?? false;
|
320
320
|
const args = OpportunityRepository.#transformQueryToPrismaFilters(query);
|
321
321
|
return await apiDbClient.opportunity.findMany({
|
322
|
-
take: items,
|
322
|
+
take: items === 0 ? undefined : items,
|
323
323
|
skip: page * items,
|
324
324
|
include: {
|
325
325
|
...OpportunityRepository.#getRecordInclusion(withTest, withPoints),
|
@@ -75,8 +75,8 @@ export class OpportunityService {
|
|
75
75
|
? params.url
|
76
76
|
: !!metadata.depositUrl
|
77
77
|
? metadata.depositUrl
|
78
|
-
: !!metadata.mainProtocol && !!protocol
|
79
|
-
? protocol
|
78
|
+
: !!metadata.mainProtocol && !!protocol?.url
|
79
|
+
? protocol?.url
|
80
80
|
: undefined,
|
81
81
|
tags,
|
82
82
|
};
|
@@ -327,6 +327,117 @@ export declare const RewardController: Elysia<"/rewards", false, {
|
|
327
327
|
};
|
328
328
|
};
|
329
329
|
};
|
330
|
+
} & {
|
331
|
+
rewards: {
|
332
|
+
total: {
|
333
|
+
distributed: {
|
334
|
+
get: {
|
335
|
+
body: unknown;
|
336
|
+
params: {};
|
337
|
+
query: {
|
338
|
+
since: Date;
|
339
|
+
};
|
340
|
+
headers: {
|
341
|
+
authorization: string;
|
342
|
+
};
|
343
|
+
response: {
|
344
|
+
200: number;
|
345
|
+
};
|
346
|
+
};
|
347
|
+
};
|
348
|
+
};
|
349
|
+
};
|
350
|
+
} & {
|
351
|
+
rewards: {
|
352
|
+
total: {
|
353
|
+
distributed: {
|
354
|
+
"by-opportunities": {
|
355
|
+
get: {
|
356
|
+
body: unknown;
|
357
|
+
params: {};
|
358
|
+
query: {
|
359
|
+
since: Date;
|
360
|
+
};
|
361
|
+
headers: {
|
362
|
+
authorization: string;
|
363
|
+
};
|
364
|
+
response: {
|
365
|
+
200: string;
|
366
|
+
};
|
367
|
+
};
|
368
|
+
};
|
369
|
+
};
|
370
|
+
};
|
371
|
+
};
|
372
|
+
} & {
|
373
|
+
rewards: {
|
374
|
+
total: {
|
375
|
+
distributed: {
|
376
|
+
"by-chains": {
|
377
|
+
get: {
|
378
|
+
body: unknown;
|
379
|
+
params: {};
|
380
|
+
query: {
|
381
|
+
since: Date;
|
382
|
+
};
|
383
|
+
headers: {
|
384
|
+
authorization: string;
|
385
|
+
};
|
386
|
+
response: {
|
387
|
+
[x: string]: any;
|
388
|
+
200: any;
|
389
|
+
};
|
390
|
+
};
|
391
|
+
};
|
392
|
+
};
|
393
|
+
};
|
394
|
+
};
|
395
|
+
} & {
|
396
|
+
rewards: {
|
397
|
+
total: {
|
398
|
+
distributed: {
|
399
|
+
"by-types": {
|
400
|
+
get: {
|
401
|
+
body: unknown;
|
402
|
+
params: {};
|
403
|
+
query: {
|
404
|
+
since: Date;
|
405
|
+
};
|
406
|
+
headers: {
|
407
|
+
authorization: string;
|
408
|
+
};
|
409
|
+
response: {
|
410
|
+
[x: string]: any;
|
411
|
+
200: any;
|
412
|
+
};
|
413
|
+
};
|
414
|
+
};
|
415
|
+
};
|
416
|
+
};
|
417
|
+
};
|
418
|
+
} & {
|
419
|
+
rewards: {
|
420
|
+
total: {
|
421
|
+
distributed: {
|
422
|
+
"by-protocols": {
|
423
|
+
get: {
|
424
|
+
body: unknown;
|
425
|
+
params: {};
|
426
|
+
query: {
|
427
|
+
since: Date;
|
428
|
+
};
|
429
|
+
headers: {
|
430
|
+
authorization: string;
|
431
|
+
};
|
432
|
+
response: {
|
433
|
+
[x: string]: any;
|
434
|
+
200: any;
|
435
|
+
};
|
436
|
+
};
|
437
|
+
};
|
438
|
+
};
|
439
|
+
};
|
440
|
+
};
|
330
441
|
}, {
|
331
442
|
derive: {};
|
332
443
|
resolve: {};
|
@@ -334,5 +445,16 @@ export declare const RewardController: Elysia<"/rewards", false, {
|
|
334
445
|
}, {
|
335
446
|
derive: {};
|
336
447
|
resolve: {};
|
337
|
-
schema: {
|
448
|
+
schema: {
|
449
|
+
body: unknown;
|
450
|
+
headers: {
|
451
|
+
authorization: string;
|
452
|
+
};
|
453
|
+
query: {
|
454
|
+
since: Date;
|
455
|
+
};
|
456
|
+
params: unknown;
|
457
|
+
cookie: unknown;
|
458
|
+
response: {};
|
459
|
+
};
|
338
460
|
}>;
|
@@ -3,8 +3,9 @@ import { AuthorizationHeadersDto, EngineGuard } from "@/guards/Engine.guard";
|
|
3
3
|
import { ChainDto } from "@/modules/v4/accounting/accounting.model";
|
4
4
|
import { CampaignService } from "@/modules/v4/campaign/campaign.service";
|
5
5
|
import { TokenService } from "@/modules/v4/token/token.service";
|
6
|
+
import bigintToString from "@/utils/bigintToString";
|
6
7
|
import { throwOnInvalidRequiredAddress, throwOnUnsupportedChainId } from "@/utils/throw";
|
7
|
-
import Elysia from "elysia";
|
8
|
+
import Elysia, { t } from "elysia";
|
8
9
|
import { CampaignIdDto, CampaignIdWithoutPageDto, CampaignRewardsDto, CreateManyBreakdownDto, CreateManyRewardDto, RegisterClaimsDto, TokenIdDto, } from "./reward.model";
|
9
10
|
import { RewardService } from "./reward.service";
|
10
11
|
// ─── Rewards Controller ──────────────────────────────────────────────────────
|
@@ -121,4 +122,15 @@ export const RewardController = new Elysia({ prefix: "/rewards", detail: { tags:
|
|
121
122
|
},
|
122
123
|
detail: { description: "Returns the total of unclaimed rewards for given campaigns" },
|
123
124
|
});
|
124
|
-
})
|
125
|
+
})
|
126
|
+
.guard({
|
127
|
+
query: t.Object({ since: t.Date() }),
|
128
|
+
headers: AuthorizationHeadersDto,
|
129
|
+
beforeHandle: BackOfficeGuard,
|
130
|
+
detail: { hide: true },
|
131
|
+
})
|
132
|
+
.get("/total/distributed", async ({ query }) => await RewardService.getTotalDistributed(query.since.getTime() / 1000))
|
133
|
+
.get("/total/distributed/by-opportunities", async ({ query }) => JSON.stringify(bigintToString(Array.from((await RewardService.getTotalDistributedByOpportunities(query.since.getTime() / 1000)).entries()))))
|
134
|
+
.get("/total/distributed/by-chains", async ({ query }) => await RewardService.getTotalDistributedByChains(query.since.getTime() / 1000))
|
135
|
+
.get("/total/distributed/by-types", async ({ query }) => await RewardService.getTotalDistributedByType(query.since.getTime() / 1000))
|
136
|
+
.get("/total/distributed/by-protocols", async ({ query }) => await RewardService.getTotalDistributedByProtocol(query.since.getTime() / 1000));
|
@@ -210,6 +210,13 @@ export declare const RewardV3Dto: import("@sinclair/typebox").TRecord<import("@s
|
|
210
210
|
symbol: import("@sinclair/typebox").TString;
|
211
211
|
}>>;
|
212
212
|
}>>;
|
213
|
+
export declare const QueryTotalDailyRewardsSinceDto: import("@sinclair/typebox").TObject<{
|
214
|
+
since: import("@sinclair/typebox").TDate;
|
215
|
+
chainId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
216
|
+
protocol: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
217
|
+
type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
218
|
+
}>;
|
219
|
+
export type QueryTotalDailyRewardsSinceModel = typeof QueryTotalDailyRewardsSinceDto.static;
|
213
220
|
export type CreateManyRewardModel = typeof CreateManyRewardDto.static;
|
214
221
|
export type CreateManyBreakdownModel = typeof CreateManyBreakdownDto.static;
|
215
222
|
export type RewardEntity = typeof RewardDto.static;
|
@@ -157,3 +157,9 @@ export const RewardV3Dto = t.Record(t.String({ title: "Chain" }), t.Object({
|
|
157
157
|
symbol: t.String(),
|
158
158
|
})),
|
159
159
|
}), { $id: "Rewards", additionalProperties: true });
|
160
|
+
export const QueryTotalDailyRewardsSinceDto = t.Object({
|
161
|
+
since: t.Date(),
|
162
|
+
chainId: t.Optional(t.Numeric()),
|
163
|
+
protocol: t.Optional(t.String()),
|
164
|
+
type: t.Optional(t.String()),
|
165
|
+
});
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import type
|
1
|
+
import { type ChainId } from "@sdk";
|
2
2
|
import type { BreakdownForCampaignsRaw, CampaignIdModel, CampaignIdWithoutPageModel, CreateManyBreakdownModel, CreateManyRewardModel, TokenIdModel } from "./reward.model";
|
3
3
|
export declare abstract class RewardRepository {
|
4
4
|
static createManyReward(rewards: CreateManyRewardModel): Promise<import("database/api/.generated/runtime/library").GetBatchResult>;
|
@@ -153,4 +153,12 @@ export declare abstract class RewardRepository {
|
|
153
153
|
amount: string;
|
154
154
|
claimed: string;
|
155
155
|
}[]>;
|
156
|
+
/**
|
157
|
+
* Calculates the sum of daily average rewards for a given opportunity since a specified timestamp.
|
158
|
+
*
|
159
|
+
* @param since - The timestamp (in seconds) from which to start calculating the rewards.
|
160
|
+
* @param opportunityId - The ID of the opportunity for which to calculate the rewards.
|
161
|
+
* @returns The sum of daily average rewards for the specified opportunity since the given timestamp.
|
162
|
+
*/
|
163
|
+
static sumDailyRewardsAvgByOpportunity(since: number, opportunityId: string): Promise<number>;
|
156
164
|
}
|
@@ -2,6 +2,7 @@ import { Campaign, Reward, RewardBreakdown } from "@db/api:drizzle";
|
|
2
2
|
import { TokenService } from "@/modules/v4/token/token.service";
|
3
3
|
import { UserService } from "@/modules/v4/user/user.service";
|
4
4
|
import { apiDbClient } from "@db";
|
5
|
+
import { DAY } from "@sdk";
|
5
6
|
import { and, eq, exists, inArray, sql } from "drizzle-orm";
|
6
7
|
import { CampaignService } from "../campaign";
|
7
8
|
import { RewardService } from "./reward.service";
|
@@ -302,4 +303,30 @@ export class RewardRepository {
|
|
302
303
|
},
|
303
304
|
});
|
304
305
|
}
|
306
|
+
/**
|
307
|
+
* Calculates the sum of daily average rewards for a given opportunity since a specified timestamp.
|
308
|
+
*
|
309
|
+
* @param since - The timestamp (in seconds) from which to start calculating the rewards.
|
310
|
+
* @param opportunityId - The ID of the opportunity for which to calculate the rewards.
|
311
|
+
* @returns The sum of daily average rewards for the specified opportunity since the given timestamp.
|
312
|
+
*/
|
313
|
+
static async sumDailyRewardsAvgByOpportunity(since, opportunityId) {
|
314
|
+
const dateToRewards = new Map();
|
315
|
+
const dailyAvg = [];
|
316
|
+
const records = await apiDbClient.dailyRewardsRecord.findMany({
|
317
|
+
where: { opportunityId, timestamp: { gte: since }, total: { gt: 0 } },
|
318
|
+
select: { timestamp: true, total: true },
|
319
|
+
});
|
320
|
+
if (records.length === 0)
|
321
|
+
return 0;
|
322
|
+
for (const record of records) {
|
323
|
+
const date = Math.floor(Number(record.timestamp) / DAY).toString();
|
324
|
+
const rewards = dateToRewards.get(date) ?? [];
|
325
|
+
rewards.push(record.total);
|
326
|
+
dateToRewards.set(date, rewards);
|
327
|
+
}
|
328
|
+
for (const rewards of dateToRewards.values())
|
329
|
+
dailyAvg.push(rewards.reduce((prev, curr) => prev + curr, 0) / rewards.length);
|
330
|
+
return dailyAvg.reduce((prev, curr) => prev + curr, 0);
|
331
|
+
}
|
305
332
|
}
|