@merkl/api 0.20.8 → 0.20.9

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.
Files changed (26) hide show
  1. package/dist/src/backgroundJobs/index.js +0 -2
  2. package/dist/src/engine/dynamicData/implementations/Ajna.js +12 -6
  3. package/dist/src/engine/dynamicData/implementations/Ambiant.js +5 -0
  4. package/dist/src/engine/dynamicData/implementations/Badger.js +12 -6
  5. package/dist/src/engine/dynamicData/implementations/Clamm.js +7 -1
  6. package/dist/src/engine/dynamicData/implementations/Compound.js +9 -6
  7. package/dist/src/engine/dynamicData/implementations/Dolomite.js +12 -6
  8. package/dist/src/engine/dynamicData/implementations/EigenLayer.js +9 -6
  9. package/dist/src/engine/dynamicData/implementations/Erc20.js +14 -8
  10. package/dist/src/engine/dynamicData/implementations/EventBased.js +5 -0
  11. package/dist/src/engine/dynamicData/implementations/Hyperdrive.js +14 -8
  12. package/dist/src/engine/dynamicData/implementations/Morpho.js +9 -6
  13. package/dist/src/engine/dynamicData/implementations/Radiant.js +13 -7
  14. package/dist/src/engine/dynamicData/implementations/Silo.js +9 -6
  15. package/dist/src/engine/dynamicData/implementations/UniswapV4.js +5 -0
  16. package/dist/src/engine/dynamicData/implementations/Vest.js +9 -6
  17. package/dist/src/jobs/dynamic-data.d.ts +1 -1
  18. package/dist/src/jobs/dynamic-data.js +122 -4
  19. package/dist/src/jobs/reparse-opportunities.d.ts +1 -0
  20. package/dist/src/jobs/reparse-opportunities.js +72 -0
  21. package/dist/src/jobs/update-rpc-calls-cache.js +4 -0
  22. package/dist/src/libs/deprecated-merklv3/index.d.ts +1 -1
  23. package/dist/tsconfig.package.tsbuildinfo +1 -1
  24. package/package.json +1 -1
  25. package/dist/src/backgroundJobs/jobs/campaignsCacheUpdater.d.ts +0 -53
  26. package/dist/src/backgroundJobs/jobs/campaignsCacheUpdater.js +0 -173
@@ -8,7 +8,6 @@ import { engineDbClient } from "@db";
8
8
  import { swagger } from "@elysiajs/swagger";
9
9
  import axios from "axios";
10
10
  import { Elysia } from "elysia";
11
- import { campaignsCacheUpdater } from "./jobs/campaignsCacheUpdater";
12
11
  import { healthCheck } from "./jobs/health";
13
12
  import { opportunityUpdater } from "./jobs/opportunityUpdater";
14
13
  // Axios with bun workaround
@@ -21,7 +20,6 @@ new Elysia({
21
20
  })
22
21
  .use(swagger())
23
22
  .get("/", () => "Merkl API")
24
- .use(campaignsCacheUpdater) // /v3/update
25
23
  .use(opportunityUpdater) // /v3/updateOpportunity
26
24
  .use(healthCheck) // /v3/health
