@defillama/sdk 5.0.83 → 5.0.85
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/Balances.d.ts +1 -0
- package/build/Balances.js +3 -0
- package/build/ChainApi.d.ts +1 -0
- package/build/ChainApi.js +3 -0
- package/build/abi/multicall.js +4 -0
- package/build/abi/multicall3.js +1 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +2 -1
- package/build/providers.json +1 -1
- package/build/util/blockscout.js +2 -3
- package/build/util/debugLog.d.ts +1 -0
- package/build/util/debugLog.js +4 -3
- package/build/util/env.js +2 -1
- package/build/util/graph.js +4 -1
- package/build/util/indexer.d.ts +39 -0
- package/build/util/indexer.js +230 -0
- package/build/util/logs.d.ts +5 -1
- package/build/util/logs.js +40 -13
- package/build/util/updateProviderList.js +5 -0
- package/package.json +1 -1
package/build/util/blockscout.js
CHANGED
|
@@ -7,17 +7,16 @@ exports.getBlockscoutBlock = exports.blockscoutEndpoints = void 0;
|
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
exports.blockscoutEndpoints = {
|
|
9
9
|
celo: 'https://explorer.celo.org',
|
|
10
|
-
kava: 'https://explorer.kava.io',
|
|
11
10
|
onus: 'https://explorer.onuschain.io',
|
|
12
11
|
base: 'https://base.blockscout.com',
|
|
13
|
-
scroll: 'https://blockscout.scroll.io',
|
|
12
|
+
// scroll: 'https://blockscout.scroll.io',
|
|
14
13
|
canto: 'https://explorer.plexnode.wtf',
|
|
15
14
|
};
|
|
16
15
|
async function getBlockscoutBlock(timestamp, chain) {
|
|
17
16
|
const api = `${exports.blockscoutEndpoints[chain]}/api?module=block&action=getblocknobytime×tamp=${timestamp}&closest=before`;
|
|
18
17
|
const { data } = await (0, axios_1.default)(api);
|
|
19
18
|
if (data.status !== '1')
|
|
20
|
-
throw new Error(
|
|
19
|
+
throw new Error('Issue fetching block from blockscout: ' + api);
|
|
21
20
|
return {
|
|
22
21
|
timestamp,
|
|
23
22
|
block: +data.result.blockNumber,
|
package/build/util/debugLog.d.ts
CHANGED
package/build/util/debugLog.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.debugTable = exports.debugLog = exports.DEBUG_ENABLED = void 0;
|
|
3
|
+
exports.debugTable = exports.debugLog = exports.DEBUG_LEVEL2 = exports.DEBUG_ENABLED = void 0;
|
|
4
4
|
const env_1 = require("./env");
|
|
5
5
|
exports.DEBUG_ENABLED = env_1.ENV_CONSTANTS.DEBUG_ENABLED === "true";
|
|
6
|
+
exports.DEBUG_LEVEL2 = env_1.ENV_CONSTANTS.DEBUG_LEVEL2 === "true";
|
|
6
7
|
function debugLog(...args) {
|
|
7
|
-
if (!exports.DEBUG_ENABLED)
|
|
8
|
+
if (!exports.DEBUG_ENABLED && !exports.DEBUG_LEVEL2)
|
|
8
9
|
return;
|
|
9
10
|
console.log(...args);
|
|
10
11
|
}
|
|
11
12
|
exports.debugLog = debugLog;
|
|
12
13
|
function debugTable(...args) {
|
|
13
|
-
if (!exports.DEBUG_ENABLED)
|
|
14
|
+
if (!exports.DEBUG_ENABLED && !exports.DEBUG_LEVEL2)
|
|
14
15
|
return;
|
|
15
16
|
console.table(...args);
|
|
16
17
|
}
|
package/build/util/env.js
CHANGED
|
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getChainRPCs = exports.getArchivalRPCs = exports.getBatchMaxCount = exports.getDefaultChunkSize = exports.getEnvMulticallAddress = exports.getEnvCacheFolder = exports.getEnvValue = exports.getEnvRPC = exports.getParallelGetBlocksLimit = exports.getParallelGetLogsLimit = exports.getMaxParallelRequests = exports.getChainId = exports.ENV_CONSTANTS = void 0;
|
|
4
4
|
const _ENV_CONSTANTS = {
|
|
5
5
|
DEBUG_ENABLED: getEnvValue('DEBUG') === "true" || process.env.LLAMA_DEBUG_MODE ? 'true' : 'false',
|
|
6
|
+
DEBUG_LEVEL2: process.env.LLAMA_DEBUG_LEVEL2 ? 'true' : 'false',
|
|
6
7
|
};
|
|
7
8
|
const whitelistedEnvConstants = [
|
|
8
9
|
'R2_ENDPOINT', 'R2_ACCESS_KEY_ID', 'R2_SECRET_ACCESS_KEY', 'TRON_PRO_API_KEY', 'COINS_API_KEY',
|
|
9
|
-
'ELASTICSEARCH_CONFIG', 'GRAPH_API_KEY'
|
|
10
|
+
'ELASTICSEARCH_CONFIG', 'GRAPH_API_KEY', 'LLAMA_INDEXER_ENDPOINT',
|
|
10
11
|
];
|
|
11
12
|
const defaultEnvValues = {
|
|
12
13
|
INTERNAL_SDK_CACHE_FILE: './cache.json',
|
package/build/util/graph.js
CHANGED
|
@@ -34,6 +34,7 @@ async function request(endpoint, query, { cache = false, cacheKey, variables, wi
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
exports.request = request;
|
|
37
|
+
let graphKeyWarned = false;
|
|
37
38
|
function modifyEndpoint(endpoint, network = 'arbitrum') {
|
|
38
39
|
// example: https://api.thegraph.com/subgraphs/name/yieldyak/reinvest-tracker
|
|
39
40
|
let graphKey = (0, env_1.getEnvValue)('GRAPH_API_KEY');
|
|
@@ -43,7 +44,9 @@ function modifyEndpoint(endpoint, network = 'arbitrum') {
|
|
|
43
44
|
return endpoint;
|
|
44
45
|
else if (!graphKey) {
|
|
45
46
|
graphKey = "5a1340b49fa9efe00" + "21452daa260564e";
|
|
46
|
-
|
|
47
|
+
if (!graphKeyWarned)
|
|
48
|
+
console.log("GRAPH_API_KEY env variable is not set, using the default api key");
|
|
49
|
+
graphKeyWarned = true;
|
|
47
50
|
}
|
|
48
51
|
endpoint = endpoint.replace('[api-key]', graphKey);
|
|
49
52
|
return endpoint;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Address } from "../types";
|
|
2
|
+
export declare const supportedChainSet: Set<unknown>;
|
|
3
|
+
declare enum TokenTypes {
|
|
4
|
+
ERC20 = "erc20",
|
|
5
|
+
ERC721 = "erc721"
|
|
6
|
+
}
|
|
7
|
+
export declare function getTokens(address: string | string[], { onlyWhitelisted, skipCacheRead, skipCache, chain, tokenType, }?: {
|
|
8
|
+
onlyWhitelisted?: boolean;
|
|
9
|
+
skipCacheRead?: boolean;
|
|
10
|
+
skipCache?: boolean;
|
|
11
|
+
chain?: string;
|
|
12
|
+
tokenType?: TokenTypes;
|
|
13
|
+
}): Promise<{
|
|
14
|
+
[chain: string]: string[];
|
|
15
|
+
}>;
|
|
16
|
+
export type IndexerGetLogsOptions = {
|
|
17
|
+
target?: Address;
|
|
18
|
+
topic?: string;
|
|
19
|
+
fromBlock?: number;
|
|
20
|
+
toBlock?: number;
|
|
21
|
+
topics?: (string | null)[];
|
|
22
|
+
extraTopics?: string[];
|
|
23
|
+
chain?: string;
|
|
24
|
+
eventAbi?: string | any;
|
|
25
|
+
fromTimestamp?: number;
|
|
26
|
+
toTimestamp?: number;
|
|
27
|
+
entireLog?: boolean;
|
|
28
|
+
cacheInCloud?: boolean;
|
|
29
|
+
onlyArgs?: boolean;
|
|
30
|
+
targets?: Address[];
|
|
31
|
+
flatten?: boolean;
|
|
32
|
+
all?: boolean;
|
|
33
|
+
limit?: number;
|
|
34
|
+
offset?: number;
|
|
35
|
+
debugMode?: boolean;
|
|
36
|
+
};
|
|
37
|
+
export declare function getLogs({ chain, topic, topics, fromBlock, toBlock, all, limit, offset, target, targets, eventAbi, entireLog, flatten, extraTopics, fromTimestamp, toTimestamp, debugMode }: IndexerGetLogsOptions): Promise<any[]>;
|
|
38
|
+
export declare function isIndexerEnabled(chain?: string): boolean;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,230 @@
|
|
|
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.isIndexerEnabled = exports.getLogs = exports.getTokens = exports.supportedChainSet = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const env_1 = require("./env");
|
|
9
|
+
const cache_1 = require("./cache");
|
|
10
|
+
const debugLog_1 = require("./debugLog");
|
|
11
|
+
const generalUtil_1 = require("../generalUtil");
|
|
12
|
+
const general_1 = require("../general");
|
|
13
|
+
const ethers_1 = require("ethers");
|
|
14
|
+
const logs_1 = require("./logs");
|
|
15
|
+
const blocks_1 = require("./blocks");
|
|
16
|
+
const indexerURL = (0, env_1.getEnvValue)('LLAMA_INDEXER_ENDPOINT');
|
|
17
|
+
const state = { chainIndexStatus: {} };
|
|
18
|
+
const cacheTime = 1 * 60 * 1000; // 1 minutes - we cache sync status for 1 minute
|
|
19
|
+
async function getChainIndexStatus() {
|
|
20
|
+
if (!indexerURL)
|
|
21
|
+
throw new Error('Llama Indexer URL not set');
|
|
22
|
+
if (state.timestamp && (Date.now() - state.timestamp) < cacheTime)
|
|
23
|
+
return state.chainIndexStatus;
|
|
24
|
+
state.timestamp = Date.now();
|
|
25
|
+
state.chainIndexStatus = _getState();
|
|
26
|
+
return state.chainIndexStatus;
|
|
27
|
+
async function _getState() {
|
|
28
|
+
const { data: { syncStatus } } = await axios_1.default.get(`${indexerURL}/syncStatus`);
|
|
29
|
+
const syncInfo = {};
|
|
30
|
+
syncStatus.forEach((d) => {
|
|
31
|
+
const chain = indexerChainIdChainMapping[d.chain];
|
|
32
|
+
syncInfo[chain] = {
|
|
33
|
+
block: d.lastIndexedBlock,
|
|
34
|
+
timestamp: +new Date(d.lastIndexedDate)
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
state.chainIndexStatus = syncInfo;
|
|
38
|
+
return syncInfo;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const indexerChainIdChainMapping = {
|
|
42
|
+
1: 'ethereum',
|
|
43
|
+
10: 'optimism',
|
|
44
|
+
56: 'bsc',
|
|
45
|
+
100: 'xdai',
|
|
46
|
+
137: 'polygon',
|
|
47
|
+
204: 'op_bnb',
|
|
48
|
+
250: 'fantom',
|
|
49
|
+
324: 'era',
|
|
50
|
+
1101: 'polygon_zkevm',
|
|
51
|
+
8453: 'base',
|
|
52
|
+
34443: 'mode',
|
|
53
|
+
42170: 'arbitrum_nova',
|
|
54
|
+
42161: 'arbitrum',
|
|
55
|
+
43114: 'avalanche',
|
|
56
|
+
59144: 'linea',
|
|
57
|
+
81457: 'blast',
|
|
58
|
+
534352: 'scroll',
|
|
59
|
+
};
|
|
60
|
+
exports.supportedChainSet = new Set(Object.values(indexerChainIdChainMapping));
|
|
61
|
+
const chainToIDMapping = {};
|
|
62
|
+
Object.entries(indexerChainIdChainMapping).forEach(([id, chain]) => {
|
|
63
|
+
chainToIDMapping[chain] = id;
|
|
64
|
+
});
|
|
65
|
+
var TokenTypes;
|
|
66
|
+
(function (TokenTypes) {
|
|
67
|
+
TokenTypes["ERC20"] = "erc20";
|
|
68
|
+
TokenTypes["ERC721"] = "erc721";
|
|
69
|
+
})(TokenTypes || (TokenTypes = {}));
|
|
70
|
+
async function getTokens(address, { onlyWhitelisted = true, skipCacheRead = false, skipCache = false, chain, tokenType, } = {}) {
|
|
71
|
+
var _a, _b;
|
|
72
|
+
if (!indexerURL)
|
|
73
|
+
throw new Error('Llama Indexer URL not set');
|
|
74
|
+
if (!address)
|
|
75
|
+
throw new Error('Address is required either as a string or an array of strings');
|
|
76
|
+
if (Array.isArray(address) && !address.length)
|
|
77
|
+
throw new Error('Address array cannot be empty');
|
|
78
|
+
if (Array.isArray(address))
|
|
79
|
+
address = address.join(',');
|
|
80
|
+
address = address.toLowerCase();
|
|
81
|
+
const project = 'llama-indexer-cache';
|
|
82
|
+
const key = onlyWhitelisted ? address : `${address}/all`;
|
|
83
|
+
const file = `${project}/${key}`;
|
|
84
|
+
const timeNow = Math.floor(Date.now() / 1e3);
|
|
85
|
+
const THREE_DAYS = 3 * 24 * 3600;
|
|
86
|
+
let cache = {};
|
|
87
|
+
if (!skipCacheRead && !skipCache) {
|
|
88
|
+
cache = (_a = (await (0, cache_1.readCache)(file))) !== null && _a !== void 0 ? _a : {};
|
|
89
|
+
if (cache.timestamp && (timeNow - cache.timestamp) < THREE_DAYS)
|
|
90
|
+
return cache.tokens;
|
|
91
|
+
}
|
|
92
|
+
(0, debugLog_1.debugLog)('[Indexer] Pulling tokens for ' + address);
|
|
93
|
+
const tokens = (_b = cache.tokens) !== null && _b !== void 0 ? _b : {};
|
|
94
|
+
const { data: { balances } } = await axios_1.default.get(`${indexerURL}/balances`, {
|
|
95
|
+
params: {
|
|
96
|
+
addresses: address,
|
|
97
|
+
chain: chain,
|
|
98
|
+
type: tokenType,
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
balances.filter((b) => +b.total_amount > 0).forEach((b) => {
|
|
102
|
+
const chain = indexerChainIdChainMapping[b.chain];
|
|
103
|
+
if (!chain) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (!tokens[chain])
|
|
107
|
+
tokens[chain] = [];
|
|
108
|
+
tokens[chain].push(b.address);
|
|
109
|
+
});
|
|
110
|
+
const tokenCache = { timestamp: timeNow, tokens, };
|
|
111
|
+
Object.entries(tokens).forEach(([chain, values]) => {
|
|
112
|
+
values.push(general_1.ETHER_ADDRESS);
|
|
113
|
+
tokens[chain] = (0, generalUtil_1.getUniqueAddresses)(values);
|
|
114
|
+
});
|
|
115
|
+
if (!skipCache)
|
|
116
|
+
await (0, cache_1.writeCache)(file, tokenCache);
|
|
117
|
+
return tokens;
|
|
118
|
+
}
|
|
119
|
+
exports.getTokens = getTokens;
|
|
120
|
+
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 }) {
|
|
121
|
+
var _a, _b;
|
|
122
|
+
if (!indexerURL)
|
|
123
|
+
throw new Error('Llama Indexer URL not set');
|
|
124
|
+
const chainId = chainToIDMapping[chain];
|
|
125
|
+
if (!chainId)
|
|
126
|
+
throw new Error('Chain not supported');
|
|
127
|
+
if (!debugMode)
|
|
128
|
+
debugMode = debugLog_1.DEBUG_LEVEL2;
|
|
129
|
+
if ((topics === null || topics === void 0 ? void 0 : topics.length) || (extraTopics === null || extraTopics === void 0 ? void 0 : extraTopics.length))
|
|
130
|
+
throw new Error('TODO: topics and extraTopics part are not yet imeplemented');
|
|
131
|
+
// if (!target && !targets?.length) throw new Error('target|targets is required')
|
|
132
|
+
if (!fromBlock && !fromTimestamp)
|
|
133
|
+
throw new Error('fromBlock or fromTimestamp is required');
|
|
134
|
+
if (!toBlock && !toTimestamp)
|
|
135
|
+
throw new Error('toBlock or toTimestamp is required');
|
|
136
|
+
if (!fromBlock)
|
|
137
|
+
fromBlock = await (0, blocks_1.getBlockNumber)(chain, fromTimestamp);
|
|
138
|
+
if (!toBlock)
|
|
139
|
+
toBlock = await (0, blocks_1.getBlockNumber)(chain, toTimestamp);
|
|
140
|
+
if (!fromBlock || !toBlock)
|
|
141
|
+
throw new Error('fromBlock and toBlock must be > 0');
|
|
142
|
+
let address = target;
|
|
143
|
+
if (typeof target === 'string')
|
|
144
|
+
targets = [target];
|
|
145
|
+
if (Array.isArray(targets))
|
|
146
|
+
address = targets.join(',');
|
|
147
|
+
if (address)
|
|
148
|
+
address = address.toLowerCase();
|
|
149
|
+
const chainIndexStatus = await getChainIndexStatus();
|
|
150
|
+
const lastIndexedBlock = (_b = (_a = chainIndexStatus[chain]) === null || _a === void 0 ? void 0 : _a.block) !== null && _b !== void 0 ? _b : 0;
|
|
151
|
+
if (lastIndexedBlock < toBlock)
|
|
152
|
+
throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${toBlock}`);
|
|
153
|
+
// Create an Interface object
|
|
154
|
+
let iface;
|
|
155
|
+
if (eventAbi)
|
|
156
|
+
iface = new ethers_1.Interface([eventAbi]);
|
|
157
|
+
if (topic)
|
|
158
|
+
topic = (0, logs_1.toFilterTopic)(topic);
|
|
159
|
+
else if (eventAbi)
|
|
160
|
+
topic = (0, logs_1.toFilterTopic)(iface);
|
|
161
|
+
let hasMore = true;
|
|
162
|
+
let logs = [];
|
|
163
|
+
const debugTimeKey = `Indexer-getLogs-${chain}-${topic}-${address}_${Math.random()}`;
|
|
164
|
+
if (debugMode) {
|
|
165
|
+
(0, debugLog_1.debugLog)('[Indexer] Pulling logs ' + debugTimeKey);
|
|
166
|
+
console.time(debugTimeKey);
|
|
167
|
+
}
|
|
168
|
+
do {
|
|
169
|
+
const params = {
|
|
170
|
+
address,
|
|
171
|
+
chain: chainId,
|
|
172
|
+
topic0: topic,
|
|
173
|
+
from_block: fromBlock,
|
|
174
|
+
to_block: toBlock,
|
|
175
|
+
limit,
|
|
176
|
+
offset,
|
|
177
|
+
};
|
|
178
|
+
const { data: { logs: _logs, totalCount } } = await axios_1.default.get(`${indexerURL}/logs`, { params });
|
|
179
|
+
logs.push(..._logs);
|
|
180
|
+
offset += limit;
|
|
181
|
+
// If we have all the logs, or we have reached the limit, or there are no logs, we stop
|
|
182
|
+
if (_logs.length < limit || totalCount <= logs.length || _logs.length === 0)
|
|
183
|
+
hasMore = false;
|
|
184
|
+
} while (all && hasMore);
|
|
185
|
+
if (debugMode) {
|
|
186
|
+
console.timeEnd(debugTimeKey);
|
|
187
|
+
(0, debugLog_1.debugLog)('Logs pulled ' + chain, address, logs.length);
|
|
188
|
+
}
|
|
189
|
+
const mappedLogs = [];
|
|
190
|
+
let addressIndexMap = {};
|
|
191
|
+
const splitByAddress = (targets === null || targets === void 0 ? void 0 : targets.length) && !flatten;
|
|
192
|
+
if (splitByAddress) {
|
|
193
|
+
for (let i = 0; i < targets.length; i++) {
|
|
194
|
+
addressIndexMap[targets[i].toLowerCase()] = i;
|
|
195
|
+
mappedLogs.push([]);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
logs = logs.map((log) => {
|
|
199
|
+
log.logIndex = log.log_index;
|
|
200
|
+
log.index = log.log_index;
|
|
201
|
+
log.transactionHash = log.transaction_hash;
|
|
202
|
+
log.blockNumber = log.block_number;
|
|
203
|
+
log.topics = [log.topic0, log.topic1, log.topic2, log.topic3,].filter(t => t !== '').map(i => ethers_1.ethers.zeroPadValue(i, 32));
|
|
204
|
+
const deleteKeys = ['chain', 'address', 'block_number', 'log_index', 'topic0', 'topic1', 'topic2', 'topic3', 'decodedArgs', 'transaction_hash',];
|
|
205
|
+
deleteKeys.forEach(k => delete log[k]);
|
|
206
|
+
const parsedLog = iface === null || iface === void 0 ? void 0 : iface.parseLog({
|
|
207
|
+
data: log.data,
|
|
208
|
+
topics: log.topics,
|
|
209
|
+
});
|
|
210
|
+
log.args = parsedLog === null || parsedLog === void 0 ? void 0 : parsedLog.args;
|
|
211
|
+
log = !entireLog ? log.args : log;
|
|
212
|
+
if (splitByAddress) {
|
|
213
|
+
const index = addressIndexMap[log.source.toLowerCase()];
|
|
214
|
+
mappedLogs[index].push(log);
|
|
215
|
+
}
|
|
216
|
+
return log;
|
|
217
|
+
});
|
|
218
|
+
if (splitByAddress)
|
|
219
|
+
return mappedLogs;
|
|
220
|
+
return logs;
|
|
221
|
+
}
|
|
222
|
+
exports.getLogs = getLogs;
|
|
223
|
+
function isIndexerEnabled(chain) {
|
|
224
|
+
if (!indexerURL)
|
|
225
|
+
return false;
|
|
226
|
+
if (chain && !exports.supportedChainSet.has(chain))
|
|
227
|
+
return false;
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
exports.isIndexerEnabled = isIndexerEnabled;
|
package/build/util/logs.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventLog } from "ethers";
|
|
1
|
+
import { EventLog, Interface } from "ethers";
|
|
2
2
|
import { Address } from "../types";
|
|
3
3
|
export type GetLogsOptions = {
|
|
4
4
|
target?: Address;
|
|
@@ -19,8 +19,12 @@ export type GetLogsOptions = {
|
|
|
19
19
|
onlyArgs?: boolean;
|
|
20
20
|
targets?: Address[];
|
|
21
21
|
flatten?: boolean;
|
|
22
|
+
skipIndexer?: boolean;
|
|
23
|
+
onlyIndexer?: boolean;
|
|
24
|
+
debugMode?: boolean;
|
|
22
25
|
};
|
|
23
26
|
export declare function getLogs(options: GetLogsOptions): Promise<EventLog[] | EventLog[][] | any[]>;
|
|
27
|
+
export declare function toFilterTopic(topic: string | Interface): string;
|
|
24
28
|
export type logCache = {
|
|
25
29
|
logs: EventLog[];
|
|
26
30
|
metadata: {
|
package/build/util/logs.js
CHANGED
|
@@ -1,17 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getLogs = void 0;
|
|
3
|
+
exports.toFilterTopic = exports.getLogs = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
5
|
const ethers_1 = require("ethers");
|
|
6
6
|
const blocks_1 = require("./blocks");
|
|
7
7
|
const cache_1 = require("./cache");
|
|
8
8
|
const debugLog_1 = require("./debugLog");
|
|
9
|
+
const indexer_1 = require("./indexer");
|
|
9
10
|
const tron_1 = require("../abi/tron");
|
|
10
11
|
const currentVersion = 'v3';
|
|
11
12
|
async function getLogs(options) {
|
|
12
13
|
let { target, chain = 'ethereum', fromBlock, toBlock, fromTimestamp, toTimestamp, eventAbi, topic, topics, extraTopics, // can be passed as input as extra filter arguments
|
|
13
14
|
skipCache = false, skipCacheRead = false, entireLog = false, cacheInCloud = false, onlyArgs = false, keys = [], // [Deprecated] This is just used to select only part of the logs
|
|
14
|
-
targets, flatten = true, } = options;
|
|
15
|
+
targets, flatten = true, skipIndexer = false, onlyIndexer = false, debugMode = false, } = options;
|
|
16
|
+
if (!skipIndexer && (0, indexer_1.isIndexerEnabled)(chain)) {
|
|
17
|
+
try {
|
|
18
|
+
const response = await (0, indexer_1.getLogs)({
|
|
19
|
+
...options,
|
|
20
|
+
all: true,
|
|
21
|
+
});
|
|
22
|
+
return response;
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
let message = e === null || e === void 0 ? void 0 : e.message;
|
|
26
|
+
(0, debugLog_1.debugLog)('Error in indexer getLogs', message);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (!debugMode)
|
|
30
|
+
debugMode = debugLog_1.DEBUG_LEVEL2;
|
|
31
|
+
if (onlyIndexer)
|
|
32
|
+
throw new Error('onlyIndexer is true, but indexer is not enabled or threw an error');
|
|
15
33
|
// if (!target && !targets?.length) throw new Error('target|targets is required')
|
|
16
34
|
if (!fromBlock && !fromTimestamp)
|
|
17
35
|
throw new Error('fromBlock or fromTimestamp is required');
|
|
@@ -89,14 +107,22 @@ async function getLogs(options) {
|
|
|
89
107
|
return logs;
|
|
90
108
|
return logs.map((i) => iface.parseLog(i)).map((i) => onlyArgs ? i.args : i);
|
|
91
109
|
async function addLogsToCache(fromBlock, toBlock) {
|
|
92
|
-
|
|
110
|
+
const debugTimeKey = `getLogs-${chain}-${topic}-${target}_${Math.random()}-${fromBlock}-${toBlock}`;
|
|
111
|
+
if (debugMode)
|
|
112
|
+
(0, debugLog_1.debugLog)('adding logs to cache: ', fromBlock, toBlock, target, topic, chain);
|
|
93
113
|
if (fromBlock > toBlock)
|
|
94
114
|
return; // no data to add
|
|
95
115
|
fromBlock = fromBlock - 10;
|
|
96
116
|
toBlock = toBlock + 10;
|
|
117
|
+
if (debugMode)
|
|
118
|
+
console.time(debugTimeKey);
|
|
97
119
|
let { output: logs } = await (0, _1.getLogs)({
|
|
98
120
|
chain, target: target, topic: topic, keys, topics, fromBlock, toBlock,
|
|
99
121
|
});
|
|
122
|
+
if (debugMode) {
|
|
123
|
+
console.timeEnd(debugTimeKey);
|
|
124
|
+
(0, debugLog_1.debugLog)('Logs pulled ' + chain, target, logs.length);
|
|
125
|
+
}
|
|
100
126
|
caches.push({
|
|
101
127
|
logs,
|
|
102
128
|
metadata: { fromBlock, toBlock, }
|
|
@@ -151,16 +177,17 @@ async function getLogs(options) {
|
|
|
151
177
|
extraKey += '-' + keys.join('-').toLowerCase();
|
|
152
178
|
return `event-logs/${chain}/${(_a = target === null || target === void 0 ? void 0 : target.toLowerCase()) !== null && _a !== void 0 ? _a : null}-${extraKey}`;
|
|
153
179
|
}
|
|
154
|
-
// we need to form filter topic with indexed keyword, else it messes up generated topic string
|
|
155
|
-
function toFilterTopic(topic) {
|
|
156
|
-
if (typeof topic === 'string') {
|
|
157
|
-
if (topic.startsWith('0x'))
|
|
158
|
-
return topic;
|
|
159
|
-
topic = new ethers_1.Interface([topic]);
|
|
160
|
-
}
|
|
161
|
-
const fragment = topic.fragments[0];
|
|
162
|
-
return (0, ethers_1.id)(`${fragment.name}(${fragment.inputs.map((i) => i.type).join(',')})`);
|
|
163
|
-
}
|
|
164
180
|
}
|
|
165
181
|
exports.getLogs = getLogs;
|
|
182
|
+
// we need to form filter topic with indexed keyword, else it messes up generated topic string
|
|
183
|
+
function toFilterTopic(topic) {
|
|
184
|
+
if (typeof topic === 'string') {
|
|
185
|
+
if (topic.startsWith('0x'))
|
|
186
|
+
return topic;
|
|
187
|
+
topic = new ethers_1.Interface([topic]);
|
|
188
|
+
}
|
|
189
|
+
const fragment = topic.fragments[0];
|
|
190
|
+
return (0, ethers_1.id)(`${fragment.name}(${fragment.inputs.map((i) => i.type).join(',')})`);
|
|
191
|
+
}
|
|
192
|
+
exports.toFilterTopic = toFilterTopic;
|
|
166
193
|
exports.default = getLogs;
|
|
@@ -67,8 +67,13 @@ async function main() {
|
|
|
67
67
|
}
|
|
68
68
|
fs_1.default.writeFileSync(__dirname + '/../providers.json', JSON.stringify(providerList));
|
|
69
69
|
}
|
|
70
|
+
const blacklist = [
|
|
71
|
+
'https://eth.api.onfinality.io/public'
|
|
72
|
+
];
|
|
70
73
|
function filterRPCs(rpc) {
|
|
71
74
|
return rpc.filter((i) => {
|
|
75
|
+
if (blacklist.includes(i))
|
|
76
|
+
return false; // remove rpcs returning bad block heights etc
|
|
72
77
|
if (i.endsWith('/demo'))
|
|
73
78
|
return false; // remove demo rpc
|
|
74
79
|
if (i.includes('$'))
|