@defillama/sdk 4.0.77 → 4.0.78
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/computeTVL/blocks.d.ts +1 -19
- package/build/computeTVL/blocks.js +7 -187
- package/build/generalUtil.js +16 -6
- package/build/providers.json +1 -1
- package/build/util/blocks.d.ts +33 -0
- package/build/util/blocks.js +423 -0
- package/build/util/blockscout.d.ts +6 -0
- package/build/util/blockscout.js +71 -0
- package/build/util/cache.d.ts +5 -0
- package/build/util/cache.js +50 -2
- package/build/util/cosmos.d.ts +11 -0
- package/build/util/cosmos.js +124 -0
- package/build/util/index.d.ts +1 -13
- package/build/util/index.js +22 -281
- package/package.json +1 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Chain } from "../general";
|
|
2
|
+
export declare const chainsForBlocks: string[];
|
|
3
|
+
export declare function getChainBlocks(timestamp: number | undefined, chains?: Chain[]): Promise<{
|
|
4
|
+
[chain: string]: number;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function getBlocks(timestamp: number, chains?: Chain[] | undefined): Promise<{
|
|
7
|
+
ethereumBlock: number;
|
|
8
|
+
chainBlocks: {
|
|
9
|
+
[chain: string]: number;
|
|
10
|
+
};
|
|
11
|
+
}>;
|
|
12
|
+
export declare function getCurrentBlocks(chains?: Chain[] | undefined): Promise<{
|
|
13
|
+
timestamp: number;
|
|
14
|
+
ethereumBlock: number;
|
|
15
|
+
chainBlocks: {
|
|
16
|
+
[chain: string]: number;
|
|
17
|
+
};
|
|
18
|
+
}>;
|
|
19
|
+
export declare function getBlock(chain: Chain, timestamp?: number): Promise<Block>;
|
|
20
|
+
export declare function getCurrentChainBlock(chain?: Chain): Promise<Block>;
|
|
21
|
+
export declare const getLatestBlock: typeof getCurrentChainBlock;
|
|
22
|
+
export declare function lookupBlock(timestamp: number, extraParams?: {
|
|
23
|
+
chain?: Chain | "kava" | "algorand";
|
|
24
|
+
allowedTimeRange?: number;
|
|
25
|
+
acceptableBlockImprecision?: number;
|
|
26
|
+
}): Promise<Block>;
|
|
27
|
+
export declare function getTimestamp(height: number, chain: Chain): Promise<number>;
|
|
28
|
+
export type Block = {
|
|
29
|
+
timestamp: number;
|
|
30
|
+
block: number;
|
|
31
|
+
hash?: string;
|
|
32
|
+
number: number;
|
|
33
|
+
};
|
|
@@ -0,0 +1,423 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
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
|
+
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"];
|
|
51
|
+
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
|
+
});
|
|
78
|
+
}
|
|
79
|
+
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
|
+
});
|
|
99
|
+
}
|
|
100
|
+
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
|
+
});
|
|
125
|
+
}
|
|
126
|
+
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
|
+
});
|
|
157
|
+
}
|
|
158
|
+
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();
|
|
164
|
+
if (!timestamp || currentTimestamp - timestamp > refreshInterval) {
|
|
165
|
+
currentChainBlockCache[chain] = {
|
|
166
|
+
timestamp: currentTimestamp,
|
|
167
|
+
promise: _getCurrentChainBlock()
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
return currentChainBlockCache[chain].promise;
|
|
171
|
+
function _getCurrentChainBlock() {
|
|
172
|
+
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
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
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
|
+
}); }
|
|
215
|
+
};
|
|
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
|
+
});
|
|
233
|
+
}
|
|
234
|
+
function getExtraProvider(chain) {
|
|
235
|
+
if (chain && (0, cosmos_1.isCosmosChain)(chain))
|
|
236
|
+
return (0, cosmos_1.getCosmosProvider)(chain);
|
|
237
|
+
if (chain === "algorand")
|
|
238
|
+
return algorandBlockProvider;
|
|
239
|
+
return (0, general_1.getProvider)(chain);
|
|
240
|
+
}
|
|
241
|
+
exports.getLatestBlock = getCurrentChainBlock;
|
|
242
|
+
var intialBlocks = {
|
|
243
|
+
terra: 4724001,
|
|
244
|
+
crab: 4969901
|
|
245
|
+
};
|
|
246
|
+
var blockTimeCache = (0, cache_1.getTempLocalCache)({ file: 'BlockCache.json', defaultData: {} });
|
|
247
|
+
function validateCurrentBlock(block, chain) {
|
|
248
|
+
var _a, _b, _c, _d, _e, _f;
|
|
249
|
+
if (chain === void 0) { chain = 'ethereum'; }
|
|
250
|
+
var provider = getExtraProvider(chain);
|
|
251
|
+
var now = Math.floor(Date.now() / 1000);
|
|
252
|
+
var minutesDiff = Math.floor((now - block.timestamp) / 60);
|
|
253
|
+
if (minutesDiff > 60)
|
|
254
|
+
throw new Error("Last block for ".concat(chain, " is ").concat(minutesDiff, " minutes behind (").concat(new Date(block.timestamp * 1000), "). Provider is \"").concat((_b = (_a = provider === null || provider === void 0 ? void 0 : provider.connection) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : (_f = (_e = (_d = ((_c = provider === null || provider === void 0 ? void 0 : provider.providerConfigs) !== null && _c !== void 0 ? _c : [])[0]) === null || _d === void 0 ? void 0 : _d.provider) === null || _e === void 0 ? void 0 : _e.connection) === null || _f === void 0 ? void 0 : _f.url, "\""));
|
|
255
|
+
}
|
|
256
|
+
function lookupBlock(timestamp, extraParams) {
|
|
257
|
+
var _a, _b;
|
|
258
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
259
|
+
function updateBlock(blocks) {
|
|
260
|
+
if (blocks === void 0) { blocks = []; }
|
|
261
|
+
blocks.forEach(addBlockToCache);
|
|
262
|
+
var getPrecision = function (block) { return block.timestamp - timestamp > 0 ? block.timestamp - timestamp : timestamp - block.timestamp; };
|
|
263
|
+
blocks.push(highBlock, lowBlock);
|
|
264
|
+
blocks.sort(function (a, b) { return getPrecision(a) - getPrecision(b); });
|
|
265
|
+
block = blocks[0];
|
|
266
|
+
// find the closest upper and lower bound between 4 points
|
|
267
|
+
lowBlock = blocks.filter(function (i) { return i.timestamp < timestamp; }).reduce(function (lowestBlock, block) { return (timestamp - lowestBlock.timestamp) < (timestamp - block.timestamp) ? lowestBlock : block; });
|
|
268
|
+
highBlock = blocks.filter(function (i) { return i.timestamp > timestamp; }).reduce(function (highestBlock, block) { return (highestBlock.timestamp - timestamp) < (block.timestamp - timestamp) ? highestBlock : block; });
|
|
269
|
+
imprecision = getPrecision(block);
|
|
270
|
+
blockImprecision = highBlock.number - lowBlock.number;
|
|
271
|
+
// 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)`)
|
|
272
|
+
}
|
|
273
|
+
function getChainBlockTimeCache(chain) {
|
|
274
|
+
if (!blockTimeCache[chain])
|
|
275
|
+
blockTimeCache[chain] = {};
|
|
276
|
+
return blockTimeCache[chain];
|
|
277
|
+
}
|
|
278
|
+
function addBlockToCache(block) {
|
|
279
|
+
var number = block.number, timestamp = block.timestamp;
|
|
280
|
+
getChainBlockTimeCache(chain)[block.number] = { number: number, timestamp: timestamp, };
|
|
281
|
+
}
|
|
282
|
+
function getLowBlock() {
|
|
283
|
+
return Object.values(getChainBlockTimeCache(chain))
|
|
284
|
+
.filter(function (i) { return i.timestamp < timestamp; })
|
|
285
|
+
.sort(function (a, b) { return b.timestamp - a.timestamp; })[0];
|
|
286
|
+
}
|
|
287
|
+
function getHighBlock() {
|
|
288
|
+
return Object.values(getChainBlockTimeCache(chain))
|
|
289
|
+
.filter(function (i) { return i.timestamp > timestamp; })
|
|
290
|
+
.sort(function (a, b) { return a.timestamp - b.timestamp; })[0];
|
|
291
|
+
}
|
|
292
|
+
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;
|
|
293
|
+
var _f;
|
|
294
|
+
return __generator(this, function (_g) {
|
|
295
|
+
switch (_g.label) {
|
|
296
|
+
case 0:
|
|
297
|
+
_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;
|
|
298
|
+
chain = (_a = extraParams === null || extraParams === void 0 ? void 0 : extraParams.chain) !== null && _a !== void 0 ? _a : "ethereum";
|
|
299
|
+
if (!blockscout_1.blockscoutEndpoints[chain]) return [3 /*break*/, 4];
|
|
300
|
+
_g.label = 1;
|
|
301
|
+
case 1:
|
|
302
|
+
_g.trys.push([1, 3, , 4]);
|
|
303
|
+
return [4 /*yield*/, (0, blockscout_1.getBlockscoutBlock)(timestamp, chain)];
|
|
304
|
+
case 2:
|
|
305
|
+
block_1 = _g.sent();
|
|
306
|
+
addBlockToCache(block_1);
|
|
307
|
+
return [2 /*return*/, block_1];
|
|
308
|
+
case 3:
|
|
309
|
+
e_3 = _g.sent();
|
|
310
|
+
(0, debugLog_1.debugLog)('error fetching block from blockscout', e_3, chain);
|
|
311
|
+
return [3 /*break*/, 4];
|
|
312
|
+
case 4:
|
|
313
|
+
if (!(chain === 'waves')) return [3 /*break*/, 7];
|
|
314
|
+
api = "https://nodes.wavesnodes.com/blocks/heightByTimestamp/".concat(timestamp);
|
|
315
|
+
return [4 /*yield*/, (0, node_fetch_1.default)(api)];
|
|
316
|
+
case 5:
|
|
317
|
+
res = _g.sent();
|
|
318
|
+
return [4 /*yield*/, res.json()];
|
|
319
|
+
case 6:
|
|
320
|
+
data = _g.sent();
|
|
321
|
+
return [2 /*return*/, {
|
|
322
|
+
timestamp: timestamp,
|
|
323
|
+
block: +data.height,
|
|
324
|
+
number: +data.height,
|
|
325
|
+
}];
|
|
326
|
+
case 7:
|
|
327
|
+
low = (_b = intialBlocks[chain]) !== null && _b !== void 0 ? _b : 100;
|
|
328
|
+
lowBlock = getLowBlock();
|
|
329
|
+
highBlock = getHighBlock();
|
|
330
|
+
i = 0;
|
|
331
|
+
time = Date.now();
|
|
332
|
+
_g.label = 8;
|
|
333
|
+
case 8:
|
|
334
|
+
_g.trys.push([8, 17, , 18]);
|
|
335
|
+
firstBlock = void 0, lastBlock = void 0;
|
|
336
|
+
if (!['evmos'].includes(chain)) return [3 /*break*/, 11];
|
|
337
|
+
return [4 /*yield*/, (0, exports.getLatestBlock)(chain)];
|
|
338
|
+
case 9:
|
|
339
|
+
lastBlock = _g.sent();
|
|
340
|
+
firstBlockNum = lastBlock.number;
|
|
341
|
+
switch (chain) {
|
|
342
|
+
default: firstBlockNum -= 2 * 1e5; // evmos hold only the last 200k block data
|
|
343
|
+
}
|
|
344
|
+
return [4 /*yield*/, fetchBlockFromProvider(firstBlockNum, chain)];
|
|
345
|
+
case 10:
|
|
346
|
+
firstBlock = _g.sent();
|
|
347
|
+
return [3 /*break*/, 13];
|
|
348
|
+
case 11: return [4 /*yield*/, Promise.all([
|
|
349
|
+
(0, exports.getLatestBlock)(chain),
|
|
350
|
+
lowBlock ? lowBlock : fetchBlockFromProvider(low, chain),
|
|
351
|
+
])];
|
|
352
|
+
case 12:
|
|
353
|
+
_f = _g.sent(), lastBlock = _f[0], firstBlock = _f[1];
|
|
354
|
+
_g.label = 13;
|
|
355
|
+
case 13:
|
|
356
|
+
lowBlock = firstBlock;
|
|
357
|
+
if (!highBlock)
|
|
358
|
+
highBlock = lastBlock;
|
|
359
|
+
if (Math.abs(highBlock.timestamp - timestamp) < 60 * 30) {
|
|
360
|
+
// Short-circuit in case we are trying to get the current block
|
|
361
|
+
return [2 /*return*/, {
|
|
362
|
+
block: highBlock.number,
|
|
363
|
+
number: highBlock.number,
|
|
364
|
+
timestamp: highBlock.timestamp
|
|
365
|
+
}];
|
|
366
|
+
}
|
|
367
|
+
updateBlock();
|
|
368
|
+
_g.label = 14;
|
|
369
|
+
case 14:
|
|
370
|
+
if (!(imprecision > allowedTimeRange && blockImprecision > acceptableBlockImprecision)) return [3 /*break*/, 16];
|
|
371
|
+
++i;
|
|
372
|
+
blockDiff = highBlock.number - lowBlock.number;
|
|
373
|
+
timeDiff = highBlock.timestamp - lowBlock.timestamp;
|
|
374
|
+
avgBlockTime = timeDiff / blockDiff;
|
|
375
|
+
closeBlock = Math.floor(lowBlock.number + (timestamp - lowBlock.timestamp) / avgBlockTime);
|
|
376
|
+
if (closeBlock > highBlock.number)
|
|
377
|
+
closeBlock = highBlock.number;
|
|
378
|
+
midBlock = Math.floor((lowBlock.number + highBlock.number) / 2);
|
|
379
|
+
return [4 /*yield*/, Promise.all([
|
|
380
|
+
fetchBlockFromProvider(closeBlock, chain),
|
|
381
|
+
fetchBlockFromProvider(midBlock, chain),
|
|
382
|
+
])];
|
|
383
|
+
case 15:
|
|
384
|
+
blocks = _g.sent();
|
|
385
|
+
updateBlock(blocks);
|
|
386
|
+
return [3 /*break*/, 14];
|
|
387
|
+
case 16:
|
|
388
|
+
(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)"));
|
|
389
|
+
if (chain !== "bsc" && // this check is there because bsc halted the chain for few days
|
|
390
|
+
Math.abs(block.timestamp - timestamp) > 3600) {
|
|
391
|
+
throw new Error("Block selected is more than 1 hour away from the requested timestamp");
|
|
392
|
+
}
|
|
393
|
+
return [2 /*return*/, {
|
|
394
|
+
number: block.number,
|
|
395
|
+
block: block.number,
|
|
396
|
+
timestamp: block.timestamp
|
|
397
|
+
}];
|
|
398
|
+
case 17:
|
|
399
|
+
e_4 = _g.sent();
|
|
400
|
+
throw (0, generalUtil_1.formError)(e_4);
|
|
401
|
+
case 18: return [2 /*return*/];
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
exports.lookupBlock = lookupBlock;
|
|
407
|
+
function getTimestamp(height, chain) {
|
|
408
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
409
|
+
var provider, block;
|
|
410
|
+
return __generator(this, function (_a) {
|
|
411
|
+
switch (_a.label) {
|
|
412
|
+
case 0:
|
|
413
|
+
provider = getExtraProvider(chain);
|
|
414
|
+
return [4 /*yield*/, provider.getBlock(height)];
|
|
415
|
+
case 1:
|
|
416
|
+
block = _a.sent();
|
|
417
|
+
return [2 /*return*/, block.timestamp];
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
exports.getTimestamp = getTimestamp;
|
|
423
|
+
var currentChainBlockCache = (0, cache_1.getTempLocalCache)({ file: 'currentChainBlockCache.json', defaultData: {} });
|
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.getBlockscoutBlock = exports.blockscoutEndpoints = void 0;
|
|
40
|
+
exports.blockscoutEndpoints = {
|
|
41
|
+
celo: 'https://explorer.celo.org',
|
|
42
|
+
kava: 'https://explorer.kava.io',
|
|
43
|
+
onus: 'https://explorer.onuschain.io',
|
|
44
|
+
base: 'https://base.blockscout.com',
|
|
45
|
+
scroll: 'https://blockscout.scroll.io',
|
|
46
|
+
};
|
|
47
|
+
function getBlockscoutBlock(timestamp, chain) {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
49
|
+
var api, res, data;
|
|
50
|
+
return __generator(this, function (_a) {
|
|
51
|
+
switch (_a.label) {
|
|
52
|
+
case 0:
|
|
53
|
+
api = "".concat(exports.blockscoutEndpoints[chain], "/api?module=block&action=getblocknobytime×tamp=").concat(timestamp, "&closest=before");
|
|
54
|
+
return [4 /*yield*/, fetch(api)];
|
|
55
|
+
case 1:
|
|
56
|
+
res = _a.sent();
|
|
57
|
+
return [4 /*yield*/, res.json()];
|
|
58
|
+
case 2:
|
|
59
|
+
data = _a.sent();
|
|
60
|
+
if (data.status !== '1')
|
|
61
|
+
throw new Error(data.message);
|
|
62
|
+
return [2 /*return*/, {
|
|
63
|
+
timestamp: timestamp,
|
|
64
|
+
block: +data.result.blockNumber,
|
|
65
|
+
number: +data.result.blockNumber,
|
|
66
|
+
}];
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
exports.getBlockscoutBlock = getBlockscoutBlock;
|
package/build/util/cache.d.ts
CHANGED
|
@@ -12,4 +12,9 @@ interface ReadCacheOptions {
|
|
|
12
12
|
export declare function writeCache(file: string, data: any, options?: WriteCacheOptions): Promise<string | undefined>;
|
|
13
13
|
export declare function parseCache(dataString: string | Buffer): Promise<any>;
|
|
14
14
|
export declare function compressCache(data: any): Promise<Buffer>;
|
|
15
|
+
export declare function getTempLocalCache({ file, defaultData, clearAfter }: {
|
|
16
|
+
file: string;
|
|
17
|
+
defaultData?: any;
|
|
18
|
+
clearAfter?: number;
|
|
19
|
+
}): any;
|
|
15
20
|
export {};
|
package/build/util/cache.js
CHANGED
|
@@ -37,7 +37,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
37
37
|
};
|
|
38
38
|
var _a;
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.compressCache = exports.parseCache = exports.writeCache = exports.readCache = exports.currentVersion = void 0;
|
|
40
|
+
exports.getTempLocalCache = exports.compressCache = exports.parseCache = exports.writeCache = exports.readCache = exports.currentVersion = void 0;
|
|
41
41
|
var debugLog_1 = require("./debugLog");
|
|
42
42
|
var r2_1 = require("./r2");
|
|
43
43
|
var zlib_1 = require("zlib");
|
|
@@ -52,7 +52,8 @@ function zipAsync(data) {
|
|
|
52
52
|
function unzipAsync(data) {
|
|
53
53
|
return (0, util_1.promisify)(zlib_1.brotliDecompress)(data, brotliOptions).then(function (r) { return r.toString(); });
|
|
54
54
|
}
|
|
55
|
-
var
|
|
55
|
+
var _fs = require('fs');
|
|
56
|
+
var fs = _fs.promises;
|
|
56
57
|
var path = require('path');
|
|
57
58
|
var foldersCreated = {};
|
|
58
59
|
exports.currentVersion = 'zlib-1.0';
|
|
@@ -226,3 +227,50 @@ exports.compressCache = compressCache;
|
|
|
226
227
|
function isSameData(data1, data2) {
|
|
227
228
|
return JSON.stringify(data1) === JSON.stringify(data2);
|
|
228
229
|
}
|
|
230
|
+
var ONE_WEEK = 1000 * 60 * 60 * 24 * 7;
|
|
231
|
+
function getTempLocalCache(_a) {
|
|
232
|
+
var file = _a.file, _b = _a.defaultData, defaultData = _b === void 0 ? {} : _b, _c = _a.clearAfter, clearAfter = _c === void 0 ? ONE_WEEK : _c;
|
|
233
|
+
var cache = defaultData;
|
|
234
|
+
var now = Math.floor(Date.now() / 1e3);
|
|
235
|
+
var emptyFile = { created: now, data: defaultData };
|
|
236
|
+
var fileData = emptyFile;
|
|
237
|
+
var filePath = getFilePath(file);
|
|
238
|
+
var saveCacheFlag = false;
|
|
239
|
+
try {
|
|
240
|
+
var data = _fs.readFileSync(filePath);
|
|
241
|
+
fileData = JSON.parse(data.toString());
|
|
242
|
+
if (now - fileData.created > clearAfter)
|
|
243
|
+
fileData = emptyFile; // clear cache
|
|
244
|
+
}
|
|
245
|
+
catch (error) { }
|
|
246
|
+
// save cache on exit
|
|
247
|
+
process.on('exit', saveCache);
|
|
248
|
+
process.on('SIGTERM', saveCache);
|
|
249
|
+
process.on('SIGINT', saveCache);
|
|
250
|
+
return fileData.data;
|
|
251
|
+
function saveCache() {
|
|
252
|
+
if (saveCacheFlag)
|
|
253
|
+
return;
|
|
254
|
+
saveCacheFlag = true;
|
|
255
|
+
try {
|
|
256
|
+
removePromisesAndFunctions(fileData);
|
|
257
|
+
_fs.writeFileSync(filePath, JSON.stringify(fileData));
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
(0, debugLog_1.debugLog)('Error writing cache:', error, file);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function removePromisesAndFunctions(data) {
|
|
264
|
+
if (typeof data === 'object') {
|
|
265
|
+
for (var key in data) {
|
|
266
|
+
if (typeof data[key] === 'function')
|
|
267
|
+
delete data[key];
|
|
268
|
+
if (data[key] instanceof Promise)
|
|
269
|
+
delete data[key];
|
|
270
|
+
else
|
|
271
|
+
removePromisesAndFunctions(data[key]);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
exports.getTempLocalCache = getTempLocalCache;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const isCosmosChain: (chain: string) => boolean;
|
|
2
|
+
export declare function getCosmosBlock(block?: number | string, chain?: string): Promise<{
|
|
3
|
+
number: number;
|
|
4
|
+
timestamp: number;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function getCosmosProvider(chain: string): {
|
|
7
|
+
getBlock: (block?: number | string) => Promise<{
|
|
8
|
+
number: number;
|
|
9
|
+
timestamp: number;
|
|
10
|
+
}>;
|
|
11
|
+
};
|