@defillama/sdk 5.0.221 → 5.0.222

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/util/env.js CHANGED
@@ -19,7 +19,8 @@ exports.shouldSkipBlockValidation = shouldSkipBlockValidation;
19
19
  exports.getBoolEnvValue = getBoolEnvValue;
20
20
  exports.whitelistedEnvConstants = [
21
21
  'R2_ENDPOINT', 'R2_ACCESS_KEY_ID', 'R2_SECRET_ACCESS_KEY', 'TRON_PRO_API_KEY', 'COINS_API_KEY', 'INTERNAL_API_KEY',
22
- 'ELASTICSEARCH_CONFIG', 'GRAPH_API_KEY', 'LLAMA_INDEXER_V2_ENDPOINT', 'LLAMA_INDEXER_V2_API_KEY', 'LLAMA_INDEXER_TIMEOUT_MS'
22
+ 'ELASTICSEARCH_CONFIG', 'GRAPH_API_KEY', 'LLAMA_INDEXER_V2_ENDPOINT', 'LLAMA_INDEXER_V2_API_KEY', 'LLAMA_INDEXER_TIMEOUT_MS',
23
+ 'LLAMA_INDEXER_V4_ENDPOINT', 'LLAMA_INDEXER_V4_API_KEY', 'LLAMA_INDEXER_PREFER_V4', 'LLAMA_INDEXER_V4_ONLY_CHAINS',
23
24
  ];
24
25
  const isDebugLevel3 = process.env.LLAMA_SDK_DEBUG_LEVEL_3 === 'true';
