Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

eth-block-tracker

Package Overview
Dependencies
Maintainers
11
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eth-block-tracker - npm Package Compare versions

Comparing version 7.1.0 to 8.0.0

dist/BlockTracker.d.ts

1

dist/index.d.ts
export * from './PollingBlockTracker';
export * from './SubscribeBlockTracker';
export * from './BlockTracker';
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {

@@ -15,2 +19,3 @@ if (k2 === undefined) k2 = k;

__exportStar(require("./SubscribeBlockTracker"), exports);
__exportStar(require("./BlockTracker"), exports);
//# sourceMappingURL=index.js.map

41

dist/PollingBlockTracker.d.ts
import type { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider';
import { BaseBlockTracker } from './BaseBlockTracker';
import SafeEventEmitter from '@metamask/safe-event-emitter';
import type { BlockTracker } from './BlockTracker';
export interface PollingBlockTrackerOptions {

@@ -12,12 +13,34 @@ provider?: SafeEventEmitterProvider;

}
export declare class PollingBlockTracker extends BaseBlockTracker {
private _provider;
private _pollingInterval;
private _retryTimeout;
private _keepEventLoopActive;
private _setSkipCacheFlag;
export declare class PollingBlockTracker extends SafeEventEmitter implements BlockTracker {
private _isRunning;
private readonly _blockResetDuration;
private readonly _usePastBlocks;
private _currentBlock;
private _blockResetTimeout?;
private readonly _provider;
private readonly _pollingInterval;
private readonly _retryTimeout;
private readonly _keepEventLoopActive;
private readonly _setSkipCacheFlag;
constructor(opts?: PollingBlockTrackerOptions);
destroy(): Promise<void>;
isRunning(): boolean;
getCurrentBlock(): string | null;
getLatestBlock(): Promise<string>;
removeAllListeners(eventName?: string | symbol): this;
private _setupInternalEvents;
private _onNewListener;
private _onRemoveListener;
private _maybeStart;
private _maybeEnd;
private _getBlockTrackerEventCount;
private _shouldUseNewBlock;
private _newPotentialLatest;
private _setCurrentBlock;
private _setupBlockResetTimeout;
private _cancelBlockResetTimeout;
private _resetCurrentBlock;
checkForLatestBlock(): Promise<string>;
protected _start(): Promise<void>;
protected _end(): Promise<void>;
private _start;
private _end;
private _synchronize;

@@ -24,0 +47,0 @@ private _updateLatestBlock;

@@ -7,5 +7,5 @@ "use strict";

exports.PollingBlockTracker = void 0;
const safe_event_emitter_1 = __importDefault(require("@metamask/safe-event-emitter"));
const json_rpc_random_id_1 = __importDefault(require("json-rpc-random-id"));
const pify_1 = __importDefault(require("pify"));
const BaseBlockTracker_1 = require("./BaseBlockTracker");
const logging_utils_1 = require("./logging-utils");

@@ -15,5 +15,6 @@ const log = (0, logging_utils_1.createModuleLogger)(logging_utils_1.projectLogger, 'polling-block-tracker');

const sec = 1000;
class PollingBlockTracker extends BaseBlockTracker_1.BaseBlockTracker {
const calculateSum = (accumulator, currentValue) => accumulator + currentValue;
const blockTrackerEvents = ['sync', 'latest'];
class PollingBlockTracker extends safe_event_emitter_1.default {
constructor(opts = {}) {
var _a;
// parse + validate args

@@ -23,4 +24,16 @@ if (!opts.provider) {

}
super(Object.assign(Object.assign({}, opts), { blockResetDuration: (_a = opts.blockResetDuration) !== null && _a !== void 0 ? _a : opts.pollingInterval }));
super();
// config
this._blockResetDuration = opts.blockResetDuration || 20 * sec;
this._usePastBlocks = opts.usePastBlocks || false;
// state
this._currentBlock = null;
this._isRunning = false;
// 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();
// config
this._provider = opts.provider;

@@ -33,2 +46,124 @@ this._pollingInterval = opts.pollingInterval || 20 * sec;

}
async destroy() {
this._cancelBlockResetTimeout();
await this._maybeEnd();
super.removeAllListeners();
}
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
const latestBlock = await new Promise((resolve) => this.once('latest', resolve));
// return newly set current block
return latestBlock;
}
// 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)) {
// TODO: Handle dangling promise
this._maybeStart();
}
}
_onRemoveListener() {
// `removeListener` is called *after* the listener is removed
if (this._getBlockTrackerEventCount() > 0) {
return;
}
this._maybeEnd();
}
async _maybeStart() {
if (this._isRunning) {
return;
}
this._isRunning = true;
// cancel setting latest block to stale
this._cancelBlockResetTimeout();
await this._start();
this.emit('_started');
}
async _maybeEnd() {
if (!this._isRunning) {
return;
}
this._isRunning = false;
this._setupBlockResetTimeout();
await this._end();
this.emit('_ended');
}
_getBlockTrackerEventCount() {
return blockTrackerEvents
.map((eventName) => this.listenerCount(eventName))
.reduce(calculateSum);
}
_shouldUseNewBlock(newBlock) {
const currentBlock = this._currentBlock;
if (!currentBlock) {
return true;
}
const newBlockInt = hexToInt(newBlock);
const currentBlockInt = hexToInt(currentBlock);
return ((this._usePastBlocks && newBlockInt < currentBlockInt) ||
newBlockInt > currentBlockInt);
}
_newPotentialLatest(newBlock) {
if (!this._shouldUseNewBlock(newBlock)) {
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;
}
// trigger block polling

@@ -102,3 +237,3 @@ async checkForLatestBlock() {

*/
function timeout(duration, unref) {
async function timeout(duration, unref) {
return new Promise((resolve) => {

@@ -112,2 +247,12 @@ const timeoutRef = setTimeout(resolve, duration);

}
/**
* Converts a number represented as a string in hexadecimal format into a native
* number.
*
* @param hexInt - The hex string.
* @returns The number.
*/
function hexToInt(hexInt) {
return Number.parseInt(hexInt, 16);
}
//# sourceMappingURL=PollingBlockTracker.js.map
import type { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider';
import { BaseBlockTracker } from './BaseBlockTracker';
import SafeEventEmitter from '@metamask/safe-event-emitter';
import type { BlockTracker } from './BlockTracker';
export interface SubscribeBlockTrackerOptions {

@@ -8,11 +9,33 @@ provider?: SafeEventEmitterProvider;

}
export declare class SubscribeBlockTracker extends BaseBlockTracker {
private _provider;
export declare class SubscribeBlockTracker extends SafeEventEmitter implements BlockTracker {
private _isRunning;
private readonly _blockResetDuration;
private readonly _usePastBlocks;
private _currentBlock;
private _blockResetTimeout?;
private readonly _provider;
private _subscriptionId;
constructor(opts?: SubscribeBlockTrackerOptions);
destroy(): Promise<void>;
isRunning(): boolean;
getCurrentBlock(): string | null;
getLatestBlock(): Promise<string>;
removeAllListeners(eventName?: string | symbol): this;
private _setupInternalEvents;
private _onNewListener;
private _onRemoveListener;
private _maybeStart;
private _maybeEnd;
private _getBlockTrackerEventCount;
private _shouldUseNewBlock;
private _newPotentialLatest;
private _setCurrentBlock;
private _setupBlockResetTimeout;
private _cancelBlockResetTimeout;
private _resetCurrentBlock;
checkForLatestBlock(): Promise<string>;
protected _start(): Promise<void>;
protected _end(): Promise<void>;
private _start;
private _end;
private _call;
private _handleSubData;
}

@@ -7,6 +7,9 @@ "use strict";

exports.SubscribeBlockTracker = void 0;
const safe_event_emitter_1 = __importDefault(require("@metamask/safe-event-emitter"));
const json_rpc_random_id_1 = __importDefault(require("json-rpc-random-id"));
const BaseBlockTracker_1 = require("./BaseBlockTracker");
const createRandomId = (0, json_rpc_random_id_1.default)();
class SubscribeBlockTracker extends BaseBlockTracker_1.BaseBlockTracker {
const sec = 1000;
const calculateSum = (accumulator, currentValue) => accumulator + currentValue;
const blockTrackerEvents = ['sync', 'latest'];
class SubscribeBlockTracker extends safe_event_emitter_1.default {
constructor(opts = {}) {

@@ -17,8 +20,141 @@ // parse + validate args

}
// BaseBlockTracker constructor
super(opts);
super();
// config
this._blockResetDuration = opts.blockResetDuration || 20 * sec;
this._usePastBlocks = opts.usePastBlocks || false;
// state
this._currentBlock = null;
this._isRunning = false;
// 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();
// config
this._provider = opts.provider;
this._subscriptionId = null;
}
async destroy() {
this._cancelBlockResetTimeout();
await this._maybeEnd();
super.removeAllListeners();
}
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
const latestBlock = await new Promise((resolve) => this.once('latest', resolve));
// return newly set current block
return latestBlock;
}
// 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)) {
// TODO: Handle dangling promise
this._maybeStart();
}
}
_onRemoveListener() {
// `removeListener` is called *after* the listener is removed
if (this._getBlockTrackerEventCount() > 0) {
return;
}
this._maybeEnd();
}
async _maybeStart() {
if (this._isRunning) {
return;
}
this._isRunning = true;
// cancel setting latest block to stale
this._cancelBlockResetTimeout();
await this._start();
this.emit('_started');
}
async _maybeEnd() {
if (!this._isRunning) {
return;
}
this._isRunning = false;
this._setupBlockResetTimeout();
await this._end();
this.emit('_ended');
}
_getBlockTrackerEventCount() {
return blockTrackerEvents
.map((eventName) => this.listenerCount(eventName))
.reduce(calculateSum);
}
_shouldUseNewBlock(newBlock) {
const currentBlock = this._currentBlock;
if (!currentBlock) {
return true;
}
const newBlockInt = hexToInt(newBlock);
const currentBlockInt = hexToInt(currentBlock);
return ((this._usePastBlocks && newBlockInt < currentBlockInt) ||
newBlockInt > currentBlockInt);
}
_newPotentialLatest(newBlock) {
if (!this._shouldUseNewBlock(newBlock)) {
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;
}
async checkForLatestBlock() {

@@ -51,3 +187,3 @@ return await this.getLatestBlock();

}
_call(method, ...params) {
async _call(method, ...params) {
return new Promise((resolve, reject) => {

@@ -78,2 +214,12 @@ this._provider.sendAsync({

exports.SubscribeBlockTracker = SubscribeBlockTracker;
/**
* Converts a number represented as a string in hexadecimal format into a native
* number.
*
* @param hexInt - The hex string.
* @returns The number.
*/
function hexToInt(hexInt) {
return Number.parseInt(hexInt, 16);
}
//# sourceMappingURL=SubscribeBlockTracker.js.map
{
"name": "eth-block-tracker",
"version": "7.1.0",
"version": "8.0.0",
"description": "A block tracker for the Ethereum blockchain. Keeps track of the latest block.",

@@ -28,7 +28,7 @@ "repository": {

"dependencies": {
"@metamask/eth-json-rpc-provider": "^1.0.0",
"@metamask/eth-json-rpc-provider": "^2.1.0",
"@metamask/safe-event-emitter": "^3.0.0",
"@metamask/utils": "^5.0.1",
"@metamask/utils": "^8.1.0",
"json-rpc-random-id": "^1.0.1",
"pify": "^3.0.0"
"pify": "^5.0.0"
},

@@ -38,31 +38,32 @@ "devDependencies": {

"@metamask/auto-changelog": "^3.0.0",
"@metamask/eslint-config": "^9.0.0",
"@metamask/eslint-config-jest": "^9.0.0",
"@metamask/eslint-config-nodejs": "^9.0.0",
"@metamask/eslint-config-typescript": "^9.0.1",
"@types/jest": "^27.4.1",
"@metamask/eslint-config": "^12.0.0",
"@metamask/eslint-config-jest": "^12.0.0",
"@metamask/eslint-config-nodejs": "^12.0.0",
"@metamask/eslint-config-typescript": "^12.0.0",
"@metamask/json-rpc-engine": "^7.1.1",
"@types/jest": "^29.1.2",
"@types/json-rpc-random-id": "^1.0.1",
"@types/node": "^17.0.23",
"@types/pify": "^5.0.1",
"@typescript-eslint/eslint-plugin": "^4.20.0",
"@typescript-eslint/parser": "^4.20.0",
"eslint": "^7.23.0",
"@typescript-eslint/eslint-plugin": "^5.61.0",
"@typescript-eslint/parser": "^5.61.0",
"eslint": "^8.21.0",
"eslint-config-prettier": "^8.1.0",
"eslint-import-resolver-typescript": "^2.7.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "^24.1.3",
"eslint-plugin-jsdoc": "^36.1.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.3.1",
"jest": "^27.5.1",
"json-rpc-engine": "^6.1.0",
"prettier": "^2.2.1",
"eslint-plugin-jest": "^27.1.5",
"eslint-plugin-jsdoc": "^39.9.1",
"eslint-plugin-n": "^15.7.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.1.1",
"jest": "^29.1.2",
"prettier": "^2.7.1",
"prettier-plugin-packagejson": "^2.2.11",
"rimraf": "^3.0.2",
"ts-jest": "^27.1.4",
"ts-jest": "^29.1.1",
"ts-node": "^10.7.0",
"typescript": "~4.4.0"
"typescript": "~4.8.4"
},
"engines": {
"node": ">=14.0.0"
"node": ">=16.20 || ^18.16"
},

@@ -69,0 +70,0 @@ "publishConfig": {

@@ -93,3 +93,3 @@ # eth-block-tracker

- Install [Node.js](https://nodejs.org) version 14
- Install [Node.js](https://nodejs.org) version 16 or greater
- If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm use` will automatically choose the right node version for you.

@@ -96,0 +96,0 @@ - Install [Yarn v1](https://yarnpkg.com/en/docs/install)

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc