@merkl/api 0.21.13 → 0.21.15
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/engine/deprecated/dynamicData/factory.js +1 -1
- package/dist/src/engine/metadata/factory.js +1 -1
- package/dist/src/jobs/update-dynamic-data.js +7 -21
- package/dist/src/modules/v4/campaign/campaign.service.js +2 -1
- package/dist/src/modules/v4/creator/creator.service.js +1 -1
- package/dist/src/modules/v4/opportunity/opportunity.repository.js +3 -1
- package/dist/src/modules/v4/user/user.controller.js +1 -1
- package/dist/src/modules/v4/user/user.repository.d.ts +5 -0
- package/dist/src/modules/v4/user/user.repository.js +3 -0
- package/dist/src/modules/v4/user/user.service.d.ts +5 -0
- package/dist/src/modules/v4/user/user.service.js +3 -0
- package/dist/tsconfig.package.tsbuildinfo +1 -1
- package/package.json +1 -1
@@ -63,6 +63,6 @@ const map = {
|
|
63
63
|
[Campaign.MULTILOG]: new DefaultDynamicData(),
|
64
64
|
[Campaign.LOCKER]: new DefaultDynamicData(), // TODO
|
65
65
|
[Campaign.CONVEX]: new DefaultDynamicData(), // TODO
|
66
|
-
[Campaign.
|
66
|
+
[Campaign.STAKEDAO_CURVEVAULT]: new DefaultDynamicData(), // TODO
|
67
67
|
};
|
68
68
|
export const dynamicDataBuilderFactory = (campaignType) => map[campaignType];
|
@@ -70,6 +70,6 @@ const map = {
|
|
70
70
|
[Campaign.MULTILOG]: new MultiLogMetaData(),
|
71
71
|
[Campaign.LOCKER]: new LockerMetadata(),
|
72
72
|
[Campaign.CONVEX]: new DefaultMetadata(), // TODO
|
73
|
-
[Campaign.
|
73
|
+
[Campaign.STAKEDAO_CURVEVAULT]: new DefaultMetadata(), // TODO
|
74
74
|
};
|
75
75
|
export const metadataBuilderFactory = (campaignType) => map[campaignType];
|
@@ -2,7 +2,7 @@ import { CampaignService } from "@/modules/v4/campaign/campaign.service";
|
|
2
2
|
import { DynamicDataService } from "@/modules/v4/dynamicData/dynamicData.service";
|
3
3
|
import { OpportunityConvertorService } from "@/modules/v4/opportunity/opportunity.converter";
|
4
4
|
import { OpportunityService } from "@/modules/v4/opportunity/opportunity.service";
|
5
|
-
import {
|
5
|
+
import { log } from "@/utils/logger";
|
6
6
|
import { Campaign as CampaignType } from "@sdk";
|
7
7
|
import moment from "moment";
|
8
8
|
// ─── Required Env Variables ──────────────────────────────────────────────────
|
@@ -12,20 +12,20 @@ if (!chainId)
|
|
12
12
|
// ─── Update Dynamic Data (APR / TVL / Daily Rewards) ─────────────────────────
|
13
13
|
const main = async () => {
|
14
14
|
// Update status of opportunities
|
15
|
-
// 1. Get current live opportunities or opportunities with
|
15
|
+
// 1. Get current live opportunities or opportunities with campaigns ending in the future
|
16
16
|
const liveOpportunities = await OpportunityService.findLiveWithCampaigns(chainId);
|
17
17
|
// 2. For each currently live opportunities, infer its updated status by looping through its campaigns
|
18
18
|
// This should handle:
|
19
19
|
// - Opportunities flagged as "SOON" once they turn live
|
20
20
|
// - Opportunities flagged as "LIVE" once they are not live anymore
|
21
|
+
// - Opportunities flagged as "PAST" that are now "LIVE"
|
22
|
+
// - Opportunities flagged as "SOON" if they were missed and should now be "PAST"
|
21
23
|
const now = moment().unix();
|
22
24
|
for (const opportunity of liveOpportunities) {
|
23
25
|
let status = "PAST";
|
24
26
|
const campaigns = opportunity.campaigns;
|
25
27
|
for (const campaign of campaigns) {
|
26
|
-
if (
|
27
|
-
status = "PAST";
|
28
|
-
else if (campaign.startTimestamp < now && campaign.endTimestamp > now)
|
28
|
+
if (campaign.startTimestamp < now && campaign.endTimestamp > now)
|
29
29
|
status = "LIVE";
|
30
30
|
else if (status !== "LIVE" && campaign.startTimestamp > now)
|
31
31
|
status = "SOON";
|
@@ -34,24 +34,10 @@ const main = async () => {
|
|
34
34
|
await OpportunityService.update(opportunity.id, { apr: 0, dailyRewards: 0 });
|
35
35
|
if (opportunity.status !== status) {
|
36
36
|
await OpportunityService.update(opportunity.id, { status });
|
37
|
+
log.info(`opportunity ${opportunity.id} status updated from ${opportunity.status} to ${status}`);
|
37
38
|
}
|
38
39
|
}
|
39
|
-
// 3. Update
|
40
|
-
const futureOpportunities = await CampaignService.getFutureCampaigns({ computeChainId: chainId });
|
41
|
-
const liveOpportunityIds = (await CampaignService.getLiveCampaigns({ computeChainId: chainId })).map(c => c.Opportunity.id);
|
42
|
-
const idToUpdate = futureOpportunities
|
43
|
-
?.filter(c => !liveOpportunityIds.includes(c.Opportunity.id) && c.Opportunity.status !== "SOON")
|
44
|
-
.map(c => c.Opportunity.id);
|
45
|
-
if (idToUpdate.length > 0) {
|
46
|
-
await OpportunityService.updateMany(idToUpdate, { status: "SOON" });
|
47
|
-
if (idToUpdate.length === 1)
|
48
|
-
logger.info(`updated opportunity ${idToUpdate[0]} to SOON status.`);
|
49
|
-
else
|
50
|
-
logger.info(`updated ${idToUpdate.length} opportunities to SOON status.`);
|
51
|
-
}
|
52
|
-
// 4. Update the status of the opportunities associated to live campaigns
|
53
|
-
await OpportunityService.updateMany(liveOpportunityIds, { status: "LIVE" });
|
54
|
-
// 5. Update records for all live campaigns
|
40
|
+
// 3. Update records for all live campaigns
|
55
41
|
const liveCampaigns = (await CampaignService.findMany({ chainId, status: "LIVE", test: true, withOpportunity: true, items: 0 }))
|
56
42
|
.concat(await CampaignService.findMany({ chainId, status: "SOON", test: true, withOpportunity: true, items: 0 }))
|
57
43
|
.map(campaign => OpportunityConvertorService.convertV4CampaignToV3(CampaignType[campaign.type], campaign, campaign.Opportunity.identifier));
|
@@ -72,7 +72,8 @@ export class CampaignService {
|
|
72
72
|
if (dryRun)
|
73
73
|
return opportunity;
|
74
74
|
}
|
75
|
-
catch (
|
75
|
+
catch (e) {
|
76
|
+
console.error(e);
|
76
77
|
throw new CannotParseOpportunity(campaign.campaignId, campaign.distributionChainId, campaign.type);
|
77
78
|
}
|
78
79
|
return await CampaignRepository.upsert(campaign, body.opportunityIdentifier);
|
@@ -41,7 +41,7 @@ export class CreatorService {
|
|
41
41
|
return await CreatorRepository.delete(id);
|
42
42
|
}
|
43
43
|
static async getCreatorIdFromAddress(address) {
|
44
|
-
return await CacheService.wrap(TTLPresets.MIN_30, async () => (await UserService.
|
44
|
+
return await CacheService.wrap(TTLPresets.MIN_30, async () => (await UserService.findUniqueOrThrow(address)).creatorId);
|
45
45
|
}
|
46
46
|
static async getCreatorAddresses(id) {
|
47
47
|
const creator = await CreatorRepository.findUnique(id);
|
@@ -382,6 +382,7 @@ export class OpportunityRepository {
|
|
382
382
|
orderBy: { endTimestamp: "desc" },
|
383
383
|
where: {
|
384
384
|
RewardToken: { isTest: false },
|
385
|
+
endTimestamp: { gte: now },
|
385
386
|
},
|
386
387
|
},
|
387
388
|
MainProtocol: true,
|
@@ -393,9 +394,10 @@ export class OpportunityRepository {
|
|
393
394
|
Chain: { id: chainId },
|
394
395
|
OR: [
|
395
396
|
{ status: "LIVE" },
|
397
|
+
{ status: "SOON" },
|
396
398
|
{
|
397
399
|
Campaigns: {
|
398
|
-
some: { RewardToken: { isTest: false },
|
400
|
+
some: { RewardToken: { isTest: false }, endTimestamp: { gte: now } },
|
399
401
|
},
|
400
402
|
},
|
401
403
|
],
|
@@ -39,7 +39,7 @@ export const UserController = new Elysia({ prefix: "/users", detail: { tags: ["U
|
|
39
39
|
// ─── Get Many Users ──────────────────────────────────────────────────
|
40
40
|
.get("/", async ({ query }) => await UserService.findMany(query), { query: GetManyUserQuery })
|
41
41
|
// ─── Get A User By Address ───────────────────────────────────────────
|
42
|
-
.get("/:address", async ({ params }) => await UserService.
|
42
|
+
.get("/:address", async ({ params }) => await UserService.findUniqueOrThrow(params.address))
|
43
43
|
// ─── Get User's Rewards With Breakdown And Details for our FE ────────
|
44
44
|
.get("/:address/rewards/breakdowns", async ({ params, query }) => {
|
45
45
|
const rewardsByChain = await RewardService.getUserRewardsByChain(params.address, true, query?.chainIds, query.reloadChainId ?? null, !!query.test ? query.test : false, !!query.claimableOnly);
|
@@ -4,6 +4,11 @@ export declare abstract class UserRepository {
|
|
4
4
|
tags: string[];
|
5
5
|
address: string;
|
6
6
|
creatorId: string | null;
|
7
|
+
} | null>;
|
8
|
+
static findUniqueOrThrow(address: string): Promise<{
|
9
|
+
tags: string[];
|
10
|
+
address: string;
|
11
|
+
creatorId: string | null;
|
7
12
|
}>;
|
8
13
|
static findMany(query: GetManyUserModel): Promise<{
|
9
14
|
tags: string[];
|
@@ -2,6 +2,9 @@ import { apiDbClient } from "@db";
|
|
2
2
|
// ─── Users Repository ────────────────────────────────────────────────────────
|
3
3
|
export class UserRepository {
|
4
4
|
static async findUnique(address) {
|
5
|
+
return await apiDbClient.user.findUnique({ where: { address } });
|
6
|
+
}
|
7
|
+
static async findUniqueOrThrow(address) {
|
5
8
|
return await apiDbClient.user.findUniqueOrThrow({ where: { address } });
|
6
9
|
}
|
7
10
|
static async findMany(query) {
|
@@ -4,6 +4,11 @@ export declare abstract class UserService {
|
|
4
4
|
tags: string[];
|
5
5
|
address: string;
|
6
6
|
creatorId: string | null;
|
7
|
+
} | null>;
|
8
|
+
static findUniqueOrThrow(address: string): Promise<{
|
9
|
+
tags: string[];
|
10
|
+
address: string;
|
11
|
+
creatorId: string | null;
|
7
12
|
}>;
|
8
13
|
static findMany(query: GetManyUserModel): Promise<{
|
9
14
|
tags: string[];
|
@@ -8,6 +8,9 @@ export class UserService {
|
|
8
8
|
static async findUnique(address) {
|
9
9
|
return await UserRepository.findUnique(address);
|
10
10
|
}
|
11
|
+
static async findUniqueOrThrow(address) {
|
12
|
+
return await UserRepository.findUniqueOrThrow(address);
|
13
|
+
}
|
11
14
|
static async findMany(query) {
|
12
15
|
return await UserRepository.findMany(query);
|
13
16
|
}
|