25
26
  const defaultEnvValues = {
@@ -1,5 +1,7 @@
1
1
  import { Address } from "../types";
2
2
  import { GetTransactionOptions } from "./transactions";
3
+ export type IndexerVersion = "v2" | "v4";
4
+ export declare function getChainIndexerVersion(chain: string): IndexerVersion;
3
5
  export declare const supportedChainSet2: Set<string>;
4
6
  export type IndexerGetLogsOptions = {
5
7
  target?: Address;
@@ -2,8 +2,10 @@
2
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
+ var _a, _b;
5
6
  Object.defineProperty(exports, "__esModule", { value: true });
6
7
  exports.supportedChainSet2 = void 0;
8
+ exports.getChainIndexerVersion = getChainIndexerVersion;
7
9
  exports.getLogs = getLogs;
8
10
  exports.getTokenTransfers = getTokenTransfers;
9
11
  exports.getTransactions = getTransactions;
@@ -22,8 +24,12 @@ const debugLog_1 = require("./debugLog");
22
24
  const env_1 = require("./env");
23
25
  const logs_1 = require("./logs");
24
26
  const logs_decode_shared_1 = require("./logs.decode.shared");
25
- const LLAMA_INDEXER_ENDPOINT = (0, env_1.getEnvValue)("LLAMA_INDEXER_V2_ENDPOINT");
26
- const LLAMA_INDEXER_API_KEY = (0, env_1.getEnvValue)("LLAMA_INDEXER_V2_API_KEY");
27
+ const LLAMA_INDEXER_V2_ENDPOINT = (0, env_1.getEnvValue)("LLAMA_INDEXER_V2_ENDPOINT");
28
+ const LLAMA_INDEXER_V2_API_KEY = (0, env_1.getEnvValue)("LLAMA_INDEXER_V2_API_KEY");
29
+ const LLAMA_INDEXER_V4_ENDPOINT = (0, env_1.getEnvValue)("LLAMA_INDEXER_V4_ENDPOINT");
30
+ const LLAMA_INDEXER_V4_API_KEY = (_a = (0, env_1.getEnvValue)("LLAMA_INDEXER_V4_API_KEY")) !== null && _a !== void 0 ? _a : LLAMA_INDEXER_V2_API_KEY;
31
+ // route every supported chain through v4 (v2 stays available as explicit config)
32
+ const LLAMA_INDEXER_PREFER_V4 = (0, env_1.getEnvValue)("LLAMA_INDEXER_PREFER_V4") === "true";
27
33
  const addressChunkSize = +(0, env_1.getEnvValue)("LLAMA_INDEXER_ADDRESS_CHUNK_SIZE") || 100;
28
34
  const INDEXER_REQUEST_TIMEOUT_MS = +(0, env_1.getEnvValue)("LLAMA_INDEXER_TIMEOUT_MS");
29
35
  const indexerChainIdChainMapping = {
@@ -52,43 +58,88 @@ const indexerChainIdChainMapping = {
52
58
  4326: "megaeth",
53
59
  196: "xlayer"
54
60
  };
61
+ const v4OnlyChainIdChainMapping = {
62
+ 4663: "robinhood",
63
+ };
64
+ ((_b = (0, env_1.getEnvValue)("LLAMA_INDEXER_V4_ONLY_CHAINS")) !== null && _b !== void 0 ? _b : "")
65
+ .split(",")
66
+ .map((entry) => entry.trim())
67
+ .filter(Boolean)
68
+ .forEach((entry) => {
69
+ const [chainId, chainName] = entry.split(":").map((i) => i.trim());
70
+ if (!chainId || !chainName || isNaN(+chainId))
71
+ throw new Error(`Invalid LLAMA_INDEXER_V4_ONLY_CHAINS entry: ${entry}`);
72
+ v4OnlyChainIdChainMapping[+chainId] = chainName;
73
+ });
74
+ const allChainIdChainMapping = { ...indexerChainIdChainMapping, ...v4OnlyChainIdChainMapping };
75
+ const v4OnlyChainSet = new Set(Object.values(v4OnlyChainIdChainMapping));
76
+ const indexerConfigs = {
77
+ v2: { endpoint: LLAMA_INDEXER_V2_ENDPOINT, apiKey: LLAMA_INDEXER_V2_API_KEY },
78
+ v4: { endpoint: LLAMA_INDEXER_V4_ENDPOINT, apiKey: LLAMA_INDEXER_V4_API_KEY },
79
+ };
55
80
  // http agents for streaming (keep-alive)
56
81
  const httpAgent = new http_1.default.Agent({ keepAlive: true, maxSockets: 256, maxFreeSockets: 64 });
57
82
  const httpsAgent = new https_1.default.Agent({ keepAlive: true, maxSockets: 256, maxFreeSockets: 64 });
58
- const axiosInstance = axios_1.default.create({
59
- headers: { "x-api-key": LLAMA_INDEXER_API_KEY },
60
- baseURL: LLAMA_INDEXER_ENDPOINT,
61
- httpAgent,
62
- httpsAgent,
63
- timeout: INDEXER_REQUEST_TIMEOUT_MS,
64
- });
65
- function checkIndexerConfig() {
66
- if (!LLAMA_INDEXER_ENDPOINT || !LLAMA_INDEXER_API_KEY)
67
- throw new Error(`Llama Indexer URL/api key is not set`);
83
+ const axiosInstances = {
84
+ v2: axios_1.default.create({
85
+ headers: { "x-api-key": LLAMA_INDEXER_V2_API_KEY },
86
+ baseURL: LLAMA_INDEXER_V2_ENDPOINT,
87
+ httpAgent,
88
+ httpsAgent,
89
+ timeout: INDEXER_REQUEST_TIMEOUT_MS,
90
+ }),
91
+ v4: axios_1.default.create({
92
+ headers: { "x-api-key": LLAMA_INDEXER_V4_API_KEY },
93
+ baseURL: LLAMA_INDEXER_V4_ENDPOINT,
94
+ httpAgent,
95
+ httpsAgent,
96
+ timeout: INDEXER_REQUEST_TIMEOUT_MS,
97
+ }),
98
+ };
99
+ function checkIndexerConfig(version) {
100
+ const { endpoint, apiKey } = indexerConfigs[version];
101
+ if (!endpoint || !apiKey)
102
+ throw new Error(`Llama Indexer (${version}) URL/api key is not set`);
103
+ }
104
+ // pick which indexer serves a given chain:
105
+ // - v4-only chains (not indexed on v2) always go to v4
106
+ // - everything else goes to v2, unless LLAMA_INDEXER_PREFER_V4 is set or v2 is not configured
107
+ function getChainIndexerVersion(chain) {
108
+ if (v4OnlyChainSet.has(chain))
109
+ return "v4";
110
+ if (!LLAMA_INDEXER_V4_ENDPOINT)
111
+ return "v2";
112
+ if (LLAMA_INDEXER_PREFER_V4 || !LLAMA_INDEXER_V2_ENDPOINT)
113
+ return "v4";
114
+ return "v2";
68
115
  }
69
116
  function getChainId(chain) {
70
117
  var _a;
71
- const chainId = (_a = Object.entries(indexerChainIdChainMapping).find(([, chainName]) => chainName === chain)) === null || _a === void 0 ? void 0 : _a[0];
118
+ const chainId = (_a = Object.entries(allChainIdChainMapping).find(([, chainName]) => chainName === chain)) === null || _a === void 0 ? void 0 : _a[0];
72
119
  if (!chainId)
73
120
  throw new Error("Chain not supported");
74
121
  return +chainId;
75
122
  }
76
123
  function getSupportedChains() {
77
- return new Set(Object.values(indexerChainIdChainMapping));
124
+ return new Set(Object.values(allChainIdChainMapping));
78
125
  }
79
126
  exports.supportedChainSet2 = getSupportedChains();
80
- const state = { chainIndexStatus: {} };
127
+ const syncStates = {
128
+ v2: { chainIndexStatus: {} },
129
+ v4: { chainIndexStatus: {} },
130
+ };
81
131
  const cacheTime = 1 * 60 * 1000; // 1 min
82
- async function getChainIndexStatus() {
83
- checkIndexerConfig();
132
+ async function getChainIndexStatus(version) {
133
+ checkIndexerConfig(version);
134
+ const state = syncStates[version];
84
135
  if (state.timestamp && Date.now() - state.timestamp < cacheTime)
85
136
  return state.chainIndexStatus;
86
137
  state.timestamp = Date.now();
87
138
  state.chainIndexStatus = (async () => {
88
- const { data: { syncStatus }, } = await axiosInstance.get(`/sync`).catch((e) => { throw (0, common_1.formError)(e); });
139
+ const { data: { syncStatus }, } = await axiosInstances[version].get(`/sync`).catch((e) => { throw (0, common_1.formError)(e); });
89
140
  const info = {};
90
141
  syncStatus.forEach((d) => {
91
- const chain = indexerChainIdChainMapping[d.chain];
142
+ const chain = allChainIdChainMapping[d.chain];
92
143
  if (chain) {
93
144
  info[chain] = {
94
145
  block: d.lastIndexedBlock,
@@ -104,11 +155,11 @@ async function getChainIndexStatus() {
104
155
  // Streaming support (disabled by default, opt-in via clientStreaming: true)
105
156
  // ---------------------------------------------------------------------------
106
157
  async function streamJsonArrayFromIndexer(opts) {
107
- const { path, arrayKey = "logs", onItem, onChunkStats, shouldStop } = opts;
158
+ const { path, version, arrayKey = "logs", onItem, onChunkStats, shouldStop } = opts;
108
159
  const controller = new AbortController();
109
160
  let bytesReceived = 0;
110
161
  let itemsProcessed = 0;
111
- const res = await axiosInstance.get(path, {
162
+ const res = await axiosInstances[version].get(path, {
112
163
  responseType: "stream",
113
164
  timeout: 0,
114
165
  maxContentLength: Infinity,
@@ -198,9 +249,10 @@ async function getLogs(options) {
198
249
  throw new Error("When noTarget is true, block range must be less than 500k blocks. Please narrow down your block range.");
199
250
  }
200
251
  // Ensure the indexer is synced far enough
201
- checkIndexerConfig();
252
+ const indexerVersion = getChainIndexerVersion(chain);
253
+ checkIndexerConfig(indexerVersion);
202
254
  const chainId = getChainId(chain);
203
- const chainIndexStatus = await getChainIndexStatus();
255
+ const chainIndexStatus = await getChainIndexStatus(indexerVersion);
204
256
  const lastIndexedBlock = (_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
205
257
  if (lastIndexedBlock < toBlock) {
206
258
  const percentageMissing = ((toBlock - lastIndexedBlock) / (toBlock - fromBlock)) * 100;
@@ -261,7 +313,7 @@ async function getLogs(options) {
261
313
  // Streaming (opt-in) — NO server-side parsing; mirror legacy semantics
262
314
  // -----------------------------------------------------------------------
263
315
  if (clientStreaming) {
264
- const useAll = options.all === true;
316
+ const useAll = all === true;
265
317
  const effectiveLimit = useAll ? Number.POSITIVE_INFINITY : ((_d = options.limit) !== null && _d !== void 0 ? _d : limit);
266
318
  const shouldLimit = !useAll && Number.isFinite(effectiveLimit);
267
319
  const effectiveOffset = useAll ? 0 : ((_f = (_e = options.offset) !== null && _e !== void 0 ? _e : initialOffset) !== null && _f !== void 0 ? _f : 0);
@@ -368,6 +420,7 @@ async function getLogs(options) {
368
420
  };
369
421
  await streamJsonArrayFromIndexer({
370
422
  path: `/logs?${qs.toString()}`,
423
+ version: indexerVersion,
371
424
  arrayKey: "logs",
372
425
  onItem: (raw) => {
373
426
  var _a, _b, _c;
@@ -437,7 +490,7 @@ async function getLogs(options) {
437
490
  offset: chunkOffset,
438
491
  noTarget,
439
492
  };
440
- const { data: { logs: _logs, totalCount }, } = await axiosInstance(`/logs`, { params }).catch(e => { throw (0, common_1.formError)(e); });
493
+ const { data: { logs: _logs, totalCount }, } = await axiosInstances[indexerVersion](`/logs`, { params }).catch((e) => { throw (0, common_1.formError)(e); });
441
494
  const filtered = _logs.filter((l) => {
442
495
  var _a, _b, _c;
443
496
  const isWhitelisted = !addressSet.size || addressSet.has((_c = (_b = ((_a = l.source) !== null && _a !== void 0 ? _a : l.address)) === null || _b === void 0 ? void 0 : _b.toLowerCase) === null || _c === void 0 ? void 0 : _c.call(_b));
@@ -505,7 +558,8 @@ async function getTokenTransfers({ chain = "ethereum", fromAddressFilter, fromBl
505
558
  var _a, _b;
506
559
  if (!debugMode)
507
560
  debugMode = debugLog_1.DEBUG_LEVEL2 && !!env_1.ENV_CONSTANTS.GET_LOGS_INDEXER;
508
- checkIndexerConfig();
561
+ const indexerVersion = getChainIndexerVersion(chain);
562
+ checkIndexerConfig(indexerVersion);
509
563
  const chainId = getChainId(chain);
510
564
  const fromFilterEnabled = !!(fromAddressFilter === null || fromAddressFilter === void 0 ? void 0 : fromAddressFilter.length);
511
565
  if (typeof fromAddressFilter === "string")
@@ -536,8 +590,8 @@ async function getTokenTransfers({ chain = "ethereum", fromAddressFilter, fromBl
536
590
  throw new Error("target|targets is required");
537
591
  targets = targets.map((t) => t.toLowerCase());
538
592
  const addresses = targets.join(",");
539
- // Ensure v2 indexer is up-to-date
540
- const chainIndexStatus = await getChainIndexStatus();
593
+ // Ensure the indexer is up-to-date
594
+ const chainIndexStatus = await getChainIndexStatus(indexerVersion);
541
595
  const lastIndexedBlock = (_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
542
596
  if (lastIndexedBlock < toBlock) {
543
597
  throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${toBlock}`);
@@ -576,7 +630,7 @@ async function getTokenTransfers({ chain = "ethereum", fromAddressFilter, fromBl
576
630
  default:
577
631
  throw new Error("Invalid transferType");
578
632
  }
579
- const { data: { transfers: _logs }, } = await axiosInstance(`/token-transfers`, { params }).catch(e => { throw (0, common_1.formError)(e); });
633
+ const { data: { transfers: _logs }, } = await axiosInstances[indexerVersion](`/token-transfers`, { params }).catch((e) => { throw (0, common_1.formError)(e); });
580
634
  rawTransfers.push(..._logs);
581
635
  currentOffset += limit;
582
636
  hasMore = _logs.length === limit;
@@ -609,13 +663,14 @@ async function getTransactions({ chain = "ethereum", addresses, transaction_hash
609
663
  var _a, _b;
610
664
  if (!debugMode)
611
665
  debugMode = debugLog_1.DEBUG_LEVEL2 && !!env_1.ENV_CONSTANTS.GET_LOGS_INDEXER;
612
- checkIndexerConfig();
666
+ const indexerVersion = getChainIndexerVersion(chain);
667
+ checkIndexerConfig(indexerVersion);
613
668
  const chainId = getChainId(chain);
614
669
  if ((!addresses || addresses.length === 0) && (!transaction_hashes || transaction_hashes.length === 0))
615
670
  throw new Error("You must provide at least 'addresses' or 'transaction_hashes'");
616
671
  if (!from_block || !to_block)
617
672
  throw new Error("'from_block' and 'to_block' are required to search for transactions");
618
- const chainIndexStatus = await getChainIndexStatus();
673
+ const chainIndexStatus = await getChainIndexStatus(indexerVersion);
619
674
  const lastIndexedBlock = (_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
620
675
  if (to_block > lastIndexedBlock) {
621
676
  throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${to_block}`);
@@ -646,7 +701,7 @@ async function getTransactions({ chain = "ethereum", addresses, transaction_hash
646
701
  (0, debugLog_1.debugLog)("[Indexer] Pulling transactions " + debugTimeKey);
647
702
  console.time(debugTimeKey);
648
703
  }
649
- const { data: { transactions } } = await axiosInstance(`/transactions`, { params }).catch(e => { throw (0, common_1.formError)(e); });
704
+ const { data: { transactions } } = await axiosInstances[indexerVersion](`/transactions`, { params }).catch((e) => { throw (0, common_1.formError)(e); });
650
705
  if (debugMode) {
651
706
  console.timeEnd(debugTimeKey);
652
707
  (0, debugLog_1.debugLog)("Transactions pulled " + chain, addresses || transaction_hashes, (transactions === null || transactions === void 0 ? void 0 : transactions.length) || 0);
@@ -678,11 +733,13 @@ async function getTransactions({ chain = "ethereum", addresses, transaction_hash
678
733
  }));
679
734
  }
680
735
  function isIndexerEnabled(chain) {
681
- if (!LLAMA_INDEXER_ENDPOINT)
736
+ if (!LLAMA_INDEXER_V2_ENDPOINT && !LLAMA_INDEXER_V4_ENDPOINT)
682
737
  return false;
683
- if (chain && !exports.supportedChainSet2.has(chain))
738
+ if (!chain)
739
+ return true;
740
+ if (!exports.supportedChainSet2.has(chain))
684
741
  return false;
685
- return true;
742
+ return !!indexerConfigs[getChainIndexerVersion(chain)].endpoint;
686
743
  }
687
744
  function isIndexer2Enabled(chain) {
688
745
  return isIndexerEnabled(chain);
@@ -0,0 +1,2 @@
1
+ export declare function isIndexerSqlEnabled(): boolean;
2
+ export declare function queryClickhouse<T = any>(sql: string, params?: Record<string, unknown>, settings?: Record<string, string | number>): Promise<T[]>;
@@ -0,0 +1,71 @@
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.isIndexerSqlEnabled = isIndexerSqlEnabled;
7
+ exports.queryClickhouse = queryClickhouse;
8
+ const axios_1 = __importDefault(require("axios"));
9
+ const http_1 = __importDefault(require("http"));
10
+ const https_1 = __importDefault(require("https"));
11
+ const env_1 = require("./env");
12
+ const httpAgent = new http_1.default.Agent({ keepAlive: true, maxSockets: 64, maxFreeSockets: 16 });
13
+ const httpsAgent = new https_1.default.Agent({ keepAlive: true, maxSockets: 64, maxFreeSockets: 16 });
14
+ function sqlConfig() {
15
+ return {
16
+ endpoint: (0, env_1.getEnvValue)("LLAMA_INDEXER_SQL_ENDPOINT"),
17
+ user: (0, env_1.getEnvValue)("LLAMA_INDEXER_SQL_USER"),
18
+ password: (0, env_1.getEnvValue)("LLAMA_INDEXER_SQL_PASSWORD"),
19
+ timeoutMs: +(0, env_1.getEnvValue)("LLAMA_INDEXER_SQL_TIMEOUT_MS") || 180000,
20
+ };
21
+ }
22
+ function isIndexerSqlEnabled() {
23
+ const c = sqlConfig();
24
+ return !!(c.endpoint && c.user && c.password);
25
+ }
26
+ async function queryClickhouse(sql, params, settings) {
27
+ var _a, _b;
28
+ const { endpoint, user, password, timeoutMs } = sqlConfig();
29
+ if (!endpoint || !user || !password) {
30
+ throw new Error("Llama indexer SQL gateway not configured (LLAMA_INDEXER_SQL_ENDPOINT/USER/PASSWORD)");
31
+ }
32
+ const search = new URLSearchParams();
33
+ search.set("default_format", "JSONEachRow");
34
+ for (const [k, v] of Object.entries(params !== null && params !== void 0 ? params : {})) {
35
+ search.set(`param_${k}`, typeof v === "object" ? JSON.stringify(v) : String(v));
36
+ }
37
+ for (const [k, v] of Object.entries(settings !== null && settings !== void 0 ? settings : {})) {
38
+ search.set(k, String(v));
39
+ }
40
+ let res;
41
+ try {
42
+ res = await axios_1.default.post(`${endpoint}?${search.toString()}`, sql, {
43
+ auth: { username: user, password },
44
+ headers: { "Content-Type": "text/plain; charset=utf-8" },
45
+ responseType: "text",
46
+ transformResponse: (d) => d,
47
+ timeout: timeoutMs,
48
+ maxBodyLength: Infinity,
49
+ maxContentLength: Infinity,
50
+ httpAgent,
51
+ httpsAgent,
52
+ });
53
+ }
54
+ catch (e) {
55
+ const status = (_a = e === null || e === void 0 ? void 0 : e.response) === null || _a === void 0 ? void 0 : _a.status;
56
+ const body = typeof ((_b = e === null || e === void 0 ? void 0 : e.response) === null || _b === void 0 ? void 0 : _b.data) === "string" ? e.response.data.slice(0, 500) : "";
57
+ throw new Error(`indexer /sql query failed${status ? ` (HTTP ${status})` : ""}: ${body || (e === null || e === void 0 ? void 0 : e.message) || e}`);
58
+ }
59
+ return parseJsonEachRow(res.data);
60
+ }
61
+ function parseJsonEachRow(text) {
62
+ if (!text)
63
+ return [];
64
+ const out = [];
65
+ for (const line of text.split("\n")) {
66
+ if (!line)
67
+ continue;
68
+ out.push(JSON.parse(line));
69
+ }
70
+ return out;
71
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defillama/sdk",
3
- "version": "5.0.221",
3
+ "version": "5.0.222",
4
4
  "description": "SDK for calculating TVL",
5
5
  "main": "build/index.js",
6
6
  "scripts": {
@@ -12,6 +12,7 @@
12
12
  "test": "npm run load-providers && TEST_MODE=true LLAMA_DEBUG_MODE='' SDK_DEBUG='' LLAMA_DEBUG_LEVEL2='' LLAMA_DEBUG_LEVEL3='' jest",
13
13
  "test-only": "echo 'skipped building providers.json' && TEST_MODE=true LLAMA_DEBUG_MODE='' SDK_DEBUG='' LLAMA_DEBUG_LEVEL2='' LLAMA_DEBUG_LEVEL3='' jest",
14
14
  "test-debug": "TEST_MODE=true jest",
15
+ "test-indexer": "TEST_MODE=true jest src/util/indexer.routing.test.ts src/util/indexer.test.ts src/util/indexer.robinhood.test.ts src/util/indexer.e2e.test.ts --runInBand",
15
16
  "update-providers": "ts-node src/util/updateProviderList.ts",
16
17
  "remove-rpcs": "ts-node src/util/removeRedundantRPCs.ts",
17
18
  "format": "prettier --write \"src/**/*.ts\"",