@merkl/api 0.10.406 → 0.10.407

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.
@@ -1,8 +1,8 @@
1
1
  // ─── Pending Rewards Etl ─────────────────────────────────────────────────────
2
2
  if (!process.env.ENV || !process.env.FILENAME)
3
3
  throw new Error("[ENV]: missing variable");
4
- import { RewardService } from "../../modules/v4/reward";
5
4
  import { log } from "../../utils/logger";
5
+ import { apiDbClient } from "../../utils/prisma";
6
6
  import { S3Client } from "bun";
7
7
  import moment from "moment";
8
8
  // ─── Constants ───────────────────────────────────────────────
@@ -49,7 +49,7 @@ const extract = async () => {
49
49
  };
50
50
  // ─── Transform & Load ────────────────────────────────────────────────────────
51
51
  const load = async (pendings) => {
52
- const { updated, created } = await RewardService.updatePendings({
52
+ const { updated, created } = await updatePendings({
53
53
  distributionChainId: chainId,
54
54
  rewardToken: pendings[0].rewardToken,
55
55
  campaignId,
@@ -58,6 +58,133 @@ const load = async (pendings) => {
58
58
  });
59
59
  return updated + created;
60
60
  };
61
+ const updatePendings = async (data) => {
62
+ const rewardTokenId = Bun.hash(`${data.distributionChainId}${data.rewardToken}`).toString();
63
+ const campaignId = Bun.hash(`${data.distributionChainId}${data.campaignId}`).toString();
64
+ const rewardUniques = {};
65
+ // Adds a record to the Reward row where pendings need to be updated
66
+ const updateRewardUniques = (recipient, pending, previousPending) => {
67
+ Bun.hash(`${root}${recipient}${rewardTokenId}`).toString();
68
+ const rewardId = Bun.hash(`${data.root}${recipient}${rewardTokenId}`).toString();
69
+ if (!rewardUniques[rewardId]) {
70
+ rewardUniques[rewardId] = { pending: "0", recipient: recipient };
71
+ }
72
+ rewardUniques[rewardId].pending = (BigInt(rewardUniques[rewardId].pending) +
73
+ BigInt(pending) -
74
+ BigInt(previousPending ?? "0")) // Store the delta
75
+ .toString();
76
+ };
77
+ const breakdownUniques = await data.data.map(({ recipient, reason }) => {
78
+ const rewardId = Bun.hash(`${data.root}${recipient}${rewardTokenId}`).toString();
79
+ return { rewardId, reason, campaignId };
80
+ });
81
+ const breakdownToUpdate = [];
82
+ const breakdownToCreate = [];
83
+ const breakdownExists = await apiDbClient.$transaction(breakdownUniques.map(x => apiDbClient.rewardBreakdown.findUnique({
84
+ select: {
85
+ pending: true,
86
+ },
87
+ where: {
88
+ rewardId_campaignId_reason: {
89
+ rewardId: x.rewardId,
90
+ campaignId: x.campaignId,
91
+ reason: x.reason,
92
+ },
93
+ },
94
+ })));
95
+ for (const [pointIndex, point] of data.data.entries()) {
96
+ updateRewardUniques(point.recipient, point.pending, breakdownExists[pointIndex]?.pending);
97
+ if (!!breakdownExists[pointIndex]) {
98
+ breakdownToUpdate.push(point);
99
+ }
100
+ else {
101
+ breakdownToCreate.push(point);
102
+ }
103
+ }
104
+ const toUpdate = [];
105
+ const toCreate = [];
106
+ const exists = await apiDbClient.$transaction(Object.keys(rewardUniques).map(x => apiDbClient.reward.findUnique({
107
+ select: {
108
+ pending: true,
109
+ },
110
+ where: {
111
+ id: x,
112
+ },
113
+ })));
114
+ for (const [pointIndex, point] of Object.values(rewardUniques).entries()) {
115
+ if (!!exists[pointIndex]) {
116
+ toUpdate.push({
117
+ ...point,
118
+ pending: (BigInt(exists[pointIndex].pending) + BigInt(point.pending)).toString(), // Store the delta
119
+ });
120
+ }
121
+ else {
122
+ toCreate.push(point);
123
+ }
124
+ }
125
+ await apiDbClient.$transaction(toUpdate.map(x => {
126
+ const rewardId = Bun.hash(`${data.root}${x.recipient}${rewardTokenId}`).toString();
127
+ return apiDbClient.reward.update({
128
+ where: {
129
+ id: rewardId,
130
+ },
131
+ data: {
132
+ pending: x.pending,
133
+ },
134
+ });
135
+ }));
136
+ let users = toCreate.map(x => x.recipient);
137
+ await apiDbClient.user.createMany({ data: users.map(x => ({ address: x, tags: [] })), skipDuplicates: true });
138
+ await apiDbClient.$transaction(toCreate.map(x => {
139
+ const rewardId = Bun.hash(`${root}${x.recipient}${rewardTokenId}`).toString();
140
+ return apiDbClient.reward.create({
141
+ data: {
142
+ id: rewardId,
143
+ MerklRoot: { connect: { root } },
144
+ User: { connect: { address: x.recipient } },
145
+ RewardToken: { connect: { id: rewardTokenId } },
146
+ proofs: [],
147
+ amount: "0",
148
+ pending: x.pending,
149
+ claimed: "0",
150
+ },
151
+ });
152
+ }));
153
+ await apiDbClient.$transaction(breakdownToUpdate.map(x => {
154
+ return apiDbClient.rewardBreakdown.update({
155
+ where: {
156
+ rewardId_campaignId_reason: {
157
+ rewardId: Bun.hash(`${root}${x.recipient}${rewardTokenId}`).toString(),
158
+ campaignId: campaignId,
159
+ reason: x.reason,
160
+ },
161
+ },
162
+ data: {
163
+ pending: x.pending,
164
+ },
165
+ });
166
+ }));
167
+ users = toCreate.map(x => x.recipient);
168
+ await apiDbClient.user.createMany({ data: users.map(x => ({ address: x, tags: [] })), skipDuplicates: true });
169
+ await apiDbClient.$transaction(breakdownToCreate.map(x => {
170
+ const rewardId = Bun.hash(`${root}${x.recipient}${rewardTokenId}`).toString();
171
+ return apiDbClient.rewardBreakdown.create({
172
+ data: {
173
+ reason: x.reason,
174
+ amount: "0",
175
+ pending: x.pending,
176
+ claimed: "0",
177
+ Reward: {
178
+ connect: {
179
+ id: rewardId,
180
+ },
181
+ },
182
+ Campaign: { connect: { id: campaignId } },
183
+ },
184
+ });
185
+ }));
186
+ return { created: breakdownToCreate.length, updated: breakdownToUpdate.length };
187
+ };
61
188
  // ─────────────────────────────────────────────────────────────────────────────
62
189
  export const main = async () => {
63
190
  const start = moment().unix();