@defillama/sdk 5.0.146 → 5.0.148
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/generalUtil.d.ts +1 -1
- package/build/generalUtil.js +2 -1
- package/build/providers.json +1 -1
- package/build/util/cache.d.ts +4 -2
- package/build/util/cache.js +30 -16
- package/build/util/index.d.ts +1 -0
- package/build/util/index.js +32 -1
- package/build/util/indexer.d.ts +16 -13
- package/build/util/indexer.js +296 -352
- package/build/util/logs.d.ts +19 -1
- package/build/util/logs.js +258 -122
- package/package.json +1 -1
package/build/util/indexer.js
CHANGED
|
@@ -3,9 +3,8 @@ 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.
|
|
6
|
+
exports.isIndexer2Enabled = exports.isIndexerEnabled = exports.getTransactions = exports.getTokenTransfers = exports.getLogs = exports.getTokens = exports.supportedChainSet2 = exports.supportedChainSet = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
|
-
const ethers_1 = require("ethers");
|
|
9
8
|
const _1 = require(".");
|
|
10
9
|
const general_1 = require("../general");
|
|
11
10
|
const generalUtil_1 = require("../generalUtil");
|
|
@@ -14,74 +13,51 @@ const cache_1 = require("./cache");
|
|
|
14
13
|
const debugLog_1 = require("./debugLog");
|
|
15
14
|
const env_1 = require("./env");
|
|
16
15
|
const logs_1 = require("./logs");
|
|
17
|
-
const indexerURL = (0, env_1.getEnvValue)(
|
|
18
|
-
const LLAMA_INDEXER_API_KEY = (0, env_1.getEnvValue)(
|
|
19
|
-
const LLAMA_INDEXER_V2_ENDPOINT = (0, env_1.getEnvValue)(
|
|
20
|
-
const LLAMA_INDEXER_V2_API_KEY = (0, env_1.getEnvValue)(
|
|
21
|
-
const addressChunkSize = +(0, env_1.getEnvValue)(
|
|
16
|
+
const indexerURL = (0, env_1.getEnvValue)("LLAMA_INDEXER_ENDPOINT");
|
|
17
|
+
const LLAMA_INDEXER_API_KEY = (0, env_1.getEnvValue)("LLAMA_INDEXER_API_KEY");
|
|
18
|
+
const LLAMA_INDEXER_V2_ENDPOINT = (0, env_1.getEnvValue)("LLAMA_INDEXER_V2_ENDPOINT");
|
|
19
|
+
const LLAMA_INDEXER_V2_API_KEY = (0, env_1.getEnvValue)("LLAMA_INDEXER_V2_API_KEY");
|
|
20
|
+
const addressChunkSize = +(0, env_1.getEnvValue)("LLAMA_INDEXER_ADDRESS_CHUNK_SIZE") || 100;
|
|
21
|
+
// v1 chains (still used for balances endpoint) -------------------------------------------------
|
|
22
22
|
const indexerChainIdChainMapping = {
|
|
23
|
-
1:
|
|
24
|
-
10:
|
|
25
|
-
56:
|
|
26
|
-
100:
|
|
27
|
-
137:
|
|
28
|
-
204:
|
|
29
|
-
250:
|
|
30
|
-
324:
|
|
31
|
-
1101:
|
|
32
|
-
8453:
|
|
33
|
-
34443:
|
|
34
|
-
42170:
|
|
35
|
-
42161:
|
|
36
|
-
43114:
|
|
37
|
-
59144:
|
|
38
|
-
81457:
|
|
39
|
-
534352:
|
|
40
|
-
146:
|
|
23
|
+
1: "ethereum",
|
|
24
|
+
10: "optimism",
|
|
25
|
+
56: "bsc",
|
|
26
|
+
100: "xdai",
|
|
27
|
+
137: "polygon",
|
|
28
|
+
204: "op_bnb",
|
|
29
|
+
250: "fantom",
|
|
30
|
+
324: "era",
|
|
31
|
+
1101: "polygon_zkevm",
|
|
32
|
+
8453: "base",
|
|
33
|
+
34443: "mode",
|
|
34
|
+
42170: "arbitrum_nova",
|
|
35
|
+
42161: "arbitrum",
|
|
36
|
+
43114: "avax",
|
|
37
|
+
59144: "linea",
|
|
38
|
+
81457: "blast",
|
|
39
|
+
534352: "scroll",
|
|
40
|
+
146: "sonic",
|
|
41
41
|
};
|
|
42
|
+
// v2 chains (superset of v1)
|
|
42
43
|
const indexer2ChainIdChainMapping = {
|
|
43
44
|
...indexerChainIdChainMapping,
|
|
44
|
-
130:
|
|
45
|
-
1868:
|
|
46
|
-
80094:
|
|
47
|
-
999:
|
|
45
|
+
130: "unichain",
|
|
46
|
+
1868: "soneium",
|
|
47
|
+
80094: "berachain",
|
|
48
|
+
999: "hyperliquid",
|
|
48
49
|
};
|
|
49
|
-
const state = { chainIndexStatus: {} };
|
|
50
|
-
const cacheTime = 1 * 60 * 1000; // 1 minutes - we cache sync status for 1 minute
|
|
51
|
-
async function getChainIndexStatus(version = 'v1') {
|
|
52
|
-
checkIndexerConfig(version);
|
|
53
|
-
if (state.timestamp && (Date.now() - state.timestamp) < cacheTime)
|
|
54
|
-
return state.chainIndexStatus;
|
|
55
|
-
state.timestamp = Date.now();
|
|
56
|
-
state.chainIndexStatus = _getState();
|
|
57
|
-
return state.chainIndexStatus;
|
|
58
|
-
async function _getState() {
|
|
59
|
-
const { data: { syncStatus } } = await axiosInstances[version].get(`/sync`);
|
|
60
|
-
const syncInfo = {};
|
|
61
|
-
syncStatus.forEach((d) => {
|
|
62
|
-
const chain = indexerConfigs[version].chainMapping[d.chain];
|
|
63
|
-
if (chain) {
|
|
64
|
-
syncInfo[chain] = {
|
|
65
|
-
block: d.lastIndexedBlock,
|
|
66
|
-
timestamp: +new Date(d.lastIndexedDate)
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
state.chainIndexStatus = syncInfo;
|
|
71
|
-
return syncInfo;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
50
|
const indexerConfigs = {
|
|
75
51
|
v1: {
|
|
76
52
|
endpoint: indexerURL,
|
|
77
53
|
apiKey: LLAMA_INDEXER_API_KEY,
|
|
78
|
-
chainMapping: indexerChainIdChainMapping
|
|
54
|
+
chainMapping: indexerChainIdChainMapping,
|
|
79
55
|
},
|
|
80
56
|
v2: {
|
|
81
57
|
endpoint: LLAMA_INDEXER_V2_ENDPOINT,
|
|
82
58
|
apiKey: LLAMA_INDEXER_V2_API_KEY,
|
|
83
|
-
chainMapping: indexer2ChainIdChainMapping
|
|
84
|
-
}
|
|
59
|
+
chainMapping: indexer2ChainIdChainMapping,
|
|
60
|
+
},
|
|
85
61
|
};
|
|
86
62
|
const axiosInstances = {
|
|
87
63
|
v1: axios_1.default.create({
|
|
@@ -91,53 +67,83 @@ const axiosInstances = {
|
|
|
91
67
|
v2: axios_1.default.create({
|
|
92
68
|
headers: { "x-api-key": indexerConfigs.v2.apiKey },
|
|
93
69
|
baseURL: indexerConfigs.v2.endpoint,
|
|
94
|
-
})
|
|
70
|
+
}),
|
|
95
71
|
};
|
|
96
72
|
function checkIndexerConfig(version) {
|
|
97
73
|
const config = indexerConfigs[version];
|
|
98
74
|
if (!config.endpoint || !config.apiKey)
|
|
99
75
|
throw new Error(`Llama Indexer ${version} URL/api key is not set`);
|
|
100
76
|
}
|
|
101
|
-
function getChainId(chain, version =
|
|
77
|
+
function getChainId(chain, version = "v2") {
|
|
102
78
|
var _a;
|
|
103
|
-
const chainId = (_a = Object.entries(indexerConfigs[version].chainMapping)
|
|
104
|
-
.find(([_, chainName]) => chainName === chain)) === null || _a === void 0 ? void 0 : _a[0];
|
|
79
|
+
const chainId = (_a = Object.entries(indexerConfigs[version].chainMapping).find(([, chainName]) => chainName === chain)) === null || _a === void 0 ? void 0 : _a[0];
|
|
105
80
|
if (!chainId)
|
|
106
|
-
throw new Error(
|
|
81
|
+
throw new Error("Chain not supported");
|
|
107
82
|
return +chainId;
|
|
108
83
|
}
|
|
109
|
-
function getSupportedChains(version =
|
|
84
|
+
function getSupportedChains(version = "v2") {
|
|
110
85
|
return new Set(Object.values(indexerConfigs[version].chainMapping));
|
|
111
86
|
}
|
|
112
|
-
exports.supportedChainSet = getSupportedChains(
|
|
113
|
-
exports.supportedChainSet2 = getSupportedChains(
|
|
87
|
+
exports.supportedChainSet = getSupportedChains("v1"); // legacy
|
|
88
|
+
exports.supportedChainSet2 = getSupportedChains("v2");
|
|
114
89
|
const chainToIDMapping = {};
|
|
115
90
|
Object.entries(indexerConfigs.v1.chainMapping).forEach(([id, chain]) => {
|
|
116
|
-
chainToIDMapping[chain] = id;
|
|
91
|
+
chainToIDMapping[chain] = +id;
|
|
117
92
|
});
|
|
118
93
|
const chainToIDMapping2 = {};
|
|
119
94
|
Object.entries(indexerConfigs.v2.chainMapping).forEach(([id, chain]) => {
|
|
120
|
-
chainToIDMapping2[chain] = id;
|
|
95
|
+
chainToIDMapping2[chain] = +id;
|
|
121
96
|
});
|
|
97
|
+
const state = {
|
|
98
|
+
chainIndexStatus: {},
|
|
99
|
+
};
|
|
100
|
+
const cacheTime = 1 * 60 * 1000; // 1 min
|
|
101
|
+
async function getChainIndexStatus(version = "v2") {
|
|
102
|
+
checkIndexerConfig(version);
|
|
103
|
+
if (state.timestamp && Date.now() - state.timestamp < cacheTime)
|
|
104
|
+
return state.chainIndexStatus;
|
|
105
|
+
state.timestamp = Date.now();
|
|
106
|
+
state.chainIndexStatus = (async () => {
|
|
107
|
+
const { data: { syncStatus }, } = await axiosInstances[version].get(`/sync`);
|
|
108
|
+
const info = {};
|
|
109
|
+
syncStatus.forEach((d) => {
|
|
110
|
+
const chain = indexerConfigs[version].chainMapping[d.chain];
|
|
111
|
+
if (chain) {
|
|
112
|
+
info[chain] = {
|
|
113
|
+
block: d.lastIndexedBlock,
|
|
114
|
+
timestamp: +new Date(d.lastIndexedDate),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
return (state.chainIndexStatus = info);
|
|
119
|
+
})();
|
|
120
|
+
return state.chainIndexStatus;
|
|
121
|
+
}
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// Utilities / Enums / Types
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
122
125
|
var TokenTypes;
|
|
123
126
|
(function (TokenTypes) {
|
|
124
127
|
TokenTypes["ERC20"] = "erc20";
|
|
125
128
|
TokenTypes["ERC721"] = "erc721";
|
|
126
129
|
})(TokenTypes || (TokenTypes = {}));
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// Token helpers (still via v1 endpoint)
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
127
133
|
async function getTokens(address, { onlyWhitelisted = true, skipCacheRead = false, skipCache = false, chain, tokenType, } = {}) {
|
|
128
134
|
var _a, _b;
|
|
129
|
-
checkIndexerConfig(
|
|
135
|
+
checkIndexerConfig("v1");
|
|
130
136
|
if (!address)
|
|
131
|
-
throw new Error(
|
|
137
|
+
throw new Error("Address is required either as a string or an array of strings");
|
|
132
138
|
if (Array.isArray(address) && !address.length)
|
|
133
|
-
throw new Error(
|
|
139
|
+
throw new Error("Address array cannot be empty");
|
|
134
140
|
if (Array.isArray(address))
|
|
135
|
-
address = address.join(
|
|
141
|
+
address = address.join(",");
|
|
136
142
|
address = address.toLowerCase();
|
|
137
143
|
let chainId;
|
|
138
144
|
if (chain)
|
|
139
145
|
chainId = chainToIDMapping[chain];
|
|
140
|
-
const project =
|
|
146
|
+
const project = "llama-indexer-cache";
|
|
141
147
|
const key = onlyWhitelisted ? address : `${address}/all`;
|
|
142
148
|
const file = `${project}/${key}`;
|
|
143
149
|
const timeNow = Math.floor(Date.now() / 1e3);
|
|
@@ -145,28 +151,29 @@ async function getTokens(address, { onlyWhitelisted = true, skipCacheRead = fals
|
|
|
145
151
|
let cache = {};
|
|
146
152
|
if (!skipCacheRead && !skipCache) {
|
|
147
153
|
cache = (_a = (await (0, cache_1.readCache)(file))) !== null && _a !== void 0 ? _a : {};
|
|
148
|
-
if (cache.timestamp &&
|
|
154
|
+
if (cache.timestamp && timeNow - cache.timestamp < THREE_DAYS)
|
|
149
155
|
return cache.tokens;
|
|
150
156
|
}
|
|
151
|
-
(0, debugLog_1.debugLog)(
|
|
157
|
+
(0, debugLog_1.debugLog)("[Indexer] Pulling tokens for " + address);
|
|
152
158
|
const tokens = (_b = cache.tokens) !== null && _b !== void 0 ? _b : {};
|
|
153
|
-
const { data: { balances } } = await axiosInstances.v1(`/balances`, {
|
|
159
|
+
const { data: { balances }, } = await axiosInstances.v1(`/balances`, {
|
|
154
160
|
params: {
|
|
155
161
|
addresses: address,
|
|
156
162
|
chainId,
|
|
157
163
|
type: tokenType,
|
|
158
164
|
},
|
|
159
165
|
});
|
|
160
|
-
balances
|
|
166
|
+
balances
|
|
167
|
+
.filter((b) => +b.total_amount > 0)
|
|
168
|
+
.forEach((b) => {
|
|
161
169
|
const chain = indexerConfigs.v1.chainMapping[b.chain];
|
|
162
|
-
if (!chain)
|
|
170
|
+
if (!chain)
|
|
163
171
|
return;
|
|
164
|
-
}
|
|
165
172
|
if (!tokens[chain])
|
|
166
173
|
tokens[chain] = [];
|
|
167
174
|
tokens[chain].push(b.address);
|
|
168
175
|
});
|
|
169
|
-
const tokenCache = { timestamp: timeNow, tokens
|
|
176
|
+
const tokenCache = { timestamp: timeNow, tokens };
|
|
170
177
|
Object.entries(tokens).forEach(([chain, values]) => {
|
|
171
178
|
values.push(general_1.ETHER_ADDRESS);
|
|
172
179
|
tokens[chain] = (0, generalUtil_1.getUniqueAddresses)(values);
|
|
@@ -176,239 +183,188 @@ async function getTokens(address, { onlyWhitelisted = true, skipCacheRead = fals
|
|
|
176
183
|
return tokens;
|
|
177
184
|
}
|
|
178
185
|
exports.getTokens = getTokens;
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
throw new Error(`Indexer not enabled for chain ${chain}`);
|
|
184
|
-
}
|
|
185
|
-
return 'v1';
|
|
186
|
-
}
|
|
187
|
-
const syncStatus = await getChainIndexStatus('v2');
|
|
188
|
-
const lastIndexedBlock = (_b = (_a = syncStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
|
|
189
|
-
if (lastIndexedBlock >= blockNumber) {
|
|
190
|
-
return 'v2';
|
|
191
|
-
}
|
|
192
|
-
return 'v1';
|
|
193
|
-
}
|
|
194
|
-
async function executeWithFallback(chain, blockNumber, v2Fn, v1Fn) {
|
|
195
|
-
const version = await getIndexerVersionForBlock(chain, blockNumber);
|
|
196
|
-
try {
|
|
197
|
-
return version === 'v2' ? await v2Fn() : await v1Fn();
|
|
198
|
-
}
|
|
199
|
-
catch (error) {
|
|
200
|
-
if (version === 'v2') {
|
|
201
|
-
console.log(`Fallback to v1 for chain ${chain} due to error:`, error);
|
|
202
|
-
return v1Fn();
|
|
203
|
-
}
|
|
204
|
-
throw error;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
async function getLogs({ chain = 'ethereum', topic, topics, fromBlock, toBlock, all = true, limit = 1000, offset = 0, target, targets, eventAbi, entireLog = false, flatten = true, extraTopics, fromTimestamp, toTimestamp, debugMode = false, noTarget = false, parseLog = true, }) {
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
// LOGS (v2 only)
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
189
|
+
async function getLogs(options) {
|
|
208
190
|
var _a, _b, _c;
|
|
191
|
+
let { all = true, limit = 1000, offset: initialOffset = 0, target, targets = [], flatten = true, debugMode = false, noTarget = false, maxBlockRange, processor, } = options;
|
|
192
|
+
const { chain, fromBlock, toBlock, topic, topic1, topic2, topic3, transformLog, } = await (0, logs_1.getLogParams)(options, true);
|
|
209
193
|
if (!debugMode)
|
|
210
194
|
debugMode = debugLog_1.DEBUG_LEVEL2;
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
let topic2;
|
|
216
|
-
let topic3;
|
|
217
|
-
if (((topics === null || topics === void 0 ? void 0 : topics.length) && topics.length > 1)) {
|
|
218
|
-
if (topics === null || topics === void 0 ? void 0 : topics.length) {
|
|
219
|
-
topic1 = topics[1];
|
|
220
|
-
topic2 = topics[2];
|
|
221
|
-
topic3 = topics[3];
|
|
222
|
-
}
|
|
195
|
+
const blockRange = toBlock - fromBlock;
|
|
196
|
+
const effectiveMaxBlockRange = maxBlockRange !== null && maxBlockRange !== void 0 ? maxBlockRange : (noTarget ? 10000 : Infinity);
|
|
197
|
+
if (noTarget && blockRange > 500000) {
|
|
198
|
+
throw new Error("When noTarget is true, block range must be less than 500k blocks. Please narrow down your block range.");
|
|
223
199
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
200
|
+
// We now only support v2 for logs ---------------------------------------------------------
|
|
201
|
+
checkIndexerConfig("v2");
|
|
202
|
+
const chainId = getChainId(chain, "v2");
|
|
203
|
+
// Ensure the indexer is synced far enough
|
|
204
|
+
const chainIndexStatus = await getChainIndexStatus("v2");
|
|
205
|
+
const lastIndexedBlock = (_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
|
|
206
|
+
if (lastIndexedBlock < toBlock) {
|
|
207
|
+
throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${toBlock}`);
|
|
228
208
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
fromBlock = await (0, blocks_1.getBlockNumber)(chain, fromTimestamp);
|
|
241
|
-
if (!toBlock)
|
|
242
|
-
toBlock = await (0, blocks_1.getBlockNumber)(chain, toTimestamp);
|
|
243
|
-
if (!fromBlock || !toBlock)
|
|
244
|
-
throw new Error('fromBlock and toBlock must be > 0');
|
|
245
|
-
if (version === 'v1') {
|
|
246
|
-
const chainIndexStatus = await getChainIndexStatus('v1');
|
|
247
|
-
const lastIndexedBlock = (_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
|
|
248
|
-
if (lastIndexedBlock < toBlock)
|
|
249
|
-
throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${toBlock}`);
|
|
209
|
+
// Re‑curse if the requested range is too large ------------------------------------------------
|
|
210
|
+
if (blockRange > effectiveMaxBlockRange) {
|
|
211
|
+
const results = [];
|
|
212
|
+
for (let currentFromBlock = fromBlock; currentFromBlock < toBlock; currentFromBlock += effectiveMaxBlockRange) {
|
|
213
|
+
const currentToBlock = Math.min(currentFromBlock + effectiveMaxBlockRange - 1, toBlock);
|
|
214
|
+
const chunk = await getLogs({ ...options, fromBlock: currentFromBlock, toBlock: currentToBlock });
|
|
215
|
+
results.push(chunk);
|
|
216
|
+
}
|
|
217
|
+
if (flatten || !(targets === null || targets === void 0 ? void 0 : targets.length))
|
|
218
|
+
return results.flat();
|
|
219
|
+
return targets.map((_, i) => results.map((r) => r[i]).flat());
|
|
250
220
|
}
|
|
221
|
+
// -------------------------------------------------------------------------
|
|
222
|
+
// Prepare address filters
|
|
223
|
+
// -------------------------------------------------------------------------
|
|
251
224
|
let address = target;
|
|
252
|
-
if (typeof target ===
|
|
225
|
+
if (typeof target === "string")
|
|
253
226
|
targets = [target];
|
|
254
|
-
if (Array.isArray(targets))
|
|
255
|
-
address = targets.join(
|
|
256
|
-
const hasAddressFilter = address
|
|
227
|
+
if (Array.isArray(targets) && targets.length)
|
|
228
|
+
address = targets.join(",");
|
|
229
|
+
const hasAddressFilter = !!(address === null || address === void 0 ? void 0 : address.length);
|
|
257
230
|
if (address)
|
|
258
231
|
address = address.toLowerCase();
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
let hasMore = true;
|
|
268
|
-
let logs = [];
|
|
232
|
+
const addressSet = new Set((address !== null && address !== void 0 ? address : "").split(",").filter(Boolean));
|
|
233
|
+
const addressChunks = (0, _1.sliceIntoChunks)((_c = address === null || address === void 0 ? void 0 : address.split(",")) !== null && _c !== void 0 ? _c : [], addressChunkSize);
|
|
234
|
+
if (noTarget && addressChunks.length === 0)
|
|
235
|
+
addressChunks.push(undefined);
|
|
236
|
+
// -------------------------------------------------------------------------
|
|
237
|
+
// Pull logs
|
|
238
|
+
// -------------------------------------------------------------------------
|
|
239
|
+
const allLogs = [];
|
|
269
240
|
const debugTimeKey = `Indexer-getLogs-${chain}-${topic}-${address}_${Math.random()}`;
|
|
270
241
|
if (debugMode) {
|
|
271
|
-
(0, debugLog_1.debugLog)(
|
|
242
|
+
(0, debugLog_1.debugLog)("[Indexer] Pulling logs " + debugTimeKey);
|
|
272
243
|
console.time(debugTimeKey);
|
|
273
244
|
}
|
|
274
|
-
const addressSet = new Set(address === null || address === void 0 ? void 0 : address.split(','));
|
|
275
|
-
const addressChunks = (0, _1.sliceIntoChunks)((_c = address === null || address === void 0 ? void 0 : address.split(',')) !== null && _c !== void 0 ? _c : [], addressChunkSize);
|
|
276
|
-
// to ensure that we have at least one chunk to process if no target is provided
|
|
277
|
-
if (noTarget && addressChunks.length === 0)
|
|
278
|
-
addressChunks.push(undefined);
|
|
279
245
|
for (const chunk of addressChunks) {
|
|
280
|
-
if (Array.isArray(chunk) && chunk.length === 0)
|
|
281
|
-
throw new Error(
|
|
282
|
-
|
|
246
|
+
if (Array.isArray(chunk) && chunk.length === 0)
|
|
247
|
+
throw new Error("Address chunk cannot be empty");
|
|
248
|
+
let chunkOffset = initialOffset;
|
|
283
249
|
let logCount = 0;
|
|
250
|
+
let hasMore = true;
|
|
284
251
|
do {
|
|
285
252
|
const params = {
|
|
286
|
-
addresses: hasAddressFilter ? chunk.join(
|
|
253
|
+
addresses: hasAddressFilter ? chunk === null || chunk === void 0 ? void 0 : chunk.join(",") : undefined,
|
|
287
254
|
chainId,
|
|
288
255
|
topic0: topic,
|
|
289
256
|
from_block: fromBlock,
|
|
290
257
|
to_block: toBlock,
|
|
291
|
-
topic1,
|
|
292
|
-
|
|
258
|
+
topic1,
|
|
259
|
+
topic2,
|
|
260
|
+
topic3,
|
|
261
|
+
limit,
|
|
262
|
+
offset: chunkOffset,
|
|
293
263
|
noTarget,
|
|
264
|
+
eventAbi: options.eventAbi,
|
|
265
|
+
parseLog: options.parseLog,
|
|
266
|
+
onlyArgs: options.onlyArgs,
|
|
294
267
|
};
|
|
295
|
-
const { data: { logs: _logs, totalCount } } = await
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (
|
|
301
|
-
|
|
268
|
+
const { data: { logs: _logs, totalCount }, } = await axiosInstances.v2(`/logs`, { params });
|
|
269
|
+
const filtered = _logs.filter((l) => {
|
|
270
|
+
const isWhitelisted = !addressSet.size || addressSet.has(l.source.toLowerCase());
|
|
271
|
+
if (!isWhitelisted)
|
|
272
|
+
return false;
|
|
273
|
+
if (l.block_number) {
|
|
274
|
+
l.blockNumber = parseInt(l.block_number);
|
|
302
275
|
}
|
|
276
|
+
return true;
|
|
303
277
|
});
|
|
278
|
+
// we need to the { raw, transformed } structure to allow for post‑processing like clustering based on `source` field
|
|
279
|
+
const transformed = filtered.map((log) => ({ raw: log, transformed: transformLog(log) }));
|
|
280
|
+
if (processor)
|
|
281
|
+
await processor(transformed.map((i) => i.transformed));
|
|
282
|
+
allLogs.push(...transformed);
|
|
304
283
|
logCount += _logs.length;
|
|
305
|
-
|
|
306
|
-
// If we have all the logs, or we have reached the limit, or there are no logs, we stop
|
|
284
|
+
chunkOffset += limit;
|
|
307
285
|
if (_logs.length < limit || totalCount <= logCount || _logs.length === 0)
|
|
308
286
|
hasMore = false;
|
|
309
287
|
} while (all && hasMore);
|
|
310
288
|
}
|
|
311
289
|
if (debugMode) {
|
|
312
290
|
console.timeEnd(debugTimeKey);
|
|
313
|
-
(0, debugLog_1.debugLog)(
|
|
291
|
+
(0, debugLog_1.debugLog)("Logs pulled " + chain, address, allLogs.length);
|
|
314
292
|
}
|
|
315
|
-
|
|
316
|
-
|
|
293
|
+
// -------------------------------------------------------------------------
|
|
294
|
+
// Map / transform result
|
|
295
|
+
// -------------------------------------------------------------------------
|
|
317
296
|
const splitByAddress = (targets === null || targets === void 0 ? void 0 : targets.length) && !flatten;
|
|
318
297
|
if (splitByAddress) {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
298
|
+
const mapped = targets.map(() => []);
|
|
299
|
+
const indexMap = {};
|
|
300
|
+
targets.forEach((t, i) => (indexMap[t.toLowerCase()] = i));
|
|
301
|
+
allLogs.forEach(({ raw, transformed }) => {
|
|
302
|
+
const idx = indexMap[raw.source.toLowerCase()];
|
|
303
|
+
if (idx === undefined)
|
|
304
|
+
return; // ignore unknown sources
|
|
305
|
+
mapped[idx].push(transformed);
|
|
306
|
+
});
|
|
307
|
+
return mapped;
|
|
323
308
|
}
|
|
324
|
-
|
|
325
|
-
const source = log.source.toLowerCase();
|
|
326
|
-
log.logIndex = log.log_index;
|
|
327
|
-
log.index = log.log_index;
|
|
328
|
-
log.transactionHash = log.transaction_hash;
|
|
329
|
-
log.blockNumber = log.block_number;
|
|
330
|
-
log.topics = [log.topic0, log.topic1, log.topic2, log.topic3,].filter(t => t !== '').map(i => ethers_1.ethers.zeroPadValue(i, 32));
|
|
331
|
-
const deleteKeys = ['chain', 'block_number', 'log_index', 'topic0', 'topic1', 'topic2', 'topic3', 'decodedArgs', 'transaction_hash',];
|
|
332
|
-
deleteKeys.forEach(k => delete log[k]);
|
|
333
|
-
const parsedLog = iface === null || iface === void 0 ? void 0 : iface.parseLog({ data: log.data, topics: log.topics, });
|
|
334
|
-
log.args = parsedLog === null || parsedLog === void 0 ? void 0 : parsedLog.args;
|
|
335
|
-
log = !entireLog ? log.args : log;
|
|
336
|
-
if (entireLog && parseLog)
|
|
337
|
-
log.parsedLog = parsedLog;
|
|
338
|
-
if (splitByAddress) {
|
|
339
|
-
const index = addressIndexMap[source];
|
|
340
|
-
mappedLogs[index].push(log);
|
|
341
|
-
}
|
|
342
|
-
return log;
|
|
343
|
-
});
|
|
344
|
-
if (splitByAddress)
|
|
345
|
-
return mappedLogs;
|
|
346
|
-
return logs;
|
|
309
|
+
return allLogs.map(i => i.transformed);
|
|
347
310
|
}
|
|
348
311
|
exports.getLogs = getLogs;
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
return false;
|
|
354
|
-
return true;
|
|
355
|
-
}
|
|
356
|
-
exports.isIndexerEnabled = isIndexerEnabled;
|
|
357
|
-
function isIndexer2Enabled(chain) {
|
|
358
|
-
if (!indexerConfigs.v2.endpoint)
|
|
359
|
-
return false;
|
|
360
|
-
if (chain && !exports.supportedChainSet2.has(chain))
|
|
361
|
-
return false;
|
|
362
|
-
return true;
|
|
363
|
-
}
|
|
364
|
-
exports.isIndexer2Enabled = isIndexer2Enabled;
|
|
365
|
-
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, }) {
|
|
312
|
+
// ---------------------------------------------------------------------------
|
|
313
|
+
// TOKEN TRANSFERS (v2 only)
|
|
314
|
+
// ---------------------------------------------------------------------------
|
|
315
|
+
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, }) {
|
|
366
316
|
var _a, _b;
|
|
367
317
|
if (!debugMode)
|
|
368
318
|
debugMode = debugLog_1.DEBUG_LEVEL2;
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
319
|
+
checkIndexerConfig("v2");
|
|
320
|
+
const chainId = getChainId(chain, "v2");
|
|
321
|
+
// -----------------------------------------------------------------------
|
|
322
|
+
// Input validation & pre‑processing
|
|
323
|
+
// -----------------------------------------------------------------------
|
|
324
|
+
const fromFilterEnabled = !!(fromAddressFilter === null || fromAddressFilter === void 0 ? void 0 : fromAddressFilter.length);
|
|
325
|
+
if (typeof fromAddressFilter === "string")
|
|
374
326
|
fromAddressFilter = [fromAddressFilter];
|
|
375
327
|
const fromFilterSet = new Set((fromAddressFilter !== null && fromAddressFilter !== void 0 ? fromAddressFilter : []).map((a) => a.toLowerCase()));
|
|
376
328
|
if (!fromBlock && !fromTimestamp)
|
|
377
|
-
throw new Error(
|
|
329
|
+
throw new Error("fromBlock or fromTimestamp is required");
|
|
378
330
|
if (!toBlock && !toTimestamp)
|
|
379
|
-
throw new Error(
|
|
331
|
+
throw new Error("toBlock or toTimestamp is required");
|
|
380
332
|
if (!fromBlock)
|
|
381
333
|
fromBlock = await (0, blocks_1.getBlockNumber)(chain, fromTimestamp);
|
|
382
334
|
if (!toBlock)
|
|
383
335
|
toBlock = await (0, blocks_1.getBlockNumber)(chain, toTimestamp);
|
|
384
336
|
if (!fromBlock || !toBlock)
|
|
385
|
-
throw new Error(
|
|
337
|
+
throw new Error("fromBlock and toBlock must be > 0");
|
|
386
338
|
if (token)
|
|
387
339
|
tokens = [token];
|
|
388
340
|
if (tokens) {
|
|
389
|
-
if (typeof tokens ===
|
|
341
|
+
if (typeof tokens === "string")
|
|
390
342
|
tokens = [tokens];
|
|
391
|
-
tokens = tokens.join(
|
|
343
|
+
tokens = tokens.join(",").toLowerCase();
|
|
392
344
|
}
|
|
393
345
|
if (target)
|
|
394
346
|
targets = [target];
|
|
395
347
|
if (!targets.length)
|
|
396
|
-
throw new Error(
|
|
397
|
-
targets = targets.map(t => t.toLowerCase());
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
348
|
+
throw new Error("target|targets is required");
|
|
349
|
+
targets = targets.map((t) => t.toLowerCase());
|
|
350
|
+
const addresses = targets.join(",");
|
|
351
|
+
// Ensure v2 indexer is up‑to‑date
|
|
352
|
+
const chainIndexStatus = await getChainIndexStatus("v2");
|
|
353
|
+
const lastIndexedBlock = (_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
|
|
354
|
+
if (lastIndexedBlock < toBlock) {
|
|
355
|
+
throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${toBlock}`);
|
|
404
356
|
}
|
|
405
|
-
|
|
406
|
-
|
|
357
|
+
// -----------------------------------------------------------------------
|
|
358
|
+
// Fetch transfers
|
|
359
|
+
// -----------------------------------------------------------------------
|
|
360
|
+
const rawTransfers = [];
|
|
407
361
|
const debugTimeKey = `Indexer-tokenTransfers-${chain}-${addresses}_${Math.random()}`;
|
|
408
362
|
if (debugMode) {
|
|
409
|
-
(0, debugLog_1.debugLog)(
|
|
363
|
+
(0, debugLog_1.debugLog)("[Indexer] Pulling token transfers " + debugTimeKey);
|
|
410
364
|
console.time(debugTimeKey);
|
|
411
365
|
}
|
|
366
|
+
let currentOffset = offset;
|
|
367
|
+
let hasMore = true;
|
|
412
368
|
do {
|
|
413
369
|
const params = {
|
|
414
370
|
addresses,
|
|
@@ -416,161 +372,149 @@ async function getTokenTransfers({ chain = 'ethereum', fromAddressFilter, fromBl
|
|
|
416
372
|
from_block: fromBlock,
|
|
417
373
|
to_block: toBlock,
|
|
418
374
|
limit,
|
|
419
|
-
offset,
|
|
375
|
+
offset: currentOffset,
|
|
420
376
|
tokens,
|
|
421
377
|
from_address: false,
|
|
422
378
|
to_address: false,
|
|
423
379
|
};
|
|
424
380
|
switch (transferType) {
|
|
425
|
-
case
|
|
381
|
+
case "in":
|
|
426
382
|
params.to_address = true;
|
|
427
383
|
break;
|
|
428
|
-
case
|
|
384
|
+
case "out":
|
|
429
385
|
params.from_address = true;
|
|
430
386
|
break;
|
|
431
|
-
case
|
|
387
|
+
case "all":
|
|
432
388
|
params.from_address = true;
|
|
433
389
|
params.to_address = true;
|
|
434
390
|
break;
|
|
435
391
|
default:
|
|
436
|
-
throw new Error(
|
|
392
|
+
throw new Error("Invalid transferType");
|
|
437
393
|
}
|
|
438
|
-
const { data: { transfers: _logs, totalCount } } = await
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
if (_logs.length < limit || totalCount <= logs.length || _logs.length === 0)
|
|
394
|
+
const { data: { transfers: _logs, totalCount }, } = await axiosInstances.v2(`/token-transfers`, { params });
|
|
395
|
+
rawTransfers.push(..._logs);
|
|
396
|
+
currentOffset += limit;
|
|
397
|
+
if (_logs.length < limit || totalCount <= rawTransfers.length || _logs.length === 0)
|
|
443
398
|
hasMore = false;
|
|
444
399
|
} while (all && hasMore);
|
|
445
|
-
|
|
400
|
+
const filteredTransfers = rawTransfers.filter((l) => {
|
|
446
401
|
if (!fromFilterEnabled)
|
|
447
402
|
return true;
|
|
448
|
-
return fromFilterSet.has(l
|
|
403
|
+
return fromFilterSet.has(l.from_address.toLowerCase());
|
|
449
404
|
});
|
|
450
405
|
if (debugMode) {
|
|
451
406
|
console.timeEnd(debugTimeKey);
|
|
452
|
-
(0, debugLog_1.debugLog)(
|
|
407
|
+
(0, debugLog_1.debugLog)("Token Transfers pulled " + chain, addresses, filteredTransfers.length);
|
|
453
408
|
}
|
|
454
|
-
|
|
455
|
-
|
|
409
|
+
// -----------------------------------------------------------------------
|
|
410
|
+
// Split result if requested
|
|
411
|
+
// -----------------------------------------------------------------------
|
|
456
412
|
const splitByAddress = (targets === null || targets === void 0 ? void 0 : targets.length) && !flatten;
|
|
457
413
|
if (splitByAddress) {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
const source = log[sourceField].toLowerCase();
|
|
467
|
-
const index = addressIndexMap[source];
|
|
468
|
-
mappedLogs[index].push(log);
|
|
414
|
+
const mapped = targets.map(() => []);
|
|
415
|
+
const indexMap = {};
|
|
416
|
+
targets.forEach((t, i) => (indexMap[t.toLowerCase()] = i));
|
|
417
|
+
filteredTransfers.forEach((log) => {
|
|
418
|
+
const sourceField = transferType === "in" ? "to_address" : "from_address";
|
|
419
|
+
const idx = indexMap[log[sourceField].toLowerCase()];
|
|
420
|
+
if (idx !== undefined)
|
|
421
|
+
mapped[idx].push(log);
|
|
469
422
|
});
|
|
470
|
-
return
|
|
423
|
+
return mapped;
|
|
471
424
|
}
|
|
472
|
-
return
|
|
425
|
+
return filteredTransfers;
|
|
473
426
|
}
|
|
474
427
|
exports.getTokenTransfers = getTokenTransfers;
|
|
475
|
-
|
|
428
|
+
// ---------------------------------------------------------------------------
|
|
429
|
+
// TRANSACTIONS (v2 only)
|
|
430
|
+
// ---------------------------------------------------------------------------
|
|
431
|
+
async function getTransactions({ chain = "ethereum", addresses, transaction_hashes, from_block, to_block, all = true, limit = 1000, offset = 0, debugMode = false, transactionType = "from", }) {
|
|
476
432
|
var _a, _b;
|
|
477
433
|
if (!debugMode)
|
|
478
434
|
debugMode = debugLog_1.DEBUG_LEVEL2;
|
|
479
|
-
checkIndexerConfig(
|
|
480
|
-
const chainId = getChainId(chain,
|
|
481
|
-
if ((!addresses || addresses.length === 0) && (!transaction_hashes || transaction_hashes.length === 0))
|
|
435
|
+
checkIndexerConfig("v2");
|
|
436
|
+
const chainId = getChainId(chain, "v2");
|
|
437
|
+
if ((!addresses || addresses.length === 0) && (!transaction_hashes || transaction_hashes.length === 0))
|
|
482
438
|
throw new Error("You must provide at least 'addresses' or 'transaction_hashes'");
|
|
483
|
-
|
|
484
|
-
if (!from_block || !to_block) {
|
|
439
|
+
if (!from_block || !to_block)
|
|
485
440
|
throw new Error("'from_block' and 'to_block' are required to search for transactions");
|
|
486
|
-
|
|
487
|
-
const chainIndexStatus = await getChainIndexStatus('v2');
|
|
441
|
+
const chainIndexStatus = await getChainIndexStatus("v2");
|
|
488
442
|
const lastIndexedBlock = (_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
|
|
489
443
|
if (to_block > lastIndexedBlock) {
|
|
490
444
|
throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${to_block}`);
|
|
491
445
|
}
|
|
492
|
-
const
|
|
446
|
+
const params = { chainId };
|
|
493
447
|
if (addresses) {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
else {
|
|
498
|
-
apiParams.addresses = addresses.toLowerCase();
|
|
499
|
-
}
|
|
448
|
+
params.addresses = Array.isArray(addresses)
|
|
449
|
+
? addresses.map((a) => a.toLowerCase()).join(",")
|
|
450
|
+
: addresses.toLowerCase();
|
|
500
451
|
}
|
|
501
452
|
if (transaction_hashes) {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
else {
|
|
506
|
-
apiParams.transaction_hashes = transaction_hashes.toLowerCase();
|
|
507
|
-
}
|
|
453
|
+
params.transaction_hashes = Array.isArray(transaction_hashes)
|
|
454
|
+
? transaction_hashes.map((h) => h.toLowerCase()).join(",")
|
|
455
|
+
: transaction_hashes.toLowerCase();
|
|
508
456
|
}
|
|
509
|
-
|
|
510
|
-
|
|
457
|
+
params.from_block = from_block;
|
|
458
|
+
params.to_block = to_block;
|
|
511
459
|
if (offset)
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
case 'to':
|
|
520
|
-
to_address = true;
|
|
521
|
-
break;
|
|
522
|
-
case 'all':
|
|
523
|
-
default:
|
|
524
|
-
from_address = true;
|
|
525
|
-
to_address = true;
|
|
526
|
-
break;
|
|
527
|
-
}
|
|
528
|
-
apiParams.from_address = from_address;
|
|
529
|
-
apiParams.to_address = to_address;
|
|
530
|
-
if (all) {
|
|
531
|
-
apiParams.limit = 'all';
|
|
532
|
-
}
|
|
533
|
-
else {
|
|
534
|
-
if (limit !== 'all' && limit !== 0) {
|
|
535
|
-
apiParams.limit = limit;
|
|
536
|
-
}
|
|
537
|
-
}
|
|
460
|
+
params.offset = offset;
|
|
461
|
+
params.from_address = transactionType !== "to";
|
|
462
|
+
params.to_address = transactionType !== "from";
|
|
463
|
+
if (all)
|
|
464
|
+
params.limit = "all";
|
|
465
|
+
else if (limit !== "all" && limit !== 0)
|
|
466
|
+
params.limit = limit;
|
|
538
467
|
const debugTimeKey = `Indexer-getTransactions-${chain}-${addresses || transaction_hashes}-${from_block}-${to_block}_${Math.random()}`;
|
|
539
468
|
if (debugMode) {
|
|
540
|
-
(0, debugLog_1.debugLog)(
|
|
469
|
+
(0, debugLog_1.debugLog)("[Indexer] Pulling transactions " + debugTimeKey);
|
|
541
470
|
console.time(debugTimeKey);
|
|
542
471
|
}
|
|
543
|
-
const { data: { transactions } } = await axiosInstances.v2(`/transactions`, {
|
|
544
|
-
params: apiParams,
|
|
545
|
-
});
|
|
472
|
+
const { data: { transactions } } = await axiosInstances.v2(`/transactions`, { params });
|
|
546
473
|
if (debugMode) {
|
|
547
474
|
console.timeEnd(debugTimeKey);
|
|
548
|
-
(0, debugLog_1.debugLog)(
|
|
475
|
+
(0, debugLog_1.debugLog)("Transactions pulled " + chain, addresses || transaction_hashes, (transactions === null || transactions === void 0 ? void 0 : transactions.length) || 0);
|
|
549
476
|
}
|
|
550
477
|
if (!(transactions === null || transactions === void 0 ? void 0 : transactions.length))
|
|
551
478
|
return null;
|
|
552
|
-
return transactions.map((
|
|
553
|
-
hash:
|
|
554
|
-
blockNumber:
|
|
555
|
-
transactionIndex:
|
|
556
|
-
from:
|
|
557
|
-
to:
|
|
558
|
-
value:
|
|
559
|
-
gasPrice:
|
|
560
|
-
gas:
|
|
561
|
-
input:
|
|
562
|
-
nonce:
|
|
563
|
-
data:
|
|
564
|
-
type:
|
|
565
|
-
maxFeePerGas:
|
|
566
|
-
maxPriorityFeePerGas:
|
|
567
|
-
baseFeePerGas:
|
|
568
|
-
effectiveGasPrice:
|
|
569
|
-
gasUsed:
|
|
570
|
-
cumulativeGasUsed:
|
|
571
|
-
status:
|
|
572
|
-
contractCreated:
|
|
573
|
-
timestamp:
|
|
479
|
+
return transactions.map((t) => ({
|
|
480
|
+
hash: t.hash,
|
|
481
|
+
blockNumber: +t.block_number,
|
|
482
|
+
transactionIndex: +t.transaction_index,
|
|
483
|
+
from: t.from_address,
|
|
484
|
+
to: t.to_address,
|
|
485
|
+
value: t.value,
|
|
486
|
+
gasPrice: t.gas_price,
|
|
487
|
+
gas: t.gas,
|
|
488
|
+
input: t.input,
|
|
489
|
+
nonce: +t.nonce,
|
|
490
|
+
data: t.input,
|
|
491
|
+
type: t.transaction_type,
|
|
492
|
+
maxFeePerGas: t.max_fee_per_gas,
|
|
493
|
+
maxPriorityFeePerGas: t.max_priority_fee_per_gas,
|
|
494
|
+
baseFeePerGas: t.base_fee_per_gas,
|
|
495
|
+
effectiveGasPrice: t.effective_gas_price,
|
|
496
|
+
gasUsed: t.gas_used,
|
|
497
|
+
cumulativeGasUsed: t.cumulative_gas_used,
|
|
498
|
+
status: t.status === "success" ? 1 : 0,
|
|
499
|
+
contractCreated: t.contract_created || undefined,
|
|
500
|
+
timestamp: t.timestamp,
|
|
574
501
|
}));
|
|
575
502
|
}
|
|
576
503
|
exports.getTransactions = getTransactions;
|
|
504
|
+
// ---------------------------------------------------------------------------
|
|
505
|
+
// Public helpers
|
|
506
|
+
// ---------------------------------------------------------------------------
|
|
507
|
+
function isIndexerEnabled(chain) {
|
|
508
|
+
// Legacy function kept for backward‑compat: return true if v2 is enabled
|
|
509
|
+
if (!indexerConfigs.v2.endpoint)
|
|
510
|
+
return false;
|
|
511
|
+
if (chain && !exports.supportedChainSet2.has(chain))
|
|
512
|
+
return false;
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
exports.isIndexerEnabled = isIndexerEnabled;
|
|
516
|
+
function isIndexer2Enabled(chain) {
|
|
517
|
+
// Alias – retained so external calls do not break
|
|
518
|
+
return isIndexerEnabled(chain);
|
|
519
|
+
}
|
|
520
|
+
exports.isIndexer2Enabled = isIndexer2Enabled;
|