@defillama/sdk 5.0.179 → 5.0.182
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/abi/multicall3.js +2 -0
- 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 +4 -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 +21 -2
- package/build/util/computeTVL.js +2 -2
- package/build/util/env.d.ts +3 -8
- package/build/util/env.js +28 -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
|
@@ -134,6 +134,9 @@ let lastBlockCacheSave = Date.now();
|
|
|
134
134
|
const blockCacheSaveInterval = 1000 * 60 * 5; // 5 minutes
|
|
135
135
|
const { data: blockTimeCache, saveCacheFile: saveBlockCacheFile } = (0, cache_1.getTempLocalCache)({ file: 'BlockCache.json', defaultData: {}, clearAfter: cache_1.ONE_WEEK, returnWithSaveFunction: true });
|
|
136
136
|
function validateCurrentBlock(block, chain = 'ethereum') {
|
|
137
|
+
// sometimes the chain is halted or facing issues, so we skip the validation for those chains
|
|
138
|
+
if ((0, env_1.shouldSkipCurrentBlockValidation)(chain))
|
|
139
|
+
return;
|
|
137
140
|
const provider = getExtraProvider(chain);
|
|
138
141
|
const now = Math.floor(Date.now() / 1000);
|
|
139
142
|
const minutesDiff = Math.floor((now - block.timestamp) / 60);
|
|
@@ -227,7 +230,7 @@ async function _lookupBlock(timestamp, extraParams) {
|
|
|
227
230
|
]);
|
|
228
231
|
updateBlock(blocks);
|
|
229
232
|
}
|
|
230
|
-
if (i > 2 && env_1.
|
|
233
|
+
if (i > 2 && env_1.ENV_CONSTANTS.GET_BLOCK_STATS)
|
|
231
234
|
(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
235
|
if (chain !== "bsc" && // this check is there because bsc halted the chain for few days
|
|
233
236
|
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)
|
|
@@ -229,7 +234,7 @@ function formErrorString(e, errorParams = {}) {
|
|
|
229
234
|
}
|
|
230
235
|
if (e.llamaRPCError) {
|
|
231
236
|
const errorString = `Llama RPC error! method: ${e.method} `;
|
|
232
|
-
const errors = e.errors.map((i) => { var _a; return `- host: ${i === null || i === void 0 ? void 0 : i.host} error: ${(_a = i === null || i === void 0 ? void 0 : i.error) === null || _a === void 0 ? void 0 : _a.message}`; });
|
|
237
|
+
const errors = e.errors.map((i) => { var _a; return `- host: ${i === null || i === void 0 ? void 0 : i.host} error: ${typeof (i === null || i === void 0 ? void 0 : i.error) === 'string' ? i === null || i === void 0 ? void 0 : i.error : (_a = i === null || i === void 0 ? void 0 : i.error) === null || _a === void 0 ? void 0 : _a.message}`; });
|
|
233
238
|
return errorString + '\n' + errors.join('\n');
|
|
234
239
|
}
|
|
235
240
|
let errorString = e.toString();
|
|
@@ -286,11 +291,20 @@ 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 = {}) {
|
|
293
304
|
var _a;
|
|
305
|
+
if (e instanceof Error && (0, env_1.getBoolEnvValue)('DEBUG_ERROR_STACK')) {
|
|
306
|
+
console.error(e);
|
|
307
|
+
}
|
|
294
308
|
const errorParamsSet = Object.keys(errorParams).length;
|
|
295
309
|
if ((e === null || e === void 0 ? void 0 : e._isCustomError) || (!errorParamsSet && typeof e === 'object' && !Object.keys(e).length))
|
|
296
310
|
return e; // already formatted or vannila error
|
|
@@ -350,3 +364,8 @@ function fixTronCallParams(params) {
|
|
|
350
364
|
if (Array.isArray(params.calls))
|
|
351
365
|
params.calls.forEach(fixTronCallParams);
|
|
352
366
|
}
|
|
367
|
+
function getHash(str) {
|
|
368
|
+
if (Array.isArray(str))
|
|
369
|
+
str = str.join('-');
|
|
370
|
+
return crypto_1.default.createHash('sha256').update(str).digest('hex').substring(0, 32);
|
|
371
|
+
}
|
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;
|
|
@@ -21,3 +14,5 @@ export declare function getBatchMaxCount(chain: string): number;
|
|
|
21
14
|
export declare function getArchivalRPCs(chain: string): string[];
|
|
22
15
|
export declare function getChainRPCs(chain: string, defaultList?: string[]): string | undefined;
|
|
23
16
|
export declare function getWhitelistedRPCs(chain: string): string[];
|
|
17
|
+
export declare function shouldSkipCurrentBlockValidation(chain: string): boolean;
|
|
18
|
+
export declare function getBoolEnvValue(key: string, defaultValue?: boolean): boolean;
|
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;
|
|
@@ -15,17 +15,13 @@ exports.getBatchMaxCount = getBatchMaxCount;
|
|
|
15
15
|
exports.getArchivalRPCs = getArchivalRPCs;
|
|
16
16
|
exports.getChainRPCs = getChainRPCs;
|
|
17
17
|
exports.getWhitelistedRPCs = getWhitelistedRPCs;
|
|
18
|
+
exports.shouldSkipCurrentBlockValidation = shouldSkipCurrentBlockValidation;
|
|
19
|
+
exports.getBoolEnvValue = getBoolEnvValue;
|
|
18
20
|
const whitelistedEnvConstants = [
|
|
19
21
|
'R2_ENDPOINT', 'R2_ACCESS_KEY_ID', 'R2_SECRET_ACCESS_KEY', 'TRON_PRO_API_KEY', 'COINS_API_KEY',
|
|
20
22
|
'ELASTICSEARCH_CONFIG', 'GRAPH_API_KEY', 'LLAMA_INDEXER_ENDPOINT', 'LLAMA_INDEXER_API_KEY', 'LLAMA_INDEXER_V2_ENDPOINT', 'LLAMA_INDEXER_V2_API_KEY',
|
|
21
23
|
];
|
|
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');
|
|
24
|
+
const isDebugLevel3 = process.env.LLAMA_SDK_DEBUG_LEVEL_3 === 'true';
|
|
29
25
|
const defaultEnvValues = {
|
|
30
26
|
INTERNAL_SDK_CACHE_FILE: './cache.json',
|
|
31
27
|
TRON_RPC_CONCURRENCY_LIMIT: '5',
|
|
@@ -43,7 +39,15 @@ const defaultEnvValues = {
|
|
|
43
39
|
};
|
|
44
40
|
const _ENV_CONSTANTS = {
|
|
45
41
|
DEBUG_ENABLED: getEnvValue('DEBUG') === "true" || process.env.LLAMA_DEBUG_MODE ? 'true' : 'false',
|
|
46
|
-
|
|
42
|
+
DEBUG_ERROR_STACK: getEnvValue('DEBUG_ERROR_STACK') === "true",
|
|
43
|
+
DEBUG_LEVEL2: process.env.LLAMA_DEBUG_LEVEL2 || process.env.LLAMA_SDK_DEBUG_LEVEL_3 ? 'true' : 'false',
|
|
44
|
+
DEBUG_LEBEL_3: isDebugLevel3,
|
|
45
|
+
LOG_LLAMA_PROVIDER_CALLS: isDebugLevel3 || process.env.LLAMA_SDK_LOG_LLAMA_PROVIDER_CALLS === 'true',
|
|
46
|
+
GET_BLOCK_STATS: isDebugLevel3 || process.env.LLAMA_SDK_GET_BLOCK_STATS === 'true',
|
|
47
|
+
// GET_LOGS_ERRORS: isDebugLevel3 || process.env.LLAMA_SDK_GET_LOGS_ERRORS === 'true',
|
|
48
|
+
GET_LOGS_DEBUG: isDebugLevel3 || process.env.LLAMA_SDK_GET_LOGS_DEBUG === 'true',
|
|
49
|
+
GET_LOGS_INDEXER: isDebugLevel3 || process.env.LLAMA_SDK_GET_LOGS_INDEXER === 'true',
|
|
50
|
+
DEFAULT_SHORTEN_STRING_LENGTH: (_a = process.env.LLAMA_SDK_DEFAULT_SHORTEN_STRING_LENGTH) !== null && _a !== void 0 ? _a : '120',
|
|
47
51
|
};
|
|
48
52
|
whitelistedEnvConstants.forEach(key => _ENV_CONSTANTS[key] = getEnvValue(key));
|
|
49
53
|
Object.keys(defaultEnvValues).forEach(key => _ENV_CONSTANTS[key] = getEnvValue(key, defaultEnvValues[key]));
|
|
@@ -130,3 +134,18 @@ function getWhitelistedRPCs(chain) {
|
|
|
130
134
|
return getEnvValue(key).split(',');
|
|
131
135
|
return [];
|
|
132
136
|
}
|
|
137
|
+
let skipCurrentBlockValidationChainSet = null;
|
|
138
|
+
function shouldSkipCurrentBlockValidation(chain) {
|
|
139
|
+
if (!skipCurrentBlockValidationChainSet) {
|
|
140
|
+
const envValue = getEnvValue('SKIP_CURRENT_BLOCK_VALIDATION_CHAINS', '');
|
|
141
|
+
const chainList = envValue ? envValue.split(',').map(c => c.trim()) : [];
|
|
142
|
+
skipCurrentBlockValidationChainSet = new Set(chainList);
|
|
143
|
+
}
|
|
144
|
+
return skipCurrentBlockValidationChainSet.has(chain);
|
|
145
|
+
}
|
|
146
|
+
function getBoolEnvValue(key, defaultValue = false) {
|
|
147
|
+
const envValue = getEnvValue(key);
|
|
148
|
+
if (envValue === undefined)
|
|
149
|
+
return defaultValue;
|
|
150
|
+
return envValue === 'true';
|
|
151
|
+
}
|
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
|