@defillama/sdk 5.0.240 → 5.0.244

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.
Files changed (133) hide show
  1. package/build/Balances.d.ts +139 -0
  2. package/build/Balances.js +363 -0
  3. package/build/ChainApi.d.ts +142 -0
  4. package/build/ChainApi.js +310 -0
  5. package/build/abi/abi2.d.ts +5 -0
  6. package/build/abi/abi2.js +215 -0
  7. package/build/abi/cachedABIs.d.ts +4 -0
  8. package/build/abi/cachedABIs.js +8 -0
  9. package/build/abi/convertResults.d.ts +5 -0
  10. package/build/abi/convertResults.js +60 -0
  11. package/build/abi/index.d.ts +31 -0
  12. package/build/abi/index.js +327 -0
  13. package/build/abi/multicall.d.ts +23 -0
  14. package/build/abi/multicall.js +383 -0
  15. package/build/abi/multicall3.d.ts +7 -0
  16. package/build/abi/multicall3.js +405 -0
  17. package/build/abi/rpcCall.d.ts +4 -0
  18. package/build/abi/rpcCall.js +62 -0
  19. package/build/abi/tron.d.ts +33 -0
  20. package/build/abi/tron.js +118 -0
  21. package/build/api.d.ts +10 -0
  22. package/build/api.js +45 -0
  23. package/build/api2.d.ts +5 -0
  24. package/build/api2.js +41 -0
  25. package/build/chains/algorand.d.ts +277 -0
  26. package/build/chains/algorand.js +618 -0
  27. package/build/chains/aptos.d.ts +269 -0
  28. package/build/chains/aptos.js +700 -0
  29. package/build/chains/cardano.d.ts +242 -0
  30. package/build/chains/cardano.js +407 -0
  31. package/build/chains/cosmos.d.ts +252 -0
  32. package/build/chains/cosmos.js +623 -0
  33. package/build/chains/icp.d.ts +235 -0
  34. package/build/chains/icp.js +1040 -0
  35. package/build/chains/index.d.ts +23 -0
  36. package/build/chains/index.js +59 -0
  37. package/build/chains/near.d.ts +192 -0
  38. package/build/chains/near.js +446 -0
  39. package/build/chains/rpc.d.ts +125 -0
  40. package/build/chains/rpc.js +332 -0
  41. package/build/chains/starknet.d.ts +205 -0
  42. package/build/chains/starknet.js +886 -0
  43. package/build/chains/stellar.d.ts +410 -0
  44. package/build/chains/stellar.js +1082 -0
  45. package/build/chains/substrate.d.ts +333 -0
  46. package/build/chains/substrate.js +1042 -0
  47. package/build/chains/sui.d.ts +392 -0
  48. package/build/chains/sui.js +1213 -0
  49. package/build/chains/svm.d.ts +340 -0
  50. package/build/chains/svm.js +764 -0
  51. package/build/chains/tezos.d.ts +225 -0
  52. package/build/chains/tezos.js +412 -0
  53. package/build/chains/ton.d.ts +353 -0
  54. package/build/chains/ton.js +788 -0
  55. package/build/chains/tron.d.ts +45 -0
  56. package/build/chains/tron.js +110 -0
  57. package/build/chains/utxo.d.ts +210 -0
  58. package/build/chains/utxo.js +678 -0
  59. package/build/chains/xrpl.d.ts +179 -0
  60. package/build/chains/xrpl.js +467 -0
  61. package/build/computeTVL/blocks.d.ts +1 -0
  62. package/build/computeTVL/blocks.js +12 -0
  63. package/build/computeTVL/humanizeNumber.d.ts +1 -0
  64. package/build/computeTVL/humanizeNumber.js +19 -0
  65. package/build/erc20/index.d.ts +31 -0
  66. package/build/erc20/index.js +56 -0
  67. package/build/eth/index.d.ts +22 -0
  68. package/build/eth/index.js +118 -0
  69. package/build/general.d.ts +5 -0
  70. package/build/general.js +20 -0
  71. package/build/generalUtil.d.ts +8 -0
  72. package/build/generalUtil.js +73 -0
  73. package/build/index.d.ts +33 -0
  74. package/build/index.js +75 -0
  75. package/build/providers.json +1 -0
  76. package/build/types.d.ts +76 -0
  77. package/build/types.js +2 -0
  78. package/build/util/LlamaProvider.d.ts +46 -0
  79. package/build/util/LlamaProvider.js +343 -0
  80. package/build/util/blocks.d.ts +36 -0
  81. package/build/util/blocks.js +500 -0
  82. package/build/util/cache.d.ts +45 -0
  83. package/build/util/cache.js +309 -0
  84. package/build/util/callStats.d.ts +74 -0
  85. package/build/util/callStats.js +385 -0
  86. package/build/util/chainUtils/data.json +1459 -0
  87. package/build/util/chainUtils/index.d.ts +11 -0
  88. package/build/util/chainUtils/index.js +136 -0
  89. package/build/util/coins.d.ts +19 -0
  90. package/build/util/coins.js +124 -0
  91. package/build/util/common.d.ts +34 -0
  92. package/build/util/common.js +376 -0
  93. package/build/util/computeTVL.d.ts +19 -0
  94. package/build/util/computeTVL.js +102 -0
  95. package/build/util/cosmos.d.ts +1 -0
  96. package/build/util/cosmos.js +8 -0
  97. package/build/util/debugLog.d.ts +4 -0
  98. package/build/util/debugLog.js +18 -0
  99. package/build/util/discord.d.ts +1 -0
  100. package/build/util/discord.js +33 -0
  101. package/build/util/elastic.d.ts +43 -0
  102. package/build/util/elastic.js +113 -0
  103. package/build/util/env.d.ts +20 -0
  104. package/build/util/env.js +176 -0
  105. package/build/util/graph.d.ts +8 -0
  106. package/build/util/graph.js +50 -0
  107. package/build/util/index.d.ts +32 -0
  108. package/build/util/index.js +227 -0
  109. package/build/util/indexer.compatibility.d.ts +6 -0
  110. package/build/util/indexer.compatibility.js +64 -0
  111. package/build/util/indexer.d.ts +92 -0
  112. package/build/util/indexer.js +854 -0
  113. package/build/util/indexerSql.d.ts +9 -0
  114. package/build/util/indexerSql.js +102 -0
  115. package/build/util/internal-cache.d.ts +11 -0
  116. package/build/util/internal-cache.js +77 -0
  117. package/build/util/logs.d.ts +58 -0
  118. package/build/util/logs.decode.shared.d.ts +8 -0
  119. package/build/util/logs.decode.shared.js +289 -0
  120. package/build/util/logs.js +432 -0
  121. package/build/util/promisePool.d.ts +8 -0
  122. package/build/util/promisePool.js +31 -0
  123. package/build/util/r2.d.ts +4 -0
  124. package/build/util/r2.js +52 -0
  125. package/build/util/removeRedundantRPCs.d.ts +1 -0
  126. package/build/util/removeRedundantRPCs.js +49 -0
  127. package/build/util/transactions.d.ts +35 -0
  128. package/build/util/transactions.js +22 -0
  129. package/build/util/updateChainLabels.d.ts +1 -0
  130. package/build/util/updateChainLabels.js +5 -0
  131. package/build/util/updateProviderList.d.ts +1 -0
  132. package/build/util/updateProviderList.js +275 -0
  133. package/package.json +3 -2
