@merkl/api 0.15.42 → 0.15.44

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.
@@ -1160,7 +1160,7 @@ export const extractOpportunities = {
1160
1160
  const opportunity = {
1161
1161
  id: `${Campaign.UNISWAP_V4}_${mainParameter}`,
1162
1162
  platform,
1163
- name: [platform, pair, params.lpFee && `${params.lpFee} %`].join(" "),
1163
+ name: [platform, pair, params.lpFee && `${params.lpFee / 10_000} %`].join(" "),
1164
1164
  chainId: computeChainId ?? chainId,
1165
1165
  distributionChainId: chainId,
1166
1166
  action: "pool",
@@ -80,7 +80,16 @@ const transform = (rewardBreakdowns) => {
80
80
  // ─── Load ────────────────────────────────────────────────────────────────────
81
81
  const load = async (rewardBreakdowns) => {
82
82
  const count = (await apiDbClient.rewardBreakdown.createMany({
83
- data: rewardBreakdowns,
83
+ data: rewardBreakdowns.map(breakdown => ({
84
+ id: breakdown.id,
85
+ protocolId: breakdown.protocolId,
86
+ reason: breakdown.reason,
87
+ amount: breakdown.amount,
88
+ claimed: breakdown.claimed,
89
+ pending: breakdown.pending,
90
+ rewardId: breakdown.rewardId,
91
+ campaignId: breakdown.campaignId,
92
+ })),
84
93
  skipDuplicates: true,
85
94
  })).count;
86
95
  log.info(`Successfully inserted ${rewardBreakdowns.length} reward breakdown(s).`);
@@ -132,7 +141,7 @@ export const main = async () => {
132
141
  log.error("breakdowns", `${failedBatches.length} breakdown(s) failed to insert.`);
133
142
  // ─── Push Missing Campaigns To Bucket ────────────────
134
143
  const bucket = new BucketService(`merkl-campaigns-lake-${process.env.ENV}`, `merkl-data-${process.env.ENV}`);
135
- await bucket.push(`${process.env.CHAIN_ID}_missing_campaigns`, JSON.stringify(missingCampaigns), {
144
+ await bucket.push(`${process.env.CHAIN_ID}_missing_campaigns.json`, JSON.stringify(missingCampaigns), {
136
145
  type: "application/json",
137
146
  });
138
147
  process.exit(1);
@@ -1,8 +1,47 @@
1
- import { BN2Number, EAprBreakdownType, NETWORK_LABELS, UniswapV4Addresses, UniswapV4StateViewInterface, getSqrtRatioAtTick, shortenAddress, } from "@sdk";
1
+ import { BucketService } from "../../../modules/v4/bucket/bucket.service";
2
+ import { engineDbClient } from "../../../utils/prisma";
3
+ import { BN2Number, ChainInteractionService, EAprBreakdownType, NETWORK_LABELS, UniswapV4Addresses, UniswapV4StateViewInterface, getSqrtRatioAtTick, shortenAddress, } from "@sdk";
2
4
  import moment from "moment";
3
5
  import { log } from "../../../utils/logger";
4
6
  import { Pricer } from "../../../utils/pricer";
7
+ // Constants
5
8
  const CALLS_LENGTH = 2;
9
+ /**
10
+ * Compute TVL
11
+ * @dev important: using the most recent state save with current prices
12
+ * it's only an estimate
13
+ */
14
+ async function computeUniV4PoolTVLFromMostRecentStateSave(chainId, poolID, priceCurrency0, priceCurrency1, decimalsCurrency0, decimalsCurrency1) {
15
+ const currentBlock = await ChainInteractionService(chainId).getBlockNumber();
16
+ const mostRecentStateSave = await engineDbClient.stateSave.findFirst({
17
+ where: {
18
+ id: `UniswapV4_${chainId}_${poolID}`,
19
+ blockNumber: {
20
+ lte: currentBlock,
21
+ },
22
+ },
23
+ orderBy: {
24
+ blockNumber: "desc",
25
+ },
26
+ });
27
+ const stateSave = mostRecentStateSave.state;
28
+ const blockNumber = mostRecentStateSave?.blockNumber;
29
+ const states = stateSave.states;
30
+ // const globalState = stateSave.globalState as { tick: number; liquidity: string };
31
+ const { fileName, bucketName } = states;
32
+ // Bucket service
33
+ const bucket = new BucketService(bucketName, "merkl-production");
34
+ const storedStates = JSON.parse(await bucket.pull(fileName));
35
+ let tvl = 0;
36
+ let amount0 = 0;
37
+ let amount1 = 0;
38
+ for (const [_, { value, params }] of Object.entries(storedStates)) {
39
+ amount0 += BN2Number(value.amount0, decimalsCurrency0);
40
+ amount1 += BN2Number(value.amount1, decimalsCurrency1);
41
+ }
42
+ tvl = amount0 * (priceCurrency0 ?? 0) + amount1 * (priceCurrency1 ?? 0);
43
+ return { tvl, amount0, amount1, blockNumber: blockNumber };
44
+ }
6
45
  export async function UniswapV4DynamicData(chainId, campaigns) {
7
46
  const dynamicData = [];
8
47
  const pricer = await Pricer.load();
@@ -28,18 +67,7 @@ export async function UniswapV4DynamicData(chainId, campaigns) {
28
67
  allowFailure: true,
29
68
  callData: UniswapV4StateViewInterface.encodeFunctionData("getSlot0", [pool.poolId]),
30
69
  target: UniswapV4Addresses[chainId].StateView,
31
- }
32
- // {
33
- // allowFailure: true,
34
- // callData: ERC20Interface.encodeFunctionData("balanceOf", [pool.address]),
35
- // target: d.campaignParameters.token0,
36
- // },
37
- // {
38
- // allowFailure: true,
39
- // callData: ERC20Interface.encodeFunctionData("balanceOf", [pool.address]),
40
- // target: d.campaignParameters.token1,
41
- // }
42
- );
70
+ });
43
71
  }
44
72
  return {
45
73
  cached: false,
@@ -54,43 +82,38 @@ export async function UniswapV4DynamicData(chainId, campaigns) {
54
82
  let poolTotalLiquidity;
55
83
  let sqrtPrice;
56
84
  let tick;
57
- const poolBalanceToken0 = 0;
58
- const poolBalanceToken1 = 0;
85
+ let poolBalanceToken0 = 0;
86
+ let poolBalanceToken1 = 0;
59
87
  const campaignsForPool = campaigns?.filter(campaign => campaign.mainParameter.toLowerCase() === pool.mainParameter.toLowerCase());
60
- // const decimalsToken0 = d.campaignParameters.decimalsCurrency0;
61
- // const decimalsToken1 = d.campaignParameters.decimalsCurrency1;
62
- const symbolToken0 = campaignsForPool[0].campaignParameters.symbolCurrency0;
63
- const symbolToken1 = campaignsForPool[0].campaignParameters.symbolCurrency1;
64
88
  const prevI = i;
65
89
  try {
66
90
  poolTotalLiquidity = UniswapV4StateViewInterface.decodeFunctionResult("getLiquidity", result[i++])[0].toString();
67
91
  const poolData = UniswapV4StateViewInterface.decodeFunctionResult("getSlot0", result[i++]);
68
92
  tick = poolData.tick;
69
93
  sqrtPrice = getSqrtRatioAtTick(tick).toString();
70
- // poolBalanceToken0 = BN2Number(
71
- // ERC20Interface.decodeFunctionResult("balanceOf", result[i++])[0],
72
- // decimalsToken0
73
- // );
74
- // poolBalanceToken1 = BN2Number(
75
- // ERC20Interface.decodeFunctionResult("balanceOf", result[i++])[0],
76
- // decimalsToken1
77
- // );
78
94
  }
79
95
  catch {
80
96
  log.warn(`merklDynamic data - failed to decode state of pool ${pool.poolId} on ${NETWORK_LABELS[chainId]}`);
81
97
  i = prevI + CALLS_LENGTH;
82
98
  continue;
83
99
  }
100
+ const decimalsCurrency0 = campaignsForPool[0].campaignParameters.decimalsCurrency0;
101
+ const decimalsCurrency1 = campaignsForPool[0].campaignParameters.decimalsCurrency1;
102
+ const symbolCurrency0 = campaignsForPool[0].campaignParameters.symbolCurrency0;
103
+ const symbolCurrency1 = campaignsForPool[0].campaignParameters.symbolCurrency1;
84
104
  const priceToken0 = (await pricer.get({
85
105
  address: campaignsForPool[0].campaignParameters.currency0,
86
106
  chainId: chainId,
87
- symbol: symbolToken0,
107
+ symbol: symbolCurrency0,
88
108
  }));
89
109
  const priceToken1 = (await pricer.get({
90
110
  address: campaignsForPool[0].campaignParameters.currency1,
91
111
  chainId: chainId,
92
- symbol: symbolToken1,
112
+ symbol: symbolCurrency1,
93
113
  }));
114
+ const { tvl, amount0, amount1, blockNumber } = await computeUniV4PoolTVLFromMostRecentStateSave(chainId, pool.poolId, priceToken0, priceToken1, decimalsCurrency0, decimalsCurrency1);
115
+ poolBalanceToken0 += amount0;
116
+ poolBalanceToken1 += amount1;
94
117
  /** Iterate over distributions to compute APRs */
95
118
  for (const campaign of campaignsForPool) {
96
119
  const c = campaign;
@@ -135,8 +158,8 @@ export async function UniswapV4DynamicData(chainId, campaigns) {
135
158
  /**
136
159
  * General APR (@notice potentially with a boost)
137
160
  */
138
- const poolBalanceToken0WithoutBlacklist = 0;
139
- const poolBalanceToken1WithoutBlacklist = 0;
161
+ const poolBalanceToken0WithoutBlacklist = poolBalanceToken0;
162
+ const poolBalanceToken1WithoutBlacklist = poolBalanceToken1;
140
163
  // const poolLiquidityWithoutBlacklist = poolTotalLiquidity - (blacklistedLiquidity ?? 0);
141
164
  const tvl = poolBalanceToken0WithoutBlacklist * priceToken0 + poolBalanceToken1WithoutBlacklist * priceToken1;
142
165
  distributionMeanAPR = (yearlyToken0Rewards + yearlyToken1Rewards + yearlyFeeRewards) / tvl;
@@ -57,7 +57,7 @@ export class StatusService {
57
57
  }
58
58
  static async findUpdatesAndDelays() {
59
59
  const merklRoots = await MerklRootService.fetchAll();
60
- const delayedCampaignPromises = Promise.allSettled(Object.keys(merklRoots).map(chainId => StatusService.findManyDelay({ chainId: Number.parseInt(chainId), delayLowerBound: 8 * HOUR })));
60
+ const delayedCampaignPromises = Promise.allSettled(Object.keys(merklRoots).map(chainId => StatusService.findManyDelay({ chainId: Number.parseInt(chainId), delayLowerBound: 9 * HOUR })));
61
61
  const liveCampaignPromises = await Promise.allSettled(Object.keys(merklRoots).map(chainId => CampaignService.countLives(Number.parseInt(chainId))));
62
62
  const delayedCampaignArray = await delayedCampaignPromises;
63
63
  const liveCampaignArray = await liveCampaignPromises;