@defillama/sdk 5.0.136 → 5.0.139

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.
@@ -9,6 +9,10 @@ const providers_json_1 = __importDefault(require("../providers.json"));
9
9
  const env_1 = require("./env");
10
10
  const debugLog_1 = require("./debugLog");
11
11
  const axios_1 = __importDefault(require("axios"));
12
+ let buildProviders = undefined;
13
+ if (process.env['TEST_MODE']) {
14
+ buildProviders = require('../../build/providers.json');
15
+ }
12
16
  const rpcRequestCounter = {};
13
17
  class LlamaProvider extends ethers_1.FallbackProvider {
14
18
  constructor({ providers, chainId, chainName, archivalRPCs, }, fallbackConfig) {
@@ -110,6 +114,12 @@ class LlamaProvider extends ethers_1.FallbackProvider {
110
114
  runners.splice(1, 0, primaryRunner);
111
115
  }
112
116
  runners = runners.slice(0, attempts);
117
+ // print stats every 5 minutes
118
+ let currentTimeMS = Date.now();
119
+ if (currentTimeMS - lastPrintTimeMS > 1000 * 60 * 5) {
120
+ lastPrintTimeMS = currentTimeMS;
121
+ printRPCCallStats();
122
+ }
113
123
  // if (this.chainName === 'rsk' && method === 'getLogs') {
114
124
  // const hostString = getEnvValue('RSK_ARCHIVAL_RPC')
115
125
  // if (!hostString)
@@ -175,8 +185,9 @@ function getProvider(chain = "ethereum", _getArchivalNode = false) {
175
185
  const rpcKey = chain === 'tron' ? 'tron_evm' : chain;
176
186
  if (exports.providers[chain])
177
187
  return exports.providers[chain];
188
+ const pList = buildProviders !== null && buildProviders !== void 0 ? buildProviders : providers_json_1.default;
178
189
  // use RPC from env variable if set else use RPC from providers.json
179
- let rpcList = (0, env_1.getChainRPCs)(rpcKey, (_a = providers_json_1.default[chain]) === null || _a === void 0 ? void 0 : _a.rpc);
190
+ let rpcList = (0, env_1.getChainRPCs)(rpcKey, (_a = pList[chain]) === null || _a === void 0 ? void 0 : _a.rpc);
180
191
  let archivalRPCList = (0, env_1.getArchivalRPCs)(rpcKey);
181
192
  if (!rpcList) {
182
193
  // @ts-ignore (throwing error here would alter function behavior and have side effects)
@@ -309,9 +320,11 @@ function getMedianBlockValue(blocks) {
309
320
  const mid = Math.floor(blocks.length / 3);
310
321
  return blocks.length % 2 !== 0 ? blocks[mid] : (blocks[mid - 1] + blocks[mid]) / 2;
311
322
  }
312
- process.on('exit', () => {
323
+ let lastPrintTimeMS = Date.now();
324
+ function printRPCCallStats() {
313
325
  if (Object.keys(rpcRequestCounter).length > 7) {
314
326
  (0, debugLog_1.debugLog)('RPC request count per chain');
315
327
  (0, debugLog_1.debugTable)(rpcRequestCounter);
316
328
  }
317
- });
329
+ }
330
+ process.on('exit', printRPCCallStats);
@@ -6,7 +6,7 @@ export declare function getMaxParallelRequests(chain: string): number;
6
6
  export declare function getParallelGetLogsLimit(chain: string, providerUrl?: string): number;
7
7
  export declare function getParallelGetBlocksLimit(chain: string): number;
8
8
  export declare function getEnvRPC(chain: string): string | undefined;
9
- export declare function getEnvValue(key: string, defaultValue?: string): string | undefined;
9
+ export declare function getEnvValue(key: string, defaultValue?: string): string;
10
10
  export declare function getEnvCacheFolder(defaultCacheFolder: string): string;
11
11
  export declare function getEnvMulticallAddress(chain: string): string | undefined;
12
12
  export declare function getDefaultChunkSize(chain: string): number;
package/build/util/env.js CHANGED
@@ -1,10 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getChainRPCs = exports.getArchivalRPCs = exports.getBatchMaxCount = exports.getDefaultChunkSize = exports.getEnvMulticallAddress = exports.getEnvCacheFolder = exports.getEnvValue = exports.getEnvRPC = exports.getParallelGetBlocksLimit = exports.getParallelGetLogsLimit = exports.getMaxParallelRequests = exports.getChainId = exports.ENV_CONSTANTS = void 0;
4
- const _ENV_CONSTANTS = {
5
- DEBUG_ENABLED: getEnvValue('DEBUG') === "true" || process.env.LLAMA_DEBUG_MODE ? 'true' : 'false',
6
- DEBUG_LEVEL2: process.env.LLAMA_DEBUG_LEVEL2 ? 'true' : 'false',
7
- };
8
4
  const whitelistedEnvConstants = [
9
5
  'R2_ENDPOINT', 'R2_ACCESS_KEY_ID', 'R2_SECRET_ACCESS_KEY', 'TRON_PRO_API_KEY', 'COINS_API_KEY',
10
6
  'ELASTICSEARCH_CONFIG', 'GRAPH_API_KEY', 'LLAMA_INDEXER_ENDPOINT', 'LLAMA_INDEXER_API_KEY',
@@ -12,6 +8,7 @@ const whitelistedEnvConstants = [
12
8
  const defaultEnvValues = {
13
9
  INTERNAL_SDK_CACHE_FILE: './cache.json',
14
10
  TRON_RPC_CONCURRENCY_LIMIT: '5',
11
+ LLAMA_INDEXER_ADDRESS_CHUNK_SIZE: '20',
15
12
  TRON_RPC: 'https://api.trongrid.io',
16
13
  TRON_EVM_RPC: 'https://rpc.ankr.com/tron_jsonrpc',
17
14
  NAKA_RPC: 'https://node.nakachain.xyz',
@@ -23,6 +20,10 @@ const defaultEnvValues = {
23
20
  ZETA_RPC: "https://zetachain-evm.blockpi.network/v1/rpc/public,https://zetachain-mainnet-archive.allthatnode.com:8545",
24
21
  DEFIVERSE_RPC: "https://rpc.defi-verse.org/",
25
22
  };
23
+ const _ENV_CONSTANTS = {
24
+ DEBUG_ENABLED: getEnvValue('DEBUG') === "true" || process.env.LLAMA_DEBUG_MODE ? 'true' : 'false',
25
+ DEBUG_LEVEL2: process.env.LLAMA_DEBUG_LEVEL2 ? 'true' : 'false',
26
+ };
26
27
  whitelistedEnvConstants.forEach(key => _ENV_CONSTANTS[key] = getEnvValue(key));
27
28
  Object.keys(defaultEnvValues).forEach(key => _ENV_CONSTANTS[key] = getEnvValue(key, defaultEnvValues[key]));
28
29
  // doing this as I am paranoid that that empty object when first declared might be exported before values are set
@@ -65,6 +66,7 @@ exports.getEnvRPC = getEnvRPC;
65
66
  function getEnvValue(key, defaultValue) {
66
67
  var _a, _b, _c;
67
68
  key = key.toUpperCase();
69
+ defaultValue = defaultValue !== null && defaultValue !== void 0 ? defaultValue : defaultEnvValues[key];
68
70
  return (_c = (_b = (_a = process.env['LLAMA_SDK_' + key]) !== null && _a !== void 0 ? _a : process.env['SDK_' + key]) !== null && _b !== void 0 ? _b : process.env[key]) !== null && _c !== void 0 ? _c : defaultValue;
69
71
  }
70
72
  exports.getEnvValue = getEnvValue;
@@ -87,10 +87,14 @@ async function _getLogs(params) {
87
87
  }
88
88
  catch (e) {
89
89
  (0, debugLog_1.debugLog)(`Error fetching logs for chain ${params.chain} blockSpread: ${blockSpread}. ${(0, generalUtil_1.formError)(e, { chain: params.chain, target: params.target, provider })}`);
90
- if (blockSpread >= 1500) {
90
+ if (blockSpread >= 1001) {
91
91
  // We got too many results
92
- // We could chop it up into 1500 block spreads as that is guaranteed to always return but then we'll have to make a lot of queries (easily >1000), so instead we'll keep dividing the block spread by two until we make it
92
+ // We could chop it up into 1001 block spreads as that is guaranteed to always return but then we'll have to make a lot of queries (easily >1000), so instead we'll keep dividing the block spread by two until we make it
93
93
  blockSpread = Math.floor(blockSpread / 2);
94
+ if (blockSpread > 510 && blockSpread < 2000)
95
+ blockSpread = 999;
96
+ if (blockSpread > 5100 && blockSpread < 10000)
97
+ blockSpread = 9999;
94
98
  }
95
99
  else {
96
100
  const error = (0, generalUtil_1.formError)(e, { chain: params.chain, target: params.target, provider });
@@ -16,6 +16,7 @@ const logs_1 = require("./logs");
16
16
  const _1 = require(".");
17
17
  const indexerURL = (0, env_1.getEnvValue)('LLAMA_INDEXER_ENDPOINT');
18
18
  const LLAMA_INDEXER_API_KEY = (0, env_1.getEnvValue)('LLAMA_INDEXER_API_KEY');
19
+ const addressChunkSize = +(0, env_1.getEnvValue)('LLAMA_INDEXER_ADDRESS_CHUNK_SIZE');
19
20
  const axiosIndexer = axios_1.default.create({
20
21
  headers: {
21
22
  "x-api-key": LLAMA_INDEXER_API_KEY,
@@ -139,8 +140,21 @@ async function getLogs({ chain = 'ethereum', topic, topics, fromBlock, toBlock,
139
140
  throw new Error('Chain not supported');
140
141
  if (!debugMode)
141
142
  debugMode = debugLog_1.DEBUG_LEVEL2;
142
- if (((topics === null || topics === void 0 ? void 0 : topics.length) && topics.length > 1) || (extraTopics === null || extraTopics === void 0 ? void 0 : extraTopics.length))
143
- throw new Error('TODO: topics and extraTopics part are not yet imeplemented');
143
+ let topic1;
144
+ let topic2;
145
+ let topic3;
146
+ if (((topics === null || topics === void 0 ? void 0 : topics.length) && topics.length > 1)) {
147
+ if (topics === null || topics === void 0 ? void 0 : topics.length) {
148
+ topic1 = topics[1];
149
+ topic2 = topics[2];
150
+ topic3 = topics[3];
151
+ }
152
+ }
153
+ else if (extraTopics === null || extraTopics === void 0 ? void 0 : extraTopics.length) {
154
+ topic1 = extraTopics[0];
155
+ topic2 = extraTopics[1];
156
+ topic3 = extraTopics[2];
157
+ }
144
158
  if (topics === null || topics === void 0 ? void 0 : topics.length)
145
159
  topic = topics[0];
146
160
  if (!eventAbi)
@@ -186,12 +200,15 @@ async function getLogs({ chain = 'ethereum', topic, topics, fromBlock, toBlock,
186
200
  console.time(debugTimeKey);
187
201
  }
188
202
  const addressSet = new Set(address === null || address === void 0 ? void 0 : address.split(','));
189
- const addressChunks = (0, _1.sliceIntoChunks)((_c = address === null || address === void 0 ? void 0 : address.split(',')) !== null && _c !== void 0 ? _c : [], 10);
203
+ const addressChunks = (0, _1.sliceIntoChunks)((_c = address === null || address === void 0 ? void 0 : address.split(',')) !== null && _c !== void 0 ? _c : [], addressChunkSize);
190
204
  // to ensure that we have at least one chunk to process if no target is provided
191
205
  if (noTarget && addressChunks.length === 0)
192
206
  addressChunks.push(undefined);
193
207
  for (const chunk of addressChunks) {
194
- let _logAgg = [];
208
+ if (Array.isArray(chunk) && chunk.length === 0) {
209
+ throw new Error('Address chunk cannot be empty');
210
+ }
211
+ let logCount = 0;
195
212
  do {
196
213
  const params = {
197
214
  addresses: hasAddressFilter ? chunk.join(',') : undefined,
@@ -199,25 +216,25 @@ async function getLogs({ chain = 'ethereum', topic, topics, fromBlock, toBlock,
199
216
  topic0: topic,
200
217
  from_block: fromBlock,
201
218
  to_block: toBlock,
202
- limit,
203
- offset,
219
+ topic1, topic2, topic3,
220
+ limit, offset,
221
+ noTarget,
204
222
  };
205
223
  const { data: { logs: _logs, totalCount } } = await axiosIndexer(`/logs`, { params, });
206
224
  // getLogs uses 'address' field to return log source, so we add the field here to make it compatible
207
225
  _logs.forEach((l) => {
208
226
  l.address = l.source;
227
+ const iswhitelisted = !addressSet.size || addressSet.has(l.source.toLowerCase());
228
+ if (iswhitelisted) {
229
+ logs.push(l);
230
+ }
209
231
  });
210
- _logAgg.push(..._logs.filter((l) => {
211
- if (!addressSet.size)
212
- return true;
213
- return addressSet.has(l === null || l === void 0 ? void 0 : l.source.toLowerCase());
214
- }));
232
+ logCount += _logs.length;
215
233
  offset += limit;
216
234
  // If we have all the logs, or we have reached the limit, or there are no logs, we stop
217
- if (_logs.length < limit || totalCount <= _logAgg.length || _logs.length === 0)
235
+ if (_logs.length < limit || totalCount <= logCount || _logs.length === 0)
218
236
  hasMore = false;
219
237
  } while (all && hasMore);
220
- logs.push(..._logAgg);
221
238
  }
222
239
  if (debugMode) {
223
240
  console.timeEnd(debugTimeKey);
@@ -239,7 +256,7 @@ async function getLogs({ chain = 'ethereum', topic, topics, fromBlock, toBlock,
239
256
  log.transactionHash = log.transaction_hash;
240
257
  log.blockNumber = log.block_number;
241
258
  log.topics = [log.topic0, log.topic1, log.topic2, log.topic3,].filter(t => t !== '').map(i => ethers_1.ethers.zeroPadValue(i, 32));
242
- const deleteKeys = ['chain', 'address', 'block_number', 'log_index', 'topic0', 'topic1', 'topic2', 'topic3', 'decodedArgs', 'transaction_hash',];
259
+ const deleteKeys = ['chain', 'block_number', 'log_index', 'topic0', 'topic1', 'topic2', 'topic3', 'decodedArgs', 'transaction_hash',];
243
260
  deleteKeys.forEach(k => delete log[k]);
244
261
  const parsedLog = iface === null || iface === void 0 ? void 0 : iface.parseLog({ data: log.data, topics: log.topics, });
245
262
  log.args = parsedLog === null || parsedLog === void 0 ? void 0 : parsedLog.args;
@@ -97,7 +97,7 @@ function filterRPCs(rpc) {
97
97
  if (i.includes('$'))
98
98
  return false; // remove anything where api key is injected
99
99
  // reject websocket, http, testnet, devnet, and anything with '='
100
- if (/(wss\:|ws\:|http\:|test|devnet|terminet\.io|huobichain\.com|getblock\.io|bitstack\.com|nodereal.io\/v1|pokt\.network|ankr\.com|\=)/.test(i))
100
+ if (/(wss\:|ws\:|http\:|test|devnet|terminet\.io|huobichain\.com|getblock\.io|bitstack\.com|nodereal.io\/v1|pokt\.network|ankr\.com|histori\.xyz|owlracle\.info\=)/.test(i))
101
101
  return false; // remove anything with blacklisted words
102
102
  return true;
103
103
  }).map((i) => {
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@defillama/sdk",
3
- "version": "5.0.136",
3
+ "version": "5.0.139",
4
4
  "description": "SDK for calculating TVL",
5
5
  "main": "build/index.js",
6
6
  "scripts": {
7
7
  "start": "npm run build && node build/index.js",
8
8
  "build": "tsc",
9
9
  "watch": "tsc --watch",
10
- "test": "LLAMA_DEBUG_MODE='' SDK_DEBUG='' jest",
10
+ "load-providers": "wget https://unpkg.com/@defillama/sdk@latest/build/providers.json -O build/providers.json",
11
+ "test": "npm run load-providers && TEST_MODE=true LLAMA_DEBUG_MODE='' SDK_DEBUG='' LLAMA_DEBUG_LEVEL2='' jest",
11
12
  "update-providers": "ts-node src/util/updateProviderList.ts",
12
13
  "remove-rpcs": "ts-node src/util/removeRedundantRPCs.ts",
13
14
  "format": "prettier --write \"src/**/*.ts\"",