27
25
  .get("/eulerUpdate", async () => {
@@ -77,14 +77,20 @@ export class AjnaDynamicData {
77
77
  // chainId,
78
78
  // symbol: campaign.campaignParameters.symbolRewardToken,
79
79
  // })) ?? 0;
80
+ let apr = (priceRewardToken *
81
+ BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
82
+ YEAR *
83
+ 100) /
84
+ campaign.campaignParameters.duration /
85
+ (totalComputedTargetToken * res?.data.results?.quote_token_underlying_price);
86
+ const rewardTokens = await TokenService.findManyOrCreate([
87
+ { chainId: campaign.chainId, address: campaign.rewardToken },
88
+ ]);
89
+ const rewardToken = rewardTokens[0];
90
+ apr = rewardToken.isPoint ? apr / 365 / 100 : apr;
80
91
  dynamicData.push({
81
92
  ...campaign,
82
- apr: (priceRewardToken *
83
- BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
84
- YEAR *
85
- 100) /
86
- campaign.campaignParameters.duration /
87
- (totalComputedTargetToken * res?.data.results?.quote_token_underlying_price),
93
+ apr,
88
94
  totalSupplyTargetToken,
89
95
  tvl: res?.data.results?.tvl,
90
96
  computedtotalSupply: totalComputedTargetToken,
@@ -206,6 +206,11 @@ export class AmbiantDynamicData {
206
206
  else {
207
207
  }
208
208
  }
209
+ const rewardTokens = await TokenService.findManyOrCreate([
210
+ { chainId: campaign.chainId, address: campaign.rewardToken },
211
+ ]);
212
+ const rewardToken = rewardTokens[0];
213
+ distributionMeanAPR = rewardToken.isPoint ? distributionMeanAPR / 365 / 100 : distributionMeanAPR;
209
214
  dynamicData.push({
210
215
  ...campaign,
211
216
  apr: distributionMeanAPR,
@@ -61,14 +61,20 @@ export class BadgerDynamicData {
61
61
  chainId,
62
62
  symbol: campaign.campaignParameters.symbolTargetToken,
63
63
  })) ?? 0;
64
+ let apr = (priceRewardToken *
65
+ BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
66
+ YEAR *
67
+ 100) /
68
+ campaign.campaignParameters.duration /
69
+ (totalSupplyTargetToken * priceTargetToken);
70
+ const rewardTokens = await TokenService.findManyOrCreate([
71
+ { chainId: campaign.chainId, address: campaign.rewardToken },
72
+ ]);
73
+ const rewardToken = rewardTokens[0];
74
+ apr = rewardToken.isPoint ? apr / 365 / 100 : apr;
64
75
  dynamicData.push({
65
76
  ...campaign,
66
- apr: (priceRewardToken *
67
- BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
68
- YEAR *
69
- 100) /
70
- campaign.campaignParameters.duration /
71
- (totalSupplyTargetToken * priceTargetToken),
77
+ apr,
72
78
  totalSupplyTargetToken,
73
79
  tvl: totalSupplyTargetToken * priceTargetToken,
74
80
  });
@@ -582,13 +582,14 @@ export class ClammDynamicData {
582
582
  /** Clear alm APRs */
583
583
  const distributionForwarders = almDetails.map(x => ({ ...x }));
584
584
  let priceRewardToken = 0;
585
- if (isLive && c.campaignParameters.symbolRewardToken !== "aglaMerkl") {
585
+ if (c.campaignParameters.symbolRewardToken !== "aglaMerkl") {
586
586
  // priceRewardToken = (await pricer.get({
587
587
  // address: c.rewardToken,
588
588
  // chainId: chainId,
589
589
  // symbol: c.campaignParameters.symbolRewardToken,
590
590
  // })) as number;
591
591
  priceRewardToken = await TokenService.getRewardTokenPrice(campaign);
592
+ console.log("priceRewardToken", priceRewardToken);
592
593
  /**
593
594
  * Handle whitelisted/blacklisted addresses to compute APR
594
595
  */
@@ -876,6 +877,11 @@ export class ClammDynamicData {
876
877
  }
877
878
  });
878
879
  }
880
+ const rewardTokens = await TokenService.findManyOrCreate([
881
+ { chainId: campaign.chainId, address: campaign.rewardToken },
882
+ ]);
883
+ const rewardToken = rewardTokens[0];
884
+ distributionMeanAPR = rewardToken.isPoint ? distributionMeanAPR / 365 / 100 : distributionMeanAPR;
879
885
  dynamicData.push({
880
886
  ...campaign,
881
887
  amm: pool.amm,
@@ -118,14 +118,17 @@ export class CompoundDynamicData {
118
118
  chainId: campaign.computeChainId,
119
119
  symbol: campaign.campaignParameters.symbolUnderlyingToken,
120
120
  })) ?? 0;
121
+ let apr = (priceRewardToken * BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) * YEAR * 100) /
122
+ campaign.campaignParameters.duration /
123
+ (totalSupplyTargetToken * priceTargetToken);
124
+ const rewardTokens = await TokenService.findManyOrCreate([
125
+ { chainId: campaign.chainId, address: campaign.rewardToken },
126
+ ]);
127
+ const rewardToken = rewardTokens[0];
128
+ apr = rewardToken.isPoint ? apr / 365 / 100 : apr;
121
129
  dynamicData.push({
122
130
  ...campaign,
123
- apr: (priceRewardToken *
124
- BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
125
- YEAR *
126
- 100) /
127
- campaign.campaignParameters.duration /
128
- (totalSupplyTargetToken * priceTargetToken),
131
+ apr,
129
132
  totalSupplyTargetToken,
130
133
  tvl: totalSupplyTargetToken * priceTargetToken,
131
134
  priceRewardToken: priceRewardToken,
@@ -30,14 +30,20 @@ export class DolomiteDynamicData {
30
30
  chainId,
31
31
  symbol: tokenData.symbol,
32
32
  })) ?? 0;
33
+ let apr = (priceRewardToken *
34
+ BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
35
+ YEAR *
36
+ 100) /
37
+ campaign.campaignParameters.duration /
38
+ (totalSupplyTargetToken * priceTargetToken);
39
+ const rewardTokens = await TokenService.findManyOrCreate([
40
+ { chainId: campaign.chainId, address: campaign.rewardToken },
41
+ ]);
42
+ const rewardToken = rewardTokens[0];
43
+ apr = rewardToken.isPoint ? apr / 365 / 100 : apr;
33
44
  dynamicData.push({
34
45
  ...campaign,
35
- apr: (priceRewardToken *
36
- BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
37
- YEAR *
38
- 100) /
39
- campaign.campaignParameters.duration /
40
- (totalSupplyTargetToken * priceTargetToken),
46
+ apr,
41
47
  totalSupplyTargetToken,
42
48
  tvl: totalSupplyTargetToken * priceTargetToken,
43
49
  });
@@ -46,14 +46,17 @@ export class EigenLayerDynamicData {
46
46
  symbol: campaign.campaignParameters.symbolUnderlyingToken,
47
47
  })) ?? 0;
48
48
  const tvl = totalSupplyStrategy * priceTargetToken;
49
+ let apr = (priceRewardToken * BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) * YEAR * 100) /
50
+ campaign.campaignParameters.duration /
51
+ (totalSupplyStrategy * priceTargetToken);
52
+ const rewardTokens = await TokenService.findManyOrCreate([
53
+ { chainId: campaign.chainId, address: campaign.rewardToken },
54
+ ]);
55
+ const rewardToken = rewardTokens[0];
56
+ apr = rewardToken.isPoint ? apr / 365 / 100 : apr;
49
57
  dynamicData.push({
50
58
  ...campaign,
51
- apr: (priceRewardToken *
52
- BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
53
- YEAR *
54
- 100) /
55
- campaign.campaignParameters.duration /
56
- (totalSupplyStrategy * priceTargetToken),
59
+ apr,
57
60
  totalSupplyTargetToken: totalSupplyStrategy,
58
61
  tvl,
59
62
  priceRewardToken: priceRewardToken,
@@ -145,16 +145,22 @@ export class Erc20DynamicData {
145
145
  field: "forfeitingBoost",
146
146
  }))?.forfeitingBoost ?? 1;
147
147
  }
