@defillama/sdk 5.0.90 → 5.0.92
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/providers.json +1 -1
- package/build/util/indexer.d.ts +19 -0
- package/build/util/indexer.js +113 -5
- package/build/util/logs.js +1 -1
- package/package.json +1 -1
package/build/util/indexer.d.ts
CHANGED
|
@@ -34,6 +34,25 @@ export type IndexerGetLogsOptions = {
|
|
|
34
34
|
offset?: number;
|
|
35
35
|
debugMode?: boolean;
|
|
36
36
|
};
|
|
37
|
+
export type IndexerGetTokenTransfersOptions = {
|
|
38
|
+
target?: Address;
|
|
39
|
+
targets?: Address[];
|
|
40
|
+
fromBlock?: number;
|
|
41
|
+
toBlock?: number;
|
|
42
|
+
chain?: string;
|
|
43
|
+
fromTimestamp?: number;
|
|
44
|
+
toTimestamp?: number;
|
|
45
|
+
flatten?: boolean;
|
|
46
|
+
all?: boolean;
|
|
47
|
+
limit?: number;
|
|
48
|
+
offset?: number;
|
|
49
|
+
debugMode?: boolean;
|
|
50
|
+
fromAddressFilter?: string | string[];
|
|
51
|
+
transferType?: 'in' | 'out';
|
|
52
|
+
tokens?: string | string[];
|
|
53
|
+
token?: string;
|
|
54
|
+
};
|
|
37
55
|
export declare function getLogs({ chain, topic, topics, fromBlock, toBlock, all, limit, offset, target, targets, eventAbi, entireLog, flatten, extraTopics, fromTimestamp, toTimestamp, debugMode }: IndexerGetLogsOptions): Promise<any[]>;
|
|
38
56
|
export declare function isIndexerEnabled(chain?: string): boolean;
|
|
57
|
+
export declare function getTokenTransfers({ chain, fromAddressFilter, fromBlock, toBlock, all, limit, offset, target, targets, flatten, fromTimestamp, toTimestamp, debugMode, transferType, token, tokens, }: IndexerGetTokenTransfersOptions): Promise<any[]>;
|
|
39
58
|
export {};
|
package/build/util/indexer.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.isIndexerEnabled = exports.getLogs = exports.getTokens = exports.supportedChainSet = void 0;
|
|
6
|
+
exports.getTokenTransfers = exports.isIndexerEnabled = exports.getLogs = exports.getTokens = exports.supportedChainSet = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
const env_1 = require("./env");
|
|
9
9
|
const cache_1 = require("./cache");
|
|
@@ -78,6 +78,9 @@ async function getTokens(address, { onlyWhitelisted = true, skipCacheRead = fals
|
|
|
78
78
|
if (Array.isArray(address))
|
|
79
79
|
address = address.join(',');
|
|
80
80
|
address = address.toLowerCase();
|
|
81
|
+
let chainId;
|
|
82
|
+
if (chain)
|
|
83
|
+
chainId = chainToIDMapping[chain];
|
|
81
84
|
const project = 'llama-indexer-cache';
|
|
82
85
|
const key = onlyWhitelisted ? address : `${address}/all`;
|
|
83
86
|
const file = `${project}/${key}`;
|
|
@@ -94,7 +97,7 @@ async function getTokens(address, { onlyWhitelisted = true, skipCacheRead = fals
|
|
|
94
97
|
const { data: { balances } } = await axios_1.default.get(`${indexerURL}/balances`, {
|
|
95
98
|
params: {
|
|
96
99
|
addresses: address,
|
|
97
|
-
|
|
100
|
+
chainId,
|
|
98
101
|
type: tokenType,
|
|
99
102
|
}
|
|
100
103
|
});
|
|
@@ -169,10 +172,11 @@ async function getLogs({ chain = 'ethereum', topic, topics, fromBlock, toBlock,
|
|
|
169
172
|
(0, debugLog_1.debugLog)('[Indexer] Pulling logs ' + debugTimeKey);
|
|
170
173
|
console.time(debugTimeKey);
|
|
171
174
|
}
|
|
175
|
+
const addressSet = new Set(address === null || address === void 0 ? void 0 : address.split(','));
|
|
172
176
|
do {
|
|
173
177
|
const params = {
|
|
174
178
|
addresses: address,
|
|
175
|
-
|
|
179
|
+
chainId,
|
|
176
180
|
topic0: topic,
|
|
177
181
|
from_block: fromBlock,
|
|
178
182
|
to_block: toBlock,
|
|
@@ -180,7 +184,11 @@ async function getLogs({ chain = 'ethereum', topic, topics, fromBlock, toBlock,
|
|
|
180
184
|
offset,
|
|
181
185
|
};
|
|
182
186
|
const { data: { logs: _logs, totalCount } } = await axios_1.default.get(`${indexerURL}/logs`, { params });
|
|
183
|
-
logs.push(..._logs)
|
|
187
|
+
logs.push(..._logs.filter((l) => {
|
|
188
|
+
if (!addressSet.size)
|
|
189
|
+
return true;
|
|
190
|
+
return addressSet.has(l === null || l === void 0 ? void 0 : l.source.toLowerCase());
|
|
191
|
+
}));
|
|
184
192
|
offset += limit;
|
|
185
193
|
// If we have all the logs, or we have reached the limit, or there are no logs, we stop
|
|
186
194
|
if (_logs.length < limit || totalCount <= logs.length || _logs.length === 0)
|
|
@@ -200,6 +208,7 @@ async function getLogs({ chain = 'ethereum', topic, topics, fromBlock, toBlock,
|
|
|
200
208
|
}
|
|
201
209
|
}
|
|
202
210
|
logs = logs.map((log) => {
|
|
211
|
+
const source = log.source.toLowerCase();
|
|
203
212
|
log.logIndex = log.log_index;
|
|
204
213
|
log.index = log.log_index;
|
|
205
214
|
log.transactionHash = log.transaction_hash;
|
|
@@ -214,7 +223,7 @@ async function getLogs({ chain = 'ethereum', topic, topics, fromBlock, toBlock,
|
|
|
214
223
|
log.args = parsedLog === null || parsedLog === void 0 ? void 0 : parsedLog.args;
|
|
215
224
|
log = !entireLog ? log.args : log;
|
|
216
225
|
if (splitByAddress) {
|
|
217
|
-
const index = addressIndexMap[
|
|
226
|
+
const index = addressIndexMap[source];
|
|
218
227
|
mappedLogs[index].push(log);
|
|
219
228
|
}
|
|
220
229
|
return log;
|
|
@@ -232,3 +241,102 @@ function isIndexerEnabled(chain) {
|
|
|
232
241
|
return true;
|
|
233
242
|
}
|
|
234
243
|
exports.isIndexerEnabled = isIndexerEnabled;
|
|
244
|
+
async function getTokenTransfers({ chain = 'ethereum', fromAddressFilter, fromBlock, toBlock, all = true, limit = 1000, offset = 0, target, targets = [], flatten = true, fromTimestamp, toTimestamp, debugMode = false, transferType = 'in', token, tokens, }) {
|
|
245
|
+
var _a, _b;
|
|
246
|
+
if (!indexerURL)
|
|
247
|
+
throw new Error('Llama Indexer URL not set');
|
|
248
|
+
const chainId = chainToIDMapping[chain];
|
|
249
|
+
if (!chainId)
|
|
250
|
+
throw new Error('Chain not supported');
|
|
251
|
+
if (!debugMode)
|
|
252
|
+
debugMode = debugLog_1.DEBUG_LEVEL2;
|
|
253
|
+
const fromFilterEnabled = fromAddressFilter && fromAddressFilter.length;
|
|
254
|
+
if (fromAddressFilter && typeof fromAddressFilter === 'string')
|
|
255
|
+
fromAddressFilter = [fromAddressFilter];
|
|
256
|
+
const fromFilterSet = new Set((fromAddressFilter !== null && fromAddressFilter !== void 0 ? fromAddressFilter : []).map((a) => a.toLowerCase()));
|
|
257
|
+
// if (!target && !targets?.length) throw new Error('target|targets is required')
|
|
258
|
+
if (!fromBlock && !fromTimestamp)
|
|
259
|
+
throw new Error('fromBlock or fromTimestamp is required');
|
|
260
|
+
if (!toBlock && !toTimestamp)
|
|
261
|
+
throw new Error('toBlock or toTimestamp is required');
|
|
262
|
+
if (!fromBlock)
|
|
263
|
+
fromBlock = await (0, blocks_1.getBlockNumber)(chain, fromTimestamp);
|
|
264
|
+
if (!toBlock)
|
|
265
|
+
toBlock = await (0, blocks_1.getBlockNumber)(chain, toTimestamp);
|
|
266
|
+
if (!fromBlock || !toBlock)
|
|
267
|
+
throw new Error('fromBlock and toBlock must be > 0');
|
|
268
|
+
if (token)
|
|
269
|
+
tokens = [token];
|
|
270
|
+
if (tokens) {
|
|
271
|
+
if (typeof tokens === 'string')
|
|
272
|
+
tokens = [tokens];
|
|
273
|
+
tokens = tokens.join(',').toLowerCase();
|
|
274
|
+
}
|
|
275
|
+
if (target)
|
|
276
|
+
targets = [target];
|
|
277
|
+
if (!targets.length)
|
|
278
|
+
throw new Error('target|targets is required');
|
|
279
|
+
targets = targets.map(t => t.toLowerCase());
|
|
280
|
+
let addresses = targets.join(',');
|
|
281
|
+
const chainIndexStatus = await getChainIndexStatus();
|
|
282
|
+
const lastIndexedBlock = (_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
|
|
283
|
+
if (lastIndexedBlock < toBlock)
|
|
284
|
+
throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${toBlock}`);
|
|
285
|
+
let hasMore = true;
|
|
286
|
+
let logs = [];
|
|
287
|
+
const debugTimeKey = `Indexer-tokenTransfers-${chain}-${addresses}_${Math.random()}`;
|
|
288
|
+
if (debugMode) {
|
|
289
|
+
(0, debugLog_1.debugLog)('[Indexer] Pulling token transfers ' + debugTimeKey);
|
|
290
|
+
console.time(debugTimeKey);
|
|
291
|
+
}
|
|
292
|
+
do {
|
|
293
|
+
const params = {
|
|
294
|
+
addresses,
|
|
295
|
+
chainId,
|
|
296
|
+
from_block: fromBlock,
|
|
297
|
+
to_block: toBlock,
|
|
298
|
+
limit,
|
|
299
|
+
offset,
|
|
300
|
+
tokens,
|
|
301
|
+
};
|
|
302
|
+
if (transferType === 'in')
|
|
303
|
+
params.to_address = true;
|
|
304
|
+
else
|
|
305
|
+
params.from_address = true;
|
|
306
|
+
const { data: { transfers: _logs, totalCount } } = await axios_1.default.get(`${indexerURL}/token-transfers`, { params });
|
|
307
|
+
logs.push(..._logs);
|
|
308
|
+
offset += limit;
|
|
309
|
+
// If we have all the logs, or we have reached the limit, or there are no logs, we stop
|
|
310
|
+
if (_logs.length < limit || totalCount <= logs.length || _logs.length === 0)
|
|
311
|
+
hasMore = false;
|
|
312
|
+
} while (all && hasMore);
|
|
313
|
+
logs = logs.filter((l) => {
|
|
314
|
+
if (!fromFilterEnabled)
|
|
315
|
+
return true;
|
|
316
|
+
return fromFilterSet.has(l === null || l === void 0 ? void 0 : l.from_address.toLowerCase());
|
|
317
|
+
});
|
|
318
|
+
if (debugMode) {
|
|
319
|
+
console.timeEnd(debugTimeKey);
|
|
320
|
+
(0, debugLog_1.debugLog)('Token Transfers pulled ' + chain, addresses, logs.length);
|
|
321
|
+
}
|
|
322
|
+
const mappedLogs = [];
|
|
323
|
+
let addressIndexMap = {};
|
|
324
|
+
const splitByAddress = (targets === null || targets === void 0 ? void 0 : targets.length) && !flatten;
|
|
325
|
+
if (splitByAddress) {
|
|
326
|
+
for (let i = 0; i < targets.length; i++) {
|
|
327
|
+
addressIndexMap[targets[i]] = i;
|
|
328
|
+
mappedLogs.push([]);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (splitByAddress) {
|
|
332
|
+
logs.forEach((log) => {
|
|
333
|
+
const sourceField = transferType === 'in' ? 'to_address' : 'from_address';
|
|
334
|
+
const source = log[sourceField].toLowerCase();
|
|
335
|
+
const index = addressIndexMap[source];
|
|
336
|
+
mappedLogs[index].push(log);
|
|
337
|
+
});
|
|
338
|
+
return mappedLogs;
|
|
339
|
+
}
|
|
340
|
+
return logs;
|
|
341
|
+
}
|
|
342
|
+
exports.getTokenTransfers = getTokenTransfers;
|
package/build/util/logs.js
CHANGED
|
@@ -44,7 +44,7 @@ async function getLogs(options) {
|
|
|
44
44
|
if (targets === null || targets === void 0 ? void 0 : targets.length) {
|
|
45
45
|
const newOptions = { ...options, fromBlock, toBlock };
|
|
46
46
|
delete newOptions.targets;
|
|
47
|
-
const res = await Promise.all(targets.map(i => getLogs({ ...newOptions, target: i })));
|
|
47
|
+
const res = await Promise.all(targets.map(i => getLogs({ ...newOptions, target: i, skipIndexer: true })));
|
|
48
48
|
if (flatten)
|
|
49
49
|
return res.flat();
|
|
50
50
|
return res;
|