@@ -0,0 +1,854 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ var _a, _b;
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.supportedChainSet2 = void 0;
8
+ exports.getChainIndexerVersion = getChainIndexerVersion;
9
+ exports.getLogs = getLogs;
10
+ exports.getTokenTransfers = getTokenTransfers;
11
+ exports.getTransactions = getTransactions;
12
+ exports.isIndexerEnabled = isIndexerEnabled;
13
+ exports.isIndexer2Enabled = isIndexer2Enabled;
14
+ const axios_1 = __importDefault(require("axios"));
15
+ const http_1 = __importDefault(require("http"));
16
+ const https_1 = __importDefault(require("https"));
17
+ const promises_1 = require("stream/promises");
18
+ const stream_json_1 = require("stream-json");
19
+ const Pick_1 = require("stream-json/filters/Pick");
20
+ const StreamArray_1 = require("stream-json/streamers/StreamArray");
21
+ const _1 = require(".");
22
+ const blocks_1 = require("./blocks");
23
+ const common_1 = require("./common");
24
+ const callStats_1 = require("./callStats");
25
+ const debugLog_1 = require("./debugLog");
26
+ const env_1 = require("./env");
27
+ const logs_1 = require("./logs");
28
+ const logs_decode_shared_1 = require("./logs.decode.shared");
29
+ const indexer_compatibility_1 = require("./indexer.compatibility");
30
+ const LLAMA_INDEXER_V2_ENDPOINT = (0, env_1.getEnvValue)("LLAMA_INDEXER_V2_ENDPOINT");
31
+ const LLAMA_INDEXER_V2_API_KEY = (0, env_1.getEnvValue)("LLAMA_INDEXER_V2_API_KEY");
32
+ const LLAMA_INDEXER_V4_ENDPOINT = (0, env_1.getEnvValue)("LLAMA_INDEXER_V4_ENDPOINT");
33
+ 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;
34
+ const LLAMA_INDEXER_PREFER_V4 = (0, env_1.getEnvValue)("LLAMA_INDEXER_PREFER_V4") !== "false"; // explicit false allows rollback
35
+ const addressChunkSize = +(0, env_1.getEnvValue)("LLAMA_INDEXER_ADDRESS_CHUNK_SIZE") || 100;
36
+ const INDEXER_REQUEST_TIMEOUT_MS = +(0, env_1.getEnvValue)("LLAMA_INDEXER_TIMEOUT_MS");
37
+ const indexerChainIdChainMapping = {
38
+ 1: "ethereum",
39
+ 10: "optimism",
40
+ 56: "bsc",
41
+ 100: "xdai",
42
+ 137: "polygon",
43
+ 204: "op_bnb",
44
+ 324: "era",
45
+ 1101: "polygon_zkevm",
46
+ 8453: "base",
47
+ 34443: "mode",
48
+ 42170: "arbitrum_nova",
49
+ 42161: "arbitrum",
50
+ 43114: "avax",
51
+ 59144: "linea",
52
+ 81457: "blast",
53
+ 534352: "scroll",
54
+ 146: "sonic",
55
+ 130: "unichain",
56
+ 1868: "soneium",
57
+ 80094: "berachain",
58
+ 999: "hyperliquid",
59
+ 143: "monad",
60
+ 4326: "megaeth",
61
+ 196: "xlayer"
62
+ };
63
+ const v4OnlyChainIdChainMapping = {
64
+ 4663: "robinhood",
65
+ };
66
+ ((_b = (0, env_1.getEnvValue)("LLAMA_INDEXER_V4_ONLY_CHAINS")) !== null && _b !== void 0 ? _b : "")
67
+ .split(",")
68
+ .map((entry) => entry.trim())
69
+ .filter(Boolean)
70
+ .forEach((entry) => {
71
+ const [chainId, chainName] = entry.split(":").map((i) => i.trim());
72
+ if (!chainId || !chainName || isNaN(+chainId))
73
+ throw new Error(`Invalid LLAMA_INDEXER_V4_ONLY_CHAINS entry: ${entry}`);
74
+ v4OnlyChainIdChainMapping[+chainId] = chainName;
75
+ });
76
+ const allChainIdChainMapping = { ...indexerChainIdChainMapping, ...v4OnlyChainIdChainMapping };
77
+ const v4OnlyChainSet = new Set(Object.values(v4OnlyChainIdChainMapping));
78
+ const indexerConfigs = {
79
+ v2: { endpoint: LLAMA_INDEXER_V2_ENDPOINT, apiKey: LLAMA_INDEXER_V2_API_KEY },
80
+ v4: { endpoint: LLAMA_INDEXER_V4_ENDPOINT, apiKey: LLAMA_INDEXER_V4_API_KEY },
81
+ };
82
+ const httpAgent = new http_1.default.Agent({ keepAlive: true, maxSockets: 256, maxFreeSockets: 64 });
83
+ const httpsAgent = new https_1.default.Agent({ keepAlive: true, maxSockets: 256, maxFreeSockets: 64 });
84
+ function createIndexerClient(version) {
85
+ const { endpoint, apiKey } = indexerConfigs[version];
86
+ return axios_1.default.create({
87
+ headers: { "x-api-key": apiKey },
88
+ baseURL: endpoint,
89
+ httpAgent,
90
+ httpsAgent,
91
+ timeout: INDEXER_REQUEST_TIMEOUT_MS,
92
+ });
93
+ }
94
+ const axiosInstances = {
95
+ v2: createIndexerClient("v2"),
96
+ v4: createIndexerClient("v4"),
97
+ };
98
+ const INDEXER_HEAD_BUFFER = 50;
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
+ // Prefer a configured v4 deployment; retain v2-only installations and explicit rollback.
105
+ function getChainIndexerVersion(chain) {
106
+ if (v4OnlyChainSet.has(chain))
107
+ return "v4";
108
+ if (!LLAMA_INDEXER_V4_ENDPOINT)
109
+ return "v2";
110
+ if (LLAMA_INDEXER_PREFER_V4 || !LLAMA_INDEXER_V2_ENDPOINT)
111
+ return "v4";
112
+ return "v2";
113
+ }
114
+ function getChainId(chain) {
115
+ var _a;
116
+ const chainId = (_a = Object.entries(allChainIdChainMapping).find(([, chainName]) => chainName === chain)) === null || _a === void 0 ? void 0 : _a[0];
117
+ if (!chainId)
118
+ throw new Error("Chain not supported");
119
+ return +chainId;
120
+ }
121
+ exports.supportedChainSet2 = new Set(Object.values(allChainIdChainMapping));
122
+ function getLogCursor(log) {
123
+ var _a, _b, _c;
124
+ if (!log)
125
+ return undefined;
126
+ const afterBlock = (_a = log.block_number) !== null && _a !== void 0 ? _a : log.blockNumber;
127
+ const afterIndex = (_c = (_b = log.log_index) !== null && _b !== void 0 ? _b : log.logIndex) !== null && _c !== void 0 ? _c : log.index;
128
+ if (afterBlock === undefined || afterIndex === undefined)
129
+ return undefined;
130
+ return { after_block: +afterBlock, after_index: +afterIndex };
131
+ }
132
+ function getTransferCursor(transfer) {
133
+ const cursor = getLogCursor(transfer);
134
+ if (!cursor)
135
+ return undefined;
136
+ if (transfer.id !== undefined && transfer.id !== null)
137
+ cursor.after_id = String(transfer.id);
138
+ return cursor;
139
+ }
140
+ function getTransactionCursor(transaction) {
141
+ if (!transaction)
142
+ return;
143
+ return { after_block: +transaction.block_number, after_index: +transaction.transaction_index };
144
+ }
145
+ function safePush(target, source) {
146
+ for (const row of source)
147
+ target.push(row);
148
+ }
149
+ function applyLocalOffset(rows, remainingOffset) {
150
+ if (remainingOffset <= 0)
151
+ return { rows, remainingOffset };
152
+ if (remainingOffset >= rows.length)
153
+ return { rows: [], remainingOffset: remainingOffset - rows.length };
154
+ return { rows: rows.slice(remainingOffset), remainingOffset: 0 };
155
+ }
156
+ function assertCursorAdvances(next, previous) {
157
+ if (!next || !Number.isSafeInteger(next.after_block) || !Number.isSafeInteger(next.after_index))
158
+ throw new Error("Indexer v4 returned a page without a valid cursor");
159
+ if (!previous)
160
+ return;
161
+ const advances = next.after_block > previous.after_block ||
162
+ (next.after_block === previous.after_block && (next.after_index > previous.after_index ||
163
+ (next.after_index === previous.after_index && next.after_id !== undefined && previous.after_id !== undefined &&
164
+ BigInt(next.after_id) > BigInt(previous.after_id))));
165
+ if (!advances)
166
+ throw new Error("Indexer v4 pagination cursor did not advance");
167
+ }
168
+ // Translate the public offset/limit contract into keyset pagination. Even all=false
169
+ // may need several requests: the v4 server caps offsets, not the public SDK API.
170
+ async function* getV4Pages(path, key, params, limit, offset, all, getCursor) {
171
+ if (!Number.isSafeInteger(limit) || limit < 0 || !Number.isSafeInteger(offset) || offset < 0)
172
+ throw new Error("Indexer pagination requires a non-negative integer limit and offset");
173
+ if (limit === 0)
174
+ return;
175
+ let cursor;
176
+ let remainingOffset = offset;
177
+ let remainingLimit = all ? Infinity : limit;
178
+ while (remainingLimit > 0) {
179
+ const pageParams = { ...params, limit, offset: 0, includeTotal: false, ...cursor };
180
+ const response = await axiosInstances.v4(path, {
181
+ params: pageParams,
182
+ ...(key === "transfers" ? { responseType: "text", transformResponse: (data) => data } : {}),
183
+ }).catch((e) => { throw (0, common_1.formError)(e); });
184
+ const data = key === "transfers" && typeof response.data === "string"
185
+ ? await (0, indexer_compatibility_1.parseTransferResponse)(response.data) : response.data;
186
+ const page = data[key];
187
+ if (!Array.isArray(page))
188
+ throw new Error(`Indexer v4 returned an invalid ${key} response`);
189
+ // Capture the cursor before consumers normalize/mutate the raw rows.
190
+ const next = getCursor(page[page.length - 1]);
191
+ const result = applyLocalOffset(page, remainingOffset);
192
+ remainingOffset = result.remainingOffset;
193
+ const rows = result.rows.slice(0, remainingLimit);
194
+ remainingLimit -= rows.length;
195
+ const hasMore = page.length >= limit && remainingLimit > 0;
196
+ if (hasMore || (page.length && cursor))
197
+ assertCursorAdvances(next, cursor);
198
+ if (rows.length)
199
+ yield rows.map(row => (0, indexer_compatibility_1.normalizeV4Row)(row, key));
200
+ if (!hasMore)
201
+ return;
202
+ cursor = next;
203
+ }
204
+ }
205
+ async function* getIndexerPages(version, path, key, params, limit, offset, all, getCursor) {
206
+ if (version === "v4") {
207
+ yield* getV4Pages(path, key, params, limit, offset, all, getCursor);
208
+ return;
209
+ }
210
+ let count = 0;
211
+ do {
212
+ const { data } = await axiosInstances.v2(path, { params: { ...params, limit, offset } })
213
+ .catch((e) => { throw (0, common_1.formError)(e); });
214
+ const rows = data[key];
215
+ yield rows;
216
+ count += rows.length;
217
+ if (!rows.length || rows.length < limit || (key === "logs" && typeof data.totalCount === "number" && data.totalCount <= count))
218
+ return;
219
+ offset += limit;
220
+ } while (all);
221
+ }
222
+ const syncStates = {
223
+ v2: { chainIndexStatus: {} },
224
+ v4: { chainIndexStatus: {} },
225
+ };
226
+ const cacheTime = 1 * 60 * 1000; // 1 min
227
+ async function getChainIndexStatus(version) {
228
+ checkIndexerConfig(version);
229
+ const state = syncStates[version];
230
+ if (state.timestamp && Date.now() - state.timestamp < cacheTime)
231
+ return state.chainIndexStatus;
232
+ state.timestamp = Date.now();
233
+ state.chainIndexStatus = (async () => {
234
+ const { data: { syncStatus }, } = await axiosInstances[version].get(`/sync`).catch((e) => { throw (0, common_1.formError)(e); });
235
+ const info = {};
236
+ syncStatus.forEach((d) => {
237
+ const chain = allChainIdChainMapping[d.chain];
238
+ if (chain) {
239
+ info[chain] = {
240
+ block: d.lastIndexedBlock,
241
+ timestamp: +new Date(d.lastIndexedDate),
242
+ };
243
+ }
244
+ });
245
+ return (state.chainIndexStatus = info);
246
+ })().catch((error) => {
247
+ state.timestamp = undefined;
248
+ state.chainIndexStatus = {};
249
+ throw error;
250
+ });
251
+ return state.chainIndexStatus;
252
+ }
253
+ async function streamLogs(opts) {
254
+ const { path, version, onItem, onChunkStats, shouldStop } = opts;
255
+ const controller = new AbortController();
256
+ let bytesReceived = 0;
257
+ let itemsProcessed = 0;
258
+ const res = await axiosInstances[version].get(path, {
259
+ responseType: "stream",
260
+ timeout: INDEXER_REQUEST_TIMEOUT_MS,
261
+ maxContentLength: Infinity,
262
+ maxBodyLength: Infinity,
263
+ headers: { Accept: "application/json", "Accept-Encoding": "gzip" },
264
+ signal: controller.signal,
265
+ }).catch((e) => { throw (0, common_1.formError)(e); });
266
+ let stopped = false;
267
+ let processingError;
268
+ try {
269
+ await (0, promises_1.pipeline)(res.data, async function* (source) {
270
+ for await (const chunk of source) {
271
+ bytesReceived += chunk.length;
272
+ onChunkStats === null || onChunkStats === void 0 ? void 0 : onChunkStats({ chunkSize: chunk.length, bytesReceived, itemsProcessed });
273
+ yield chunk;
274
+ }
275
+ }, (0, stream_json_1.parser)(), (0, Pick_1.pick)({ filter: "logs" }), (0, StreamArray_1.streamArray)(), async (source) => {
276
+ for await (const { value } of source) {
277
+ try {
278
+ await onItem(value);
279
+ }
280
+ catch (e) {
281
+ processingError = e;
282
+ throw e;
283
+ }
284
+ itemsProcessed++;
285
+ if (shouldStop === null || shouldStop === void 0 ? void 0 : shouldStop()) {
286
+ stopped = true;
287
+ controller.abort();
288
+ break;
289
+ }
290
+ }
291
+ });
292
+ }
293
+ catch (e) {
294
+ // Only our requested early stop is successful; remote truncation and decode
295
+ // or processor errors must reject instead of returning incomplete results.
296
+ if (!stopped)
297
+ throw processingError !== null && processingError !== void 0 ? processingError : e;
298
+ }
299
+ onChunkStats === null || onChunkStats === void 0 ? void 0 : onChunkStats({ chunkSize: 0, bytesReceived, itemsProcessed });
300
+ }
301
+ async function decodeStreamingLogs(logs, transformLog, batchDecoder, onlyArgs) {
302
+ for (const log of logs)
303
+ (0, logs_decode_shared_1.normalizeLog)(log, true);
304
+ if (!batchDecoder)
305
+ return Promise.all(logs.map(log => transformLog(log)));
306
+ // The historical streaming fast path returns args without buffered parsedLog metadata.
307
+ const args = await batchDecoder(logs);
308
+ return logs.map((log, i) => {
309
+ if (onlyArgs)
310
+ return args[i];
311
+ const decoded = { ...log, args: args[i] };
312
+ if (!decoded.transactionHash && decoded._originalTransactionHash)
313
+ decoded.transactionHash = decoded._originalTransactionHash;
314
+ return decoded;
315
+ });
316
+ }
317
+ async function getLogs(options) {
318
+ var _a, _b, _c, _d, _e;
319
+ let { all = true, limit = 1000, offset: initialOffset = 0, target, targets = [], flatten = true, debugMode = false, noTarget = false, maxBlockRange, processor, clientStreaming = false, decoderType = "viem", onWireStats, onDecodeStats, } = options;
320
+ if (processor && typeof options.collect === "undefined" && clientStreaming) {
321
+ options = { ...options, collect: false };
322
+ }
323
+ const { chain, fromBlock, toBlock, topic, topic1, topic2, topic3, topics, transformLog, } = await (0, logs_1.getLogParams)(options, true);
324
+ const viemFastPath =
325
+ // Preserve the historical streaming shape, including entireLog: the viem
326
+ // fast path exposes args without adding the buffered decoder's parsedLog.
327
+ decoderType === "viem" && options.eventAbi && options.parseLog !== false && !options.allowParseFailure
328
+ ? (0, logs_decode_shared_1.createViemFastPathBatchDecoder)(options.eventAbi)
329
+ : null;
330
+ if (!debugMode)
331
+ debugMode = debugLog_1.DEBUG_LEVEL2 && !!env_1.ENV_CONSTANTS.GET_LOGS_INDEXER;
332
+ // === Match logs.ts semantic regarding processor + multiple targets (flatten=false) ===
333
+ if (processor && (targets === null || targets === void 0 ? void 0 : targets.length) > 1 && !flatten)
334
+ throw new Error("processor is not supported with multiple targets when flatten=false");
335
+ const blockRange = toBlock - fromBlock;
336
+ if (!Number.isSafeInteger(fromBlock) || !Number.isSafeInteger(toBlock) || fromBlock > toBlock)
337
+ throw new Error("getLogs requires integer block bounds with fromBlock <= toBlock");
338
+ const effectiveMaxBlockRange = maxBlockRange !== null && maxBlockRange !== void 0 ? maxBlockRange : (noTarget ? 10000 : Infinity);
339
+ if (!(effectiveMaxBlockRange > 0) || (effectiveMaxBlockRange !== Infinity && !Number.isSafeInteger(effectiveMaxBlockRange)))
340
+ throw new Error("maxBlockRange must be a positive integer");
341
+ if (noTarget && blockRange > 500000) {
342
+ throw new Error("When noTarget is true, block range must be less than 500k blocks. Please narrow down your block range.");
343
+ }
344
+ // Ensure the indexer is synced far enough
345
+ const indexerVersion = getChainIndexerVersion(chain);
346
+ // one logical getLogs query against the indexer (chunks over maxBlockRange recurse here and count separately)
347
+ if (blockRange <= effectiveMaxBlockRange)
348
+ (0, callStats_1.recordMethod)('indexerGetLogs', chain);
349
+ checkIndexerConfig(indexerVersion);
350
+ const chainId = getChainId(chain);
351
+ const chainIndexStatus = await getChainIndexStatus(indexerVersion);
352
+ const lastIndexedBlock = Number((_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0);
353
+ if (!Number.isSafeInteger(lastIndexedBlock) || lastIndexedBlock < 0)
354
+ throw new Error(`Indexer returned an invalid last indexed block for ${chain}`);
355
+ if (lastIndexedBlock < toBlock) {
356
+ const percentageMissing = ((toBlock - lastIndexedBlock) / (toBlock - fromBlock)) * 100;
357
+ if (percentageMissing > 50)
358
+ throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${toBlock}`);
359
+ if (env_1.ENV_CONSTANTS.GET_LOGS_INDEXER)
360
+ (0, debugLog_1.debugLog)(`Indexer only partially up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${toBlock}, missing ${Number(percentageMissing).toFixed(2)}%. Pulling part of the logs through RPC calls.`);
361
+ // An empty indexer prefix uses RPC for exactly the original window. The two
362
+ // inclusive ranges otherwise meet at breakBlock / breakBlock + 1.
363
+ const breakBlock = Math.max(fromBlock - 1, lastIndexedBlock - INDEXER_HEAD_BUFFER);
364
+ return getPartiallyIndexedLogs(breakBlock);
365
+ }
366
+ // Re-curse if the requested range is too large
367
+ if (blockRange > effectiveMaxBlockRange) {
368
+ const results = [];
369
+ for (let currentFromBlock = fromBlock; currentFromBlock <= toBlock; currentFromBlock += effectiveMaxBlockRange) {
370
+ const currentToBlock = Math.min(currentFromBlock + effectiveMaxBlockRange - 1, toBlock);
371
+ const chunk = await getLogs({ ...options, fromBlock: currentFromBlock, toBlock: currentToBlock });
372
+ results.push(chunk);
373
+ }
374
+ const splitTargets = typeof target === "string" ? [target] : targets;
375
+ if (flatten || !splitTargets.length)
376
+ return results.flat();
377
+ return splitTargets.map((_, i) => results.map((r) => r[i]).flat());
378
+ }
379
+ let address = target;
380
+ if (typeof target === "string")
381
+ targets = [target];
382
+ if (Array.isArray(targets) && targets.length)
383
+ address = targets.join(",");
384
+ const hasAddressFilter = !!(address === null || address === void 0 ? void 0 : address.length);
385
+ if (address)
386
+ address = address.toLowerCase();
387
+ const addressSet = new Set((address !== null && address !== void 0 ? address : "").split(",").filter(Boolean));
388
+ const addressChunks = (0, _1.sliceIntoChunks)((_c = address === null || address === void 0 ? void 0 : address.split(",")) !== null && _c !== void 0 ? _c : [], addressChunkSize);
389
+ if (noTarget && addressChunks.length === 0)
390
+ addressChunks.push(undefined);
391
+ if (clientStreaming) {
392
+ const useAll = all === true;
393
+ const effectiveLimit = useAll ? Number.POSITIVE_INFINITY : ((_d = options.limit) !== null && _d !== void 0 ? _d : limit);
394
+ const shouldLimit = !useAll && Number.isFinite(effectiveLimit);
395
+ const effectiveOffset = (_e = options.offset) !== null && _e !== void 0 ? _e : initialOffset;
396
+ const collected = [];
397
+ const start = debugMode ? Date.now() : 0;
398
+ const MICRO_BATCH_SIZE = +(process.env.LLAMA_INDEXER_MICRO_BATCH || 10000);
399
+ const splitByAddress = (targets === null || targets === void 0 ? void 0 : targets.length) && !flatten;
400
+ const addressBuckets = splitByAddress ? targets.map(() => []) : [];
401
+ const addressIndexMap = splitByAddress
402
+ ? Object.fromEntries(targets.map((t, i) => [t.toLowerCase(), i]))
403
+ : {};
404
+ let remainingOffset = effectiveOffset;
405
+ let remainingLimit = shouldLimit ? effectiveLimit : Number.POSITIVE_INFINITY;
406
+ const flushBatch = async (batch) => {
407
+ var _a, _b, _c;
408
+ if (!batch.length)
409
+ return;
410
+ const t0 = Date.now();
411
+ const transformedLogs = await decodeStreamingLogs(batch, transformLog, viemFastPath !== null && viemFastPath !== void 0 ? viemFastPath : transformLog.batch, options.onlyArgs);
412
+ const decodeTime = Date.now() - t0;
413
+ onDecodeStats === null || onDecodeStats === void 0 ? void 0 : onDecodeStats({ batchSize: batch.length, decodeTime, itemsDecoded: batch.length });
414
+ if (processor)
415
+ await processor(transformedLogs);
416
+ if (splitByAddress && options.collect !== false) {
417
+ for (let i = 0; i < batch.length; i++) {
418
+ const raw = batch[i];
419
+ const transformed = transformedLogs[i];
420
+ const idx = addressIndexMap[(_c = (_b = ((_a = raw.source) !== null && _a !== void 0 ? _a : raw.address)) === null || _b === void 0 ? void 0 : _b.toLowerCase) === null || _c === void 0 ? void 0 : _c.call(_b)];
421
+ if (idx !== undefined) {
422
+ addressBuckets[idx].push(transformed);
423
+ }
424
+ }
425
+ }
426
+ else if (options.collect !== false) {
427
+ safePush(collected, transformedLogs);
428
+ }
429
+ };
430
+ for (const chunk of addressChunks) {
431
+ if (Array.isArray(chunk) && chunk.length === 0)
432
+ throw new Error("Address chunk cannot be empty");
433
+ const qs = new URLSearchParams();
434
+ qs.set("chainId", String(chainId));
435
+ qs.set("topic0", topic);
436
+ if (topic1)
437
+ qs.set("topic1", topic1);
438
+ if (topic2)
439
+ qs.set("topic2", topic2);
440
+ if (topic3)
441
+ qs.set("topic3", topic3);
442
+ if (fromBlock != null)
443
+ qs.set("from_block", String(fromBlock));
444
+ if (toBlock != null)
445
+ qs.set("to_block", String(toBlock));
446
+ if (chunk && Array.isArray(chunk))
447
+ qs.set("addresses", chunk.join(",").toLowerCase());
448
+ if (noTarget)
449
+ qs.set("noTarget", "true");
450
+ qs.set("limit", "all");
451
+ qs.set("offset", "0");
452
+ const transformBatch = [];
453
+ let stopNow = false;
454
+ await streamLogs({
455
+ path: `/logs?${qs.toString()}`,
456
+ version: indexerVersion,
457
+ onItem: async (raw) => {
458
+ var _a, _b, _c;
459
+ if (stopNow)
460
+ return;
461
+ if (indexerVersion === "v4")
462
+ (0, indexer_compatibility_1.normalizeV4Row)(raw, "logs");
463
+ const okAddress = !addressSet.size || addressSet.has((_c = (_b = ((_a = raw.source) !== null && _a !== void 0 ? _a : raw.address)) === null || _b === void 0 ? void 0 : _b.toLowerCase) === null || _c === void 0 ? void 0 : _c.call(_b));
464
+ if (!okAddress)
465
+ return;
466
+ if (remainingOffset > 0) {
467
+ remainingOffset--;
468
+ return;
469
+ }
470
+ if (remainingLimit <= 0) {
471
+ stopNow = true;
472
+ return;
473
+ }
474
+ transformBatch.push(raw);
475
+ remainingLimit--;
476
+ if (remainingLimit <= 0)
477
+ stopNow = true;
478
+ if (transformBatch.length >= MICRO_BATCH_SIZE) {
479
+ const batch = transformBatch.splice(0, MICRO_BATCH_SIZE);
480
+ await flushBatch(batch);
481
+ }
482
+ },
483
+ shouldStop: () => stopNow,
484
+ onChunkStats: onWireStats,
485
+ });
486
+ if (transformBatch.length > 0) {
487
+ await flushBatch(transformBatch.splice(0, transformBatch.length));
488
+ }
489
+ if (remainingLimit <= 0)
490
+ break;
491
+ }
492
+ if (debugMode) {
493
+ const ms = Date.now() - start;
494
+ (0, debugLog_1.debugLog)(`[Indexer] stream finished: ${collected.length} items in ${ms}ms`);
495
+ }
496
+ if (splitByAddress) {
497
+ return addressBuckets;
498
+ }
499
+ return collected;
500
+ }
501
+ const allLogsPairs = [];
502
+ const debugTimeKey = `Indexer-getLogs-${chain}-${topic}-${address}_${Math.random()}`;
503
+ if (debugMode) {
504
+ (0, debugLog_1.debugLog)("[Indexer] Pulling logs " + debugTimeKey);
505
+ console.time(debugTimeKey);
506
+ }
507
+ for (const chunk of addressChunks) {
508
+ if (Array.isArray(chunk) && chunk.length === 0)
509
+ throw new Error("Address chunk cannot be empty");
510
+ const params = {
511
+ addresses: hasAddressFilter ? chunk === null || chunk === void 0 ? void 0 : chunk.join(",") : undefined,
512
+ chainId, topic0: topic, from_block: fromBlock, to_block: toBlock,
513
+ topic1, topic2, topic3, noTarget,
514
+ };
515
+ for await (const rows of getIndexerPages(indexerVersion, "/logs", "logs", params, limit, initialOffset, all, getLogCursor)) {
516
+ const filtered = rows.filter((l) => {
517
+ var _a, _b, _c;
518
+ 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));
519
+ return !!isWhitelisted;
520
+ });
521
+ const t0 = Date.now();
522
+ for (const log of filtered) {
523
+ (0, logs_decode_shared_1.normalizeLog)(log, true);
524
+ }
525
+ const transformBatchFn = transformLog.batch || ((logs) => Promise.all(logs.map((log) => transformLog(log))));
526
+ const transformedLogs = await transformBatchFn(filtered);
527
+ const transformedPair = filtered.map((log, idx) => ({ raw: log, transformed: transformedLogs[idx] }));
528
+ const decodeTime = Date.now() - t0;
529
+ if (onDecodeStats && filtered.length > 0)
530
+ onDecodeStats({ batchSize: filtered.length, decodeTime, itemsDecoded: filtered.length });
531
+ if (processor)
532
+ await processor(transformedPair.map((i) => i.transformed));
533
+ if (options.collect !== false) {
534
+ safePush(allLogsPairs, transformedPair);
535
+ }
536
+ }
537
+ }
538
+ if (debugMode) {
539
+ console.timeEnd(debugTimeKey);
540
+ (0, debugLog_1.debugLog)("Logs pulled " + chain, address, allLogsPairs.length);
541
+ }
542
+ const splitByAddress = (targets === null || targets === void 0 ? void 0 : targets.length) && !flatten;
543
+ if (splitByAddress) {
544
+ const mapped = targets.map(() => []);
545
+ const indexMap = {};
546
+ targets.forEach((t, i) => (indexMap[t.toLowerCase()] = i));
547
+ allLogsPairs.forEach(({ raw, transformed }) => {
548
+ var _a, _b, _c;
549
+ const idx = indexMap[(_c = (_b = ((_a = raw.source) !== null && _a !== void 0 ? _a : raw.address)) === null || _b === void 0 ? void 0 : _b.toLowerCase) === null || _c === void 0 ? void 0 : _c.call(_b)];
550
+ if (idx === undefined)
551
+ return; // ignore unknown sources
552
+ mapped[idx].push(transformed);
553
+ });
554
+ return mapped;
555
+ }
556
+ return allLogsPairs.map(i => i.transformed);
557
+ async function getPartiallyIndexedLogs(breakBlock) {
558
+ if (!Number.isSafeInteger(limit) || limit < 0 || !Number.isSafeInteger(initialOffset) || initialOffset < 0)
559
+ throw new Error("Indexer pagination requires a non-negative integer limit and offset");
560
+ const requestedTargets = typeof target === "string" ? [target] : targets;
561
+ const uniqueTargets = [...new Set(requestedTargets.map(t => t.toLowerCase()))];
562
+ const splitByAddress = requestedTargets.length > 0 && !flatten;
563
+ const collected = splitByAddress ? requestedTargets.map(() => []) : [];
564
+ const targetBuckets = new Map();
565
+ requestedTargets.forEach((t, i) => {
566
+ var _a;
567
+ const key = t.toLowerCase();
568
+ targetBuckets.set(key, [...((_a = targetBuckets.get(key)) !== null && _a !== void 0 ? _a : []), i]);
569
+ });
570
+ let remainingOffset = initialOffset;
571
+ let remainingLimit = all ? Infinity : limit;
572
+ if (limit === 0)
573
+ return collected;
574
+ const rpcTransform = (await (0, logs_1.getLogParams)(options, false)).transformLog;
575
+ const finished = Symbol("partial log limit reached");
576
+ let seenBlock;
577
+ const seen = new Set();
578
+ async function consume(rawRows, isIndexer, start, end) {
579
+ var _a, _b, _c, _d;
580
+ const selected = [];
581
+ for (const row of rawRows) {
582
+ const block = Number((_a = row.blockNumber) !== null && _a !== void 0 ? _a : row.block_number);
583
+ if (!Number.isSafeInteger(block))
584
+ throw new Error("Log returned without a valid block number");
585
+ if (block < start || block > end)
586
+ continue;
587
+ if (block !== seenBlock) {
588
+ seenBlock = block;
589
+ seen.clear();
590
+ }
591
+ const hash = (_b = row.transactionHash) !== null && _b !== void 0 ? _b : row.transaction_hash;
592
+ const index = (_d = (_c = row.logIndex) !== null && _c !== void 0 ? _c : row.index) !== null && _d !== void 0 ? _d : row.log_index;
593
+ if (hash !== undefined && index !== undefined) {
594
+ const key = `${String(hash).toLowerCase()}:${index}`;
595
+ if (seen.has(key))
596
+ continue;
597
+ seen.add(key);
598
+ }
599
+ if (remainingOffset > 0) {
600
+ remainingOffset--;
601
+ continue;
602
+ }
603
+ if (remainingLimit <= 0)
604
+ break;
605
+ selected.push(clientStreaming && !isIndexer ? { ...row } : row);
606
+ remainingLimit--;
607
+ }
608
+ if (selected.length) {
609
+ const transform = isIndexer ? transformLog : rpcTransform;
610
+ const startTime = Date.now();
611
+ const decoded = clientStreaming
612
+ ? await decodeStreamingLogs(selected, transform, viemFastPath !== null && viemFastPath !== void 0 ? viemFastPath : transform.batch, options.onlyArgs)
613
+ : await Promise.all(selected.map(row => transform(row)));
614
+ onDecodeStats === null || onDecodeStats === void 0 ? void 0 : onDecodeStats({ batchSize: selected.length, decodeTime: Date.now() - startTime, itemsDecoded: selected.length });
615
+ if (processor)
616
+ await processor(decoded);
617
+ if (options.collect !== false) {
618
+ if (splitByAddress)
619
+ selected.forEach((row, i) => {
620
+ var _a, _b, _c;
621
+ for (const bucket of (_c = targetBuckets.get((_b = ((_a = row.source) !== null && _a !== void 0 ? _a : row.address)) === null || _b === void 0 ? void 0 : _b.toLowerCase())) !== null && _c !== void 0 ? _c : [])
622
+ collected[bucket].push(decoded[i]);
623
+ });
624
+ else
625
+ safePush(collected, decoded);
626
+ }
627
+ }
628
+ if (remainingLimit <= 0)
629
+ throw finished;
630
+ }
631
+ const rawOptions = {
632
+ ...options, chain, topic, topics, target: undefined, targets: uniqueTargets,
633
+ eventAbi: undefined, parseLog: false, entireLog: true, onlyArgs: false,
634
+ flatten: true, onDecodeStats: undefined,
635
+ };
636
+ try {
637
+ if (breakBlock >= fromBlock) {
638
+ await getLogs({
639
+ ...rawOptions, fromBlock, toBlock: breakBlock, all: true, offset: 0, collect: false,
640
+ processor: rows => consume(rows, true, fromBlock, breakBlock),
641
+ });
642
+ }
643
+ // RPC cache reads may extend the physical fetch by a buffer, but logs.ts
644
+ // filters to these exact bounds before any decoding or processing here.
645
+ for (let start = breakBlock + 1; start <= toBlock; start += effectiveMaxBlockRange) {
646
+ const end = Math.min(toBlock, start + effectiveMaxBlockRange - 1);
647
+ const rows = await (0, logs_1.getLogs)({
648
+ ...rawOptions, fromBlock: start, toBlock: end, skipIndexer: true,
649
+ maxBlockRange: undefined, processor: undefined,
650
+ });
651
+ rows.sort((a, b) => { var _a, _b; return a.blockNumber - b.blockNumber || ((_a = a.logIndex) !== null && _a !== void 0 ? _a : a.index) - ((_b = b.logIndex) !== null && _b !== void 0 ? _b : b.index); });
652
+ await consume(rows, false, start, end);
653
+ }
654
+ }
655
+ catch (error) {
656
+ if (error !== finished)
657
+ throw error;
658
+ }
659
+ return collected;
660
+ }
661
+ }
662
+ 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, }) {
663
+ var _a, _b;
664
+ if (!debugMode)
665
+ debugMode = debugLog_1.DEBUG_LEVEL2 && !!env_1.ENV_CONSTANTS.GET_LOGS_INDEXER;
666
+ const indexerVersion = getChainIndexerVersion(chain);
667
+ checkIndexerConfig(indexerVersion);
668
+ const chainId = getChainId(chain);
669
+ const fromFilterEnabled = !!(fromAddressFilter === null || fromAddressFilter === void 0 ? void 0 : fromAddressFilter.length);
670
+ if (typeof fromAddressFilter === "string")
671
+ fromAddressFilter = [fromAddressFilter];
672
+ const fromFilterSet = new Set((fromAddressFilter !== null && fromAddressFilter !== void 0 ? fromAddressFilter : []).map((a) => a.toLowerCase()));
673
+ if (!fromBlock && !fromTimestamp)
674
+ throw new Error("fromBlock or fromTimestamp is required");
675
+ if (!toBlock && !toTimestamp)
676
+ throw new Error("toBlock or toTimestamp is required");
677
+ if (!fromBlock)
678
+ fromBlock = await (0, blocks_1.getBlockNumber)(chain, fromTimestamp);
679
+ if (!toBlock)
680
+ toBlock = await (0, blocks_1.getBlockNumber)(chain, toTimestamp);
681
+ if (!fromBlock || !toBlock)
682
+ throw new Error("fromBlock and toBlock must be > 0");
683
+ if (token)
684
+ tokens = [token];
685
+ if (tokens) {
686
+ if (typeof tokens === "string")
687
+ tokens = [tokens];
688
+ if (!Array.isArray(tokens))
689
+ throw new Error("tokens must be a string or an array of strings");
690
+ tokens = tokens.join(",").toLowerCase();
691
+ }
692
+ if (target)
693
+ targets = [target];
694
+ if (!targets.length)
695
+ throw new Error("target|targets is required");
696
+ targets = targets.map((t) => t.toLowerCase());
697
+ const addresses = targets.join(",");
698
+ // Ensure the indexer is up-to-date
699
+ const chainIndexStatus = await getChainIndexStatus(indexerVersion);
700
+ const lastIndexedBlock = (_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
701
+ if (lastIndexedBlock < toBlock) {
702
+ throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${toBlock}`);
703
+ }
704
+ const rawTransfers = [];
705
+ const debugTimeKey = `Indexer-tokenTransfers-${chain}-${addresses}_${Math.random()}`;
706
+ if (debugMode) {
707
+ (0, debugLog_1.debugLog)("[Indexer] Pulling token transfers " + debugTimeKey);
708
+ console.time(debugTimeKey);
709
+ }
710
+ const params = {
711
+ addresses, chainId, from_block: fromBlock, to_block: toBlock, tokens,
712
+ from_address: false, to_address: false,
713
+ };
714
+ switch (transferType) {
715
+ case "in":
716
+ params.to_address = true;
717
+ break;
718
+ case "out":
719
+ params.from_address = true;
720
+ break;
721
+ case "all":
722
+ params.from_address = true;
723
+ params.to_address = true;
724
+ break;
725
+ default:
726
+ throw new Error("Invalid transferType");
727
+ }
728
+ for await (const rows of getIndexerPages(indexerVersion, "/token-transfers", "transfers", params, limit, offset, all, getTransferCursor)) {
729
+ safePush(rawTransfers, rows);
730
+ }
731
+ const filteredTransfers = rawTransfers.filter((l) => {
732
+ if (!fromFilterEnabled)
733
+ return true;
734
+ return fromFilterSet.has(l.from_address.toLowerCase());
735
+ });
736
+ if (debugMode) {
737
+ console.timeEnd(debugTimeKey);
738
+ (0, debugLog_1.debugLog)("Token Transfers pulled " + chain, addresses, filteredTransfers.length);
739
+ }
740
+ const splitByAddress = (targets === null || targets === void 0 ? void 0 : targets.length) && !flatten;
741
+ if (splitByAddress) {
742
+ const mapped = targets.map(() => []);
743
+ const indexMap = {};
744
+ targets.forEach((t, i) => (indexMap[t.toLowerCase()] = i));
745
+ filteredTransfers.forEach((log) => {
746
+ const sourceField = transferType === "in" ? "to_address" : "from_address";
747
+ const idx = indexMap[log[sourceField].toLowerCase()];
748
+ if (idx !== undefined)
749
+ mapped[idx].push(log);
750
+ });
751
+ return mapped;
752
+ }
753
+ return filteredTransfers;
754
+ }
755
+ async function getTransactions({ chain = "ethereum", addresses, transaction_hashes, from_block, to_block, all = true, limit = 1000, offset = 0, debugMode = false, transactionType = "from", }) {
756
+ var _a, _b;
757
+ if (!debugMode)
758
+ debugMode = debugLog_1.DEBUG_LEVEL2 && !!env_1.ENV_CONSTANTS.GET_LOGS_INDEXER;
759
+ const indexerVersion = getChainIndexerVersion(chain);
760
+ checkIndexerConfig(indexerVersion);
761
+ const chainId = getChainId(chain);
762
+ if ((!addresses || addresses.length === 0) && (!transaction_hashes || transaction_hashes.length === 0))
763
+ throw new Error("You must provide at least 'addresses' or 'transaction_hashes'");
764
+ if (!from_block || !to_block)
765
+ throw new Error("'from_block' and 'to_block' are required to search for transactions");
766
+ const chainIndexStatus = await getChainIndexStatus(indexerVersion);
767
+ const lastIndexedBlock = (_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
768
+ if (to_block > lastIndexedBlock) {
769
+ throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${to_block}`);
770
+ }
771
+ const params = { chainId };
772
+ if (addresses) {
773
+ params.addresses = Array.isArray(addresses)
774
+ ? addresses.map((a) => a.toLowerCase()).join(",")
775
+ : addresses.toLowerCase();
776
+ }
777
+ if (transaction_hashes) {
778
+ params.transaction_hashes = Array.isArray(transaction_hashes)
779
+ ? transaction_hashes.map((h) => h.toLowerCase()).join(",")
780
+ : transaction_hashes.toLowerCase();
781
+ }
782
+ params.from_block = from_block;
783
+ params.to_block = to_block;
784
+ if (offset)
785
+ params.offset = offset;
786
+ params.from_address = transactionType !== "to";
787
+ params.to_address = transactionType !== "from";
788
+ if (all)
789
+ params.limit = "all";
790
+ else if (limit !== "all" && limit !== 0)
791
+ params.limit = limit;
792
+ const debugTimeKey = `Indexer-getTransactions-${chain}-${addresses || transaction_hashes}-${from_block}-${to_block}_${Math.random()}`;
793
+ if (debugMode) {
794
+ (0, debugLog_1.debugLog)("[Indexer] Pulling transactions " + debugTimeKey);
795
+ console.time(debugTimeKey);
796
+ }
797
+ let transactions;
798
+ if (indexerVersion === "v4") {
799
+ transactions = [];
800
+ // all=false with limit=0 historically omitted limit (server default 1000).
801
+ const requestedLimit = typeof limit === "number" && limit > 0 ? limit : 1000;
802
+ // v2 ignores limit when all=true. Preserve that public contract without
803
+ // turning a small caller limit into hundreds of v4 network round trips.
804
+ const pageLimit = all ? Math.max(1000, requestedLimit) : requestedLimit;
805
+ for await (const rows of getV4Pages("/transactions", "transactions", params, pageLimit, offset, all, getTransactionCursor)) {
806
+ safePush(transactions, rows);
807
+ }
808
+ }
809
+ else {
810
+ const { data } = await axiosInstances.v2('/transactions', { params }).catch((e) => { throw (0, common_1.formError)(e); });
811
+ transactions = data.transactions;
812
+ }
813
+ if (debugMode) {
814
+ console.timeEnd(debugTimeKey);
815
+ (0, debugLog_1.debugLog)("Transactions pulled " + chain, addresses || transaction_hashes, (transactions === null || transactions === void 0 ? void 0 : transactions.length) || 0);
816
+ }
817
+ if (!(transactions === null || transactions === void 0 ? void 0 : transactions.length))
818
+ return null;
819
+ return transactions.map((t) => ({
820
+ hash: t.hash,
821
+ blockNumber: +t.block_number,
822
+ transactionIndex: +t.transaction_index,
823
+ from: t.from_address,
824
+ to: t.to_address,
825
+ value: t.value,
826
+ gasPrice: t.gas_price,
827
+ gas: t.gas,
828
+ input: t.input,
829
+ nonce: +t.nonce,
830
+ data: t.input,
831
+ type: t.transaction_type,
832
+ maxFeePerGas: t.max_fee_per_gas,
833
+ maxPriorityFeePerGas: t.max_priority_fee_per_gas,
834
+ baseFeePerGas: t.base_fee_per_gas,
835
+ effectiveGasPrice: t.effective_gas_price,
836
+ gasUsed: t.gas_used,
837
+ cumulativeGasUsed: t.cumulative_gas_used,
838
+ status: t.status === "success" ? 1 : 0,
839
+ contractCreated: t.contract_created || undefined,
840
+ timestamp: t.timestamp,
841
+ }));
842
+ }
843
+ function isIndexerEnabled(chain) {
844
+ if (!LLAMA_INDEXER_V2_ENDPOINT && !LLAMA_INDEXER_V4_ENDPOINT)
845
+ return false;
846
+ if (!chain)
847
+ return true;
848
+ if (!exports.supportedChainSet2.has(chain))
849
+ return false;
850
+ return !!indexerConfigs[getChainIndexerVersion(chain)].endpoint;
851
+ }
852
+ function isIndexer2Enabled(chain) {
853
+ return isIndexerEnabled(chain);
854
+ }