@defillama/sdk 5.0.179 → 5.0.180
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/index.d.ts +1 -1
- package/build/index.js +1 -1
- package/build/providers.json +1 -1
- package/build/util/LlamaProvider.js +1 -1
- package/build/util/blocks.js +1 -1
- package/build/util/cache.js +2 -6
- package/build/util/coins.js +98 -0
- package/build/util/common.d.ts +1 -0
- package/build/util/common.js +17 -1
- package/build/util/computeTVL.js +2 -2
- package/build/util/env.d.ts +1 -8
- package/build/util/env.js +10 -9
- package/build/util/index.js +2 -2
- package/build/util/indexer.js +5 -5
- package/build/util/logs.js +43 -4
- package/package.json +1 -1
- package/build/util/coinsApi.js +0 -125
- /package/build/util/{coinsApi.d.ts → coins.d.ts} +0 -0
|
@@ -60,7 +60,7 @@ class LlamaProvider extends ethers_1.FallbackProvider {
|
|
|
60
60
|
currentBlocks[url] = block;
|
|
61
61
|
}
|
|
62
62
|
catch (e) {
|
|
63
|
-
if (env_1.
|
|
63
|
+
if (env_1.ENV_CONSTANTS.LOG_LLAMA_PROVIDER_CALLS)
|
|
64
64
|
(0, debugLog_1.debugLog)(`${_this.chainName} skipping RPC ${url} is not working, error: ${e.message}`);
|
|
65
65
|
_this._removeProvider(url);
|
|
66
66
|
}
|
package/build/util/blocks.js
CHANGED
|
@@ -227,7 +227,7 @@ async function _lookupBlock(timestamp, extraParams) {
|
|
|
227
227
|
]);
|
|
228
228
|
updateBlock(blocks);
|
|
229
229
|
}
|
|
230
|
-
if (i > 2 && env_1.
|
|
230
|
+
if (i > 2 && env_1.ENV_CONSTANTS.GET_BLOCK_STATS)
|
|
231
231
|
(0, debugLog_1.debugLog)(`chain: ${chain} block: ${block.number} #calls: ${i} imprecision: ${Number((imprecision) / 60).toFixed(2)} (min) Time Taken: ${Number((Date.now() - time) / 1000).toFixed(2)} (in sec)`);
|
|
232
232
|
if (chain !== "bsc" && // this check is there because bsc halted the chain for few days
|
|
233
233
|
Math.abs(block.timestamp - timestamp) > 3600) {
|
package/build/util/cache.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.ONE_WEEK = exports.currentVersion = void 0;
|
|
7
4
|
exports.readCache = readCache;
|
|
@@ -19,7 +16,6 @@ const zlib_1 = require("zlib");
|
|
|
19
16
|
const util_1 = require("util");
|
|
20
17
|
const env_1 = require("./env");
|
|
21
18
|
const common_1 = require("./common");
|
|
22
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
23
19
|
const brotliOptions = {
|
|
24
20
|
[zlib_1.constants.BROTLI_PARAM_MODE]: zlib_1.constants.BROTLI_MODE_TEXT,
|
|
25
21
|
[zlib_1.constants.BROTLI_PARAM_QUALITY]: zlib_1.constants.BROTLI_MAX_QUALITY,
|
|
@@ -99,7 +95,7 @@ async function writeCache(file, data, options = {}) {
|
|
|
99
95
|
(0, debugLog_1.debugLog)('Data too small to cache: ', file);
|
|
100
96
|
return;
|
|
101
97
|
}
|
|
102
|
-
if (isSameData(data, await readCache(file, { skipR2Cache: true, skipCompression: options.skipCompression, })))
|
|
98
|
+
if (!options.skipCompression && isSameData(data, await readCache(file, { skipR2Cache: true, skipCompression: options.skipCompression, })))
|
|
103
99
|
return;
|
|
104
100
|
if (options.skipCompression)
|
|
105
101
|
file = `${file}-uncompressed`;
|
|
@@ -241,7 +237,7 @@ async function cachedFetch({ key, endpoint, postData, fetcher, fetchOptions, err
|
|
|
241
237
|
if (!key) {
|
|
242
238
|
if (!endpoint || postData || fetcher)
|
|
243
239
|
throw new Error('Key is required for cachedFetch');
|
|
244
|
-
key =
|
|
240
|
+
key = (0, common_1.getHash)(endpoint);
|
|
245
241
|
}
|
|
246
242
|
const fileKey = 'cached-fetch/' + key;
|
|
247
243
|
try {
|
|
@@ -0,0 +1,98 @@
|
|
|
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.getPrices = getPrices;
|
|
7
|
+
exports.getMcaps = getMcaps;
|
|
8
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
const env_1 = require("./env");
|
|
10
|
+
const promisePool_1 = __importDefault(require("./promisePool"));
|
|
11
|
+
const common_1 = require("./common");
|
|
12
|
+
const _1 = require(".");
|
|
13
|
+
const coinsApiKey = (0, env_1.getEnvValue)("COINS_API_KEY");
|
|
14
|
+
const bodySize = 100;
|
|
15
|
+
function getBodies(readKeys, timestamp) {
|
|
16
|
+
const chunks = (0, _1.sliceIntoChunks)(readKeys, bodySize);
|
|
17
|
+
return chunks.map(chunk => {
|
|
18
|
+
const body = { coins: chunk };
|
|
19
|
+
if (timestamp !== "now")
|
|
20
|
+
body.timestamp = timestamp;
|
|
21
|
+
return body;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
async function restCallWrapper(request, retries = 3, name = "-") {
|
|
25
|
+
retries--;
|
|
26
|
+
try {
|
|
27
|
+
const res = await request();
|
|
28
|
+
return res;
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
if (retries <= 0)
|
|
32
|
+
throw (0, common_1.formError)(e);
|
|
33
|
+
}
|
|
34
|
+
await (0, common_1.sleepRandom)(5000 + 10000, 5000);
|
|
35
|
+
return restCallWrapper(request, retries, name);
|
|
36
|
+
}
|
|
37
|
+
const priceCacheAll = {
|
|
38
|
+
now: {
|
|
39
|
+
"coingecko:tether": {
|
|
40
|
+
price: 1,
|
|
41
|
+
symbol: "USDT",
|
|
42
|
+
timestamp: Math.floor(Date.now() / 1e3 + 3600), // an hour from script start time
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const mcapCacheAll = {};
|
|
47
|
+
async function getPrices(readKeys, timestamp) {
|
|
48
|
+
return getPricesData(readKeys, timestamp, "price");
|
|
49
|
+
}
|
|
50
|
+
async function getPricesData(readKeys, timestamp, dataType) {
|
|
51
|
+
if (!readKeys.length)
|
|
52
|
+
return {};
|
|
53
|
+
const cacheAllObject = dataType === "price" ? priceCacheAll : mcapCacheAll;
|
|
54
|
+
const subRoute = dataType === "price" ? "prices" : "mcaps";
|
|
55
|
+
const aggregatedRes = {};
|
|
56
|
+
const timestampString = timestamp.toString();
|
|
57
|
+
const priceCache = cacheAllObject[timestampString] || {};
|
|
58
|
+
if (!cacheAllObject[timestampString])
|
|
59
|
+
cacheAllObject[timestampString] = priceCache;
|
|
60
|
+
// read data from cache where possible
|
|
61
|
+
readKeys = readKeys.filter((PK) => {
|
|
62
|
+
const pkNormalized = PK.toLowerCase();
|
|
63
|
+
let pkData = priceCache[pkNormalized];
|
|
64
|
+
if (pkData) {
|
|
65
|
+
aggregatedRes[PK] = { ...pkData, PK };
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
});
|
|
70
|
+
const bodies = getBodies(readKeys, timestamp);
|
|
71
|
+
await (0, promisePool_1.default)({
|
|
72
|
+
items: bodies,
|
|
73
|
+
concurrency: 10,
|
|
74
|
+
processor: async (body) => {
|
|
75
|
+
if (!body.coins.length)
|
|
76
|
+
return;
|
|
77
|
+
const res = await restCallWrapper(() => axios_1.default.post(`https://coins.llama.fi/${subRoute}`, body, {
|
|
78
|
+
headers: { "Content-Type": "application/json" },
|
|
79
|
+
params: { source: "internal", apikey: coinsApiKey },
|
|
80
|
+
}));
|
|
81
|
+
const data = dataType === "price" ? res.data.coins : res.data;
|
|
82
|
+
Object.entries(data).forEach(([PK, value]) => {
|
|
83
|
+
const pkNormalized = PK.toLowerCase();
|
|
84
|
+
priceCache[pkNormalized] = value;
|
|
85
|
+
});
|
|
86
|
+
body.coins.forEach((PK) => {
|
|
87
|
+
const pkNormalized = PK.toLowerCase();
|
|
88
|
+
const coinData = priceCache[pkNormalized];
|
|
89
|
+
if (coinData)
|
|
90
|
+
aggregatedRes[PK] = { ...coinData, PK };
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
return aggregatedRes;
|
|
95
|
+
}
|
|
96
|
+
async function getMcaps(readKeys, timestamp) {
|
|
97
|
+
return getPricesData(readKeys, timestamp, "mcap");
|
|
98
|
+
}
|
package/build/util/common.d.ts
CHANGED
|
@@ -30,4 +30,5 @@ export declare function evmToTronAddress(address: string): string;
|
|
|
30
30
|
export declare function sleep(ms: number): Promise<unknown>;
|
|
31
31
|
export declare function sleepRandom(max: number, min?: number): Promise<unknown>;
|
|
32
32
|
export declare function fixTronCallParams(params: any): void;
|
|
33
|
+
export declare function getHash(str: string | string[]): string;
|
|
33
34
|
export {};
|
package/build/util/common.js
CHANGED
|
@@ -33,6 +33,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
return result;
|
|
34
34
|
};
|
|
35
35
|
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
36
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
40
|
exports.convertToBigInt = convertToBigInt;
|
|
38
41
|
exports.sumMultiBalanceOf = sumMultiBalanceOf;
|
|
@@ -52,10 +55,12 @@ exports.evmToTronAddress = evmToTronAddress;
|
|
|
52
55
|
exports.sleep = sleep;
|
|
53
56
|
exports.sleepRandom = sleepRandom;
|
|
54
57
|
exports.fixTronCallParams = fixTronCallParams;
|
|
58
|
+
exports.getHash = getHash;
|
|
55
59
|
const axios_1 = __importStar(require("axios"));
|
|
56
60
|
const ethers = __importStar(require("ethers"));
|
|
57
61
|
const TronAddressFormatter = __importStar(require("tron-format-address"));
|
|
58
62
|
const env_1 = require("./env");
|
|
63
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
59
64
|
function convertToBigInt(value) {
|
|
60
65
|
const balance = value;
|
|
61
66
|
if (!value)
|
|
@@ -286,7 +291,13 @@ function formErrorString(e, errorParams = {}) {
|
|
|
286
291
|
}
|
|
287
292
|
return errorString;
|
|
288
293
|
}
|
|
289
|
-
function shortenString(str, length
|
|
294
|
+
function shortenString(str, length) {
|
|
295
|
+
if (!length) {
|
|
296
|
+
if (!isNaN(+env_1.ENV_CONSTANTS.DEFAULT_SHORTEN_STRING_LENGTH))
|
|
297
|
+
length = +env_1.ENV_CONSTANTS.DEFAULT_SHORTEN_STRING_LENGTH;
|
|
298
|
+
if (!length || isNaN(length))
|
|
299
|
+
length = 120;
|
|
300
|
+
}
|
|
290
301
|
return str.length > length ? str.slice(0, length).concat('...') : str;
|
|
291
302
|
}
|
|
292
303
|
function formError(e, errorParams = {}) {
|
|
@@ -350,3 +361,8 @@ function fixTronCallParams(params) {
|
|
|
350
361
|
if (Array.isArray(params.calls))
|
|
351
362
|
params.calls.forEach(fixTronCallParams);
|
|
352
363
|
}
|
|
364
|
+
function getHash(str) {
|
|
365
|
+
if (Array.isArray(str))
|
|
366
|
+
str = str.join('-');
|
|
367
|
+
return crypto_1.default.createHash('sha256').update(str).digest('hex').substring(0, 32);
|
|
368
|
+
}
|
package/build/util/computeTVL.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.default = computeTVL;
|
|
4
4
|
exports.getUnique = getUnique;
|
|
5
5
|
const generalUtil_1 = require("../generalUtil");
|
|
6
|
-
const
|
|
6
|
+
const coins_1 = require("./coins");
|
|
7
7
|
const currentPriceCache = {};
|
|
8
8
|
const priceCaches = {};
|
|
9
9
|
let lastPriceUpdate = 0;
|
|
@@ -69,7 +69,7 @@ async function updatePriceCache(keys, timestamp) {
|
|
|
69
69
|
"confidence": 1
|
|
70
70
|
};
|
|
71
71
|
const missingKeys = keys.filter(key => !pricesCache[key.toLowerCase()]);
|
|
72
|
-
const coins = await (0,
|
|
72
|
+
const coins = await (0, coins_1.getPrices)(missingKeys, timestamp !== null && timestamp !== void 0 ? timestamp : "now");
|
|
73
73
|
for (const [token, data] of Object.entries(coins)) {
|
|
74
74
|
pricesCache[token.toLowerCase()] = data;
|
|
75
75
|
}
|
package/build/util/env.d.ts
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
export declare const isDebugLevel3: boolean;
|
|
2
|
-
export declare const logLlamaProviderCalls: boolean;
|
|
3
|
-
export declare const logGetBlockStats: boolean;
|
|
4
|
-
export declare const logGetLogsErrors: boolean;
|
|
5
|
-
export declare const logGetLogsDebug: boolean;
|
|
6
|
-
export declare const logGetLogsIndexer: boolean;
|
|
7
|
-
export declare const defaultShortenStringLength: number;
|
|
8
1
|
export declare const ENV_CONSTANTS: {
|
|
9
|
-
[key: string]: string | undefined;
|
|
2
|
+
[key: string]: string | boolean | undefined;
|
|
10
3
|
};
|
|
11
4
|
export declare function getChainId(chain: string, chainId: number): number;
|
|
12
5
|
export declare function getMaxParallelRequests(chain: string): number;
|
package/build/util/env.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var _a;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.ENV_CONSTANTS =
|
|
4
|
+
exports.ENV_CONSTANTS = void 0;
|
|
5
5
|
exports.getChainId = getChainId;
|
|
6
6
|
exports.getMaxParallelRequests = getMaxParallelRequests;
|
|
7
7
|
exports.getParallelGetLogsLimit = getParallelGetLogsLimit;
|
|
@@ -19,13 +19,7 @@ const whitelistedEnvConstants = [
|
|
|
19
19
|
'R2_ENDPOINT', 'R2_ACCESS_KEY_ID', 'R2_SECRET_ACCESS_KEY', 'TRON_PRO_API_KEY', 'COINS_API_KEY',
|
|
20
20
|
'ELASTICSEARCH_CONFIG', 'GRAPH_API_KEY', 'LLAMA_INDEXER_ENDPOINT', 'LLAMA_INDEXER_API_KEY', 'LLAMA_INDEXER_V2_ENDPOINT', 'LLAMA_INDEXER_V2_API_KEY',
|
|
21
21
|
];
|
|
22
|
-
|
|
23
|
-
exports.logLlamaProviderCalls = process.env.LLAMA_SDK_LOG_LLAMA_PROVIDER_CALLS === 'true' || exports.isDebugLevel3;
|
|
24
|
-
exports.logGetBlockStats = process.env.LLAMA_SDK_LOG_GET_BLOCK_STATS === 'true' || exports.isDebugLevel3;
|
|
25
|
-
exports.logGetLogsErrors = process.env.LLAMA_SDK_LOG_GET_LOGS_ERRORS === 'true' || exports.isDebugLevel3;
|
|
26
|
-
exports.logGetLogsDebug = process.env.LLAMA_SDK_LOG_GET_LOGS_DEBUG === 'true' || exports.isDebugLevel3;
|
|
27
|
-
exports.logGetLogsIndexer = process.env.LLAMA_SDK_LOG_GET_LOGS_INDEXER === 'true' || exports.isDebugLevel3;
|
|
28
|
-
exports.defaultShortenStringLength = +((_a = process.env.LLAMA_SDK_DEFAULT_SHORTEN_STRING_LENGTH) !== null && _a !== void 0 ? _a : '120');
|
|
22
|
+
const isDebugLevel3 = process.env.LLAMA_SDK_DEBUG_LEVEL_3 === 'true';
|
|
29
23
|
const defaultEnvValues = {
|
|
30
24
|
INTERNAL_SDK_CACHE_FILE: './cache.json',
|
|
31
25
|
TRON_RPC_CONCURRENCY_LIMIT: '5',
|
|
@@ -43,7 +37,14 @@ const defaultEnvValues = {
|
|
|
43
37
|
};
|
|
44
38
|
const _ENV_CONSTANTS = {
|
|
45
39
|
DEBUG_ENABLED: getEnvValue('DEBUG') === "true" || process.env.LLAMA_DEBUG_MODE ? 'true' : 'false',
|
|
46
|
-
DEBUG_LEVEL2: process.env.LLAMA_DEBUG_LEVEL2 ? 'true' : 'false',
|
|
40
|
+
DEBUG_LEVEL2: process.env.LLAMA_DEBUG_LEVEL2 || process.env.LLAMA_SDK_DEBUG_LEVEL_3 ? 'true' : 'false',
|
|
41
|
+
DEBUG_LEBEL_3: isDebugLevel3,
|
|
42
|
+
LOG_LLAMA_PROVIDER_CALLS: isDebugLevel3 || process.env.LLAMA_SDK_LOG_LLAMA_PROVIDER_CALLS === 'true',
|
|
43
|
+
GET_BLOCK_STATS: isDebugLevel3 || process.env.LLAMA_SDK_GET_BLOCK_STATS === 'true',
|
|
44
|
+
// GET_LOGS_ERRORS: isDebugLevel3 || process.env.LLAMA_SDK_GET_LOGS_ERRORS === 'true',
|
|
45
|
+
GET_LOGS_DEBUG: isDebugLevel3 || process.env.LLAMA_SDK_GET_LOGS_DEBUG === 'true',
|
|
46
|
+
GET_LOGS_INDEXER: isDebugLevel3 || process.env.LLAMA_SDK_GET_LOGS_INDEXER === 'true',
|
|
47
|
+
DEFAULT_SHORTEN_STRING_LENGTH: (_a = process.env.LLAMA_SDK_DEFAULT_SHORTEN_STRING_LENGTH) !== null && _a !== void 0 ? _a : '120',
|
|
47
48
|
};
|
|
48
49
|
whitelistedEnvConstants.forEach(key => _ENV_CONSTANTS[key] = getEnvValue(key));
|
|
49
50
|
Object.keys(defaultEnvValues).forEach(key => _ENV_CONSTANTS[key] = getEnvValue(key, defaultEnvValues[key]));
|
package/build/util/index.js
CHANGED
|
@@ -55,7 +55,7 @@ async function getLogs(options) {
|
|
|
55
55
|
catch (e) {
|
|
56
56
|
options.provider = (0, general_1.getProvider)(options.chain, false);
|
|
57
57
|
// if (provider === options.provider) throw e // the provider for archival and non-archival request is the same
|
|
58
|
-
if (env_1.
|
|
58
|
+
if (env_1.ENV_CONSTANTS.GET_LOGS_DEBUG)
|
|
59
59
|
(0, debugLog_1.debugLog)(`Error fetching logs for chain ${options.chain} ${(0, common_1.formError)(e, { chain: options.chain, target: options.target, })}, retrying...`);
|
|
60
60
|
return getLimiter()(() => _getLogs(options));
|
|
61
61
|
}
|
|
@@ -91,7 +91,7 @@ async function _getLogs(params) {
|
|
|
91
91
|
currentBlock = nextBlock;
|
|
92
92
|
}
|
|
93
93
|
catch (e) {
|
|
94
|
-
if (env_1.
|
|
94
|
+
if (env_1.ENV_CONSTANTS.GET_LOGS_DEBUG)
|
|
95
95
|
(0, debugLog_1.debugLog)(`Error fetching logs for chain ${params.chain} blockSpread: ${blockSpread}. ${(0, common_1.formError)(e, { chain: params.chain, target: params.target, provider })}`);
|
|
96
96
|
if (blockSpread >= 1001) {
|
|
97
97
|
// We got too many results
|
package/build/util/indexer.js
CHANGED
|
@@ -160,7 +160,7 @@ async function getTokens(address, { onlyWhitelisted = true, skipCacheRead = fals
|
|
|
160
160
|
if (cache.timestamp && timeNow - cache.timestamp < THREE_DAYS)
|
|
161
161
|
return cache.tokens;
|
|
162
162
|
}
|
|
163
|
-
if (env_1.
|
|
163
|
+
if (env_1.ENV_CONSTANTS.GET_LOGS_INDEXER)
|
|
164
164
|
(0, debugLog_1.debugLog)("[Indexer] Pulling tokens for " + address);
|
|
165
165
|
const tokens = (_b = cache.tokens) !== null && _b !== void 0 ? _b : {};
|
|
166
166
|
const { data: { balances }, } = await axiosInstances.v1(`/balances`, {
|
|
@@ -197,7 +197,7 @@ async function getLogs(options) {
|
|
|
197
197
|
let { all = true, limit = 1000, offset: initialOffset = 0, target, targets = [], flatten = true, debugMode = false, noTarget = false, maxBlockRange, processor, } = options;
|
|
198
198
|
const { chain, fromBlock, toBlock, topic, topic1, topic2, topic3, transformLog, } = await (0, logs_1.getLogParams)(options, true);
|
|
199
199
|
if (!debugMode)
|
|
200
|
-
debugMode = debugLog_1.DEBUG_LEVEL2 && env_1.
|
|
200
|
+
debugMode = debugLog_1.DEBUG_LEVEL2 && !!env_1.ENV_CONSTANTS.GET_LOGS_INDEXER;
|
|
201
201
|
const blockRange = toBlock - fromBlock;
|
|
202
202
|
const effectiveMaxBlockRange = maxBlockRange !== null && maxBlockRange !== void 0 ? maxBlockRange : (noTarget ? 10000 : Infinity);
|
|
203
203
|
if (noTarget && blockRange > 500000) {
|
|
@@ -213,7 +213,7 @@ async function getLogs(options) {
|
|
|
213
213
|
const percentageMissing = ((toBlock - lastIndexedBlock) / (toBlock - fromBlock)) * 100;
|
|
214
214
|
if (percentageMissing > 50) // more than 50% of the requested range is missing, throw an error and so we pull the logs through rpc calls
|
|
215
215
|
throw new Error(`Indexer not up to date for ${chain}. Last indexed block: ${lastIndexedBlock}, requested block: ${toBlock}`);
|
|
216
|
-
if (env_1.
|
|
216
|
+
if (env_1.ENV_CONSTANTS.GET_LOGS_INDEXER)
|
|
217
217
|
(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.`);
|
|
218
218
|
// now we split the request into two parts, one that goes to the indexer and one that goes through rpc calls
|
|
219
219
|
const breakBlock = lastIndexedBlock - 50; // we add a small buffer to avoid missing logs due to reorgs
|
|
@@ -329,7 +329,7 @@ async function getLogs(options) {
|
|
|
329
329
|
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, }) {
|
|
330
330
|
var _a, _b;
|
|
331
331
|
if (!debugMode)
|
|
332
|
-
debugMode = debugLog_1.DEBUG_LEVEL2 && env_1.
|
|
332
|
+
debugMode = debugLog_1.DEBUG_LEVEL2 && !!env_1.ENV_CONSTANTS.GET_LOGS_INDEXER;
|
|
333
333
|
checkIndexerConfig("v2");
|
|
334
334
|
const chainId = getChainId(chain, "v2");
|
|
335
335
|
// -----------------------------------------------------------------------
|
|
@@ -446,7 +446,7 @@ async function getTokenTransfers({ chain = "ethereum", fromAddressFilter, fromBl
|
|
|
446
446
|
async function getTransactions({ chain = "ethereum", addresses, transaction_hashes, from_block, to_block, all = true, limit = 1000, offset = 0, debugMode = false, transactionType = "from", }) {
|
|
447
447
|
var _a, _b;
|
|
448
448
|
if (!debugMode)
|
|
449
|
-
debugMode = debugLog_1.DEBUG_LEVEL2 && env_1.
|
|
449
|
+
debugMode = debugLog_1.DEBUG_LEVEL2 && !!env_1.ENV_CONSTANTS.GET_LOGS_INDEXER;
|
|
450
450
|
checkIndexerConfig("v2");
|
|
451
451
|
const chainId = getChainId(chain, "v2");
|
|
452
452
|
if ((!addresses || addresses.length === 0) && (!transaction_hashes || transaction_hashes.length === 0))
|
package/build/util/logs.js
CHANGED
|
@@ -46,7 +46,7 @@ async function getLogs(options) {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
if (!debugMode)
|
|
49
|
-
debugMode = debugLog_1.DEBUG_LEVEL2 && env_1.
|
|
49
|
+
debugMode = debugLog_1.DEBUG_LEVEL2 && !!env_1.ENV_CONSTANTS.GET_LOGS_DEBUG;
|
|
50
50
|
/* ----------------------- Split by maxBlockRange ------------------------- */
|
|
51
51
|
const blockRange = toBlock - fromBlock;
|
|
52
52
|
if (maxBlockRange && blockRange > maxBlockRange) {
|
|
@@ -166,8 +166,42 @@ async function getLogs(options) {
|
|
|
166
166
|
merged.push(c);
|
|
167
167
|
});
|
|
168
168
|
caches = merged;
|
|
169
|
-
if (!skipCache)
|
|
170
|
-
|
|
169
|
+
if (!skipCache) {
|
|
170
|
+
let storeCaches = caches;
|
|
171
|
+
let randomLogLength = 0;
|
|
172
|
+
const totalLogCount = caches.reduce((acc, c) => {
|
|
173
|
+
if (c.logs.length)
|
|
174
|
+
randomLogLength = JSON.stringify(c.logs[0]).length;
|
|
175
|
+
return acc + c.logs.length;
|
|
176
|
+
}, 0);
|
|
177
|
+
const fileSizeInMB = (totalLogCount * randomLogLength) / (1024 * 1024);
|
|
178
|
+
if (fileSizeInMB > 300) { // if cache size is larger than ~300MB, trim it down
|
|
179
|
+
console.log(`getLogs: large cache size detected ${totalLogCount} logs size: ${fileSizeInMB}MB, retaining only the latest 200k logs to limit memory usage target=${target} topic=${topic} fromBlock=${fromBlock} toBlock=${toBlock}`);
|
|
180
|
+
// retain only the latest logs that fit within 300,000 logs
|
|
181
|
+
if (caches.length > 1) {
|
|
182
|
+
let cacheWithLatestFromBlock = caches[0];
|
|
183
|
+
for (const c of caches) {
|
|
184
|
+
if (c.metadata.fromBlock > cacheWithLatestFromBlock.metadata.fromBlock) {
|
|
185
|
+
cacheWithLatestFromBlock = c;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
storeCaches = [cacheWithLatestFromBlock];
|
|
189
|
+
}
|
|
190
|
+
storeCaches = storeCaches.map(c => {
|
|
191
|
+
const clone = { logs: [], metadata: JSON.parse(JSON.stringify(c.metadata)) };
|
|
192
|
+
if (c.logs.length > 200000) {
|
|
193
|
+
// sort the logs by block number descending and keep only the latest 200k logs
|
|
194
|
+
c.logs.sort((a, b) => b.blockNumber - a.blockNumber);
|
|
195
|
+
clone.logs = c.logs.slice(0, 200000);
|
|
196
|
+
const lastLog = clone.logs[clone.logs.length - 1];
|
|
197
|
+
clone.metadata.fromBlock = lastLog.blockNumber;
|
|
198
|
+
}
|
|
199
|
+
return clone;
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
// we are skipping compression by default, so reads & writes are faster
|
|
203
|
+
await (0, cache_1.writeCache)(getFile(), { caches: storeCaches, version: currentVersion }, { skipR2CacheWrite: !cacheInCloud, skipCompression: !cacheInCloud });
|
|
204
|
+
}
|
|
171
205
|
}
|
|
172
206
|
function dedupLogs(...arr) {
|
|
173
207
|
const seen = new Set();
|
|
@@ -203,7 +237,12 @@ async function getLogs(options) {
|
|
|
203
237
|
throw new Error("extraKey is required");
|
|
204
238
|
if (keys.length)
|
|
205
239
|
extraKey += "-" + keys.join("-").toLowerCase();
|
|
206
|
-
|
|
240
|
+
let file = `${(_a = target === null || target === void 0 ? void 0 : target.toLowerCase()) !== null && _a !== void 0 ? _a : null}-${extraKey}`;
|
|
241
|
+
const normalKeyLength = '0x27e5cb712334e101b3c232eb0be198baaa595f5f-0xe8137aa901976cc8eaf1cef5dec491873faadc99d9720ccaec95673294a9d7c5-uncompressed'.length;
|
|
242
|
+
// sometimes, there is a lot of topics and we hit the file name length limit
|
|
243
|
+
if (file.length > normalKeyLength)
|
|
244
|
+
file = (0, common_1.getHash)(file);
|
|
245
|
+
return `event-logs/${chain}/${file}`;
|
|
207
246
|
}
|
|
208
247
|
}
|
|
209
248
|
/* -------------------------------------------------------------------------- */
|
package/package.json
CHANGED
package/build/util/coinsApi.js
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
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.getPrices = getPrices;
|
|
7
|
-
exports.getMcaps = getMcaps;
|
|
8
|
-
const axios_1 = __importDefault(require("axios"));
|
|
9
|
-
const env_1 = require("./env");
|
|
10
|
-
const promisePool_1 = __importDefault(require("./promisePool"));
|
|
11
|
-
const common_1 = require("./common");
|
|
12
|
-
const coinsApiKey = (0, env_1.getEnvValue)("COINS_API_KEY");
|
|
13
|
-
const bodySize = 2; // 100;
|
|
14
|
-
function getBodies(readKeys, timestamp) {
|
|
15
|
-
const bodies = [];
|
|
16
|
-
for (let i = 0; i < readKeys.length; i += bodySize) {
|
|
17
|
-
const body = {
|
|
18
|
-
coins: readKeys.slice(i, i + bodySize),
|
|
19
|
-
};
|
|
20
|
-
if (timestamp !== "now")
|
|
21
|
-
body.timestamp = timestamp;
|
|
22
|
-
bodies.push(JSON.stringify(body));
|
|
23
|
-
}
|
|
24
|
-
return bodies;
|
|
25
|
-
}
|
|
26
|
-
async function restCallWrapper(request, retries = 3, name = "-") {
|
|
27
|
-
while (retries > 0) {
|
|
28
|
-
try {
|
|
29
|
-
const res = await request();
|
|
30
|
-
return res;
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
await (0, common_1.sleepRandom)(5000 + 10000, 5000);
|
|
34
|
-
restCallWrapper(request, retries--, name);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
throw new Error(`couldnt work ${name} call after retries!`);
|
|
38
|
-
}
|
|
39
|
-
const priceCache = {
|
|
40
|
-
"coingecko:tether": {
|
|
41
|
-
price: 1,
|
|
42
|
-
symbol: "USDT",
|
|
43
|
-
timestamp: Math.floor(Date.now() / 1e3 + 3600), // an hour from script start time
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
async function getPrices(readKeys, timestamp) {
|
|
47
|
-
if (!readKeys.length)
|
|
48
|
-
return {};
|
|
49
|
-
const aggregatedRes = {};
|
|
50
|
-
// read data from cache where possible
|
|
51
|
-
readKeys = readKeys.filter((PK) => {
|
|
52
|
-
if (timestamp !== "now")
|
|
53
|
-
return true;
|
|
54
|
-
if (priceCache[PK]) {
|
|
55
|
-
aggregatedRes[PK] = { ...priceCache[PK], PK };
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
return true;
|
|
59
|
-
});
|
|
60
|
-
const bodies = getBodies(readKeys, timestamp);
|
|
61
|
-
const tokenData = [];
|
|
62
|
-
await (0, promisePool_1.default)({
|
|
63
|
-
items: bodies,
|
|
64
|
-
concurrency: 10,
|
|
65
|
-
processor: async (body) => {
|
|
66
|
-
const res = await restCallWrapper(() => axios_1.default.post(`https://coins.llama.fi/prices?source=internal${coinsApiKey ? `?apikey=${coinsApiKey}` : ""}`, body, {
|
|
67
|
-
headers: { "Content-Type": "application/json" },
|
|
68
|
-
params: { source: "internal", apikey: coinsApiKey },
|
|
69
|
-
}));
|
|
70
|
-
const data = (res.data.coins = Object.entries(res.data.coins).map(([PK, value]) => ({
|
|
71
|
-
...value,
|
|
72
|
-
PK,
|
|
73
|
-
})));
|
|
74
|
-
tokenData.push(data);
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
const normalizedReadKeys = readKeys.map((k) => k.toLowerCase());
|
|
78
|
-
tokenData.map((batch) => {
|
|
79
|
-
batch.map((a) => {
|
|
80
|
-
if (!a.PK)
|
|
81
|
-
return;
|
|
82
|
-
const i = normalizedReadKeys.indexOf(a.PK.toLowerCase());
|
|
83
|
-
aggregatedRes[readKeys[i]] = a;
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
return aggregatedRes;
|
|
87
|
-
}
|
|
88
|
-
const mcapCache = {};
|
|
89
|
-
async function getMcaps(readKeys, timestamp) {
|
|
90
|
-
if (!readKeys.length)
|
|
91
|
-
return {};
|
|
92
|
-
const aggregatedRes = {};
|
|
93
|
-
// read data from cache where possible
|
|
94
|
-
readKeys = readKeys.filter((PK) => {
|
|
95
|
-
if (timestamp !== "now")
|
|
96
|
-
return true;
|
|
97
|
-
if (mcapCache[PK]) {
|
|
98
|
-
aggregatedRes[PK] = { ...mcapCache[PK], PK };
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
return true;
|
|
102
|
-
});
|
|
103
|
-
const bodies = getBodies(readKeys, timestamp);
|
|
104
|
-
const tokenData = [];
|
|
105
|
-
await (0, promisePool_1.default)({
|
|
106
|
-
items: bodies,
|
|
107
|
-
concurrency: 10,
|
|
108
|
-
processor: async (body) => {
|
|
109
|
-
const res = await restCallWrapper(() => axios_1.default.post(`https://coins.llama.fi/mcaps${coinsApiKey ? `?apikey=${coinsApiKey}` : ""}`, body, {
|
|
110
|
-
headers: { "Content-Type": "application/json" },
|
|
111
|
-
}));
|
|
112
|
-
tokenData.push(res.data);
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
const normalizedReadKeys = readKeys.map((k) => k.toLowerCase());
|
|
116
|
-
tokenData.map((batch) => {
|
|
117
|
-
Object.keys(batch).map((a) => {
|
|
118
|
-
if (!batch[a].mcap)
|
|
119
|
-
return;
|
|
120
|
-
const i = normalizedReadKeys.indexOf(a.toLowerCase());
|
|
121
|
-
aggregatedRes[readKeys[i]] = batch[a];
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
return aggregatedRes;
|
|
125
|
-
}
|
|
File without changes
|