@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.
@@ -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 {};
@@ -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
- chain: chain,
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
- chain: chainId,
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[log.source.toLowerCase()];
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;
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defillama/sdk",
3
- "version": "5.0.90",
3
+ "version": "5.0.92",
4
4
  "description": "SDK for calculating TVL",
5
5
  "main": "build/index.js",
6
6
  "scripts": {