UNPKG

@vechain/connex-driver

Version:
238 lines 20.1 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { blake2b256 } from 'thor-devkit'; import { Cache } from './cache'; import { sleep } from './common'; import { InterruptedError, PromInt } from './promint'; /** class implements Connex.Driver leaves out Vendor related methods */ export class DriverNoVendor { constructor(net, genesis, initialHead) { this.net = net; this.genesis = genesis; this.headResolvers = []; this.int = new PromInt(); this.cache = new Cache(); // to merge concurrent identical remote requests this.pendingRequests = {}; if (initialHead) { this.head = initialHead; } else { this.head = { id: genesis.id, number: genesis.number, timestamp: genesis.timestamp, parentID: genesis.parentID, txsFeatures: genesis.txsFeatures, gasLimit: genesis.gasLimit }; if (genesis.baseFeePerGas) { this.head.baseFeePerGas = genesis.baseFeePerGas; } } void this.headTrackerLoop(); } // close the driver to prevent mem leak close() { this.int.interrupt(); } // implementations pollHead() { return this.int.wrap(new Promise(resolve => { this.headResolvers.push(() => resolve(this.head)); })); } getBlock(revision) { return this.cache.getBlock(revision, () => this.httpGet(`blocks/${revision}`)); } getFeesHistory(newestBlock, blockCount, rewardPercentiles) { return this.cache.getFeesHistory(newestBlock, blockCount, rewardPercentiles || [], () => { const params = { newestBlock: newestBlock.toString(), blockCount: blockCount.toString() }; if (rewardPercentiles && rewardPercentiles.length > 0) { params.rewardPercentiles = rewardPercentiles.join(','); } return this.httpGet('fees/history', params); }); } getPriorityFeeSuggestion() { // No cache since we do not have a key for it return this.httpGet('fees/priority').then(res => res.maxPriorityFeePerGas); } getTransaction(id, allowPending) { return this.cache.getTx(id, () => { const query = { head: this.head.id }; if (allowPending) { query.pending = 'true'; } return this.httpGet(`transactions/${id}`, query); }); } getReceipt(id) { return this.cache.getReceipt(id, () => this.httpGet(`transactions/${id}/receipt`, { head: this.head.id })); } getAccount(addr, revision) { return this.cache.getAccount(addr, revision, () => this.httpGet(`accounts/${addr}`, { revision })); } getCode(addr, revision) { return this.cache.getTied(`code-${addr}`, revision, () => this.httpGet(`accounts/${addr}/code`, { revision })); } getStorage(addr, key, revision) { return this.cache.getTied(`storage-${addr}-${key}`, revision, () => this.httpGet(`accounts/${addr}/storage/${key}`, { revision })); } explain(arg, revision, cacheHints) { const cacheKey = `explain-${blake2b256(JSON.stringify(arg)).toString('hex')}`; return this.cache.getTied(cacheKey, revision, () => this.httpPost('accounts/*', arg, { revision }), cacheHints); } filterEventLogs(arg, cacheHints) { const cacheKey = `event-${blake2b256(JSON.stringify(arg)).toString('hex')}`; return this.cache.getTied(cacheKey, this.head.id, () => this.httpPost('logs/event', arg), cacheHints); } filterTransferLogs(arg, cacheHints) { const cacheKey = `transfer-${blake2b256(JSON.stringify(arg)).toString('hex')}`; return this.cache.getTied(cacheKey, this.head.id, () => this.httpPost('logs/transfer', arg), cacheHints); } signTx(msg, options) { throw new Error('signer not implemented'); } signCert(msg, options) { throw new Error('signer not implemented'); } ////// mergeRequest(req, ...keyParts) { const key = JSON.stringify(keyParts); const pending = this.pendingRequests[key]; // eslint-disable-next-line @typescript-eslint/no-misused-promises if (pending) { return pending; } return this.pendingRequests[key] = (() => __awaiter(this, void 0, void 0, function* () { try { return yield req(); } finally { delete this.pendingRequests[key]; } }))(); } httpGet(path, query) { return this.mergeRequest(() => { return this.net.http('GET', path, { query, validateResponseHeader: this.headerValidator }); }, path, query || ''); } httpPost(path, body, query) { return this.mergeRequest(() => { return this.net.http('POST', path, { query, body, validateResponseHeader: this.headerValidator }); }, path, query || '', body || ''); } get headerValidator() { return (headers) => { const xgid = headers['x-genesis-id']; if (xgid && xgid !== this.genesis.id) { throw new Error(`responded 'x-genesis-id' not matched`); } }; } emitNewHead() { const resolvers = this.headResolvers; this.headResolvers = []; resolvers.forEach(r => r()); } headTrackerLoop() { return __awaiter(this, void 0, void 0, function* () { for (;;) { let attemptWs = false; try { const best = yield this.int.wrap(this.httpGet('blocks/best')); if (best.id !== this.head.id && best.number >= this.head.number) { this.head = { id: best.id, number: best.number, timestamp: best.timestamp, parentID: best.parentID, txsFeatures: best.txsFeatures, gasLimit: best.gasLimit }; if (best.baseFeePerGas) { this.head.baseFeePerGas = best.baseFeePerGas; } this.cache.handleNewBlock(this.head, undefined, best); this.emitNewHead(); if (Date.now() - this.head.timestamp * 1000 < 60 * 1000) { // nearly synced attemptWs = true; } } } catch (err) { if (err instanceof InterruptedError) { break; } } if (attemptWs) { try { yield this.trackWs(); } catch (err) { if (err instanceof InterruptedError) { break; } } } try { yield this.int.wrap(sleep(8 * 1000)); } catch (_a) { break; } } }); } trackWs() { return __awaiter(this, void 0, void 0, function* () { const wsPath = `subscriptions/beat2?pos=${this.head.parentID}`; const wsr = this.net.openWebSocketReader(wsPath); try { for (;;) { const data = yield this.int.wrap(wsr.read()); const beat = JSON.parse(data); if (!beat.obsolete && beat.id !== this.head.id && beat.number >= this.head.number) { this.head = { id: beat.id, number: beat.number, timestamp: beat.timestamp, parentID: beat.parentID, txsFeatures: beat.txsFeatures, gasLimit: beat.gasLimit }; if (beat.baseFeePerGas) { this.head.baseFeePerGas = beat.baseFeePerGas; } this.cache.handleNewBlock(this.head, { k: beat.k, bits: beat.bloom }); this.emitNewHead(); } } } finally { wsr.close(); } }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJpdmVyLW5vLXZlbmRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kcml2ZXItbm8tdmVuZG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDeEMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUMvQixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBRWhDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFFckQsdUVBQXVFO0FBQ3ZFLE1BQU0sT0FBTyxjQUFjO0lBU3ZCLFlBQ3VCLEdBQVEsRUFDbEIsT0FBMEIsRUFDbkMsV0FBd0M7UUFGckIsUUFBRyxHQUFILEdBQUcsQ0FBSztRQUNsQixZQUFPLEdBQVAsT0FBTyxDQUFtQjtRQVIvQixrQkFBYSxHQUFHLEVBQXVCLENBQUE7UUFDOUIsUUFBRyxHQUFHLElBQUksT0FBTyxFQUFFLENBQUE7UUFDbkIsVUFBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUE7UUFDcEMsZ0RBQWdEO1FBQy9CLG9CQUFlLEdBQWlDLEVBQUUsQ0FBQTtRQU8vRCxJQUFJLFdBQVcsRUFBRTtZQUNiLElBQUksQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFBO1NBQzFCO2FBQU07WUFDSCxJQUFJLENBQUMsSUFBSSxHQUFHO2dCQUNSLEVBQUUsRUFBRSxPQUFPLENBQUMsRUFBRTtnQkFDZCxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07Z0JBQ3RCLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztnQkFDNUIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO2dCQUMxQixXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVc7Z0JBQ2hDLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTthQUM3QixDQUFBO1lBQ0QsSUFBSSxPQUFPLENBQUMsYUFBYSxFQUFFO2dC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