@defillama/sdk 5.0.10 → 5.0.12
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 +10 -0
- package/build/Balances.js +51 -107
- package/build/ChainApi.d.ts +1 -0
- package/build/ChainApi.js +152 -253
- package/build/abi/abi2.js +47 -144
- package/build/abi/convertResults.js +9 -29
- package/build/abi/index.js +220 -326
- package/build/abi/multicall.js +115 -217
- package/build/abi/multicall3.js +59 -123
- package/build/abi/rpcCall.js +43 -106
- package/build/abi/tron.js +153 -283
- package/build/api.js +3 -4
- package/build/computeTVL/blocks.d.ts +1 -1
- package/build/computeTVL/blocks.js +2 -1
- package/build/computeTVL/humanizeNumber.js +6 -7
- package/build/computeTVL/prices.js +55 -145
- package/build/erc20/index.js +34 -122
- package/build/eth/index.js +37 -107
- package/build/general.js +22 -23
- package/build/generalUtil.js +68 -127
- package/build/index.js +2 -2
- package/build/providers.json +1 -1
- package/build/util/blocks.d.ts +5 -2
- package/build/util/blocks.js +234 -373
- package/build/util/blockscout.js +13 -58
- package/build/util/cache.js +112 -274
- package/build/util/computeTVL.js +72 -150
- package/build/util/cosmos.js +21 -75
- package/build/util/debugLog.js +5 -13
- package/build/util/env.d.ts +3 -2
- package/build/util/env.js +30 -35
- package/build/util/index.d.ts +5 -3
- package/build/util/index.js +105 -134
- package/build/util/internal-cache.js +7 -8
- package/build/util/logs.d.ts +1 -2
- package/build/util/logs.js +148 -236
- package/build/util/promisePool.js +11 -62
- package/build/util/r2.js +36 -95
- package/build/util/updateProviderList.js +23 -83
- package/package.json +2 -3
package/build/util/blocks.js
CHANGED
|
@@ -1,166 +1,75 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
4
|
};
|
|
41
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.getTimestamp = exports.lookupBlock = exports.getLatestBlock = exports.getCurrentChainBlock = exports.getBlock = exports.getCurrentBlocks = exports.getBlocks = exports.getChainBlocks = exports.chainsForBlocks = void 0;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
6
|
+
exports.getTimestamp = exports.lookupBlock = exports.getLatestBlock = exports.getCurrentChainBlock = exports.getBlockNumber = exports.getBlock = exports.getCurrentBlocks = exports.getBlocks = exports.getChainBlocks = exports.chainsForBlocks = void 0;
|
|
7
|
+
const general_1 = require("../general");
|
|
8
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
const generalUtil_1 = require("../generalUtil");
|
|
10
|
+
const debugLog_1 = require("./debugLog");
|
|
11
|
+
const cosmos_1 = require("./cosmos");
|
|
12
|
+
const cache_1 = require("./cache");
|
|
13
|
+
const blockscout_1 = require("./blockscout");
|
|
14
|
+
const p_limit_1 = __importDefault(require("p-limit"));
|
|
15
|
+
const env_1 = require("./env");
|
|
16
|
+
const defaultChains = ["avax", "bsc", "polygon", "arbitrum"];
|
|
51
17
|
exports.chainsForBlocks = defaultChains;
|
|
52
|
-
|
|
53
|
-
function getChainBlocks(timestamp, chains) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return __generator(this, function (_a) {
|
|
59
|
-
switch (_a.label) {
|
|
60
|
-
case 0:
|
|
61
|
-
chainBlocks = {};
|
|
62
|
-
setBlock = function (chain) { return __awaiter(_this, void 0, void 0, function () { var _a, _b; return __generator(this, function (_c) {
|
|
63
|
-
switch (_c.label) {
|
|
64
|
-
case 0:
|
|
65
|
-
_a = chainBlocks;
|
|
66
|
-
_b = chain;
|
|
67
|
-
return [4 /*yield*/, getBlock(chain, timestamp)];
|
|
68
|
-
case 1: return [2 /*return*/, _a[_b] = (_c.sent()).block];
|
|
69
|
-
}
|
|
70
|
-
}); }); };
|
|
71
|
-
return [4 /*yield*/, Promise.all(chains.map(setBlock))];
|
|
72
|
-
case 1:
|
|
73
|
-
_a.sent();
|
|
74
|
-
return [2 /*return*/, chainBlocks];
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
});
|
|
18
|
+
const blockRetries = 3;
|
|
19
|
+
async function getChainBlocks(timestamp, chains = defaultChains) {
|
|
20
|
+
const chainBlocks = {};
|
|
21
|
+
const setBlock = async (chain) => chainBlocks[chain] = await getBlockNumber(chain, timestamp);
|
|
22
|
+
await Promise.all(chains.map(setBlock));
|
|
23
|
+
return chainBlocks;
|
|
78
24
|
}
|
|
79
25
|
exports.getChainBlocks = getChainBlocks;
|
|
80
|
-
function getBlocks(timestamp, chains) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return [4 /*yield*/, Promise.all([getBlock('ethereum', timestamp), getChainBlocks(timestamp, chains)])];
|
|
89
|
-
case 1:
|
|
90
|
-
_a = _b.sent(), ethBlock = _a[0], chainBlocks = _a[1];
|
|
91
|
-
chainBlocks['ethereum'] = ethBlock.block;
|
|
92
|
-
return [2 /*return*/, {
|
|
93
|
-
ethereumBlock: ethBlock.block,
|
|
94
|
-
chainBlocks: chainBlocks,
|
|
95
|
-
}];
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
});
|
|
26
|
+
async function getBlocks(timestamp, chains = undefined) {
|
|
27
|
+
chains = chains === null || chains === void 0 ? void 0 : chains.filter(i => i !== 'ethereum');
|
|
28
|
+
const [ethBlock, chainBlocks] = await Promise.all([getBlockNumber('ethereum', timestamp), getChainBlocks(timestamp, chains)]);
|
|
29
|
+
chainBlocks['ethereum'] = ethBlock;
|
|
30
|
+
return {
|
|
31
|
+
ethereumBlock: ethBlock,
|
|
32
|
+
chainBlocks,
|
|
33
|
+
};
|
|
99
34
|
}
|
|
100
35
|
exports.getBlocks = getBlocks;
|
|
101
|
-
function getCurrentBlocks(chains) {
|
|
102
|
-
if (chains
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
block = _a.sent();
|
|
113
|
-
return [4 /*yield*/, getChainBlocks(undefined, chains)];
|
|
114
|
-
case 2:
|
|
115
|
-
chainBlocks = _a.sent();
|
|
116
|
-
chainBlocks['ethereum'] = block.block;
|
|
117
|
-
return [2 /*return*/, {
|
|
118
|
-
timestamp: block.timestamp,
|
|
119
|
-
ethereumBlock: block.block,
|
|
120
|
-
chainBlocks: chainBlocks,
|
|
121
|
-
}];
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
});
|
|
36
|
+
async function getCurrentBlocks(chains = undefined) {
|
|
37
|
+
if (chains)
|
|
38
|
+
chains = chains.filter(i => i !== "ethereum");
|
|
39
|
+
const block = await getBlock('ethereum');
|
|
40
|
+
const chainBlocks = await getChainBlocks(undefined, chains);
|
|
41
|
+
chainBlocks['ethereum'] = block.block;
|
|
42
|
+
return {
|
|
43
|
+
timestamp: block.timestamp,
|
|
44
|
+
ethereumBlock: block.block,
|
|
45
|
+
chainBlocks,
|
|
46
|
+
};
|
|
125
47
|
}
|
|
126
48
|
exports.getCurrentBlocks = getCurrentBlocks;
|
|
127
|
-
function getBlock(chain, timestamp) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
_a.trys.push([2, 4, , 5]);
|
|
142
|
-
return [4 /*yield*/, lookupBlock(timestamp, { chain: chain, })];
|
|
143
|
-
case 3:
|
|
144
|
-
res = _a.sent();
|
|
145
|
-
return [2 /*return*/, res];
|
|
146
|
-
case 4:
|
|
147
|
-
e_1 = _a.sent();
|
|
148
|
-
error = e_1;
|
|
149
|
-
return [3 /*break*/, 5];
|
|
150
|
-
case 5:
|
|
151
|
-
i++;
|
|
152
|
-
return [3 /*break*/, 1];
|
|
153
|
-
case 6: throw error;
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
});
|
|
49
|
+
async function getBlock(chain, timestamp) {
|
|
50
|
+
if (!timestamp)
|
|
51
|
+
return getCurrentChainBlock(chain);
|
|
52
|
+
let error;
|
|
53
|
+
for (let i = 0; i < blockRetries; i++) {
|
|
54
|
+
try {
|
|
55
|
+
let res = await lookupBlock(timestamp, { chain, });
|
|
56
|
+
return res;
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
error = e;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
throw error;
|
|
157
63
|
}
|
|
158
64
|
exports.getBlock = getBlock;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
65
|
+
async function getBlockNumber(chain, timestamp) {
|
|
66
|
+
return (await getBlock(chain, timestamp)).block;
|
|
67
|
+
}
|
|
68
|
+
exports.getBlockNumber = getBlockNumber;
|
|
69
|
+
const refreshInterval = 1000 * 60 * 1; // 5 minutes
|
|
70
|
+
function getCurrentChainBlock(chain = 'ethereum') {
|
|
71
|
+
const { timestamp, } = currentChainBlockCache[chain] || {};
|
|
72
|
+
const currentTimestamp = Date.now();
|
|
164
73
|
if (!timestamp || currentTimestamp - timestamp > refreshInterval) {
|
|
165
74
|
currentChainBlockCache[chain] = {
|
|
166
75
|
timestamp: currentTimestamp,
|
|
@@ -168,68 +77,46 @@ function getCurrentChainBlock(chain) {
|
|
|
168
77
|
};
|
|
169
78
|
}
|
|
170
79
|
return currentChainBlockCache[chain].promise;
|
|
171
|
-
function _getCurrentChainBlock() {
|
|
80
|
+
async function _getCurrentChainBlock() {
|
|
172
81
|
var _a, _b;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
case 2:
|
|
188
|
-
e_2 = _d.sent();
|
|
189
|
-
delete currentChainBlockCache[chain];
|
|
190
|
-
if ((_b = (_a = e_2 === null || e_2 === void 0 ? void 0 : e_2.message) === null || _a === void 0 ? void 0 : _a.includes) === null || _b === void 0 ? void 0 : _b.call(_a, "Last block of chain"))
|
|
191
|
-
throw e_2;
|
|
192
|
-
throw (0, generalUtil_1.formError)(e_2);
|
|
193
|
-
case 3: return [2 /*return*/];
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
});
|
|
82
|
+
try {
|
|
83
|
+
const provider = getExtraProvider(chain);
|
|
84
|
+
const { number, timestamp, } = await provider.getBlock('latest');
|
|
85
|
+
const response = { block: number, timestamp, number };
|
|
86
|
+
validateCurrentBlock(response, chain);
|
|
87
|
+
currentChainBlockCache[chain] = { timestamp: currentTimestamp, promise: response };
|
|
88
|
+
return response; // we are interested only in these fields
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
delete currentChainBlockCache[chain];
|
|
92
|
+
if ((_b = (_a = e === null || e === void 0 ? void 0 : e.message) === null || _a === void 0 ? void 0 : _a.includes) === null || _b === void 0 ? void 0 : _b.call(_a, "Last block of chain"))
|
|
93
|
+
throw e;
|
|
94
|
+
throw (0, generalUtil_1.formError)(e);
|
|
95
|
+
}
|
|
197
96
|
}
|
|
198
97
|
}
|
|
199
98
|
exports.getCurrentChainBlock = getCurrentChainBlock;
|
|
200
|
-
|
|
201
|
-
getBlock:
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
});
|
|
214
|
-
}); }
|
|
99
|
+
const algorandBlockProvider = {
|
|
100
|
+
getBlock: async (height) => {
|
|
101
|
+
if (height !== 'latest')
|
|
102
|
+
return (0, axios_1.default)(`https://algoindexer.algoexplorerapi.io/v2/blocks/${height}`)
|
|
103
|
+
.then((res) => res.data)
|
|
104
|
+
.then((block) => ({
|
|
105
|
+
number: block.round,
|
|
106
|
+
timestamp: block.timestamp
|
|
107
|
+
}));
|
|
108
|
+
return (0, axios_1.default)('https://algoindexer.algoexplorerapi.io/health')
|
|
109
|
+
.then((res) => res.data)
|
|
110
|
+
.then((block) => algorandBlockProvider.getBlock(block.round));
|
|
111
|
+
}
|
|
215
112
|
};
|
|
216
|
-
function fetchBlockFromProvider(height, chain) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
return [4 /*yield*/, provider.getBlock(height)];
|
|
224
|
-
case 1:
|
|
225
|
-
block = _a.sent();
|
|
226
|
-
if (block === null) {
|
|
227
|
-
throw new Error("Can't get block of chain ".concat(chain !== null && chain !== void 0 ? chain : "ethereum"));
|
|
228
|
-
}
|
|
229
|
-
return [2 /*return*/, block];
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
});
|
|
113
|
+
async function fetchBlockFromProvider(height, chain) {
|
|
114
|
+
const provider = getExtraProvider(chain !== null && chain !== void 0 ? chain : "ethereum");
|
|
115
|
+
const block = await provider.getBlock(height);
|
|
116
|
+
if (block === null) {
|
|
117
|
+
throw new Error(`Can't get block of chain ${chain !== null && chain !== void 0 ? chain : "ethereum"}`);
|
|
118
|
+
}
|
|
119
|
+
return block;
|
|
233
120
|
}
|
|
234
121
|
function getExtraProvider(chain) {
|
|
235
122
|
if (chain && (0, cosmos_1.isCosmosChain)(chain))
|
|
@@ -239,184 +126,158 @@ function getExtraProvider(chain) {
|
|
|
239
126
|
return (0, general_1.getProvider)(chain);
|
|
240
127
|
}
|
|
241
128
|
exports.getLatestBlock = getCurrentChainBlock;
|
|
242
|
-
|
|
129
|
+
const intialBlocks = {
|
|
243
130
|
terra: 4724001,
|
|
244
131
|
crab: 4969901
|
|
245
132
|
};
|
|
246
|
-
|
|
247
|
-
function validateCurrentBlock(block, chain) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
var minutesDiff = Math.floor((now - block.timestamp) / 60);
|
|
133
|
+
const blockTimeCache = (0, cache_1.getTempLocalCache)({ file: 'BlockCache.json', defaultData: {} });
|
|
134
|
+
function validateCurrentBlock(block, chain = 'ethereum') {
|
|
135
|
+
const provider = getExtraProvider(chain);
|
|
136
|
+
const now = Math.floor(Date.now() / 1000);
|
|
137
|
+
const minutesDiff = Math.floor((now - block.timestamp) / 60);
|
|
252
138
|
if (minutesDiff > 60)
|
|
253
|
-
throw new Error(
|
|
139
|
+
throw new Error(`Last block for ${chain} is ${minutesDiff} minutes behind (${new Date(block.timestamp * 1000)}). Provider is "${(0, generalUtil_1.getProviderUrl)(provider)}"`);
|
|
140
|
+
}
|
|
141
|
+
const chainLimiters = {};
|
|
142
|
+
function getChainLimiter(chain) {
|
|
143
|
+
if (!chainLimiters[chain])
|
|
144
|
+
chainLimiters[chain] = createLimiter(chain);
|
|
145
|
+
return chainLimiters[chain];
|
|
146
|
+
function createLimiter(chain) {
|
|
147
|
+
return (0, p_limit_1.default)((0, env_1.getParallelGetBlocksLimit)(chain));
|
|
148
|
+
}
|
|
254
149
|
}
|
|
255
|
-
function lookupBlock(timestamp, extraParams) {
|
|
150
|
+
async function lookupBlock(timestamp, extraParams) {
|
|
151
|
+
const { chain = "ethereum" } = extraParams !== null && extraParams !== void 0 ? extraParams : {};
|
|
152
|
+
const limiter = getChainLimiter(chain);
|
|
153
|
+
return limiter(() => _lookupBlock(timestamp, extraParams));
|
|
154
|
+
}
|
|
155
|
+
exports.lookupBlock = lookupBlock;
|
|
156
|
+
async function _lookupBlock(timestamp, extraParams) {
|
|
256
157
|
var _a, _b;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
158
|
+
const { allowedTimeRange = 5 * 60, acceptableBlockImprecision = 10 } = extraParams !== null && extraParams !== void 0 ? extraParams : {};
|
|
159
|
+
const chain = (_a = extraParams === null || extraParams === void 0 ? void 0 : extraParams.chain) !== null && _a !== void 0 ? _a : "ethereum";
|
|
160
|
+
if (blockscout_1.blockscoutEndpoints[chain]) {
|
|
161
|
+
try {
|
|
162
|
+
const block = await (0, blockscout_1.getBlockscoutBlock)(timestamp, chain);
|
|
163
|
+
addBlockToCache(block);
|
|
164
|
+
return block;
|
|
165
|
+
}
|
|
166
|
+
catch (e) { // fallback to usual way of fetching logs
|
|
167
|
+
(0, debugLog_1.debugLog)('error fetching block from blockscout', e, chain);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (chain === 'waves') {
|
|
171
|
+
const api = `https://nodes.wavesnodes.com/blocks/heightByTimestamp/${timestamp}`;
|
|
172
|
+
const { data } = await (0, axios_1.default)(api);
|
|
173
|
+
return {
|
|
174
|
+
timestamp,
|
|
175
|
+
block: +data.height,
|
|
176
|
+
number: +data.height,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
let low = (_b = intialBlocks[chain]) !== null && _b !== void 0 ? _b : 100;
|
|
180
|
+
let lowBlock = getLowBlock();
|
|
181
|
+
let highBlock = getHighBlock();
|
|
182
|
+
let block;
|
|
183
|
+
let i = 0;
|
|
184
|
+
let time = Date.now();
|
|
185
|
+
let blockImprecision;
|
|
186
|
+
let imprecision;
|
|
187
|
+
try {
|
|
188
|
+
let firstBlock, lastBlock;
|
|
189
|
+
if (['evmos'].includes(chain)) {
|
|
190
|
+
lastBlock = await (0, exports.getLatestBlock)(chain);
|
|
191
|
+
let firstBlockNum = lastBlock.number;
|
|
192
|
+
switch (chain) {
|
|
193
|
+
default: firstBlockNum -= 2 * 1e5; // evmos hold only the last 200k block data
|
|
194
|
+
}
|
|
195
|
+
firstBlock = await fetchBlockFromProvider(firstBlockNum, chain);
|
|
271
196
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
197
|
+
else {
|
|
198
|
+
[lastBlock, firstBlock] = await Promise.all([
|
|
199
|
+
(0, exports.getLatestBlock)(chain),
|
|
200
|
+
lowBlock ? lowBlock : fetchBlockFromProvider(low, chain),
|
|
201
|
+
]);
|
|
276
202
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
203
|
+
lowBlock = firstBlock;
|
|
204
|
+
if (!highBlock)
|
|
205
|
+
highBlock = lastBlock;
|
|
206
|
+
if (Math.abs(highBlock.timestamp - timestamp) < 60 * 30) {
|
|
207
|
+
// Short-circuit in case we are trying to get the current block
|
|
208
|
+
return {
|
|
209
|
+
block: highBlock.number,
|
|
210
|
+
number: highBlock.number,
|
|
211
|
+
timestamp: highBlock.timestamp
|
|
212
|
+
};
|
|
280
213
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
214
|
+
updateBlock();
|
|
215
|
+
while (imprecision > allowedTimeRange && blockImprecision > acceptableBlockImprecision) { // We lose some precision (max ~15 minutes) but reduce #calls needed
|
|
216
|
+
++i;
|
|
217
|
+
const blockDiff = highBlock.number - lowBlock.number;
|
|
218
|
+
const timeDiff = highBlock.timestamp - lowBlock.timestamp;
|
|
219
|
+
const avgBlockTime = timeDiff / blockDiff;
|
|
220
|
+
let closeBlock = Math.floor(lowBlock.number + (timestamp - lowBlock.timestamp) / avgBlockTime);
|
|
221
|
+
if (closeBlock > highBlock.number)
|
|
222
|
+
closeBlock = highBlock.number;
|
|
223
|
+
const midBlock = Math.floor((lowBlock.number + highBlock.number) / 2);
|
|
224
|
+
const blocks = await Promise.all([
|
|
225
|
+
fetchBlockFromProvider(closeBlock, chain),
|
|
226
|
+
fetchBlockFromProvider(midBlock, chain),
|
|
227
|
+
]);
|
|
228
|
+
updateBlock(blocks);
|
|
285
229
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
230
|
+
(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)`);
|
|
231
|
+
if (chain !== "bsc" && // this check is there because bsc halted the chain for few days
|
|
232
|
+
Math.abs(block.timestamp - timestamp) > 3600) {
|
|
233
|
+
throw new Error("Block selected is more than 1 hour away from the requested timestamp");
|
|
290
234
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
case 8:
|
|
333
|
-
_g.trys.push([8, 17, , 18]);
|
|
334
|
-
firstBlock = void 0, lastBlock = void 0;
|
|
335
|
-
if (!['evmos'].includes(chain)) return [3 /*break*/, 11];
|
|
336
|
-
return [4 /*yield*/, (0, exports.getLatestBlock)(chain)];
|
|
337
|
-
case 9:
|
|
338
|
-
lastBlock = _g.sent();
|
|
339
|
-
firstBlockNum = lastBlock.number;
|
|
340
|
-
switch (chain) {
|
|
341
|
-
default: firstBlockNum -= 2 * 1e5; // evmos hold only the last 200k block data
|
|
342
|
-
}
|
|
343
|
-
return [4 /*yield*/, fetchBlockFromProvider(firstBlockNum, chain)];
|
|
344
|
-
case 10:
|
|
345
|
-
firstBlock = _g.sent();
|
|
346
|
-
return [3 /*break*/, 13];
|
|
347
|
-
case 11: return [4 /*yield*/, Promise.all([
|
|
348
|
-
(0, exports.getLatestBlock)(chain),
|
|
349
|
-
lowBlock ? lowBlock : fetchBlockFromProvider(low, chain),
|
|
350
|
-
])];
|
|
351
|
-
case 12:
|
|
352
|
-
_f = _g.sent(), lastBlock = _f[0], firstBlock = _f[1];
|
|
353
|
-
_g.label = 13;
|
|
354
|
-
case 13:
|
|
355
|
-
lowBlock = firstBlock;
|
|
356
|
-
if (!highBlock)
|
|
357
|
-
highBlock = lastBlock;
|
|
358
|
-
if (Math.abs(highBlock.timestamp - timestamp) < 60 * 30) {
|
|
359
|
-
// Short-circuit in case we are trying to get the current block
|
|
360
|
-
return [2 /*return*/, {
|
|
361
|
-
block: highBlock.number,
|
|
362
|
-
number: highBlock.number,
|
|
363
|
-
timestamp: highBlock.timestamp
|
|
364
|
-
}];
|
|
365
|
-
}
|
|
366
|
-
updateBlock();
|
|
367
|
-
_g.label = 14;
|
|
368
|
-
case 14:
|
|
369
|
-
if (!(imprecision > allowedTimeRange && blockImprecision > acceptableBlockImprecision)) return [3 /*break*/, 16];
|
|
370
|
-
++i;
|
|
371
|
-
blockDiff = highBlock.number - lowBlock.number;
|
|
372
|
-
timeDiff = highBlock.timestamp - lowBlock.timestamp;
|
|
373
|
-
avgBlockTime = timeDiff / blockDiff;
|
|
374
|
-
closeBlock = Math.floor(lowBlock.number + (timestamp - lowBlock.timestamp) / avgBlockTime);
|
|
375
|
-
if (closeBlock > highBlock.number)
|
|
376
|
-
closeBlock = highBlock.number;
|
|
377
|
-
midBlock = Math.floor((lowBlock.number + highBlock.number) / 2);
|
|
378
|
-
return [4 /*yield*/, Promise.all([
|
|
379
|
-
fetchBlockFromProvider(closeBlock, chain),
|
|
380
|
-
fetchBlockFromProvider(midBlock, chain),
|
|
381
|
-
])];
|
|
382
|
-
case 15:
|
|
383
|
-
blocks = _g.sent();
|
|
384
|
-
updateBlock(blocks);
|
|
385
|
-
return [3 /*break*/, 14];
|
|
386
|
-
case 16:
|
|
387
|
-
(0, debugLog_1.debugLog)("chain: ".concat(chain, " block: ").concat(block.number, " #calls: ").concat(i, " imprecision: ").concat(Number((imprecision) / 60).toFixed(2), " (min) Time Taken: ").concat(Number((Date.now() - time) / 1000).toFixed(2), " (in sec)"));
|
|
388
|
-
if (chain !== "bsc" && // this check is there because bsc halted the chain for few days
|
|
389
|
-
Math.abs(block.timestamp - timestamp) > 3600) {
|
|
390
|
-
throw new Error("Block selected is more than 1 hour away from the requested timestamp");
|
|
391
|
-
}
|
|
392
|
-
return [2 /*return*/, {
|
|
393
|
-
number: block.number,
|
|
394
|
-
block: block.number,
|
|
395
|
-
timestamp: block.timestamp
|
|
396
|
-
}];
|
|
397
|
-
case 17:
|
|
398
|
-
e_4 = _g.sent();
|
|
399
|
-
throw (0, generalUtil_1.formError)(e_4);
|
|
400
|
-
case 18: return [2 /*return*/];
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
|
-
});
|
|
235
|
+
return {
|
|
236
|
+
number: block.number,
|
|
237
|
+
block: block.number,
|
|
238
|
+
timestamp: block.timestamp
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
catch (e) {
|
|
242
|
+
throw (0, generalUtil_1.formError)(e);
|
|
243
|
+
}
|
|
244
|
+
function updateBlock(blocks = []) {
|
|
245
|
+
blocks.forEach(addBlockToCache);
|
|
246
|
+
const getPrecision = (block) => block.timestamp - timestamp > 0 ? block.timestamp - timestamp : timestamp - block.timestamp;
|
|
247
|
+
blocks.push(highBlock, lowBlock);
|
|
248
|
+
blocks.sort((a, b) => getPrecision(a) - getPrecision(b));
|
|
249
|
+
block = blocks[0];
|
|
250
|
+
// find the closest upper and lower bound between 4 points
|
|
251
|
+
lowBlock = blocks.filter(i => i.timestamp < timestamp).reduce((lowestBlock, block) => (timestamp - lowestBlock.timestamp) < (timestamp - block.timestamp) ? lowestBlock : block);
|
|
252
|
+
highBlock = blocks.filter(i => i.timestamp > timestamp).reduce((highestBlock, block) => (highestBlock.timestamp - timestamp) < (block.timestamp - timestamp) ? highestBlock : block);
|
|
253
|
+
imprecision = getPrecision(block);
|
|
254
|
+
blockImprecision = highBlock.number - lowBlock.number;
|
|
255
|
+
// debugLog(`chain: ${chain} block: ${block.number} #calls: ${i} imprecision: ${Number((imprecision)/60).toFixed(2)} (min) block diff: ${blockImprecision} Time Taken: ${Number((Date.now()-time)/1000).toFixed(2)} (in sec)`)
|
|
256
|
+
}
|
|
257
|
+
function getChainBlockTimeCache(chain) {
|
|
258
|
+
if (!blockTimeCache[chain])
|
|
259
|
+
blockTimeCache[chain] = {};
|
|
260
|
+
return blockTimeCache[chain];
|
|
261
|
+
}
|
|
262
|
+
function addBlockToCache(block) {
|
|
263
|
+
const { number, timestamp } = block;
|
|
264
|
+
getChainBlockTimeCache(chain)[block.number] = { number, timestamp, };
|
|
265
|
+
}
|
|
266
|
+
function getLowBlock() {
|
|
267
|
+
return Object.values(getChainBlockTimeCache(chain))
|
|
268
|
+
.filter(i => i.timestamp < timestamp)
|
|
269
|
+
.sort((a, b) => b.timestamp - a.timestamp)[0];
|
|
270
|
+
}
|
|
271
|
+
function getHighBlock() {
|
|
272
|
+
return Object.values(getChainBlockTimeCache(chain))
|
|
273
|
+
.filter(i => i.timestamp > timestamp)
|
|
274
|
+
.sort((a, b) => a.timestamp - b.timestamp)[0];
|
|
275
|
+
}
|
|
404
276
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
return __generator(this, function (_a) {
|
|
410
|
-
switch (_a.label) {
|
|
411
|
-
case 0:
|
|
412
|
-
provider = getExtraProvider(chain);
|
|
413
|
-
return [4 /*yield*/, provider.getBlock(height)];
|
|
414
|
-
case 1:
|
|
415
|
-
block = _a.sent();
|
|
416
|
-
return [2 /*return*/, block.timestamp];
|
|
417
|
-
}
|
|
418
|
-
});
|
|
419
|
-
});
|
|
277
|
+
async function getTimestamp(height, chain) {
|
|
278
|
+
const provider = getExtraProvider(chain);
|
|
279
|
+
const block = await provider.getBlock(height);
|
|
280
|
+
return block.timestamp;
|
|
420
281
|
}
|
|
421
282
|
exports.getTimestamp = getTimestamp;
|
|
422
|
-
|
|
283
|
+
const currentChainBlockCache = (0, cache_1.getTempLocalCache)({ file: 'currentChainBlockCache.json', defaultData: {} });
|