@defillama/sdk 5.0.9 → 5.0.11

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.
@@ -1,166 +1,69 @@
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
6
  exports.getTimestamp = exports.lookupBlock = exports.getLatestBlock = exports.getCurrentChainBlock = exports.getBlock = exports.getCurrentBlocks = exports.getBlocks = exports.getChainBlocks = exports.chainsForBlocks = void 0;
43
- var general_1 = require("../general");
44
- var node_fetch_1 = __importDefault(require("node-fetch"));
45
- var generalUtil_1 = require("../generalUtil");
46
- var debugLog_1 = require("./debugLog");
47
- var cosmos_1 = require("./cosmos");
48
- var cache_1 = require("./cache");
49
- var blockscout_1 = require("./blockscout");
50
- var defaultChains = ["avax", "bsc", "polygon", "arbitrum"];
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 defaultChains = ["avax", "bsc", "polygon", "arbitrum"];
51
15
  exports.chainsForBlocks = defaultChains;
52
- var blockRetries = 3;
53
- function getChainBlocks(timestamp, chains) {
54
- if (chains === void 0) { chains = defaultChains; }
55
- return __awaiter(this, void 0, void 0, function () {
56
- var chainBlocks, setBlock;
57
- var _this = this;
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
- });
16
+ const blockRetries = 3;
17
+ async function getChainBlocks(timestamp, chains = defaultChains) {
18
+ const chainBlocks = {};
19
+ const setBlock = async (chain) => chainBlocks[chain] = (await getBlock(chain, timestamp)).block;
20
+ await Promise.all(chains.map(setBlock));
21
+ return chainBlocks;
78
22
  }
79
23
  exports.getChainBlocks = getChainBlocks;
80
- function getBlocks(timestamp, chains) {
81
- if (chains === void 0) { chains = undefined; }
82
- return __awaiter(this, void 0, void 0, function () {
83
- var _a, ethBlock, chainBlocks;
84
- return __generator(this, function (_b) {
85
- switch (_b.label) {
86
- case 0:
87
- chains = chains === null || chains === void 0 ? void 0 : chains.filter(function (i) { return i !== 'ethereum'; });
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
- });
24
+ async function getBlocks(timestamp, chains = undefined) {
25
+ chains = chains === null || chains === void 0 ? void 0 : chains.filter(i => i !== 'ethereum');
26
+ const [ethBlock, chainBlocks] = await Promise.all([getBlock('ethereum', timestamp), getChainBlocks(timestamp, chains)]);
27
+ chainBlocks['ethereum'] = ethBlock.block;
28
+ return {
29
+ ethereumBlock: ethBlock.block,
30
+ chainBlocks,
31
+ };
99
32
  }
100
33
  exports.getBlocks = getBlocks;
101
- function getCurrentBlocks(chains) {
102
- if (chains === void 0) { chains = undefined; }
103
- return __awaiter(this, void 0, void 0, function () {
104
- var block, chainBlocks;
105
- return __generator(this, function (_a) {
106
- switch (_a.label) {
107
- case 0:
108
- if (chains)
109
- chains = chains.filter(function (i) { return i !== "ethereum"; });
110
- return [4 /*yield*/, getBlock('ethereum')];
111
- case 1:
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
- });
34
+ async function getCurrentBlocks(chains = undefined) {
35
+ if (chains)
36
+ chains = chains.filter(i => i !== "ethereum");
37
+ const block = await getBlock('ethereum');
38
+ const chainBlocks = await getChainBlocks(undefined, chains);
39
+ chainBlocks['ethereum'] = block.block;
40
+ return {
41
+ timestamp: block.timestamp,
42
+ ethereumBlock: block.block,
43
+ chainBlocks,
44
+ };
125
45
  }
126
46
  exports.getCurrentBlocks = getCurrentBlocks;
127
- function getBlock(chain, timestamp) {
128
- return __awaiter(this, void 0, void 0, function () {
129
- var error, i, res, e_1;
130
- return __generator(this, function (_a) {
131
- switch (_a.label) {
132
- case 0:
133
- if (!timestamp)
134
- return [2 /*return*/, getCurrentChainBlock(chain)];
135
- i = 0;
136
- _a.label = 1;
137
- case 1:
138
- if (!(i < blockRetries)) return [3 /*break*/, 6];
139
- _a.label = 2;
140
- case 2:
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
- });
47
+ async function getBlock(chain, timestamp) {
48
+ if (!timestamp)
49
+ return getCurrentChainBlock(chain);
50
+ let error;
51
+ for (let i = 0; i < blockRetries; i++) {
52
+ try {
53
+ let res = await lookupBlock(timestamp, { chain, });
54
+ return res;
55
+ }
56
+ catch (e) {
57
+ error = e;
58
+ }
59
+ }
60
+ throw error;
157
61
  }
158
62
  exports.getBlock = getBlock;
159
- var refreshInterval = 1000 * 60 * 5; // 5 minutes
160
- function getCurrentChainBlock(chain) {
161
- if (chain === void 0) { chain = 'ethereum'; }
162
- var timestamp = (currentChainBlockCache[chain] || {}).timestamp;
163
- var currentTimestamp = Date.now();
63
+ const refreshInterval = 1000 * 60 * 5; // 5 minutes
64
+ function getCurrentChainBlock(chain = 'ethereum') {
65
+ const { timestamp, } = currentChainBlockCache[chain] || {};
66
+ const currentTimestamp = Date.now();
164
67
  if (!timestamp || currentTimestamp - timestamp > refreshInterval) {
165
68
  currentChainBlockCache[chain] = {
166
69
  timestamp: currentTimestamp,
@@ -168,68 +71,46 @@ function getCurrentChainBlock(chain) {
168
71
  };
169
72
  }
170
73
  return currentChainBlockCache[chain].promise;
171
- function _getCurrentChainBlock() {
74
+ async function _getCurrentChainBlock() {
172
75
  var _a, _b;
173
- return __awaiter(this, void 0, void 0, function () {
174
- var provider, _c, number, timestamp_1, response, e_2;
175
- return __generator(this, function (_d) {
176
- switch (_d.label) {
177
- case 0:
178
- _d.trys.push([0, 2, , 3]);
179
- provider = getExtraProvider(chain);
180
- return [4 /*yield*/, provider.getBlock('latest')];
181
- case 1:
182
- _c = _d.sent(), number = _c.number, timestamp_1 = _c.timestamp;
183
- response = { block: number, timestamp: timestamp_1, number: number };
184
- validateCurrentBlock(response, chain);
185
- currentChainBlockCache[chain] = { timestamp: currentTimestamp, promise: response };
186
- return [2 /*return*/, response]; // we are interested only in these fields
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
- });
76
+ try {
77
+ const provider = getExtraProvider(chain);
78
+ const { number, timestamp, } = await provider.getBlock('latest');
79
+ const response = { block: number, timestamp, number };
80
+ validateCurrentBlock(response, chain);
81
+ currentChainBlockCache[chain] = { timestamp: currentTimestamp, promise: response };
82
+ return response; // we are interested only in these fields
83
+ }
84
+ catch (e) {
85
+ delete currentChainBlockCache[chain];
86
+ 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"))
87
+ throw e;
88
+ throw (0, generalUtil_1.formError)(e);
89
+ }
197
90
  }
198
91
  }
199
92
  exports.getCurrentChainBlock = getCurrentChainBlock;
200
- var algorandBlockProvider = {
201
- getBlock: function (height) { return __awaiter(void 0, void 0, void 0, function () {
202
- return __generator(this, function (_a) {
203
- if (height !== 'latest')
204
- return [2 /*return*/, (0, node_fetch_1.default)("https://algoindexer.algoexplorerapi.io/v2/blocks/".concat(height))
205
- .then(function (res) { return res.json(); })
206
- .then(function (block) { return ({
207
- number: block.round,
208
- timestamp: block.timestamp
209
- }); })];
210
- return [2 /*return*/, (0, node_fetch_1.default)('https://algoindexer.algoexplorerapi.io/health')
211
- .then(function (res) { return res.json(); })
212
- .then(function (block) { return algorandBlockProvider.getBlock(block.round); })];
213
- });
214
- }); }
93
+ const algorandBlockProvider = {
94
+ getBlock: async (height) => {
95
+ if (height !== 'latest')
96
+ return (0, axios_1.default)(`https://algoindexer.algoexplorerapi.io/v2/blocks/${height}`)
97
+ .then((res) => res.data)
98
+ .then((block) => ({
99
+ number: block.round,
100
+ timestamp: block.timestamp
101
+ }));
102
+ return (0, axios_1.default)('https://algoindexer.algoexplorerapi.io/health')
103
+ .then((res) => res.data)
104
+ .then((block) => algorandBlockProvider.getBlock(block.round));
105
+ }
215
106
  };
216
- function fetchBlockFromProvider(height, chain) {
217
- return __awaiter(this, void 0, void 0, function () {
218
- var provider, block;
219
- return __generator(this, function (_a) {
220
- switch (_a.label) {
221
- case 0:
222
- provider = getExtraProvider(chain !== null && chain !== void 0 ? chain : "ethereum");
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
- });
107
+ async function fetchBlockFromProvider(height, chain) {
108
+ const provider = getExtraProvider(chain !== null && chain !== void 0 ? chain : "ethereum");
109
+ const block = await provider.getBlock(height);
110
+ if (block === null) {
111
+ throw new Error(`Can't get block of chain ${chain !== null && chain !== void 0 ? chain : "ethereum"}`);
112
+ }
113
+ return block;
233
114
  }
234
115
  function getExtraProvider(chain) {
235
116
  if (chain && (0, cosmos_1.isCosmosChain)(chain))
@@ -239,184 +120,144 @@ function getExtraProvider(chain) {
239
120
  return (0, general_1.getProvider)(chain);
240
121
  }
241
122
  exports.getLatestBlock = getCurrentChainBlock;
242
- var intialBlocks = {
123
+ const intialBlocks = {
243
124
  terra: 4724001,
244
125
  crab: 4969901
245
126
  };
246
- var blockTimeCache = (0, cache_1.getTempLocalCache)({ file: 'BlockCache.json', defaultData: {} });
247
- function validateCurrentBlock(block, chain) {
248
- if (chain === void 0) { chain = 'ethereum'; }
249
- var provider = getExtraProvider(chain);
250
- var now = Math.floor(Date.now() / 1000);
251
- var minutesDiff = Math.floor((now - block.timestamp) / 60);
127
+ const blockTimeCache = (0, cache_1.getTempLocalCache)({ file: 'BlockCache.json', defaultData: {} });
128
+ function validateCurrentBlock(block, chain = 'ethereum') {
129
+ const provider = getExtraProvider(chain);
130
+ const now = Math.floor(Date.now() / 1000);
131
+ const minutesDiff = Math.floor((now - block.timestamp) / 60);
252
132
  if (minutesDiff > 60)
253
- throw new Error("Last block for ".concat(chain, " is ").concat(minutesDiff, " minutes behind (").concat(new Date(block.timestamp * 1000), "). Provider is \"").concat((0, generalUtil_1.getProviderUrl)(provider), "\""));
133
+ throw new Error(`Last block for ${chain} is ${minutesDiff} minutes behind (${new Date(block.timestamp * 1000)}). Provider is "${(0, generalUtil_1.getProviderUrl)(provider)}"`);
254
134
  }
255
- function lookupBlock(timestamp, extraParams) {
135
+ async function lookupBlock(timestamp, extraParams) {
256
136
  var _a, _b;
257
- return __awaiter(this, void 0, void 0, function () {
258
- function updateBlock(blocks) {
259
- if (blocks === void 0) { blocks = []; }
260
- blocks.forEach(addBlockToCache);
261
- var getPrecision = function (block) { return block.timestamp - timestamp > 0 ? block.timestamp - timestamp : timestamp - block.timestamp; };
262
- blocks.push(highBlock, lowBlock);
263
- blocks.sort(function (a, b) { return getPrecision(a) - getPrecision(b); });
264
- block = blocks[0];
265
- // find the closest upper and lower bound between 4 points
266
- lowBlock = blocks.filter(function (i) { return i.timestamp < timestamp; }).reduce(function (lowestBlock, block) { return (timestamp - lowestBlock.timestamp) < (timestamp - block.timestamp) ? lowestBlock : block; });
267
- highBlock = blocks.filter(function (i) { return i.timestamp > timestamp; }).reduce(function (highestBlock, block) { return (highestBlock.timestamp - timestamp) < (block.timestamp - timestamp) ? highestBlock : block; });
268
- imprecision = getPrecision(block);
269
- blockImprecision = highBlock.number - lowBlock.number;
270
- // 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)`)
137
+ const { allowedTimeRange = 5 * 60, acceptableBlockImprecision = 10 } = extraParams !== null && extraParams !== void 0 ? extraParams : {};
138
+ const chain = (_a = extraParams === null || extraParams === void 0 ? void 0 : extraParams.chain) !== null && _a !== void 0 ? _a : "ethereum";
139
+ if (blockscout_1.blockscoutEndpoints[chain]) {
140
+ try {
141
+ const block = await (0, blockscout_1.getBlockscoutBlock)(timestamp, chain);
142
+ addBlockToCache(block);
143
+ return block;
271
144
  }
272
- function getChainBlockTimeCache(chain) {
273
- if (!blockTimeCache[chain])
274
- blockTimeCache[chain] = {};
275
- return blockTimeCache[chain];
145
+ catch (e) { // fallback to usual way of fetching logs
146
+ (0, debugLog_1.debugLog)('error fetching block from blockscout', e, chain);
276
147
  }
277
- function addBlockToCache(block) {
278
- var number = block.number, timestamp = block.timestamp;
279
- getChainBlockTimeCache(chain)[block.number] = { number: number, timestamp: timestamp, };
148
+ }
149
+ if (chain === 'waves') {
150
+ const api = `https://nodes.wavesnodes.com/blocks/heightByTimestamp/${timestamp}`;
151
+ const { data } = await (0, axios_1.default)(api);
152
+ return {
153
+ timestamp,
154
+ block: +data.height,
155
+ number: +data.height,
156
+ };
157
+ }
158
+ let low = (_b = intialBlocks[chain]) !== null && _b !== void 0 ? _b : 100;
159
+ let lowBlock = getLowBlock();
160
+ let highBlock = getHighBlock();
161
+ let block;
162
+ let i = 0;
163
+ let time = Date.now();
164
+ let blockImprecision;
165
+ let imprecision;
166
+ try {
167
+ let firstBlock, lastBlock;
168
+ if (['evmos'].includes(chain)) {
169
+ lastBlock = await (0, exports.getLatestBlock)(chain);
170
+ let firstBlockNum = lastBlock.number;
171
+ switch (chain) {
172
+ default: firstBlockNum -= 2 * 1e5; // evmos hold only the last 200k block data
173
+ }
174
+ firstBlock = await fetchBlockFromProvider(firstBlockNum, chain);
280
175
  }
281
- function getLowBlock() {
282
- return Object.values(getChainBlockTimeCache(chain))
283
- .filter(function (i) { return i.timestamp < timestamp; })
284
- .sort(function (a, b) { return b.timestamp - a.timestamp; })[0];
176
+ else {
177
+ [lastBlock, firstBlock] = await Promise.all([
178
+ (0, exports.getLatestBlock)(chain),
179
+ lowBlock ? lowBlock : fetchBlockFromProvider(low, chain),
180
+ ]);
285
181
  }
286
- function getHighBlock() {
287
- return Object.values(getChainBlockTimeCache(chain))
288
- .filter(function (i) { return i.timestamp > timestamp; })
289
- .sort(function (a, b) { return a.timestamp - b.timestamp; })[0];
182
+ lowBlock = firstBlock;
183
+ if (!highBlock)
184
+ highBlock = lastBlock;
185
+ if (Math.abs(highBlock.timestamp - timestamp) < 60 * 30) {
186
+ // Short-circuit in case we are trying to get the current block
187
+ return {
188
+ block: highBlock.number,
189
+ number: highBlock.number,
190
+ timestamp: highBlock.timestamp
191
+ };
290
192
  }
291
- var _c, _d, allowedTimeRange, _e, acceptableBlockImprecision, chain, block_1, e_3, api, res, data, low, lowBlock, highBlock, block, i, time, blockImprecision, imprecision, firstBlock, lastBlock, firstBlockNum, blockDiff, timeDiff, avgBlockTime, closeBlock, midBlock, blocks, e_4;
292
- var _f;
293
- return __generator(this, function (_g) {
294
- switch (_g.label) {
295
- case 0:
296
- _c = extraParams !== null && extraParams !== void 0 ? extraParams : {}, _d = _c.allowedTimeRange, allowedTimeRange = _d === void 0 ? 5 * 60 : _d, _e = _c.acceptableBlockImprecision, acceptableBlockImprecision = _e === void 0 ? 10 : _e;
297
- chain = (_a = extraParams === null || extraParams === void 0 ? void 0 : extraParams.chain) !== null && _a !== void 0 ? _a : "ethereum";
298
- if (!blockscout_1.blockscoutEndpoints[chain]) return [3 /*break*/, 4];
299
- _g.label = 1;
300
- case 1:
301
- _g.trys.push([1, 3, , 4]);
302
- return [4 /*yield*/, (0, blockscout_1.getBlockscoutBlock)(timestamp, chain)];
303
- case 2:
304
- block_1 = _g.sent();
305
- addBlockToCache(block_1);
306
- return [2 /*return*/, block_1];
307
- case 3:
308
- e_3 = _g.sent();
309
- (0, debugLog_1.debugLog)('error fetching block from blockscout', e_3, chain);
310
- return [3 /*break*/, 4];
311
- case 4:
312
- if (!(chain === 'waves')) return [3 /*break*/, 7];
313
- api = "https://nodes.wavesnodes.com/blocks/heightByTimestamp/".concat(timestamp);
314
- return [4 /*yield*/, (0, node_fetch_1.default)(api)];
315
- case 5:
316
- res = _g.sent();
317
- return [4 /*yield*/, res.json()];
318
- case 6:
319
- data = _g.sent();
320
- return [2 /*return*/, {
321
- timestamp: timestamp,
322
- block: +data.height,
323
- number: +data.height,
324
- }];
325
- case 7:
326
- low = (_b = intialBlocks[chain]) !== null && _b !== void 0 ? _b : 100;
327
- lowBlock = getLowBlock();
328
- highBlock = getHighBlock();
329
- i = 0;
330
- time = Date.now();
331
- _g.label = 8;
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
- });
193
+ updateBlock();
194
+ while (imprecision > allowedTimeRange && blockImprecision > acceptableBlockImprecision) { // We lose some precision (max ~15 minutes) but reduce #calls needed
195
+ ++i;
196
+ const blockDiff = highBlock.number - lowBlock.number;
197
+ const timeDiff = highBlock.timestamp - lowBlock.timestamp;
198
+ const avgBlockTime = timeDiff / blockDiff;
199
+ let closeBlock = Math.floor(lowBlock.number + (timestamp - lowBlock.timestamp) / avgBlockTime);
200
+ if (closeBlock > highBlock.number)
201
+ closeBlock = highBlock.number;
202
+ const midBlock = Math.floor((lowBlock.number + highBlock.number) / 2);
203
+ const blocks = await Promise.all([
204
+ fetchBlockFromProvider(closeBlock, chain),
205
+ fetchBlockFromProvider(midBlock, chain),
206
+ ]);
207
+ updateBlock(blocks);
208
+ }
209
+ (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)`);
210
+ if (chain !== "bsc" && // this check is there because bsc halted the chain for few days
211
+ Math.abs(block.timestamp - timestamp) > 3600) {
212
+ throw new Error("Block selected is more than 1 hour away from the requested timestamp");
213
+ }
214
+ return {
215
+ number: block.number,
216
+ block: block.number,
217
+ timestamp: block.timestamp
218
+ };
219
+ }
220
+ catch (e) {
221
+ throw (0, generalUtil_1.formError)(e);
222
+ }
223
+ function updateBlock(blocks = []) {
224
+ blocks.forEach(addBlockToCache);
225
+ const getPrecision = (block) => block.timestamp - timestamp > 0 ? block.timestamp - timestamp : timestamp - block.timestamp;
226
+ blocks.push(highBlock, lowBlock);
227
+ blocks.sort((a, b) => getPrecision(a) - getPrecision(b));
228
+ block = blocks[0];
229
+ // find the closest upper and lower bound between 4 points
230
+ lowBlock = blocks.filter(i => i.timestamp < timestamp).reduce((lowestBlock, block) => (timestamp - lowestBlock.timestamp) < (timestamp - block.timestamp) ? lowestBlock : block);
231
+ highBlock = blocks.filter(i => i.timestamp > timestamp).reduce((highestBlock, block) => (highestBlock.timestamp - timestamp) < (block.timestamp - timestamp) ? highestBlock : block);
232
+ imprecision = getPrecision(block);
233
+ blockImprecision = highBlock.number - lowBlock.number;
234
+ // 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)`)
235
+ }
236
+ function getChainBlockTimeCache(chain) {
237
+ if (!blockTimeCache[chain])
238
+ blockTimeCache[chain] = {};
239
+ return blockTimeCache[chain];
240
+ }
241
+ function addBlockToCache(block) {
242
+ const { number, timestamp } = block;
243
+ getChainBlockTimeCache(chain)[block.number] = { number, timestamp, };
244
+ }
245
+ function getLowBlock() {
246
+ return Object.values(getChainBlockTimeCache(chain))
247
+ .filter(i => i.timestamp < timestamp)
248
+ .sort((a, b) => b.timestamp - a.timestamp)[0];
249
+ }
250
+ function getHighBlock() {
251
+ return Object.values(getChainBlockTimeCache(chain))
252
+ .filter(i => i.timestamp > timestamp)
253
+ .sort((a, b) => a.timestamp - b.timestamp)[0];
254
+ }
404
255
  }
405
256
  exports.lookupBlock = lookupBlock;
406
- function getTimestamp(height, chain) {
407
- return __awaiter(this, void 0, void 0, function () {
408
- var provider, block;
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
- });
257
+ async function getTimestamp(height, chain) {
258
+ const provider = getExtraProvider(chain);
259
+ const block = await provider.getBlock(height);
260
+ return block.timestamp;
420
261
  }
421
262
  exports.getTimestamp = getTimestamp;
422
- var currentChainBlockCache = (0, cache_1.getTempLocalCache)({ file: 'currentChainBlockCache.json', defaultData: {} });
263
+ const currentChainBlockCache = (0, cache_1.getTempLocalCache)({ file: 'currentChainBlockCache.json', defaultData: {} });