@defillama/sdk 5.0.91 → 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 +105 -3
- 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
|
});
|
|
@@ -173,7 +176,7 @@ async function getLogs({ chain = 'ethereum', topic, topics, fromBlock, toBlock,
|
|
|
173
176
|
do {
|
|
174
177
|
const params = {
|
|
175
178
|
addresses: address,
|
|
176
|
-
|
|
179
|
+
chainId,
|
|
177
180
|
topic0: topic,
|
|
178
181
|
from_block: fromBlock,
|
|
179
182
|
to_block: toBlock,
|
|
@@ -238,3 +241,102 @@ function isIndexerEnabled(chain) {
|
|
|
238
241
|
return true;
|
|
239
242
|
}
|
|
240
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;
|