148
+ let apr = (lastEligibilityRatio *
149
+ forfeitingBoost *
150
+ (priceRewardToken *
151
+ BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
152
+ YEAR *
153
+ 100)) /
154
+ campaign.campaignParameters.duration /
155
+ (whitelistedSupplyTargetToken * priceTargetToken);
156
+ const rewardTokens = await TokenService.findManyOrCreate([
157
+ { chainId: campaign.chainId, address: campaign.rewardToken },
158
+ ]);
159
+ const rewardToken = rewardTokens[0];
160
+ apr = rewardToken.isPoint ? apr / 365 / 100 : apr;
148
161
  dynamicData.push({
149
162
  ...campaign,
150
- apr: (lastEligibilityRatio *
151
- forfeitingBoost *
152
- (priceRewardToken *
153
- BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
154
- YEAR *
155
- 100)) /
156
- campaign.campaignParameters.duration /
157
- (whitelistedSupplyTargetToken * priceTargetToken),
163
+ apr,
158
164
  totalSupplyTargetToken,
159
165
  tvl: whitelistedSupplyTargetToken * priceTargetToken,
160
166
  type: tokenTypesByCampaign[campaign.campaignId].type,
@@ -82,6 +82,11 @@ export class EventBasedDynamicData {
82
82
  (fixRewardRate * amount * (moment().unix() - startTimestamp)) / (endTimestamp - startTimestamp) / tvl;
83
83
  }
84
84
  distributionMeanAPR = !distributionMeanAPR || Number.isNaN(distributionMeanAPR) ? 0 : distributionMeanAPR;
85
+ const rewardTokens = await TokenService.findManyOrCreate([
86
+ { chainId: campaign.chainId, address: campaign.rewardToken },
87
+ ]);
88
+ const rewardToken = rewardTokens[0];
89
+ distributionMeanAPR = rewardToken.isPoint ? distributionMeanAPR / 365 / 100 : distributionMeanAPR;
85
90
  dynamicData.push({
86
91
  ...campaign,
87
92
  apr: distributionMeanAPR,
@@ -59,18 +59,24 @@ export class HyperdriveDynamicData {
59
59
  : campaign.campaignSubType === HyperDriveSubCampaignType.LONG
60
60
  ? priceBaseToken * longSupply
61
61
  : (priceBaseToken * shortSupply) / multiplier;
62
+ let apr = priceRewardToken !== 0
63
+ ? (priceRewardToken *
64
+ BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
65
+ YEAR *
66
+ 100) /
67
+ campaign.campaignParameters.duration /
68
+ tvl
69
+ : 0;
70
+ const rewardTokens = await TokenService.findManyOrCreate([
71
+ { chainId: campaign.chainId, address: campaign.rewardToken },
72
+ ]);
73
+ const rewardToken = rewardTokens[0];
74
+ apr = rewardToken.isPoint ? apr / 365 / 100 : apr;
62
75
  dynamicData.push({
63
76
  ...campaign,
64
77
  totalSupplyTargetToken: marketSupply,
65
78
  tvl: tvl,
66
- apr: priceRewardToken !== 0
67
- ? (priceRewardToken *
68
- BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
69
- YEAR *
70
- 100) /
71
- campaign.campaignParameters.duration /
72
- tvl
73
- : 0,
79
+ apr,
74
80
  priceRewardToken: priceRewardToken,
75
81
  });
76
82
  }
@@ -111,14 +111,17 @@ export class MorphoDynamicData {
111
111
  console.log(e);
112
112
  }
113
113
  }
114
+ let apr = (priceRewardToken * BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) * YEAR * 100) /
115
+ campaign.campaignParameters.duration /
116
+ tvl;
117
+ const rewardTokens = await TokenService.findManyOrCreate([
118
+ { chainId: campaign.chainId, address: campaign.rewardToken },
119
+ ]);
120
+ const rewardToken = rewardTokens[0];
121
+ apr = rewardToken.isPoint ? apr / 365 / 100 : apr;
114
122
  dynamicData.push({
115
123
  ...campaign,
116
- apr: (priceRewardToken *
117
- BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
118
- YEAR *
119
- 100) /
120
- campaign.campaignParameters.duration /
121
- tvl,
124
+ apr,
122
125
  totalSupplyTargetToken,
123
126
  tvl: tvl,
124
127
  priceRewardToken: priceRewardToken,
@@ -97,15 +97,21 @@ export class RadiantDynamicData {
97
97
  })) ?? 0;
98
98
  }
99
99
  i++;
100
+ let apr = (lastEligibilityRatio *
101
+ priceRewardToken *
102
+ BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
103
+ YEAR *
104
+ 100) /
105
+ campaign.campaignParameters.duration /
106
+ (totalSupplyTargetToken * priceTargetToken);
107
+ const rewardTokens = await TokenService.findManyOrCreate([
108
+ { chainId: campaign.chainId, address: campaign.rewardToken },
109
+ ]);
110
+ const rewardToken = rewardTokens[0];
111
+ apr = rewardToken.isPoint ? apr / 365 / 100 : apr;
100
112
  dynamicData.push({
101
113
  ...campaign,
102
- apr: (lastEligibilityRatio *
103
- priceRewardToken *
104
- BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
105
- YEAR *
106
- 100) /
107
- campaign.campaignParameters.duration /
108
- (totalSupplyTargetToken * priceTargetToken),
114
+ apr,
109
115
  totalSupplyTargetToken,
110
116
  tvl: totalSupplyTargetToken * priceTargetToken,
111
117
  lastEligibilityRatio,
@@ -91,14 +91,17 @@ export class SiloDynamicData {
91
91
  }
92
92
  // Remove all silo forwarders
93
93
  campaign.campaignParameters.forwarders = forwarders.filter(forwarder => forwarder.forwarderType !== Forwarder.SILO);
94
+ let apr = (priceRewardToken * BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) * YEAR * 100) /
95
+ campaign.campaignParameters.duration /
96
+ (totalSupplyTargetToken * priceTargetToken);
97
+ const rewardTokens = await TokenService.findManyOrCreate([
98
+ { chainId: campaign.chainId, address: campaign.rewardToken },
99
+ ]);
100
+ const rewardToken = rewardTokens[0];
101
+ apr = rewardToken.isPoint ? apr / 365 / 100 : apr;
94
102
  dynamicData.push({
95
103
  ...campaign,
96
- apr: (priceRewardToken *
97
- BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
98
- YEAR *
99
- 100) /
100
- campaign.campaignParameters.duration /
101
- (totalSupplyTargetToken * priceTargetToken),
104
+ apr,
102
105
  totalSupplyTargetToken,
103
106
  tvl: totalSupplyTargetToken * priceTargetToken,
104
107
  priceRewardToken: priceRewardToken,
@@ -224,6 +224,11 @@ export class UniswapV4DynamicData {
224
224
  aprs[poolAPRkey] += distributionMeanAPR;
225
225
  }
226
226
  }
227
+ const rewardTokens = await TokenService.findManyOrCreate([
228
+ { chainId: campaign.chainId, address: campaign.rewardToken },
229
+ ]);
230
+ const rewardToken = rewardTokens[0];
231
+ distributionMeanAPR = rewardToken.isPoint ? distributionMeanAPR / 365 / 100 : distributionMeanAPR;
227
232
  dynamicData.push({
228
233
  ...campaign,
229
234
  apr: distributionMeanAPR,
@@ -40,14 +40,17 @@ export class VestDynamicData {
40
40
  symbol: "USDC.e",
41
41
  })) ?? 0;
42
42
  const tvl = totalSupply * priceTargetToken;
43
+ let apr = (priceRewardToken * BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) * YEAR * 100) /
44
+ campaign.campaignParameters.duration /
45
+ (totalSupply * priceTargetToken);
46
+ const rewardTokens = await TokenService.findManyOrCreate([
47
+ { chainId: campaign.chainId, address: campaign.rewardToken },
48
+ ]);
49
+ const rewardToken = rewardTokens[0];
50
+ apr = rewardToken.isPoint ? apr / 365 / 100 : apr;
43
51
  dynamicData.push({
44
52
  ...campaign,
45
- apr: (priceRewardToken *
46
- BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) *
47
- YEAR *
48
- 100) /
49
- campaign.campaignParameters.duration /
50
- (totalSupply * priceTargetToken),
53
+ apr,
51
54
  totalSupplyTargetToken: totalSupply,
52
55
  tvl,
53
56
  priceRewardToken: priceRewardToken,
@@ -1,4 +1,4 @@
1
- import { type Campaign, type CampaignDynamicData } from "@sdk";
1
+ import { Campaign, type CampaignDynamicData } from "@sdk";
2
2
  export type CampaignsCacheUpdaterReturnType = {
3
3
  [type_mainParameter: string]: {
4
4
  [campaignId: string]: CampaignDynamicData<Campaign>;
@@ -1,7 +1,18 @@
1
- import { campaignCacheUpdate } from "@/backgroundJobs/jobs/campaignsCacheUpdater";
1
+ // @ts-nocheck
2
+ /**
3
+ @deprecated Used only for the v3/campaigns route
4
+ */
5
+ import { Redis } from "@/cache";
6
+ import { dynamicDataBuilderFactory } from "@/engine/dynamicData/factory";
7
+ import { merklChainData } from "@/libs/merklChainData";
8
+ import { staticCampaignWithCache } from "@/libs/staticCampaigns";
2
9
  import { InvalidParameter, UnsupportedNetwork } from "@/utils/error";
3
- import { ChainId, isSupportedChain } from "@sdk";
4
- const campaignTypes = process.env.CAMPAIGN_TYPES ? JSON.parse(process.env.CAMPAIGN_TYPES) : [];
10
+ import { log } from "@/utils/logger";
11
+ import { ALL_CAMPAIGNS_FOR_CHAIN_AFTER } from "@/utils/queries/allCampaigns";
12
+ import { engineDbClient } from "@db";
13
+ import { Campaign, ChainId, NETWORK_LABELS, isSupportedChain, } from "@sdk";
14
+ import moment from "moment";
15
+ const queryCampaignTypes = process.env.CAMPAIGN_TYPES ? JSON.parse(process.env.CAMPAIGN_TYPES) : [];
5
16
  const highCampaignsChains = [ChainId.ARBITRUM, ChainId.POLYGON, ChainId.BLAST, ChainId.BASE];
6
17
  export const main = async () => {
7
18
  const rawChainId = process.env.CHAIN_ID;
@@ -14,7 +25,114 @@ export const main = async () => {
14
25
  else {
15
26
  throw new InvalidParameter("Invalid chainId provided");
16
27
  }
17
- return campaignCacheUpdate(rawChainId, campaignTypes, highCampaignsChains);
28
+ let success = true;
29
+ try {
30
+ await Redis.safeSet(`MerklChainData_${chainId}`, await merklChainData(chainId));
31
+ }
32
+ catch (error) {
33
+ log.error(`❌ update merklChainData cache failed for ${NETWORK_LABELS[chainId]}`, error);
34
+ success = false;
35
+ }
36
+ log.local(`🔁 updating ${NETWORK_LABELS[chainId]} Campaigns cache`);
37
+ let campaignsAfter = moment().subtract(3, "months").unix();
38
+ if (highCampaignsChains.includes(chainId)) {
39
+ campaignsAfter = moment().subtract(1, "months").unix();
40
+ }
41
+ const TWO_WEEKS_AGO = moment().subtract(2, "weeks").unix();
42
+ try {
43
+ const dynamicData = {};
44
+ let staticData = (await engineDbClient.$queryRaw(ALL_CAMPAIGNS_FOR_CHAIN_AFTER(chainId, campaignsAfter)));
45
+ log.local(`Data length before filtering: ${staticData.length}`);
46
+ const mainParameters = {};
47
+ staticData = staticData.filter(campaign => {
48
+ if (campaign.endTimestamp < TWO_WEEKS_AGO && campaign.campaignType === Campaign.CLAMM) {
49
+ campaign.campaignParameters.forwarders = [];
50
+ }
51
+ mainParameters[campaign.mainParameter] = true;
52
+ return true;
53
+ });
54
+ log.local(`Data length after filtering: ${staticData.length}`);
55
+ if (!!staticData) {
56
+ // Build list of existing campaign types for this chain
57
+ const campaignTypes = !!queryCampaignTypes?.length
58
+ ? queryCampaignTypes
59
+ : !staticData
60
+ ? []
61
+ : staticData
62
+ .map(campaign => campaign.campaignType)
63
+ .reduce((prev, campaignType) => {
64
+ if (!prev.includes(campaignType))
65
+ prev.push(campaignType);
66
+ return prev;
67
+ }, []);
68
+ // Fetch dynamic data for all these types
69
+ const promisesPerType = campaignTypes.map(async (campaignType) => {
70
+ const campaigns = staticData.filter(campaign => campaign.campaignType === campaignType);
71
+ await dynamicDataBuilderFactory(campaignType)
72
+ .build(chainId, campaigns)
73
+ .then(r => {
74
+ for (const d of r) {
75
+ if (!!d) {
76
+ // Main Parameter OVERRIDING
77
+ if (d.campaignType === Campaign.SILO && d.campaignParameters.whitelist?.length === 1) {
78
+ d.mainParameter = `${d.mainParameter}-${d.campaignParameters.whitelist[0]}`;
79
+ }
80
+ if (!dynamicData[`${d.campaignType}_${d.mainParameter}`])
81
+ dynamicData[`${d.campaignType}_${d.mainParameter}`] = {};
82
+ dynamicData[`${d.campaignType}_${d.mainParameter}`][d.campaignId] = d;
83
+ }
84
+ }
85
+ });
86
+ });
87
+ await Promise.all(promisesPerType);
88
+ }
89
+ if (!!dynamicData && Object.keys(dynamicData).length > 0) {
90
+ await Redis.safeSet(`Campaigns_${chainId}`, dynamicData);
91
+ // Set live or future campaigns
92
+ const liveDynamicData = {};
93
+ for (const [type_mainParameter, value] of Object.entries(dynamicData)) {
94
+ for (const [campaignId, data] of Object.entries(value)) {
95
+ if (data.endTimestamp > moment().unix()) {
96
+ if (!liveDynamicData[type_mainParameter]) {
97
+ liveDynamicData[type_mainParameter] = {};
98
+ }
99
+ liveDynamicData[type_mainParameter][campaignId] = data;
100
+ }
101
+ }
102
+ }
103
+ await Redis.safeSet(`LiveCampaigns_${chainId}`, liveDynamicData);
104
+ const merklChainData = await Redis.get("MerklChainData", chainId);
105
+ await Redis.safeSet(`CampaignsOldFormat_${chainId}`, campaignsToOldFormat(dynamicData, merklChainData));
106
+ await Redis.safeSet(`LiveCampaignsOldFormat_${chainId}`, campaignsToOldFormat(liveDynamicData, merklChainData));
107
+ log.info(`✅ ${NETWORK_LABELS[chainId]} caches updated successfully`);
108
+ }
109
+ else {
110
+ if (chainId === ChainId.CORE || chainId === ChainId.THUNDERCORE) {
111
+ log.info(`⚠️ no campaigns found for ${NETWORK_LABELS[chainId]}, setting empty cache`);
112
+ for (const key of [
113
+ "Campaigns",
114
+ "LiveCampaigns",
115
+ "CampaignsOldFormat",
116
+ "LiveCampaignsOldFormat",
117
+ ]) {
118
+ await Redis.safeSet(`${key}_${chainId}`, {});
119
+ }
120
+ log.info(`✅ ${NETWORK_LABELS[chainId]} caches updated - empty cache`);
121
+ }
122
+ }
123
+ }
124
+ catch (error) {
125
+ log.error(`❌ update Campaigns cache failed for ${NETWORK_LABELS[chainId]}`, error);
126
+ success = false;
127
+ }
128
+ // This is independant of campaigns cache update, so not in the if condition
129
+ try {
130
+ await staticCampaignWithCache(chainId);
131
+ }
132
+ catch (error) {
133
+ log.error(`❌ update Campaigns cache failed for ${NETWORK_LABELS[chainId]}`, error);
134
+ }
135
+ return { success };
18
136
  };
19
137
  main()
20
138
  .then(success => (success ? process.exit(0) : process.exit(1)))
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,72 @@
1
+ import { metadataBuilderFactory } from "@/engine/opportunityMetadata/factory";
2
+ import { log } from "@/utils/logger";
3
+ import { apiDbClient } from "@db";
4
+ import { Campaign as CampaignEnum } from "@sdk";
5
+ const opportunities = await apiDbClient.opportunity.findMany({
6
+ select: {
7
+ id: true,
8
+ name: true,
9
+ explorerAddress: true,
10
+ depositUrl: true,
11
+ MainProtocol: {
12
+ select: {
13
+ url: true,
14
+ },
15
+ },
16
+ type: true,
17
+ Campaigns: {
18
+ take: 1,
19
+ include: {
20
+ RewardToken: {
21
+ select: {
22
+ address: true,
23
+ },
24
+ },
25
+ },
26
+ },
27
+ },
28
+ where: {
29
+ status: "PAST",
30
+ id: {
31
+ gt: "8105750301162585090",
32
+ },
33
+ },
34
+ orderBy: {
35
+ id: "asc",
36
+ },
37
+ });
38
+ for (const opportunity of opportunities) {
39
+ try {
40
+ const campaign = opportunity?.Campaigns?.[0];
41
+ const metadata = await metadataBuilderFactory(CampaignEnum[opportunity.type]).build(campaign?.computeChainId, campaign?.params, campaign?.subType, campaign?.RewardToken?.address, campaign?.distributionChainId, campaign.campaignId, campaign.creatorAddress);
42
+ if (!!metadata?.explorerAddress && !opportunity.explorerAddress) {
43
+ await apiDbClient.opportunity.update({
44
+ where: {
45
+ id: opportunity.id,
46
+ },
47
+ data: {
48
+ explorerAddress: metadata.explorerAddress,
49
+ },
50
+ });
51
+ log.info(`updated explorerAdd for ${opportunity.id} - ${opportunity.name} to ${metadata.explorerAddress}`);
52
+ }
53
+ if (!!metadata?.depositUrl &&
54
+ (!opportunity.depositUrl ||
55
+ (opportunity.depositUrl === opportunity?.MainProtocol?.url &&
56
+ metadata.depositUrl !== opportunity?.MainProtocol?.url))) {
57
+ await apiDbClient.opportunity.update({
58
+ where: {
59
+ id: opportunity.id,
60
+ },
61
+ data: {
62
+ depositUrl: metadata.depositUrl,
63
+ },
64
+ });
65
+ log.info(`updated depositUrl for ${opportunity.id} - ${opportunity.name} from ${opportunity.depositUrl} to ${metadata.depositUrl}`);
66
+ }
67
+ }
68
+ catch (e) {
69
+ console.error(e);
70
+ }
71
+ }
72
+ process.exit(0);
@@ -2,8 +2,12 @@ import { CacheService } from "@/modules/v4/cache";
2
2
  import { TTLPresets } from "@/modules/v4/cache/cache.model";
3
3
  import { ChainService } from "@/modules/v4/chain/chain.service";
4
4
  import { MerklRootRepository } from "@/modules/v4/merklRoot/merklRoot.repository";
5
+ import { OpportunityService } from "@/modules/v4/opportunity";
5
6
  import { NETWORK_LABELS, log } from "@sdk";
6
7
  const main = async () => {
8
+ // ─── Refresh Cache For GET /opportunities ────
9
+ await CacheService.set(TTLPresets.MIN_5, OpportunityService.findMany, { items: 25, page: 0 });
10
+ await CacheService.set(TTLPresets.MIN_5, OpportunityService.findMany, { items: 50, page: 0 });
7
11
  try {
8
12
  const chains = await ChainService.getSupportedIds();
9
13
  const promises = [];
@@ -1,4 +1,4 @@
1
- import type { CampaignsCacheUpdaterReturnType } from "@/backgroundJobs/jobs/campaignsCacheUpdater";
1
+ import type { CampaignsCacheUpdaterReturnType } from "@/jobs/dynamic-data";
2
2
  import { AMM, type ChainId, type MerklAPIType } from "@sdk";
3
3
  import type { MerklChainData } from "../../types";
4
4
  export declare function getClamsInfo(chainIds?: number[] | readonly ChainId[], AMMs?: Lowercase<keyof typeof AMM>[], user?: string, onlyLive?: boolean): Promise<MerklAPIType>;