@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.
@@ -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.CURVEVAULT]: new DefaultDynamicData(), // TODO
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.CURVEVAULT]: new DefaultMetadata(), // TODO
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 { logger } from "@/utils/logger";
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 live campaigns
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 (status !== "LIVE" && status !== "SOON" && campaign.endTimestamp < now)
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 the status of the opportunities associated to future campaigns
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 (_err) {
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.findUnique(address)).creatorId);
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 }, startTimestamp: { lte: now }, endTimestamp: { gte: now } },
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.findUnique(params.address))
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
  }