@defillama/sdk 5.0.240 → 5.0.244
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/build/Balances.d.ts +139 -0
- package/build/Balances.js +363 -0
- package/build/ChainApi.d.ts +142 -0
- package/build/ChainApi.js +310 -0
- package/build/abi/abi2.d.ts +5 -0
- package/build/abi/abi2.js +215 -0
- package/build/abi/cachedABIs.d.ts +4 -0
- package/build/abi/cachedABIs.js +8 -0
- package/build/abi/convertResults.d.ts +5 -0
- package/build/abi/convertResults.js +60 -0
- package/build/abi/index.d.ts +31 -0
- package/build/abi/index.js +327 -0
- package/build/abi/multicall.d.ts +23 -0
- package/build/abi/multicall.js +383 -0
- package/build/abi/multicall3.d.ts +7 -0
- package/build/abi/multicall3.js +405 -0
- package/build/abi/rpcCall.d.ts +4 -0
- package/build/abi/rpcCall.js +62 -0
- package/build/abi/tron.d.ts +33 -0
- package/build/abi/tron.js +118 -0
- package/build/api.d.ts +10 -0
- package/build/api.js +45 -0
- package/build/api2.d.ts +5 -0
- package/build/api2.js +41 -0
- package/build/chains/algorand.d.ts +277 -0
- package/build/chains/algorand.js +618 -0
- package/build/chains/aptos.d.ts +269 -0
- package/build/chains/aptos.js +700 -0
- package/build/chains/cardano.d.ts +242 -0
- package/build/chains/cardano.js +407 -0
- package/build/chains/cosmos.d.ts +252 -0
- package/build/chains/cosmos.js +623 -0
- package/build/chains/icp.d.ts +235 -0
- package/build/chains/icp.js +1040 -0
- package/build/chains/index.d.ts +23 -0
- package/build/chains/index.js +59 -0
- package/build/chains/near.d.ts +192 -0
- package/build/chains/near.js +446 -0
- package/build/chains/rpc.d.ts +125 -0
- package/build/chains/rpc.js +332 -0
- package/build/chains/starknet.d.ts +205 -0
- package/build/chains/starknet.js +886 -0
- package/build/chains/stellar.d.ts +410 -0
- package/build/chains/stellar.js +1082 -0
- package/build/chains/substrate.d.ts +333 -0
- package/build/chains/substrate.js +1042 -0
- package/build/chains/sui.d.ts +392 -0
- package/build/chains/sui.js +1213 -0
- package/build/chains/svm.d.ts +340 -0
- package/build/chains/svm.js +764 -0
- package/build/chains/tezos.d.ts +225 -0
- package/build/chains/tezos.js +412 -0
- package/build/chains/ton.d.ts +353 -0
- package/build/chains/ton.js +788 -0
- package/build/chains/tron.d.ts +45 -0
- package/build/chains/tron.js +110 -0
- package/build/chains/utxo.d.ts +210 -0
- package/build/chains/utxo.js +678 -0
- package/build/chains/xrpl.d.ts +179 -0
- package/build/chains/xrpl.js +467 -0
- package/build/computeTVL/blocks.d.ts +1 -0
- package/build/computeTVL/blocks.js +12 -0
- package/build/computeTVL/humanizeNumber.d.ts +1 -0
- package/build/computeTVL/humanizeNumber.js +19 -0
- package/build/erc20/index.d.ts +31 -0
- package/build/erc20/index.js +56 -0
- package/build/eth/index.d.ts +22 -0
- package/build/eth/index.js +118 -0
- package/build/general.d.ts +5 -0
- package/build/general.js +20 -0
- package/build/generalUtil.d.ts +8 -0
- package/build/generalUtil.js +73 -0
- package/build/index.d.ts +33 -0
- package/build/index.js +75 -0
- package/build/providers.json +1 -0
- package/build/types.d.ts +76 -0
- package/build/types.js +2 -0
- package/build/util/LlamaProvider.d.ts +46 -0
- package/build/util/LlamaProvider.js +343 -0
- package/build/util/blocks.d.ts +36 -0
- package/build/util/blocks.js +500 -0
- package/build/util/cache.d.ts +45 -0
- package/build/util/cache.js +309 -0
- package/build/util/callStats.d.ts +74 -0
- package/build/util/callStats.js +385 -0
- package/build/util/chainUtils/data.json +1459 -0
- package/build/util/chainUtils/index.d.ts +11 -0
- package/build/util/chainUtils/index.js +136 -0
- package/build/util/coins.d.ts +19 -0
- package/build/util/coins.js +124 -0
- package/build/util/common.d.ts +34 -0
- package/build/util/common.js +376 -0
- package/build/util/computeTVL.d.ts +19 -0
- package/build/util/computeTVL.js +102 -0
- package/build/util/cosmos.d.ts +1 -0
- package/build/util/cosmos.js +8 -0
- package/build/util/debugLog.d.ts +4 -0
- package/build/util/debugLog.js +18 -0
- package/build/util/discord.d.ts +1 -0
- package/build/util/discord.js +33 -0
- package/build/util/elastic.d.ts +43 -0
- package/build/util/elastic.js +113 -0
- package/build/util/env.d.ts +20 -0
- package/build/util/env.js +176 -0
- package/build/util/graph.d.ts +8 -0
- package/build/util/graph.js +50 -0
- package/build/util/index.d.ts +32 -0
- package/build/util/index.js +227 -0
- package/build/util/indexer.compatibility.d.ts +6 -0
- package/build/util/indexer.compatibility.js +64 -0
- package/build/util/indexer.d.ts +92 -0
- package/build/util/indexer.js +854 -0
- package/build/util/indexerSql.d.ts +9 -0
- package/build/util/indexerSql.js +102 -0
- package/build/util/internal-cache.d.ts +11 -0
- package/build/util/internal-cache.js +77 -0
- package/build/util/logs.d.ts +58 -0
- package/build/util/logs.decode.shared.d.ts +8 -0
- package/build/util/logs.decode.shared.js +289 -0
- package/build/util/logs.js +432 -0
- package/build/util/promisePool.d.ts +8 -0
- package/build/util/promisePool.js +31 -0
- package/build/util/r2.d.ts +4 -0
- package/build/util/r2.js +52 -0
- package/build/util/removeRedundantRPCs.d.ts +1 -0
- package/build/util/removeRedundantRPCs.js +49 -0
- package/build/util/transactions.d.ts +35 -0
- package/build/util/transactions.js +22 -0
- package/build/util/updateChainLabels.d.ts +1 -0
- package/build/util/updateChainLabels.js +5 -0
- package/build/util/updateProviderList.d.ts +1 -0
- package/build/util/updateProviderList.js +275 -0
- package/package.json +3 -2
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getBufferedToBlock = getBufferedToBlock;
|
|
7
|
+
exports.getLogs = getLogs;
|
|
8
|
+
exports.maxLogsForStorage = maxLogsForStorage;
|
|
9
|
+
exports.trimCachesForStorage = trimCachesForStorage;
|
|
10
|
+
exports.toFilterTopic = toFilterTopic;
|
|
11
|
+
exports.getLogParams = getLogParams;
|
|
12
|
+
const ethers_1 = require("ethers");
|
|
13
|
+
const _1 = require(".");
|
|
14
|
+
const blocks_1 = require("./blocks");
|
|
15
|
+
const cache_1 = require("./cache");
|
|
16
|
+
const debugLog_1 = require("./debugLog");
|
|
17
|
+
const indexer_1 = require("./indexer");
|
|
18
|
+
const promisePool_1 = __importDefault(require("./promisePool"));
|
|
19
|
+
const env_1 = require("./env");
|
|
20
|
+
const common_1 = require("./common");
|
|
21
|
+
const logs_decode_shared_1 = require("./logs.decode.shared");
|
|
22
|
+
const currentVersion = "v3";
|
|
23
|
+
const BLOCK_BUFFER = 10;
|
|
24
|
+
// widen the fetched range forward by BLOCK_BUFFER, without asking for blocks the chain does not
|
|
25
|
+
// have yet and without ever returning less than the caller asked for
|
|
26
|
+
function getBufferedToBlock(toBlock, head, buffer = BLOCK_BUFFER) {
|
|
27
|
+
const buffered = toBlock + buffer;
|
|
28
|
+
if (head === undefined)
|
|
29
|
+
return buffered;
|
|
30
|
+
return Math.min(buffered, Math.max(toBlock, head));
|
|
31
|
+
}
|
|
32
|
+
/* -------------------------------------------------------------------------- */
|
|
33
|
+
/* getLogs */
|
|
34
|
+
/* -------------------------------------------------------------------------- */
|
|
35
|
+
async function getLogs(options) {
|
|
36
|
+
let { target, skipCache = false, skipCacheRead = false, cacheInCloud = false, keys = [], targets, flatten = true, skipIndexer = false, onlyIndexer = false, debugMode = false, processor, maxBlockRange, } = options;
|
|
37
|
+
const { fromBlock, toBlock, topics, topic, transformLog, chain } = await getLogParams(options, false);
|
|
38
|
+
/* ----------------------------- Indexer path ----------------------------- */
|
|
39
|
+
// If the caller demands indexer only but it is disabled, fail fast
|
|
40
|
+
if (onlyIndexer && !(0, indexer_1.isIndexerEnabled)(chain))
|
|
41
|
+
throw new Error("onlyIndexer is true, but indexer is not enabled");
|
|
42
|
+
if (!skipIndexer && (0, indexer_1.isIndexerEnabled)(chain)) {
|
|
43
|
+
try {
|
|
44
|
+
const response = await (0, indexer_1.getLogs)({
|
|
45
|
+
...options,
|
|
46
|
+
all: true, // internal service – always fetch full set
|
|
47
|
+
});
|
|
48
|
+
return response;
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
(0, debugLog_1.debugLog)("Error in indexer getLogs", e.message);
|
|
52
|
+
// If caller insisted on indexer only, propagate the error
|
|
53
|
+
if (onlyIndexer)
|
|
54
|
+
throw e;
|
|
55
|
+
// Otherwise continue with RPC fallback
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!debugMode)
|
|
59
|
+
debugMode = debugLog_1.DEBUG_LEVEL2 && !!env_1.ENV_CONSTANTS.GET_LOGS_DEBUG;
|
|
60
|
+
/* ----------------------- Split by maxBlockRange ------------------------- */
|
|
61
|
+
const blockRange = toBlock - fromBlock;
|
|
62
|
+
if (maxBlockRange && blockRange > maxBlockRange) {
|
|
63
|
+
const results = [];
|
|
64
|
+
for (let currentFromBlock = fromBlock; currentFromBlock <= toBlock; currentFromBlock += maxBlockRange) {
|
|
65
|
+
const currentToBlock = Math.min(currentFromBlock + maxBlockRange - 1, toBlock);
|
|
66
|
+
const chunk = await getLogs({
|
|
67
|
+
...options,
|
|
68
|
+
fromBlock: currentFromBlock,
|
|
69
|
+
toBlock: currentToBlock,
|
|
70
|
+
});
|
|
71
|
+
results.push(chunk);
|
|
72
|
+
}
|
|
73
|
+
return flatten ? results.flat() : results;
|
|
74
|
+
}
|
|
75
|
+
/* ------------------------ Multi-target parallel ------------------------- */
|
|
76
|
+
if (targets === null || targets === void 0 ? void 0 : targets.length) {
|
|
77
|
+
const baseOpts = { ...options, fromBlock, toBlock, skipIndexer: true };
|
|
78
|
+
delete baseOpts.targets;
|
|
79
|
+
const jobs = targets.map((address, idx) => ({ idx, address }));
|
|
80
|
+
const proc = async (job) => {
|
|
81
|
+
const logs = await getLogs({ ...baseOpts, target: job.address });
|
|
82
|
+
return { idx: job.idx, logs };
|
|
83
|
+
};
|
|
84
|
+
const results = await (0, promisePool_1.default)({ items: jobs, concurrency: 5, processor: proc });
|
|
85
|
+
const ordered = new Array(targets.length);
|
|
86
|
+
for (const { idx, logs } of results)
|
|
87
|
+
ordered[idx] = logs;
|
|
88
|
+
return flatten ? ordered.flat() : ordered;
|
|
89
|
+
}
|
|
90
|
+
/* ----------------------------- RPC fallback ----------------------------- */
|
|
91
|
+
if (chain === "tron")
|
|
92
|
+
target = (0, common_1.tronToEvmAddress)(target);
|
|
93
|
+
let caches = (await _getCache());
|
|
94
|
+
const firstRun = !caches.length;
|
|
95
|
+
if (firstRun || skipCacheRead) {
|
|
96
|
+
await addLogsToCache(fromBlock, toBlock);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
// try to fill gaps compared to what is already cached
|
|
100
|
+
let _from = fromBlock;
|
|
101
|
+
let _to = toBlock;
|
|
102
|
+
const firstCache = caches[0];
|
|
103
|
+
const lastCache = caches[caches.length - 1];
|
|
104
|
+
for (const c of caches) {
|
|
105
|
+
const { fromBlock: cStart, toBlock: cEnd } = c.metadata;
|
|
106
|
+
if (_to < firstCache.metadata.fromBlock || _from > lastCache.metadata.toBlock) {
|
|
107
|
+
await addLogsToCache(_from, _to);
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
if (_from >= cEnd)
|
|
111
|
+
continue;
|
|
112
|
+
if (_from <= cStart) {
|
|
113
|
+
await addLogsToCache(_from, Math.min(_to, cStart - 1));
|
|
114
|
+
}
|
|
115
|
+
if (_to <= cEnd) {
|
|
116
|
+
_from = cEnd;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
_from = cEnd;
|
|
120
|
+
}
|
|
121
|
+
if (_from < _to)
|
|
122
|
+
await addLogsToCache(_from, _to);
|
|
123
|
+
}
|
|
124
|
+
/* ---------------------------- Return result ----------------------------- */
|
|
125
|
+
let out = [];
|
|
126
|
+
for (const c of caches) {
|
|
127
|
+
const { fromBlock: cStart, toBlock: cEnd } = c.metadata;
|
|
128
|
+
if (fromBlock > cEnd || toBlock < cStart)
|
|
129
|
+
continue;
|
|
130
|
+
const filtered = c.logs
|
|
131
|
+
.filter((i) => i.blockNumber >= fromBlock && i.blockNumber <= toBlock)
|
|
132
|
+
.map(transformLog);
|
|
133
|
+
if (processor)
|
|
134
|
+
await processor(filtered);
|
|
135
|
+
// Always include filtered logs in the return value, even when a processor is provided
|
|
136
|
+
out = out.concat(filtered); // use concat instead of ... to avoid running into issues with large arrays (RangeError: Maximum call stack size exceeded)
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
/* ----------------------------------------------------------------------- */
|
|
140
|
+
/* Internal helper functions */
|
|
141
|
+
/* ----------------------------------------------------------------------- */
|
|
142
|
+
async function addLogsToCache(fromBlock, toBlock) {
|
|
143
|
+
const dbgKey = `getLogs-${chain}-${topic}-${target}_${Math.random()}-${fromBlock}-${toBlock}`;
|
|
144
|
+
if (debugMode)
|
|
145
|
+
(0, debugLog_1.debugLog)("adding logs to cache:", fromBlock, toBlock);
|
|
146
|
+
if (fromBlock > toBlock)
|
|
147
|
+
return;
|
|
148
|
+
fromBlock = Math.max(fromBlock - BLOCK_BUFFER, 0); // avoid negative block
|
|
149
|
+
// the forward buffer must not run past the chain head. Several RPCs reject a range that ends
|
|
150
|
+
// beyond their latest block outright, and since every RPC in the pool rejects it the whole call
|
|
151
|
+
// fails. If the head cannot be read (halted chain, provider error) keep the previous behaviour.
|
|
152
|
+
let head;
|
|
153
|
+
try {
|
|
154
|
+
head = await (0, blocks_1.getBlockNumber)(chain);
|
|
155
|
+
}
|
|
156
|
+
catch (e) { }
|
|
157
|
+
toBlock = getBufferedToBlock(toBlock, head);
|
|
158
|
+
if (debugMode)
|
|
159
|
+
console.time(dbgKey);
|
|
160
|
+
const { output: newLogs } = await (0, _1.getLogs)({
|
|
161
|
+
chain,
|
|
162
|
+
target: target,
|
|
163
|
+
topic: topic,
|
|
164
|
+
keys,
|
|
165
|
+
topics,
|
|
166
|
+
fromBlock,
|
|
167
|
+
toBlock,
|
|
168
|
+
});
|
|
169
|
+
if (debugMode) {
|
|
170
|
+
console.timeEnd(dbgKey);
|
|
171
|
+
(0, debugLog_1.debugLog)("Logs pulled", chain, target, newLogs.length);
|
|
172
|
+
}
|
|
173
|
+
caches.push({ logs: newLogs, metadata: { fromBlock, toBlock } });
|
|
174
|
+
caches.sort((a, b) => a.metadata.fromBlock - b.metadata.fromBlock);
|
|
175
|
+
// merge overlapping ranges
|
|
176
|
+
const merged = [caches[0]];
|
|
177
|
+
caches.slice(1).forEach((c) => {
|
|
178
|
+
const last = merged[merged.length - 1];
|
|
179
|
+
if (last.metadata.toBlock + 1 >= c.metadata.fromBlock) {
|
|
180
|
+
last.metadata.toBlock = Math.max(last.metadata.toBlock, c.metadata.toBlock);
|
|
181
|
+
last.logs = dedupLogs(last.logs, c.logs);
|
|
182
|
+
}
|
|
183
|
+
else
|
|
184
|
+
merged.push(c);
|
|
185
|
+
});
|
|
186
|
+
caches = merged;
|
|
187
|
+
if (!skipCache) {
|
|
188
|
+
let storeCaches = caches;
|
|
189
|
+
let randomLogLength = 0;
|
|
190
|
+
const totalLogCount = caches.reduce((acc, c) => {
|
|
191
|
+
if (c.logs.length)
|
|
192
|
+
randomLogLength = JSON.stringify(c.logs[0]).length;
|
|
193
|
+
return acc + c.logs.length;
|
|
194
|
+
}, 0);
|
|
195
|
+
const fileSizeInMB = (totalLogCount * randomLogLength) / (1024 * 1024);
|
|
196
|
+
if (fileSizeInMB > 300) { // if cache size is larger than ~300MB, trim it down
|
|
197
|
+
const maxLogs = maxLogsForStorage(randomLogLength);
|
|
198
|
+
console.log(`getLogs: large cache size detected ${totalLogCount} logs size: ${fileSizeInMB}MB, retaining only the latest ${maxLogs} logs to limit memory usage target=${target} topic=${topic} fromBlock=${fromBlock} toBlock=${toBlock}`);
|
|
199
|
+
storeCaches = trimCachesForStorage(storeCaches, maxLogs);
|
|
200
|
+
}
|
|
201
|
+
// we are skipping compression by default, so reads & writes are faster
|
|
202
|
+
await (0, cache_1.writeCache)(getFile(), { caches: storeCaches, version: currentVersion }, { skipR2CacheWrite: !cacheInCloud, skipCompression: !cacheInCloud });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function dedupLogs(...arr) {
|
|
206
|
+
const seen = new Set();
|
|
207
|
+
return arr.flat().filter((i) => {
|
|
208
|
+
var _a;
|
|
209
|
+
const key = `${i.transactionHash}-${(_a = i.logIndex) !== null && _a !== void 0 ? _a : i.index}`;
|
|
210
|
+
if (!(i.hasOwnProperty("logIndex") ||
|
|
211
|
+
i.hasOwnProperty("index")) ||
|
|
212
|
+
!i.hasOwnProperty("transactionHash")) {
|
|
213
|
+
(0, debugLog_1.debugLog)("Missing crucial field", i);
|
|
214
|
+
throw new Error("Missing crucial field: logIndex/index");
|
|
215
|
+
}
|
|
216
|
+
if (seen.has(key))
|
|
217
|
+
return false;
|
|
218
|
+
seen.add(key);
|
|
219
|
+
return true;
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
async function _getCache() {
|
|
223
|
+
const key = getFile();
|
|
224
|
+
const def = [];
|
|
225
|
+
if (skipCache)
|
|
226
|
+
return def;
|
|
227
|
+
let cache = await (0, cache_1.readCache)(key, { skipR2Cache: !cacheInCloud, skipCompression: !cacheInCloud, });
|
|
228
|
+
if (!cache.caches || !cache.caches.length || cache.version !== currentVersion)
|
|
229
|
+
return def;
|
|
230
|
+
return cache.caches;
|
|
231
|
+
}
|
|
232
|
+
function getFile() {
|
|
233
|
+
var _a;
|
|
234
|
+
let extraKey = topics === null || topics === void 0 ? void 0 : topics.join("-").toLowerCase();
|
|
235
|
+
if (!extraKey)
|
|
236
|
+
throw new Error("extraKey is required");
|
|
237
|
+
if (keys.length)
|
|
238
|
+
extraKey += "-" + keys.join("-").toLowerCase();
|
|
239
|
+
let file = `${(_a = target === null || target === void 0 ? void 0 : target.toLowerCase()) !== null && _a !== void 0 ? _a : null}-${extraKey}`;
|
|
240
|
+
const normalKeyLength = '0x27e5cb712334e101b3c232eb0be198baaa595f5f-0xe8137aa901976cc8eaf1cef5dec491873faadc99d9720ccaec95673294a9d7c5-uncompressed'.length;
|
|
241
|
+
// sometimes, there is a lot of topics and we hit the file name length limit
|
|
242
|
+
if (file.length > normalKeyLength)
|
|
243
|
+
file = (0, common_1.getHash)(file);
|
|
244
|
+
return `event-logs/${chain}/${file}`;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/* -------------------------------------------------------------------------- */
|
|
248
|
+
/* Utility helpers exported */
|
|
249
|
+
/* -------------------------------------------------------------------------- */
|
|
250
|
+
// the log count that fits the same byte budget the size check uses, so a wide log trims before the flat cap
|
|
251
|
+
function maxLogsForStorage(bytesPerLog, cap = 200000, budgetMB = 300) {
|
|
252
|
+
if (!bytesPerLog || bytesPerLog < 1)
|
|
253
|
+
return cap;
|
|
254
|
+
return Math.max(1, Math.min(cap, Math.floor((budgetMB * 1024 * 1024) / bytesPerLog)));
|
|
255
|
+
}
|
|
256
|
+
// keeps the newest range and at most maxLogs of its logs, narrowing the metadata to match what is kept
|
|
257
|
+
function trimCachesForStorage(caches, maxLogs = 200000) {
|
|
258
|
+
if (!caches.length)
|
|
259
|
+
return caches;
|
|
260
|
+
let trimmed = caches;
|
|
261
|
+
if (caches.length > 1) {
|
|
262
|
+
let cacheWithLatestFromBlock = caches[0];
|
|
263
|
+
for (const c of caches) {
|
|
264
|
+
if (c.metadata.fromBlock > cacheWithLatestFromBlock.metadata.fromBlock) {
|
|
265
|
+
cacheWithLatestFromBlock = c;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
trimmed = [cacheWithLatestFromBlock];
|
|
269
|
+
}
|
|
270
|
+
return trimmed.map(c => {
|
|
271
|
+
const clone = { logs: c.logs, metadata: JSON.parse(JSON.stringify(c.metadata)) };
|
|
272
|
+
if (c.logs.length > maxLogs) {
|
|
273
|
+
const sorted = [...c.logs].sort((a, b) => b.blockNumber - a.blockNumber);
|
|
274
|
+
clone.logs = sorted.slice(0, maxLogs);
|
|
275
|
+
clone.metadata.fromBlock = clone.logs[clone.logs.length - 1].blockNumber;
|
|
276
|
+
}
|
|
277
|
+
return clone;
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
function toFilterTopic(topic) {
|
|
281
|
+
if (topic.startsWith("0x"))
|
|
282
|
+
return topic;
|
|
283
|
+
const fragment = ethers_1.EventFragment.from(topic);
|
|
284
|
+
return (0, ethers_1.id)(fragment.format());
|
|
285
|
+
}
|
|
286
|
+
exports.default = getLogs;
|
|
287
|
+
async function getLogParams(options, isIndexerCall = false) {
|
|
288
|
+
let { target, chain = "ethereum", fromBlock, toBlock, fromTimestamp, toTimestamp, eventAbi, topic, topics, extraTopics, entireLog = false, onlyArgs = false, targets = [], noTarget = false, parseLog = false, allowParseFailure = false, processor, flatten = false, } = options;
|
|
289
|
+
let parseLogWasImplicit = false;
|
|
290
|
+
let parseFailureWarned = false;
|
|
291
|
+
if (eventAbi && !Object.prototype.hasOwnProperty.call(options, "parseLog")) {
|
|
292
|
+
parseLog = true;
|
|
293
|
+
parseLogWasImplicit = true;
|
|
294
|
+
}
|
|
295
|
+
// keep raw log if entireLog=true
|
|
296
|
+
if (entireLog)
|
|
297
|
+
onlyArgs = false;
|
|
298
|
+
if (processor && targets.length > 1 && !flatten)
|
|
299
|
+
throw new Error("processor is not supported with multiple targets when flatten=false");
|
|
300
|
+
if (!fromBlock && !fromTimestamp)
|
|
301
|
+
throw new Error("fromBlock or fromTimestamp is required");
|
|
302
|
+
if (!toBlock && !toTimestamp)
|
|
303
|
+
throw new Error("toBlock or toTimestamp is required");
|
|
304
|
+
if (!fromBlock)
|
|
305
|
+
fromBlock = await (0, blocks_1.getBlockNumber)(chain, fromTimestamp);
|
|
306
|
+
if (!toBlock)
|
|
307
|
+
toBlock = await (0, blocks_1.getBlockNumber)(chain, toTimestamp);
|
|
308
|
+
if (!fromBlock || !toBlock)
|
|
309
|
+
throw new Error("fromBlock and toBlock must be > 0");
|
|
310
|
+
if (!noTarget && !target && !targets.length)
|
|
311
|
+
throw new Error('target|targets is required or set the flag "noTarget" to true');
|
|
312
|
+
let iface;
|
|
313
|
+
let event = null;
|
|
314
|
+
if (eventAbi) {
|
|
315
|
+
iface = new ethers_1.Interface([eventAbi]);
|
|
316
|
+
const fragments = iface.fragments.filter(f => f.type === 'event');
|
|
317
|
+
if (fragments.length > 0) {
|
|
318
|
+
event = fragments[0];
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (!(topics === null || topics === void 0 ? void 0 : topics.length)) {
|
|
322
|
+
if (topic)
|
|
323
|
+
topic = toFilterTopic(topic);
|
|
324
|
+
else if (eventAbi)
|
|
325
|
+
topic = toFilterTopic(eventAbi);
|
|
326
|
+
else
|
|
327
|
+
throw new Error("eventAbi | topic | topics are required");
|
|
328
|
+
topics = [topic];
|
|
329
|
+
if (extraTopics)
|
|
330
|
+
topics.push(...extraTopics);
|
|
331
|
+
}
|
|
332
|
+
if (topics === null || topics === void 0 ? void 0 : topics.length)
|
|
333
|
+
topic = topics[0];
|
|
334
|
+
function transformLog(log) {
|
|
335
|
+
// normalize indexer payload
|
|
336
|
+
if (isIndexerCall) {
|
|
337
|
+
log.address = log.source;
|
|
338
|
+
// Preserve logIndex/index if already set by normalizeLog, otherwise set from log_index
|
|
339
|
+
if (log.logIndex === undefined && log.index === undefined) {
|
|
340
|
+
log.logIndex = log.log_index;
|
|
341
|
+
log.index = log.log_index;
|
|
342
|
+
}
|
|
343
|
+
log.transactionHash = log.transaction_hash;
|
|
344
|
+
log.blockNumber = parseInt(log.block_number);
|
|
345
|
+
// Ensure topics are properly formatted
|
|
346
|
+
const topics = [log.topic0, log.topic1, log.topic2, log.topic3]
|
|
347
|
+
.filter(Boolean)
|
|
348
|
+
.map(logs_decode_shared_1.padTopic32);
|
|
349
|
+
// Ensure first topic (event signature) is present
|
|
350
|
+
if (!topics[0]) {
|
|
351
|
+
return log;
|
|
352
|
+
}
|
|
353
|
+
log.topics = topics;
|
|
354
|
+
// Store original topics for later use
|
|
355
|
+
log._originalTopics = {
|
|
356
|
+
topic0: log.topic0,
|
|
357
|
+
topic1: log.topic1,
|
|
358
|
+
topic2: log.topic2,
|
|
359
|
+
topic3: log.topic3
|
|
360
|
+
};
|
|
361
|
+
// Store original transaction hash
|
|
362
|
+
log._originalTransactionHash = log.transaction_hash;
|
|
363
|
+
// Only delete fields that are not needed for parsing
|
|
364
|
+
[
|
|
365
|
+
"chain",
|
|
366
|
+
"log_index",
|
|
367
|
+
].forEach((k) => delete log[k]);
|
|
368
|
+
}
|
|
369
|
+
if (log.blockNumber === undefined && log.block_number !== undefined)
|
|
370
|
+
log.blockNumber = parseInt(log.block_number);
|
|
371
|
+
if ((entireLog && !parseLog) || !iface) {
|
|
372
|
+
return log;
|
|
373
|
+
}
|
|
374
|
+
// Restore topics if they were lost
|
|
375
|
+
if (!log.topics && log._originalTopics) {
|
|
376
|
+
log.topics = [log._originalTopics.topic0, log._originalTopics.topic1, log._originalTopics.topic2, log._originalTopics.topic3]
|
|
377
|
+
.filter(Boolean)
|
|
378
|
+
.map(logs_decode_shared_1.padTopic32);
|
|
379
|
+
}
|
|
380
|
+
// Restore transaction hash if it was lost
|
|
381
|
+
if (!log.transactionHash && log._originalTransactionHash) {
|
|
382
|
+
log.transactionHash = log._originalTransactionHash;
|
|
383
|
+
}
|
|
384
|
+
let parsed = null;
|
|
385
|
+
if (!iface) {
|
|
386
|
+
log.args = undefined;
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
const parseFailureTolerated = allowParseFailure || (entireLog && parseLogWasImplicit);
|
|
390
|
+
try {
|
|
391
|
+
parsed = iface.parseLog(log);
|
|
392
|
+
}
|
|
393
|
+
catch (e) {
|
|
394
|
+
if (!parseFailureTolerated)
|
|
395
|
+
throw e;
|
|
396
|
+
parsed = null;
|
|
397
|
+
}
|
|
398
|
+
if (!parsed && !parseFailureTolerated)
|
|
399
|
+
throw new Error(`Failed to parse log: ${JSON.stringify(log.transactionHash)}`);
|
|
400
|
+
// keep tolerated failures visible (once per call)
|
|
401
|
+
if (!parsed && !allowParseFailure && !parseFailureWarned) {
|
|
402
|
+
parseFailureWarned = true;
|
|
403
|
+
console.warn(`[sdk.getLogs] some logs did not decode against the provided eventAbi and were returned without .args ` +
|
|
404
|
+
`(chain=${chain}, topic0=${topic}, firstTx=${log.transactionHash}). ` +
|
|
405
|
+
`Pass parseLog: true to make this an error, or allowParseFailure: true to silence this warning.`);
|
|
406
|
+
}
|
|
407
|
+
// Enrich args with named properties to match Viem output structure
|
|
408
|
+
if ((parsed === null || parsed === void 0 ? void 0 : parsed.args) && event && iface) {
|
|
409
|
+
log.args = (0, logs_decode_shared_1.enrichEthersArgsWithNamedProperties)(parsed.args, event, iface);
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
log.args = parsed === null || parsed === void 0 ? void 0 : parsed.args;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (entireLog)
|
|
416
|
+
log.parsedLog = parsed;
|
|
417
|
+
return onlyArgs ? log.args : log;
|
|
418
|
+
}
|
|
419
|
+
return {
|
|
420
|
+
chain,
|
|
421
|
+
fromBlock,
|
|
422
|
+
toBlock,
|
|
423
|
+
target,
|
|
424
|
+
topic: topic,
|
|
425
|
+
topic1: topics[1],
|
|
426
|
+
topic2: topics[2],
|
|
427
|
+
topic3: topics[3],
|
|
428
|
+
iface,
|
|
429
|
+
transformLog,
|
|
430
|
+
topics,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = runInPromisePool;
|
|
4
|
+
exports.runInPromisePool = runInPromisePool;
|
|
5
|
+
const promise_pool_1 = require("@supercharge/promise-pool");
|
|
6
|
+
const common_1 = require("./common");
|
|
7
|
+
async function runInPromisePool(params) {
|
|
8
|
+
const errors = [];
|
|
9
|
+
const { results, } = await promise_pool_1.PromisePool
|
|
10
|
+
.withConcurrency(params.concurrency)
|
|
11
|
+
.for(params.items)
|
|
12
|
+
.process(async (item, i) => {
|
|
13
|
+
try {
|
|
14
|
+
if (errors.length && !params.permitFailure)
|
|
15
|
+
throw new Error('Aborting, previous errors in promise pool');
|
|
16
|
+
const res = await params.processor(item, i);
|
|
17
|
+
return [res, i];
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
errors.push(e);
|
|
21
|
+
return [undefined, i];
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
if (errors.length && !params.permitFailure)
|
|
25
|
+
throw (0, common_1.formError)(null, { promisePoolErrors: errors });
|
|
26
|
+
// Preserve order of results
|
|
27
|
+
const flatResults = results.sort((a, b) => a[1] - b[1]).map((i => i[0]));
|
|
28
|
+
if (params.withMetadata)
|
|
29
|
+
return { results: flatResults, errors };
|
|
30
|
+
return flatResults;
|
|
31
|
+
}
|
package/build/util/r2.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.storeR2JSONString = storeR2JSONString;
|
|
4
|
+
exports.getR2JSONString = getR2JSONString;
|
|
5
|
+
const env_1 = require("./env");
|
|
6
|
+
const common_1 = require("./common");
|
|
7
|
+
const { S3Client, PutObjectCommand, GetObjectCommand, } = require("@aws-sdk/client-s3");
|
|
8
|
+
const { R2_ENDPOINT, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY } = env_1.ENV_CONSTANTS;
|
|
9
|
+
const datasetBucket = "defillama-datasets";
|
|
10
|
+
const publicBucketUrl = "https://defillama-datasets.llama.fi";
|
|
11
|
+
let R2;
|
|
12
|
+
if (R2_ENDPOINT && R2_ACCESS_KEY_ID && R2_SECRET_ACCESS_KEY) {
|
|
13
|
+
R2 = new S3Client({
|
|
14
|
+
region: "auto",
|
|
15
|
+
endpoint: "https://" + R2_ENDPOINT,
|
|
16
|
+
credentials: {
|
|
17
|
+
accessKeyId: R2_ACCESS_KEY_ID,
|
|
18
|
+
secretAccessKey: R2_SECRET_ACCESS_KEY,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const getKey = (filename) => filename.replace(/(:|'|#)/g, '/');
|
|
23
|
+
async function storeR2JSONString(filename, body) {
|
|
24
|
+
if (typeof body !== 'string')
|
|
25
|
+
body = body.toString('base64');
|
|
26
|
+
if (!R2)
|
|
27
|
+
return;
|
|
28
|
+
const command = new PutObjectCommand({
|
|
29
|
+
Bucket: datasetBucket,
|
|
30
|
+
Key: getKey(filename),
|
|
31
|
+
Body: body,
|
|
32
|
+
ContentType: "application/json",
|
|
33
|
+
});
|
|
34
|
+
return R2.send(command);
|
|
35
|
+
}
|
|
36
|
+
async function getR2JSONString(filename, { throwErrorOnFail = false } = {}) {
|
|
37
|
+
try {
|
|
38
|
+
if (!R2)
|
|
39
|
+
return await _fetchData();
|
|
40
|
+
const command = new GetObjectCommand({ Bucket: datasetBucket, Key: getKey(filename), });
|
|
41
|
+
const { Body } = await R2.send(command);
|
|
42
|
+
return await Body.transformToString();
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
if (throwErrorOnFail)
|
|
46
|
+
throw e;
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
async function _fetchData() {
|
|
50
|
+
return (0, common_1.fetchJson)(`${publicBucketUrl}/${filename}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const providers_json_1 = __importDefault(require("../providers.json"));
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const generalUtil_1 = require("../generalUtil");
|
|
9
|
+
const providerList = providers_json_1.default;
|
|
10
|
+
async function getChainData() {
|
|
11
|
+
try {
|
|
12
|
+
const chainData = await (0, generalUtil_1.fetchJson)('https://chainlist.org/rpcs.json');
|
|
13
|
+
return chainData;
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
console.log('Failed to fetch chainlist.org, falling back to local copy');
|
|
17
|
+
// https://unpkg.com/@defillama/sdk@latest/build/providers.json
|
|
18
|
+
return require(__dirname + '/chainlistOrgCache.json');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function main() {
|
|
22
|
+
let chainData = await getChainData();
|
|
23
|
+
const providerIDMap = {};
|
|
24
|
+
Object.values(chainData).forEach((i) => providerIDMap[i.chainId] = {
|
|
25
|
+
...i,
|
|
26
|
+
rpc: new Set(i.rpc.map((j) => j.url))
|
|
27
|
+
});
|
|
28
|
+
Object.entries(providerList).forEach(([key, data]) => {
|
|
29
|
+
const chainListdata = providerIDMap[data.chainId];
|
|
30
|
+
if (!chainListdata)
|
|
31
|
+
return;
|
|
32
|
+
data.rpc = data.rpc.filter((i) => {
|
|
33
|
+
if (i.endsWith('/'))
|
|
34
|
+
i = i.slice(0, -1);
|
|
35
|
+
if (chainListdata.rpc.has(i)) {
|
|
36
|
+
console.log(`Removing rpc ${i} from ${key} as it is already in chainlist`);
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
});
|
|
41
|
+
if (!data.rpc.length && chainListdata.shortName === key) {
|
|
42
|
+
delete providerList[key];
|
|
43
|
+
console.log(`Removing ${key} as it has no rpcs left`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
fs_1.default.writeFileSync(__dirname + '/../providers.json', JSON.stringify(providers_json_1.default, null, 2));
|
|
48
|
+
}
|
|
49
|
+
main();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface GetTransactionOptions {
|
|
2
|
+
addresses?: string[];
|
|
3
|
+
from_block?: number;
|
|
4
|
+
to_block?: number;
|
|
5
|
+
transaction_hashes?: string[];
|
|
6
|
+
limit?: number | 'all';
|
|
7
|
+
offset?: number;
|
|
8
|
+
chain?: string;
|
|
9
|
+
all?: boolean;
|
|
10
|
+
debugMode?: boolean;
|
|
11
|
+
transactionType?: 'from' | 'to' | 'all';
|
|
12
|
+
}
|
|
13
|
+
export declare function getTransactions(params: GetTransactionOptions): Promise<{
|
|
14
|
+
hash: any;
|
|
15
|
+
blockNumber: number;
|
|
16
|
+
transactionIndex: number;
|
|
17
|
+
from: any;
|
|
18
|
+
to: any;
|
|
19
|
+
value: any;
|
|
20
|
+
gasPrice: any;
|
|
21
|
+
gas: any;
|
|
22
|
+
input: any;
|
|
23
|
+
nonce: number;
|
|
24
|
+
data: any;
|
|
25
|
+
type: any;
|
|
26
|
+
maxFeePerGas: any;
|
|
27
|
+
maxPriorityFeePerGas: any;
|
|
28
|
+
baseFeePerGas: any;
|
|
29
|
+
effectiveGasPrice: any;
|
|
30
|
+
gasUsed: any;
|
|
31
|
+
cumulativeGasUsed: any;
|
|
32
|
+
status: number;
|
|
33
|
+
contractCreated: any;
|
|
34
|
+
timestamp: any;
|
|
35
|
+
}[] | null>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTransactions = getTransactions;
|
|
4
|
+
const debugLog_1 = require("./debugLog");
|
|
5
|
+
const indexer_1 = require("./indexer");
|
|
6
|
+
async function getTransactions(params) {
|
|
7
|
+
const { chain } = params;
|
|
8
|
+
if (!(0, indexer_1.isIndexer2Enabled)(chain)) {
|
|
9
|
+
throw new Error(`Indexer v2 not available for chain ${chain}`);
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
const response = await (0, indexer_1.getTransactions)(params);
|
|
13
|
+
if (response)
|
|
14
|
+
return response;
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
let message = e === null || e === void 0 ? void 0 : e.message;
|
|
18
|
+
(0, debugLog_1.debugLog)('Error in indexer getTransactions', message);
|
|
19
|
+
throw e;
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const chainUtils_1 = require("./chainUtils");
|
|
4
|
+
// pulls latest chain key <-> label mappings and dead chain list from the llama api and writes them to chainUtils/data.json
|
|
5
|
+
(0, chainUtils_1.updateChainLabels)();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|