@machinomy/hdwallet-provider
Version:
HD Wallet-enabled Web3 provider
127 lines • 4.37 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseBlockTracker = exports.SECOND = void 0;
const events_1 = require("events");
exports.SECOND = 1000;
const calculateSum = (accumulator, currentValue) => accumulator + currentValue;
const blockTrackerEvents = ['sync', 'latest'];
class BaseBlockTracker extends events_1.EventEmitter {
constructor(opts = {}) {
super();
this._blockResetTimeout = undefined;
this._currentBlock = null;
this._isRunning = false;
// config
this._blockResetDuration = opts.blockResetDuration || 20 * exports.SECOND;
// bind functions for internal use
this._onNewListener = this._onNewListener.bind(this);
this._onRemoveListener = this._onRemoveListener.bind(this);
this._resetCurrentBlock = this._resetCurrentBlock.bind(this);
// listen for handler changes
this._setupInternalEvents();
}
isRunning() {
return this._isRunning;
}
getCurrentBlock() {
return this._currentBlock;
}
async getLatestBlock() {
// return if available
if (this._currentBlock)
return this._currentBlock;
// wait for a new latest block
return new Promise(resolve => this.once('latest', resolve));
}
// dont allow module consumer to remove our internal event listeners
removeAllListeners(eventName) {
// perform default behavior, preserve fn arity
if (eventName) {
super.removeAllListeners(eventName);
}
else {
super.removeAllListeners();
}
// re-add internal events
this._setupInternalEvents();
// trigger stop check just in case
this._onRemoveListener();
return this;
}
_setupInternalEvents() {
// first remove listeners for idempotence
this.removeListener('newListener', this._onNewListener);
this.removeListener('removeListener', this._onRemoveListener);
// then add them
this.on('newListener', this._onNewListener);
this.on('removeListener', this._onRemoveListener);
}
_onNewListener(eventName) {
// `newListener` is called *before* the listener is added
if (!blockTrackerEvents.includes(eventName))
return;
this._maybeStart();
}
_onRemoveListener() {
// `removeListener` is called *after* the listener is removed
if (this._getBlockTrackerEventCount() > 0)
return;
this._maybeEnd();
}
_maybeStart() {
if (this._isRunning)
return;
this._isRunning = true;
// cancel setting latest block to stale
this._cancelBlockResetTimeout();
this._start();
}
_maybeEnd() {
if (!this._isRunning)
return;
this._isRunning = false;
this._setupBlockResetTimeout();
this._end();
}
_getBlockTrackerEventCount() {
return blockTrackerEvents
.map(eventName => this.listenerCount(eventName))
.reduce(calculateSum);
}
_newPotentialLatest(newBlock) {
const currentBlock = this._currentBlock;
// only update if blok number is higher
if (currentBlock && (hexToInt(newBlock) <= hexToInt(currentBlock)))
return;
this._setCurrentBlock(newBlock);
}
_setCurrentBlock(newBlock) {
const oldBlock = this._currentBlock;
this._currentBlock = newBlock;
this.emit('latest', newBlock);
this.emit('sync', { oldBlock, newBlock });
}
_setupBlockResetTimeout() {
// clear any existing timeout
this._cancelBlockResetTimeout();
// clear latest block when stale
this._blockResetTimeout = setTimeout(this._resetCurrentBlock, this._blockResetDuration);
// nodejs - dont hold process open
if (this._blockResetTimeout.unref) {
this._blockResetTimeout.unref();
}
}
_cancelBlockResetTimeout() {
if (this._blockResetTimeout) {
clearTimeout(this._blockResetTimeout);
}
}
_resetCurrentBlock() {
this._currentBlock = null;
}
}
exports.BaseBlockTracker = BaseBlockTracker;
function hexToInt(hexInt) {
return Number.parseInt(hexInt, 16);
}
//# sourceMappingURL=base.js.map