@merkl/api 0.10.406 → 0.10.408
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,12 +1,12 @@
|
|
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 ───────────────────────────────────────────────
|
9
|
-
const BATCH_SIZE =
|
9
|
+
const BATCH_SIZE = 5_000;
|
10
10
|
// ─── Global Variables ────────────────────────────────────────
|
11
11
|
const [chainIdString, root, campaignId] = process.env.FILENAME.split("_");
|
12
12
|
const chainId = Number.parseInt(chainIdString);
|
@@ -49,7 +49,7 @@ const extract = async () => {
|
|
49
49
|
};
|
50
50
|
// ─── Transform & Load ────────────────────────────────────────────────────────
|
51
51
|
const load = async (pendings) => {
|
52
|
-
const { updated, created } = await
|
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();
|