@render-foundation/utils 0.0.165 → 0.0.166
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.
- package/lib/cjs/backfiller.js +640 -270
- package/lib/cjs/backfiller.js.map +1 -1
- package/lib/cjs/constants.js +2 -1
- package/lib/cjs/constants.js.map +1 -1
- package/lib/esm/src/backfiller.js +605 -254
- package/lib/esm/src/backfiller.js.map +1 -1
- package/lib/esm/src/constants.js +1 -0
- package/lib/esm/src/constants.js.map +1 -1
- package/lib/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/types/src/backfiller.d.ts +24 -15
- package/lib/types/src/backfiller.d.ts.map +1 -1
- package/lib/types/src/constants.d.ts +1 -0
- package/lib/types/src/constants.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,194 +1,445 @@
|
|
|
1
|
-
import { PublicKey } from
|
|
2
|
-
import { renderMint, buyAndBurnEscrow, passthruEscrow, v3SquadsVault, upgradeRewardsEscrow, upgradeRewardsCircuitBreaker, usdcMint, devsSquadsVault, masterSquadsVault, bridgeEscrow, } from
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import { renderMint, buyAndBurnEscrow, passthruEscrow, v3SquadsVault, upgradeRewardsEscrow, upgradeRewardsCircuitBreaker, usdcMint, devsSquadsVault, masterSquadsVault, bridgeEscrow, polyBridgeEscrow, } from "./constants";
|
|
3
|
+
import { pgClient } from "./client/pg/v2Client";
|
|
4
|
+
import { emissionDistributorKey, emissionDistributorV1Key } from "@render-foundation/emission-distributor-sdk";
|
|
5
|
+
import { Helius } from "helius-sdk";
|
|
6
|
+
export const solscanProClient = (apiKey) => {
|
|
5
7
|
const headers = {
|
|
6
|
-
|
|
7
|
-
'accept-language': 'en-US,en;q=0.9',
|
|
8
|
-
'accept-encoding': 'gzip, deflate, br',
|
|
9
|
-
connection: 'keep-alive',
|
|
10
|
-
cookie: cookie,
|
|
11
|
-
origin: 'https://solscan.io',
|
|
12
|
-
referer: 'https://solscan.io/',
|
|
13
|
-
'sec-ch-ua': '"Not A(Brand";v="99", "Google Chrome";v="120", "Chromium";v="120"',
|
|
14
|
-
'sec-ch-ua-mobile': '?0',
|
|
15
|
-
'sec-ch-ua-platform': '"macOS"',
|
|
16
|
-
'sec-fetch-dest': 'empty',
|
|
17
|
-
'sec-fetch-mode': 'cors',
|
|
18
|
-
'sec-fetch-site': 'same-site',
|
|
19
|
-
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
20
|
-
'cache-control': 'no-cache',
|
|
21
|
-
pragma: 'no-cache',
|
|
8
|
+
token: apiKey,
|
|
22
9
|
};
|
|
23
|
-
const
|
|
10
|
+
const baseUrl = "https://pro-api.solscan.io/v2.0";
|
|
24
11
|
return {
|
|
25
|
-
async
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
12
|
+
async getSignaturesForAddress(addr, options) {
|
|
13
|
+
const allSignatures = [];
|
|
14
|
+
let before = options?.before;
|
|
15
|
+
const limit = Math.min(options?.limit || 40, 40);
|
|
16
|
+
while (true) {
|
|
17
|
+
const params = new URLSearchParams({
|
|
18
|
+
address: addr.toString(),
|
|
19
|
+
limit: limit.toString(),
|
|
20
|
+
});
|
|
21
|
+
if (before) {
|
|
22
|
+
params.append("before", before);
|
|
23
|
+
}
|
|
24
|
+
const endpoint = `${baseUrl}/account/transactions?${params}`;
|
|
25
|
+
const response = await fetch(endpoint, { headers });
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
throw new Error(`Failed to fetch signatures: ${response.statusText}`);
|
|
28
|
+
}
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
const signatures = data.data || [];
|
|
31
|
+
const transformedSigs = signatures.map((tx) => ({
|
|
32
|
+
signature: tx.txHash || tx.signature,
|
|
33
|
+
blockTime: tx.blockTime || tx.block_time || 0,
|
|
34
|
+
err: tx.status !== "Success" ? { err: tx.status } : null,
|
|
35
|
+
}));
|
|
36
|
+
allSignatures.push(...transformedSigs);
|
|
37
|
+
if (signatures.length < limit || (options?.limit && allSignatures.length >= options.limit)) {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
// Set before to the last signature for next page
|
|
41
|
+
if (signatures.length > 0) {
|
|
42
|
+
before = signatures[signatures.length - 1].txHash || signatures[signatures.length - 1].signature;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return allSignatures.slice(0, options?.limit);
|
|
46
|
+
},
|
|
47
|
+
async getParsedTransaction(signature) {
|
|
48
|
+
const endpoint = `${baseUrl}/transaction/details?tx=${signature}`;
|
|
49
|
+
const response = await fetch(endpoint, { headers });
|
|
50
|
+
if (!response.ok) {
|
|
51
|
+
throw new Error(`Failed to fetch transaction: ${response.statusText}`);
|
|
52
|
+
}
|
|
53
|
+
const data = await response.json();
|
|
54
|
+
return {
|
|
55
|
+
meta: {
|
|
56
|
+
err: data.status !== "Success" ? { err: data.status } : null,
|
|
57
|
+
logMessages: data.logMessages || [],
|
|
58
|
+
preTokenBalances: data.inputAccount || [],
|
|
59
|
+
postTokenBalances: data.outputAccount || [],
|
|
60
|
+
},
|
|
61
|
+
blockTime: data.blockTime || data.block_time || 0,
|
|
62
|
+
status: data.status,
|
|
63
|
+
err: data.status !== "Success" ? { err: data.status } : null,
|
|
64
|
+
tokenBalances: data.tokenBalances || [],
|
|
65
|
+
preTokenBalances: data.inputAccount || [],
|
|
66
|
+
postTokenBalances: data.outputAccount || [],
|
|
29
67
|
};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
68
|
+
},
|
|
69
|
+
async getBalanceChange(f) {
|
|
70
|
+
try {
|
|
71
|
+
const allTransfers = [];
|
|
72
|
+
let page = 1;
|
|
73
|
+
const pageSize = Math.min(f.options?.limit || 100, 100);
|
|
74
|
+
while (true) {
|
|
75
|
+
const params = new URLSearchParams({
|
|
76
|
+
address: f.addr.toString(),
|
|
77
|
+
page: page.toString(),
|
|
78
|
+
page_size: pageSize.toString(),
|
|
79
|
+
});
|
|
80
|
+
if (f.mint) {
|
|
81
|
+
params.append("token", f.mint.toString());
|
|
82
|
+
}
|
|
83
|
+
if (f.flow) {
|
|
84
|
+
params.append("flow", f.flow);
|
|
85
|
+
}
|
|
86
|
+
if (f.tokenAccount) {
|
|
87
|
+
params.append("token_account", f.tokenAccount.toString());
|
|
88
|
+
}
|
|
89
|
+
const endpoint = `${baseUrl}/account/balance_change?${params}`;
|
|
90
|
+
const response = await fetch(endpoint, { headers });
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
console.error(`Failed to fetch balance changes: ${response.statusText}`);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
const body = await response.json();
|
|
96
|
+
const transfers = [];
|
|
97
|
+
for (const item of body.data || []) {
|
|
98
|
+
if (item.change_type === (f.flow === "in" ? "inc" : "dec")) {
|
|
99
|
+
transfers.push({
|
|
100
|
+
amount: Math.abs(item.amount || 0),
|
|
101
|
+
tokenDecimals: item.token_decimals || 0,
|
|
102
|
+
sig: item.trans_id,
|
|
103
|
+
blockTime: item.block_time || 0,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
allTransfers.push(...transfers);
|
|
108
|
+
if (transfers.length === 0 || transfers.length < pageSize) {
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
page++;
|
|
112
|
+
}
|
|
113
|
+
return allTransfers.filter((t) => t.amount !== 0);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error("Error in getBalanceChange:", error);
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
53
119
|
},
|
|
54
120
|
async getTransfers(f) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
121
|
+
try {
|
|
122
|
+
const allTransfers = [];
|
|
123
|
+
let page = 1;
|
|
124
|
+
const pageSize = Math.min(f.pageSize || 100, 100);
|
|
125
|
+
while (true) {
|
|
126
|
+
const params = new URLSearchParams({
|
|
127
|
+
address: f.addr.toString(),
|
|
128
|
+
token: f.mint.toString(),
|
|
129
|
+
flow: f.flow,
|
|
130
|
+
page: page.toString(),
|
|
131
|
+
page_size: pageSize.toString(),
|
|
132
|
+
});
|
|
133
|
+
const endpoint = `${baseUrl}/account/transfer?${params}`;
|
|
134
|
+
const response = await fetch(endpoint, { headers });
|
|
135
|
+
if (!response.ok) {
|
|
136
|
+
throw new Error(`Failed to fetch transfers: ${response.statusText}`);
|
|
137
|
+
}
|
|
138
|
+
const body = await response.json();
|
|
139
|
+
const transfers = [];
|
|
140
|
+
for (const item of body.data || []) {
|
|
141
|
+
transfers.push({
|
|
142
|
+
amount: item.amount || 0,
|
|
143
|
+
tokenDecimals: item.token_decimals || 0,
|
|
144
|
+
fromAddress: item.from_address ? new PublicKey(item.from_address) : undefined,
|
|
145
|
+
toAddress: item.to_address ? new PublicKey(item.to_address) : undefined,
|
|
146
|
+
sig: item.trans_id,
|
|
147
|
+
blockTime: item.block_time || 0,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
allTransfers.push(...transfers);
|
|
151
|
+
if (transfers.length === 0 || transfers.length < pageSize) {
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
page++;
|
|
155
|
+
}
|
|
156
|
+
return allTransfers.filter((t) => t.amount !== 0);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
console.error("Error in getTransfers:", error);
|
|
160
|
+
throw new Error(`Failed to get transfers: ${error}`);
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
export const heliusClient = (apiKey) => {
|
|
166
|
+
const helius = new Helius(apiKey, 'mainnet-beta');
|
|
167
|
+
return {
|
|
168
|
+
async getSignaturesForAddress(addr, options) {
|
|
169
|
+
return helius.connection.getSignaturesForAddress(addr, {
|
|
170
|
+
before: options?.before,
|
|
171
|
+
limit: options?.limit || 1000,
|
|
172
|
+
});
|
|
173
|
+
},
|
|
174
|
+
async getParsedTransaction(signature) {
|
|
175
|
+
return helius.connection.getTransaction(signature, {
|
|
176
|
+
maxSupportedTransactionVersion: 0,
|
|
177
|
+
});
|
|
178
|
+
},
|
|
179
|
+
async getBalanceChange(f) {
|
|
180
|
+
try {
|
|
181
|
+
// Get transactions for the address
|
|
182
|
+
const response = await helius.connection.getSignaturesForAddress(f.addr, {
|
|
183
|
+
limit: 100,
|
|
184
|
+
});
|
|
185
|
+
const transfers = [];
|
|
186
|
+
// Process each signature to get transaction details
|
|
187
|
+
for (const sig of response) {
|
|
188
|
+
try {
|
|
189
|
+
const tx = await helius.connection.getTransaction(sig.signature, {
|
|
190
|
+
maxSupportedTransactionVersion: 0,
|
|
191
|
+
});
|
|
192
|
+
if (!tx || tx.meta?.err)
|
|
193
|
+
continue;
|
|
194
|
+
// Look for token balance changes
|
|
195
|
+
const preBalances = tx.meta.preTokenBalances || [];
|
|
196
|
+
const postBalances = tx.meta.postTokenBalances || [];
|
|
197
|
+
for (const postBalance of postBalances) {
|
|
198
|
+
if (postBalance.mint !== f.mint.toString())
|
|
199
|
+
continue;
|
|
200
|
+
if (postBalance.owner !== f.addr.toString())
|
|
201
|
+
continue;
|
|
202
|
+
const preBalance = preBalances.find((pre) => pre.accountIndex === postBalance.accountIndex);
|
|
203
|
+
const preAmount = Number(preBalance?.uiTokenAmount?.amount || 0);
|
|
204
|
+
const postAmount = Number(postBalance.uiTokenAmount?.amount || 0);
|
|
205
|
+
const change = postAmount - preAmount;
|
|
206
|
+
if (change !== 0) {
|
|
207
|
+
const isInflow = change > 0;
|
|
208
|
+
if ((f.flow === 'in' && isInflow) || (f.flow === 'out' && !isInflow)) {
|
|
209
|
+
transfers.push({
|
|
210
|
+
amount: Math.abs(change),
|
|
211
|
+
tokenDecimals: postBalance.uiTokenAmount?.decimals || 0,
|
|
212
|
+
sig: sig.signature,
|
|
213
|
+
blockTime: tx.blockTime || 0,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch (e) {
|
|
220
|
+
console.error(`Error processing signature ${sig.signature}:`, e);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return transfers.filter(t => t.amount !== 0);
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
console.error('Error in getBalanceChange:', error);
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
async getTransfers(f) {
|
|
231
|
+
try {
|
|
232
|
+
// Use enhanced transactions API for better token transfer data
|
|
233
|
+
const response = await helius.connection.getSignaturesForAddress(f.addr, {
|
|
234
|
+
limit: f.pageSize || 100,
|
|
235
|
+
});
|
|
236
|
+
const transfers = [];
|
|
237
|
+
for (const sig of response) {
|
|
238
|
+
try {
|
|
239
|
+
const tx = await helius.connection.getTransaction(sig.signature, {
|
|
240
|
+
maxSupportedTransactionVersion: 0,
|
|
241
|
+
});
|
|
242
|
+
if (!tx || tx.meta?.err)
|
|
243
|
+
continue;
|
|
244
|
+
// Parse token transfers from transaction
|
|
245
|
+
const preTokenBalances = tx.meta.preTokenBalances || [];
|
|
246
|
+
const postTokenBalances = tx.meta.postTokenBalances || [];
|
|
247
|
+
// Group by account index to track transfers
|
|
248
|
+
const balanceChanges = new Map();
|
|
249
|
+
for (const postBalance of postTokenBalances) {
|
|
250
|
+
if (postBalance.mint !== f.mint.toString())
|
|
251
|
+
continue;
|
|
252
|
+
const preBalance = preTokenBalances.find(pre => pre.accountIndex === postBalance.accountIndex);
|
|
253
|
+
const preAmount = Number(preBalance?.uiTokenAmount?.amount || 0);
|
|
254
|
+
const postAmount = Number(postBalance.uiTokenAmount?.amount || 0);
|
|
255
|
+
const change = postAmount - preAmount;
|
|
256
|
+
if (change !== 0) {
|
|
257
|
+
balanceChanges.set(postBalance.accountIndex, {
|
|
258
|
+
mint: postBalance.mint,
|
|
259
|
+
owner: postBalance.owner,
|
|
260
|
+
change,
|
|
261
|
+
decimals: postBalance.uiTokenAmount?.decimals || 0
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// Find transfers involving the target address
|
|
266
|
+
for (const [accountIndex, balanceChange] of balanceChanges) {
|
|
267
|
+
const isFromTarget = balanceChange.owner === f.addr.toString() && balanceChange.change < 0;
|
|
268
|
+
const isToTarget = balanceChange.owner === f.addr.toString() && balanceChange.change > 0;
|
|
269
|
+
if ((f.flow === 'out' && isFromTarget) || (f.flow === 'in' && isToTarget)) {
|
|
270
|
+
// Find the counterpart transfer
|
|
271
|
+
let fromAddress;
|
|
272
|
+
let toAddress;
|
|
273
|
+
if (isFromTarget) {
|
|
274
|
+
fromAddress = f.addr;
|
|
275
|
+
// Find who received the tokens
|
|
276
|
+
for (const [_, otherChange] of balanceChanges) {
|
|
277
|
+
if (otherChange.owner !== f.addr.toString() && otherChange.change > 0) {
|
|
278
|
+
toAddress = new PublicKey(otherChange.owner);
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
toAddress = f.addr;
|
|
285
|
+
// Find who sent the tokens
|
|
286
|
+
for (const [_, otherChange] of balanceChanges) {
|
|
287
|
+
if (otherChange.owner !== f.addr.toString() && otherChange.change < 0) {
|
|
288
|
+
fromAddress = new PublicKey(otherChange.owner);
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
transfers.push({
|
|
294
|
+
amount: Math.abs(balanceChange.change),
|
|
295
|
+
tokenDecimals: balanceChange.decimals,
|
|
296
|
+
fromAddress,
|
|
297
|
+
toAddress,
|
|
298
|
+
sig: sig.signature,
|
|
299
|
+
blockTime: tx.blockTime || 0,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
catch (e) {
|
|
305
|
+
console.error(`Error processing signature ${sig.signature}:`, e);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return transfers.filter(t => t.amount !== 0);
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
console.error('Error in getTransfers:', error);
|
|
312
|
+
throw new Error(`Failed to get transfers: ${error}`);
|
|
313
|
+
}
|
|
83
314
|
},
|
|
84
315
|
};
|
|
85
316
|
};
|
|
86
317
|
export class Backfiller {
|
|
87
318
|
_types = {};
|
|
88
|
-
conn;
|
|
89
319
|
_txs = [];
|
|
320
|
+
solscanClient;
|
|
321
|
+
heliusClient;
|
|
90
322
|
pg;
|
|
323
|
+
isDryRun = false;
|
|
91
324
|
solscan = { pageSize: 100 };
|
|
92
|
-
constructor(
|
|
93
|
-
this.
|
|
325
|
+
constructor(solscanApiKey, heliusApiKey, pg, isDryRun = false) {
|
|
326
|
+
this.solscan.apiKey = solscanApiKey;
|
|
327
|
+
this.solscanClient = solscanProClient(solscanApiKey);
|
|
328
|
+
this.heliusClient = heliusClient(heliusApiKey);
|
|
94
329
|
this.pg = pg;
|
|
330
|
+
this.isDryRun = isDryRun;
|
|
95
331
|
}
|
|
96
332
|
emit() {
|
|
97
|
-
this._types[
|
|
333
|
+
this._types["emit"] = {};
|
|
98
334
|
return this;
|
|
99
335
|
}
|
|
100
336
|
loans() {
|
|
101
|
-
this._types[
|
|
337
|
+
this._types["loan"] = {};
|
|
102
338
|
return this;
|
|
103
339
|
}
|
|
104
|
-
buyBurnUSDCInflow(
|
|
105
|
-
this._types[
|
|
106
|
-
this.solscan.cookie = solscanCookie;
|
|
340
|
+
buyBurnUSDCInflow() {
|
|
341
|
+
this._types["buyBurnUSDCInflow"] = {};
|
|
107
342
|
return this;
|
|
108
343
|
}
|
|
109
|
-
manualMint(
|
|
110
|
-
this._types[
|
|
111
|
-
this.solscan.cookie = solscanCookie;
|
|
344
|
+
manualMint() {
|
|
345
|
+
this._types["manualMint"] = {};
|
|
112
346
|
return this;
|
|
113
347
|
}
|
|
114
348
|
vaultOutflows(p) {
|
|
115
|
-
this._types[
|
|
116
|
-
this.solscan.
|
|
117
|
-
this.solscan.pageSize = p.pageSize;
|
|
349
|
+
this._types["vaultOutflows"] = {};
|
|
350
|
+
this.solscan.pageSize = p.pageSize || 100;
|
|
118
351
|
return this;
|
|
119
352
|
}
|
|
120
353
|
txs(...sigs) {
|
|
121
354
|
this._txs.push(...sigs);
|
|
122
355
|
}
|
|
123
|
-
|
|
356
|
+
formatAmount(amount, decimals = 8) {
|
|
357
|
+
const amt = typeof amount === "bigint" ? Number(amount) : amount;
|
|
358
|
+
return (amt / Math.pow(10, decimals)).toLocaleString(undefined, {
|
|
359
|
+
maximumFractionDigits: 8,
|
|
360
|
+
minimumFractionDigits: 0,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
formatTimestamp(blockTime) {
|
|
364
|
+
return new Date(blockTime * 1000).toISOString();
|
|
365
|
+
}
|
|
366
|
+
async indexLoans() {
|
|
124
367
|
const trs = [
|
|
125
368
|
{
|
|
126
369
|
transfer: {
|
|
127
|
-
toSolKey:
|
|
370
|
+
toSolKey: "2P2gisXpbsYEUsTDQKdcDKSg1UZvx7qxfLTkvJGZdeJC",
|
|
128
371
|
fromSolKey: v3SquadsVault,
|
|
129
|
-
solTx:
|
|
130
|
-
executedAt: new Date(
|
|
131
|
-
symbol:
|
|
132
|
-
channel:
|
|
372
|
+
solTx: "3oC8BybX5YrkfPyvV8rAE1tnJr6egtZFHLghqHuLi3eaT4aWm87qZPJFrjFRn6nwVemd2ponsew85tBs6VVQzTJv",
|
|
373
|
+
executedAt: new Date("December 22, 2023 04:13:58 UTC"),
|
|
374
|
+
symbol: "RENDER",
|
|
375
|
+
channel: "loan",
|
|
133
376
|
amountPayed: BigInt(44999 * Math.pow(10, 8)),
|
|
134
377
|
},
|
|
135
378
|
},
|
|
136
379
|
{
|
|
137
380
|
transfer: {
|
|
138
|
-
toSolKey:
|
|
381
|
+
toSolKey: "2P2gisXpbsYEUsTDQKdcDKSg1UZvx7qxfLTkvJGZdeJC",
|
|
139
382
|
fromSolKey: v3SquadsVault,
|
|
140
|
-
channel:
|
|
141
|
-
solTx:
|
|
142
|
-
executedAt: new Date(
|
|
143
|
-
symbol:
|
|
383
|
+
channel: "loan",
|
|
384
|
+
solTx: "2f5sEBHcP8wpF79voUEUiP8pryDt7FvqrTXQrEpXzAxbzyFYPkavZGtJc5N8CXhfbJav8hQTr9YcENKseiouaWzc",
|
|
385
|
+
executedAt: new Date("December 22, 2023 02:39:53 UTC"),
|
|
386
|
+
symbol: "RENDER",
|
|
144
387
|
amountPayed: BigInt(1 * Math.pow(10, 8)),
|
|
145
388
|
},
|
|
146
389
|
},
|
|
147
390
|
{
|
|
148
391
|
transfer: {
|
|
149
|
-
toSolKey:
|
|
392
|
+
toSolKey: "5DGbogKUo8haEYC9Tt4FTHE5ue55bjLC4DpSgE1g6yT1",
|
|
150
393
|
fromSolKey: v3SquadsVault,
|
|
151
|
-
channel:
|
|
152
|
-
solTx:
|
|
153
|
-
executedAt: new Date(
|
|
154
|
-
symbol:
|
|
394
|
+
channel: "loan",
|
|
395
|
+
solTx: "42n55BZcKVBCSZQoaneBQLn57v7zZGZorGe3uBLheGu4BQtpaTChdT1z3vHwgU4MHghJw3wJ72rFLkib761ewJCj",
|
|
396
|
+
executedAt: new Date("January 12, 2024 00:17:02 UTC"),
|
|
397
|
+
symbol: "RENDER",
|
|
155
398
|
amountPayed: BigInt(1 * Math.pow(10, 8)),
|
|
156
399
|
},
|
|
157
400
|
},
|
|
158
401
|
{
|
|
159
402
|
transfer: {
|
|
160
|
-
toSolKey:
|
|
403
|
+
toSolKey: "5DGbogKUo8haEYC9Tt4FTHE5ue55bjLC4DpSgE1g6yT1",
|
|
161
404
|
fromSolKey: v3SquadsVault,
|
|
162
|
-
channel:
|
|
163
|
-
solTx:
|
|
164
|
-
executedAt: new Date(
|
|
165
|
-
symbol:
|
|
405
|
+
channel: "loan",
|
|
406
|
+
solTx: "THJLvA1UTqH22hNP7Ecnfn4iY736VJAZ8scgSUjrDDaGpSQJmGYKJYXGtDu6TB96fKo6mJBtUBZvLb4ors17JUR",
|
|
407
|
+
executedAt: new Date("January 17, 2024 22:09:58 UTC"),
|
|
408
|
+
symbol: "RENDER",
|
|
166
409
|
amountPayed: BigInt(49999 * Math.pow(10, 8)),
|
|
167
410
|
},
|
|
168
411
|
},
|
|
169
412
|
{
|
|
170
413
|
transfer: {
|
|
171
|
-
toSolKey:
|
|
414
|
+
toSolKey: "5DGbogKUo8haEYC9Tt4FTHE5ue55bjLC4DpSgE1g6yT1",
|
|
172
415
|
fromSolKey: devsSquadsVault,
|
|
173
|
-
channel:
|
|
174
|
-
solTx:
|
|
175
|
-
executedAt: new Date(
|
|
176
|
-
symbol:
|
|
416
|
+
channel: "loan",
|
|
417
|
+
solTx: "5BcxrMExq34jtMB5c3bH3A8TN4pCp9sxjC5HMcS7Mh8pig3r2eQhvRnJeE1RBTyQ4JDXyANWmDU9SKdYFyT2wDoq",
|
|
418
|
+
executedAt: new Date("February 28, 2024 22:43:21 UTC"),
|
|
419
|
+
symbol: "RENDER",
|
|
177
420
|
amountPayed: BigInt(1 * Math.pow(10, 8)),
|
|
178
421
|
},
|
|
179
422
|
},
|
|
180
423
|
{
|
|
181
424
|
transfer: {
|
|
182
|
-
toSolKey:
|
|
425
|
+
toSolKey: "5DGbogKUo8haEYC9Tt4FTHE5ue55bjLC4DpSgE1g6yT1",
|
|
183
426
|
fromSolKey: devsSquadsVault,
|
|
184
|
-
channel:
|
|
185
|
-
solTx:
|
|
186
|
-
executedAt: new Date(
|
|
187
|
-
symbol:
|
|
427
|
+
channel: "loan",
|
|
428
|
+
solTx: "5E4E35CT4e3fhbMAwcKdfAvJL4uUHR8hHE8REmKnDCEsFZ6mxaE1YyeYK8Sbg5AJqBJxsZkcYSohY8T14YLC5pXs",
|
|
429
|
+
executedAt: new Date("February 29, 2024 01:17:51 UTC"),
|
|
430
|
+
symbol: "RENDER",
|
|
188
431
|
amountPayed: BigInt(199999 * Math.pow(10, 8)),
|
|
189
432
|
},
|
|
190
433
|
},
|
|
191
434
|
];
|
|
435
|
+
if (this.isDryRun) {
|
|
436
|
+
for (const t of trs) {
|
|
437
|
+
const amount = this.formatAmount(t.transfer.amountPayed);
|
|
438
|
+
const timestamp = this.formatTimestamp(t.transfer.executedAt.getTime() / 1000);
|
|
439
|
+
console.log(`${t.transfer.solTx} | ${timestamp} | ${t.transfer.channel} | ${t.transfer.fromSolKey} -> ${t.transfer.toSolKey} | ${amount} ${t.transfer.symbol}`);
|
|
440
|
+
}
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
192
443
|
for (const t of trs) {
|
|
193
444
|
try {
|
|
194
445
|
await this.pg.createPayments(this.pg.db, [t]);
|
|
@@ -197,7 +448,7 @@ export class Backfiller {
|
|
|
197
448
|
console.log(`except ${e}`);
|
|
198
449
|
}
|
|
199
450
|
}
|
|
200
|
-
}
|
|
451
|
+
}
|
|
201
452
|
async findEmitTxs() {
|
|
202
453
|
const fetchSigs = async (ads) => {
|
|
203
454
|
const uniqSigs = {};
|
|
@@ -205,9 +456,10 @@ export class Backfiller {
|
|
|
205
456
|
for (const ad of ads) {
|
|
206
457
|
const sigs = [];
|
|
207
458
|
while (true) {
|
|
208
|
-
const sigsBatch = await this.
|
|
459
|
+
const sigsBatch = await this.heliusClient.getSignaturesForAddress(ad, {
|
|
209
460
|
before: sigs.length > 0 ? sigs[sigs.length - 1].signature : undefined,
|
|
210
|
-
|
|
461
|
+
limit: 1000,
|
|
462
|
+
});
|
|
211
463
|
sigs.push(...sigsBatch.filter((s) => !uniqSigs[s.signature]));
|
|
212
464
|
for (const s of sigsBatch) {
|
|
213
465
|
uniqSigs[s.signature] = true;
|
|
@@ -216,7 +468,9 @@ export class Backfiller {
|
|
|
216
468
|
break;
|
|
217
469
|
}
|
|
218
470
|
}
|
|
219
|
-
|
|
471
|
+
if (!this.isDryRun) {
|
|
472
|
+
console.log(`fetched ${sigs.length} sigs for ${ad}`);
|
|
473
|
+
}
|
|
220
474
|
sigsAgg.push(...sigs);
|
|
221
475
|
}
|
|
222
476
|
sigsAgg.sort((a, b) => b.blockTime - a.blockTime);
|
|
@@ -226,98 +480,130 @@ export class Backfiller {
|
|
|
226
480
|
emissionDistributorKey(new PublicKey(renderMint))[0],
|
|
227
481
|
emissionDistributorV1Key(new PublicKey(renderMint))[0],
|
|
228
482
|
]);
|
|
229
|
-
|
|
483
|
+
if (!this.isDryRun) {
|
|
484
|
+
console.log(`sigs ${sigs.length}`);
|
|
485
|
+
}
|
|
230
486
|
let proced = 0;
|
|
231
487
|
const out = [];
|
|
232
488
|
for (const s of sigs) {
|
|
233
|
-
const p = await this.
|
|
234
|
-
|
|
235
|
-
commitment: 'confirmed',
|
|
236
|
-
});
|
|
237
|
-
if (p.meta.err) {
|
|
489
|
+
const p = await this.heliusClient.getParsedTransaction(s.signature);
|
|
490
|
+
if (p?.meta?.err || p?.err) {
|
|
238
491
|
continue;
|
|
239
492
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
493
|
+
const logMessages = p?.meta?.logMessages || [];
|
|
494
|
+
for (const l of logMessages) {
|
|
495
|
+
if (l.includes("DistributeEmissionsV0") || l.includes("DistributeEmissionsV1")) {
|
|
243
496
|
out.push(s.signature);
|
|
497
|
+
if (this.isDryRun) {
|
|
498
|
+
console.log(`${s.signature} | ${this.formatTimestamp(s.blockTime)} | emission | Emission Distributor -> Various Recipients | N/A RENDER`);
|
|
499
|
+
}
|
|
500
|
+
break;
|
|
244
501
|
}
|
|
245
502
|
}
|
|
246
503
|
proced += 1;
|
|
247
|
-
if (proced %
|
|
504
|
+
if (proced % 10 == 0 && !this.isDryRun) {
|
|
248
505
|
console.log(`proced ${proced}`);
|
|
249
506
|
}
|
|
250
507
|
}
|
|
251
508
|
console.log(`emit txs: ${out.length}`);
|
|
252
|
-
//console.log(`last ${sigs.slice(sigs.length - 5).map((s) => s.signature)}`)
|
|
253
509
|
return out;
|
|
254
510
|
}
|
|
255
|
-
async
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
511
|
+
async indexTxs(txs, channel, reindexTx = false, deleteFailed = false, mints = [renderMint, usdcMint], senders = [passthruEscrow, v3SquadsVault, upgradeRewardsEscrow, upgradeRewardsCircuitBreaker, renderMint], assertSender = "") {
|
|
512
|
+
let proced = 0;
|
|
513
|
+
console.log(`processing ${txs.length} txs`);
|
|
514
|
+
const insertedIds = [];
|
|
515
|
+
for (const solTx of txs) {
|
|
516
|
+
if (solTx == "") {
|
|
517
|
+
continue;
|
|
260
518
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
for (const t of trs) {
|
|
268
|
-
console.log(`buyBurnUSDCInflows: ${JSON.stringify(t)}`);
|
|
269
|
-
const { stop } = await this.indexTransfers({ [buyAndBurnEscrow]: { mint: usdcMint, amt: t.amount } }, { blockTime: t.blockTime, sig: t.sig }, t.fromAddress.toString(), 'internal');
|
|
270
|
-
if (stop) {
|
|
271
|
-
break;
|
|
272
|
-
}
|
|
519
|
+
console.log(`solTx ${solTx}`);
|
|
520
|
+
const tx = await this.heliusClient.getParsedTransaction(solTx);
|
|
521
|
+
if (!tx || (tx.status !== "Success" && tx.err)) {
|
|
522
|
+
if (this.isDryRun) {
|
|
523
|
+
console.log(`[DRY RUN] Would delete failed transaction ${solTx} from database`);
|
|
524
|
+
continue;
|
|
273
525
|
}
|
|
526
|
+
console.log(`shouldnt exist ${solTx} in db. deleting`);
|
|
527
|
+
const res = await this.pg.db.trx.deleteFrom("sol_tx").where("sig", "=", solTx).executeTakeFirstOrThrow();
|
|
528
|
+
console.log(`deleted ${res.numDeletedRows} tx`);
|
|
529
|
+
continue;
|
|
274
530
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const { stop } = await this.indexTransfers({ [bridgeEscrow]: { mint: renderMint, amt: t.amount } }, { blockTime: t.blockTime, sig: t.sig }, renderMint, 'manual_mint');
|
|
285
|
-
if (stop) {
|
|
286
|
-
break;
|
|
287
|
-
}
|
|
531
|
+
const onchain = {};
|
|
532
|
+
const tokenBalances = tx.tokenBalances || [];
|
|
533
|
+
const preTokenBalances = tx.preTokenBalances || [];
|
|
534
|
+
const postTokenBalances = tx.postTokenBalances || [];
|
|
535
|
+
for (const balance of postTokenBalances) {
|
|
536
|
+
const mint = mints.find((m) => balance.mint === m);
|
|
537
|
+
if (mint) {
|
|
538
|
+
const amt = Number(balance.uiTokenAmount?.amount || balance.amount || 0);
|
|
539
|
+
onchain[balance.owner] = { mint, amt };
|
|
288
540
|
}
|
|
289
541
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
542
|
+
let sender = "";
|
|
543
|
+
for (const balance of preTokenBalances) {
|
|
544
|
+
const mint = mints.find((m) => balance.mint === m);
|
|
545
|
+
if (mint) {
|
|
546
|
+
const amt = Number(balance.uiTokenAmount?.amount || balance.amount || 0);
|
|
547
|
+
if (onchain[balance.owner]) {
|
|
548
|
+
onchain[balance.owner] = { mint, amt: onchain[balance.owner].amt - amt };
|
|
549
|
+
if (onchain[balance.owner].amt < 0) {
|
|
550
|
+
const foundSender = senders.find((s) => s === balance.owner.toString());
|
|
551
|
+
if (!foundSender) {
|
|
552
|
+
throw new Error(`sender ${balance.owner} not in expected senders ${senders}`);
|
|
553
|
+
}
|
|
554
|
+
if (assertSender !== "" && foundSender !== assertSender) {
|
|
555
|
+
throw new Error(`assert sender ${balance.owner} != ${assertSender}`);
|
|
556
|
+
}
|
|
557
|
+
sender = foundSender;
|
|
305
558
|
}
|
|
306
559
|
}
|
|
307
560
|
}
|
|
308
561
|
}
|
|
309
|
-
|
|
310
|
-
|
|
562
|
+
if (channel === "emit") {
|
|
563
|
+
sender = renderMint;
|
|
564
|
+
}
|
|
565
|
+
if (!sender) {
|
|
566
|
+
console.log(`no matching sender found`);
|
|
567
|
+
}
|
|
568
|
+
if (Object.keys(onchain).length === 0) {
|
|
569
|
+
console.log(`skipping ${solTx}. nothing to index`);
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
const { stop } = await this.indexTransfers(onchain, { blockTime: tx.blockTime || tx.blocktime || 0, sig: solTx }, sender, channel);
|
|
573
|
+
if (stop) {
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
proced += 1;
|
|
577
|
+
if (proced % 10 === 0 && !this.isDryRun) {
|
|
578
|
+
console.log(`proced ${proced}`);
|
|
311
579
|
}
|
|
312
580
|
}
|
|
581
|
+
console.log(`done. inserted ${insertedIds.length} transfers: ${insertedIds.join(",")}`);
|
|
313
582
|
}
|
|
314
583
|
async indexTransfers(onchain, tx, sender, channel, reindexTx = false) {
|
|
315
584
|
const ents = Object.entries(onchain).filter(([k, { mint, amt }]) => amt != 0);
|
|
585
|
+
if (this.isDryRun) {
|
|
586
|
+
for (const [k, { amt, mint }] of ents) {
|
|
587
|
+
if (k == sender) {
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
const symbol = (() => {
|
|
591
|
+
if (mint == renderMint) {
|
|
592
|
+
return "RENDER";
|
|
593
|
+
}
|
|
594
|
+
if (mint == usdcMint) {
|
|
595
|
+
return "USDC";
|
|
596
|
+
}
|
|
597
|
+
return "UNKNOWN";
|
|
598
|
+
})();
|
|
599
|
+
const amount = this.formatAmount(amt);
|
|
600
|
+
const timestamp = this.formatTimestamp(tx.blockTime);
|
|
601
|
+
console.log(`${tx.sig} | ${timestamp} | ${channel} | ${sender} -> ${k} | ${amount} ${symbol}`);
|
|
602
|
+
}
|
|
603
|
+
return { stop: false };
|
|
604
|
+
}
|
|
316
605
|
if (reindexTx) {
|
|
317
|
-
|
|
318
|
-
.deleteFrom('sol_tx')
|
|
319
|
-
.where('sig', '=', tx.sig)
|
|
320
|
-
.executeTakeFirstOrThrow();
|
|
606
|
+
const res = await this.pg.db.trx.deleteFrom("sol_tx").where("sig", "=", tx.sig).executeTakeFirstOrThrow();
|
|
321
607
|
console.log(`deleted ${res.numDeletedRows} tx`);
|
|
322
608
|
}
|
|
323
609
|
console.log(`diffs: ${ents.map(([k, v]) => `k ${k} v -> ${JSON.stringify(v)}`)}`);
|
|
@@ -335,10 +621,10 @@ export class Backfiller {
|
|
|
335
621
|
toSolKey: k,
|
|
336
622
|
symbol: (() => {
|
|
337
623
|
if (mint == renderMint) {
|
|
338
|
-
return
|
|
624
|
+
return "RENDER";
|
|
339
625
|
}
|
|
340
626
|
if (mint == usdcMint) {
|
|
341
|
-
return
|
|
627
|
+
return "USDC";
|
|
342
628
|
}
|
|
343
629
|
throw new Error(`unknown mint ${mint}`);
|
|
344
630
|
})(),
|
|
@@ -355,7 +641,7 @@ export class Backfiller {
|
|
|
355
641
|
}
|
|
356
642
|
catch (e) {
|
|
357
643
|
trx.rollback();
|
|
358
|
-
if (`${e}`.includes(
|
|
644
|
+
if (`${e}`.includes("duplicate key value violates unique constraint")) {
|
|
359
645
|
console.log(`caught up indexing ${e}`);
|
|
360
646
|
return { stop: true };
|
|
361
647
|
}
|
|
@@ -365,81 +651,146 @@ export class Backfiller {
|
|
|
365
651
|
console.log(`tx ${tx.sig} -> insertedIds ${insertedIds.length}`);
|
|
366
652
|
return { stop: false };
|
|
367
653
|
}
|
|
368
|
-
async
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
upgradeRewardsEscrow,
|
|
374
|
-
upgradeRewardsCircuitBreaker,
|
|
375
|
-
renderMint,
|
|
376
|
-
], assertSender = '') {
|
|
377
|
-
let proced = 0;
|
|
378
|
-
console.log(`processing ${txs.length} txs`);
|
|
379
|
-
const insertedIds = [];
|
|
380
|
-
for (const solTx of txs) {
|
|
381
|
-
if (solTx == '') {
|
|
382
|
-
continue;
|
|
654
|
+
async run() {
|
|
655
|
+
for (const t of Object.keys(this._types)) {
|
|
656
|
+
if (t == "emit") {
|
|
657
|
+
const txs = await this.findEmitTxs();
|
|
658
|
+
await this.indexTxs(txs, "emit");
|
|
383
659
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
.
|
|
395
|
-
|
|
396
|
-
|
|
660
|
+
else if (t == "buyBurnUSDCInflow") {
|
|
661
|
+
const trs = await this.solscanClient.getTransfers({
|
|
662
|
+
mint: new PublicKey(usdcMint),
|
|
663
|
+
flow: "in",
|
|
664
|
+
addr: new PublicKey(buyAndBurnEscrow),
|
|
665
|
+
});
|
|
666
|
+
for (const t of trs) {
|
|
667
|
+
if (!this.isDryRun) {
|
|
668
|
+
console.log(`buyBurnUSDCInflows: ${JSON.stringify(t)}`);
|
|
669
|
+
}
|
|
670
|
+
const { stop } = await this.indexTransfers({ [buyAndBurnEscrow]: { mint: usdcMint, amt: t.amount } }, { blockTime: t.blockTime, sig: t.sig }, t.fromAddress.toString(), "internal");
|
|
671
|
+
if (stop) {
|
|
672
|
+
break;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
397
675
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
676
|
+
else if (t == "manualMint") {
|
|
677
|
+
const trs = await this.solscanClient.getBalanceChange({
|
|
678
|
+
mint: new PublicKey(renderMint),
|
|
679
|
+
addr: new PublicKey("AYm4Knn6Sw1f52Eq42ujQ2ez5Xb7iBJeviprFCA7ADCy"),
|
|
680
|
+
flow: "in",
|
|
681
|
+
tokenAccount: new PublicKey(bridgeEscrow),
|
|
682
|
+
});
|
|
683
|
+
for (const t of trs) {
|
|
684
|
+
if (!this.isDryRun) {
|
|
685
|
+
console.log(`manualMints: ${JSON.stringify(t)}`);
|
|
686
|
+
}
|
|
687
|
+
const { stop } = await this.indexTransfers({ [bridgeEscrow]: { mint: renderMint, amt: t.amount } }, { blockTime: t.blockTime, sig: t.sig }, renderMint, "manual_mint");
|
|
688
|
+
if (stop) {
|
|
689
|
+
break;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
const polyTrs = await this.solscanClient.getBalanceChange({
|
|
693
|
+
mint: new PublicKey(renderMint),
|
|
694
|
+
addr: new PublicKey("AYm4Knn6Sw1f52Eq42ujQ2ez5Xb7iBJeviprFCA7ADCy"),
|
|
695
|
+
flow: "in",
|
|
696
|
+
tokenAccount: new PublicKey(polyBridgeEscrow),
|
|
697
|
+
});
|
|
698
|
+
for (const t of polyTrs) {
|
|
699
|
+
if (!this.isDryRun) {
|
|
700
|
+
console.log(`polyManualMints: ${JSON.stringify(t)}`);
|
|
701
|
+
}
|
|
702
|
+
const { stop } = await this.indexTransfers({ [polyBridgeEscrow]: { mint: renderMint, amt: t.amount } }, { blockTime: t.blockTime, sig: t.sig }, renderMint, "manual_mint");
|
|
703
|
+
if (stop) {
|
|
704
|
+
break;
|
|
705
|
+
}
|
|
404
706
|
}
|
|
405
707
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
708
|
+
else if (t == "vaultOutflows") {
|
|
709
|
+
for (const addr of [devsSquadsVault, masterSquadsVault]) {
|
|
710
|
+
const trs = await this.solscanClient.getTransfers({
|
|
711
|
+
mint: new PublicKey(renderMint),
|
|
712
|
+
flow: "out",
|
|
713
|
+
addr: new PublicKey(addr),
|
|
714
|
+
pageSize: this.solscan.pageSize,
|
|
715
|
+
});
|
|
716
|
+
for (const t of trs) {
|
|
717
|
+
if (!this.isDryRun) {
|
|
718
|
+
console.log(`vaultOutflow: ${JSON.stringify(t)}`);
|
|
416
719
|
}
|
|
417
|
-
|
|
418
|
-
|
|
720
|
+
const { stop } = await this.indexTransfers({
|
|
721
|
+
[t.toAddress.toString()]: { mint: renderMint, amt: t.amount },
|
|
722
|
+
}, { blockTime: t.blockTime, sig: t.sig }, addr, "internal");
|
|
723
|
+
if (stop) {
|
|
724
|
+
break;
|
|
419
725
|
}
|
|
420
726
|
}
|
|
421
727
|
}
|
|
422
728
|
}
|
|
423
|
-
if (
|
|
424
|
-
|
|
425
|
-
}
|
|
426
|
-
if (!sender) {
|
|
427
|
-
console.log(`no matching sender found`);
|
|
428
|
-
}
|
|
429
|
-
if (Object.keys(onchain).length == 0) {
|
|
430
|
-
console.log(`skipping ${solTx}. nothing to index`);
|
|
431
|
-
continue;
|
|
432
|
-
}
|
|
433
|
-
const { stop } = await this.indexTransfers(onchain, { blockTime: tx.blockTime, sig: solTx }, sender, channel);
|
|
434
|
-
if (stop) {
|
|
435
|
-
break;
|
|
436
|
-
}
|
|
437
|
-
proced += 1;
|
|
438
|
-
if (proced % 10 == 0) {
|
|
439
|
-
console.log(`proced ${proced}`);
|
|
729
|
+
else if (t == "loan") {
|
|
730
|
+
await this.indexLoans();
|
|
440
731
|
}
|
|
441
732
|
}
|
|
442
|
-
console.log(`done. inserted ${insertedIds.length} transfers: ${insertedIds.join(',')}`);
|
|
443
733
|
}
|
|
444
734
|
}
|
|
735
|
+
async function main() {
|
|
736
|
+
const args = process.argv.slice(2);
|
|
737
|
+
const getArgValue = (argName) => {
|
|
738
|
+
const argIndex = args.indexOf(`--${argName}`);
|
|
739
|
+
return argIndex !== -1 && argIndex + 1 < args.length ? args[argIndex + 1] : undefined;
|
|
740
|
+
};
|
|
741
|
+
const hasFlag = (flagName) => {
|
|
742
|
+
return args.includes(`--${flagName}`);
|
|
743
|
+
};
|
|
744
|
+
const solscanApiKey = getArgValue("solscanApiKey");
|
|
745
|
+
if (!solscanApiKey) {
|
|
746
|
+
console.error("Error: --solscanApiKey is required");
|
|
747
|
+
process.exit(1);
|
|
748
|
+
}
|
|
749
|
+
const heliusApiKey = getArgValue("heliusApiKey");
|
|
750
|
+
if (!heliusApiKey) {
|
|
751
|
+
console.error("Error: --heliusApiKey is required");
|
|
752
|
+
process.exit(1);
|
|
753
|
+
}
|
|
754
|
+
const isDryRun = hasFlag("dryRun");
|
|
755
|
+
let pg;
|
|
756
|
+
if (!isDryRun) {
|
|
757
|
+
const pgUrl = getArgValue("pgUrl");
|
|
758
|
+
if (!pgUrl) {
|
|
759
|
+
console.error("Error: --pgUrl is required (unless using --dryRun)");
|
|
760
|
+
process.exit(1);
|
|
761
|
+
}
|
|
762
|
+
pg = pgClient({
|
|
763
|
+
connectionString: pgUrl,
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
const backfiller = new Backfiller(solscanApiKey, heliusApiKey, pg, isDryRun);
|
|
767
|
+
if (hasFlag("loans")) {
|
|
768
|
+
backfiller.loans();
|
|
769
|
+
}
|
|
770
|
+
if (hasFlag("vaultOutflows")) {
|
|
771
|
+
backfiller.vaultOutflows({});
|
|
772
|
+
}
|
|
773
|
+
if (hasFlag("emissions")) {
|
|
774
|
+
backfiller.emit();
|
|
775
|
+
}
|
|
776
|
+
if (hasFlag("buyBurnUSDCInflow")) {
|
|
777
|
+
backfiller.buyBurnUSDCInflow();
|
|
778
|
+
}
|
|
779
|
+
if (hasFlag("manualMints")) {
|
|
780
|
+
backfiller.manualMint();
|
|
781
|
+
}
|
|
782
|
+
if (hasFlag("loans") ||
|
|
783
|
+
hasFlag("vaultOutflows") ||
|
|
784
|
+
hasFlag("emissions") ||
|
|
785
|
+
hasFlag("buyBurnUSDCInflow") ||
|
|
786
|
+
hasFlag("manualMints")) {
|
|
787
|
+
await backfiller.run();
|
|
788
|
+
}
|
|
789
|
+
else {
|
|
790
|
+
console.log("No operations specified. Available flags: --loans, --vaultOutflows, --emissions, --buyBurnUSDCInflow, --manualMints, --dryRun");
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
if (require.main === module) {
|
|
794
|
+
main().catch(console.error);
|
|
795
|
+
}
|
|
445
796
|
//# sourceMappingURL=backfiller.js.map
|