@metamask/eth-block-tracker 12.0.0 → 12.0.1

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/README.md CHANGED
@@ -123,7 +123,7 @@ The project follows the same release process as the other libraries in the MetaM
123
123
  - Generally any changes that don't affect consumers of the package (e.g. lockfile changes or development environment changes) are omitted. Exceptions may be made for changes that might be of interest despite not having an effect upon the published package (e.g. major test improvements, security improvements, improved documentation, etc.).
124
124
  - Try to explain each change in terms that users of the package would understand (e.g. avoid referencing internal variables/concepts).
125
125
  - Consolidate related changes into one change entry if it makes it easier to explain.
126
- - Run `yarn auto-changelog validate --rc` to check that the changelog is correctly formatted.
126
+ - Run `yarn auto-changelog validate --rc --prettier` to check that the changelog is correctly formatted.
127
127
 
128
128
  5. Review and QA the release.
129
129
 
@@ -57,9 +57,8 @@ class PollingBlockTracker extends safe_event_emitter_1.default {
57
57
  }
58
58
  async destroy() {
59
59
  this._cancelBlockResetTimeout();
60
- this._maybeEnd();
61
60
  super.removeAllListeners();
62
- __classPrivateFieldGet(this, _PollingBlockTracker_instances, "m", _PollingBlockTracker_rejectPendingLatestBlock).call(this, new Error('Block tracker destroyed'));
61
+ this._maybeEnd();
63
62
  }
64
63
  isRunning() {
65
64
  return this._isRunning;
@@ -159,6 +158,7 @@ class PollingBlockTracker extends safe_event_emitter_1.default {
159
158
  this._isRunning = false;
160
159
  this._setupBlockResetTimeout();
161
160
  this._end();
161
+ __classPrivateFieldGet(this, _PollingBlockTracker_instances, "m", _PollingBlockTracker_rejectPendingLatestBlock).call(this, new Error('Block tracker destroyed'));
162
162
  this.emit('_ended');
163
163
  }
164
164
  _getBlockTrackerEventCount() {
@@ -1 +1 @@
1
- {"version":3,"file":"PollingBlockTracker.js","sourceRoot":"","sources":["../src/PollingBlockTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider';\nimport SafeEventEmitter from '@metamask/safe-event-emitter';\nimport {\n createDeferredPromise,\n type DeferredPromise,\n getErrorMessage,\n type JsonRpcRequest,\n} from '@metamask/utils';\nimport getCreateRandomId from 'json-rpc-random-id';\n\nimport type { BlockTracker } from './BlockTracker';\nimport { projectLogger, createModuleLogger } from './logging-utils';\n\nconst log = createModuleLogger(projectLogger, 'polling-block-tracker');\nconst createRandomId = getCreateRandomId();\nconst sec = 1000;\n\nconst blockTrackerEvents: (string | symbol)[] = ['sync', 'latest'];\n\nexport interface PollingBlockTrackerOptions {\n provider?: SafeEventEmitterProvider;\n pollingInterval?: number;\n retryTimeout?: number;\n keepEventLoopActive?: boolean;\n setSkipCacheFlag?: boolean;\n blockResetDuration?: number;\n usePastBlocks?: boolean;\n}\n\ninterface ExtendedJsonRpcRequest extends JsonRpcRequest<[]> {\n skipCache?: boolean;\n}\n\ntype InternalListener = (value: string) => void;\n\nexport class PollingBlockTracker\n extends SafeEventEmitter\n implements BlockTracker\n{\n private _isRunning: boolean;\n\n private readonly _blockResetDuration: number;\n\n private readonly _usePastBlocks: boolean;\n\n private _currentBlock: string | null;\n\n private _blockResetTimeout?: ReturnType<typeof setTimeout>;\n\n private _pollingTimeout?: ReturnType<typeof setTimeout>;\n\n private readonly _provider: SafeEventEmitterProvider;\n\n private readonly _pollingInterval: number;\n\n private readonly _retryTimeout: number;\n\n private readonly _keepEventLoopActive: boolean;\n\n private readonly _setSkipCacheFlag: boolean;\n\n readonly #internalEventListeners: InternalListener[] = [];\n\n #pendingLatestBlock?: Omit<DeferredPromise<string>, 'resolve'>;\n\n #pendingFetch?: Omit<DeferredPromise<string>, 'resolve'>;\n\n constructor(opts: PollingBlockTrackerOptions = {}) {\n // parse + validate args\n if (!opts.provider) {\n throw new Error('PollingBlockTracker - no provider specified.');\n }\n\n super();\n\n // config\n this._blockResetDuration = opts.blockResetDuration || 20 * sec;\n this._usePastBlocks = opts.usePastBlocks || false;\n // state\n this._currentBlock = null;\n this._isRunning = false;\n\n // bind functions for internal use\n this._onNewListener = this._onNewListener.bind(this);\n this._onRemoveListener = this._onRemoveListener.bind(this);\n this._resetCurrentBlock = this._resetCurrentBlock.bind(this);\n\n // listen for handler changes\n this._setupInternalEvents();\n\n // config\n this._provider = opts.provider;\n this._pollingInterval = opts.pollingInterval || 20 * sec;\n this._retryTimeout = opts.retryTimeout || this._pollingInterval / 10;\n this._keepEventLoopActive =\n opts.keepEventLoopActive === undefined ? true : opts.keepEventLoopActive;\n this._setSkipCacheFlag = opts.setSkipCacheFlag || false;\n }\n\n async destroy() {\n this._cancelBlockResetTimeout();\n this._maybeEnd();\n super.removeAllListeners();\n this.#rejectPendingLatestBlock(new Error('Block tracker destroyed'));\n }\n\n isRunning(): boolean {\n return this._isRunning;\n }\n\n getCurrentBlock(): string | null {\n return this._currentBlock;\n }\n\n async getLatestBlock(): Promise<string> {\n // return if available\n if (this._currentBlock) {\n return this._currentBlock;\n }\n\n if (this.#pendingLatestBlock) {\n return await this.#pendingLatestBlock.promise;\n }\n\n const { promise, resolve, reject } = createDeferredPromise<string>({\n suppressUnhandledRejection: true,\n });\n this.#pendingLatestBlock = { reject, promise };\n\n try {\n // If tracker isn't running, just fetch directly\n if (!this._isRunning) {\n const latestBlock = await this._fetchLatestBlock();\n this._newPotentialLatest(latestBlock);\n resolve(latestBlock);\n return latestBlock;\n }\n\n // If tracker is running, wait for next block with timeout\n const onLatestBlock = (value: string) => {\n this.#removeInternalListener(onLatestBlock);\n this.removeListener('latest', onLatestBlock);\n resolve(value);\n };\n\n this.#addInternalListener(onLatestBlock);\n this.once('latest', onLatestBlock);\n\n return await promise;\n } catch (error) {\n reject(error);\n throw error;\n } finally {\n this.#pendingLatestBlock = undefined;\n }\n }\n\n // dont allow module consumer to remove our internal event listeners\n removeAllListeners(eventName?: string | symbol) {\n // perform default behavior, preserve fn arity\n if (eventName) {\n super.removeAllListeners(eventName);\n } else {\n super.removeAllListeners();\n }\n\n // re-add internal events\n this._setupInternalEvents();\n // trigger stop check just in case\n this._onRemoveListener();\n\n return this;\n }\n\n private _setupInternalEvents(): void {\n // first remove listeners for idempotence\n this.removeListener('newListener', this._onNewListener);\n this.removeListener('removeListener', this._onRemoveListener);\n // then add them\n this.on('newListener', this._onNewListener);\n this.on('removeListener', this._onRemoveListener);\n }\n\n private _onNewListener(eventName: string | symbol): void {\n // `newListener` is called *before* the listener is added\n if (blockTrackerEvents.includes(eventName)) {\n // TODO: Handle dangling promise\n this._maybeStart();\n }\n }\n\n private _onRemoveListener(): void {\n // `removeListener` is called *after* the listener is removed\n if (this._getBlockTrackerEventCount() > 0) {\n return;\n }\n this._maybeEnd();\n }\n\n private _maybeStart() {\n if (this._isRunning) {\n return;\n }\n\n this._isRunning = true;\n // cancel setting latest block to stale\n this._cancelBlockResetTimeout();\n this._start();\n this.emit('_started');\n }\n\n private _maybeEnd() {\n if (!this._isRunning) {\n return;\n }\n\n this._isRunning = false;\n this._setupBlockResetTimeout();\n this._end();\n this.emit('_ended');\n }\n\n private _getBlockTrackerEventCount(): number {\n return (\n blockTrackerEvents\n .map((eventName) => this.listeners(eventName))\n .flat()\n // internal listeners are not included in the count\n .filter((listener) =>\n this.#internalEventListeners.every(\n (internalListener) => !Object.is(internalListener, listener),\n ),\n ).length\n );\n }\n\n private _shouldUseNewBlock(newBlock: string) {\n const currentBlock = this._currentBlock;\n if (!currentBlock) {\n return true;\n }\n const newBlockInt = hexToInt(newBlock);\n const currentBlockInt = hexToInt(currentBlock);\n\n return (\n (this._usePastBlocks && newBlockInt < currentBlockInt) ||\n newBlockInt > currentBlockInt\n );\n }\n\n private _newPotentialLatest(newBlock: string): void {\n if (!this._shouldUseNewBlock(newBlock)) {\n return;\n }\n this._setCurrentBlock(newBlock);\n }\n\n private _setCurrentBlock(newBlock: string): void {\n const oldBlock = this._currentBlock;\n this._currentBlock = newBlock;\n this.emit('latest', newBlock);\n this.emit('sync', { oldBlock, newBlock });\n }\n\n private _setupBlockResetTimeout(): void {\n // clear any existing timeout\n this._cancelBlockResetTimeout();\n // clear latest block when stale\n this._blockResetTimeout = setTimeout(\n this._resetCurrentBlock,\n this._blockResetDuration,\n );\n\n // nodejs - dont hold process open\n if (this._blockResetTimeout.unref) {\n this._blockResetTimeout.unref();\n }\n }\n\n private _cancelBlockResetTimeout(): void {\n if (this._blockResetTimeout) {\n clearTimeout(this._blockResetTimeout);\n }\n }\n\n private _resetCurrentBlock(): void {\n this._currentBlock = null;\n }\n\n async checkForLatestBlock() {\n await this._updateLatestBlock();\n return await this.getLatestBlock();\n }\n\n private _start() {\n // Intentionally not awaited as this starts the polling via a timeout chain.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this._updateAndQueue();\n }\n\n private _end() {\n this._clearPollingTimeout();\n }\n\n private async _updateLatestBlock(): Promise<void> {\n // fetch + set latest block\n const latestBlock = await this._fetchLatestBlock();\n this._newPotentialLatest(latestBlock);\n }\n\n private async _fetchLatestBlock(): Promise<string> {\n // If there's already a pending fetch, reuse it\n if (this.#pendingFetch) {\n return await this.#pendingFetch.promise;\n }\n\n // Create a new deferred promise for this request\n const { promise, resolve, reject } = createDeferredPromise<string>({\n suppressUnhandledRejection: true,\n });\n this.#pendingFetch = { reject, promise };\n\n try {\n const req: ExtendedJsonRpcRequest = {\n jsonrpc: '2.0',\n id: createRandomId(),\n method: 'eth_blockNumber',\n params: [] as [],\n };\n if (this._setSkipCacheFlag) {\n req.skipCache = true;\n }\n\n log('Making request', req);\n const result = await this._provider.request<[], string>(req);\n log('Got result', result);\n resolve(result);\n return result;\n } catch (error) {\n log('Encountered error fetching block', getErrorMessage(error));\n reject(error);\n this.#rejectPendingLatestBlock(error);\n throw error;\n } finally {\n this.#pendingFetch = undefined;\n }\n }\n\n /**\n * The core polling function that runs after each interval.\n * Updates the latest block and then queues the next update.\n */\n private async _updateAndQueue() {\n let interval = this._pollingInterval;\n\n try {\n await this._updateLatestBlock();\n } catch (error: unknown) {\n try {\n this.emit('error', error);\n } catch {\n console.error(`Error updating latest block: ${getErrorMessage(error)}`);\n }\n\n interval = this._retryTimeout;\n }\n\n if (!this._isRunning) {\n return;\n }\n\n this._clearPollingTimeout();\n\n const timeoutRef = setTimeout(() => {\n // Intentionally not awaited as this just continues the polling loop.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this._updateAndQueue();\n }, interval);\n\n if (timeoutRef.unref && !this._keepEventLoopActive) {\n timeoutRef.unref();\n }\n\n this._pollingTimeout = timeoutRef;\n\n this.emit('_waitingForNextIteration');\n }\n\n _clearPollingTimeout() {\n if (this._pollingTimeout) {\n clearTimeout(this._pollingTimeout);\n this._pollingTimeout = undefined;\n }\n }\n\n #addInternalListener(listener: InternalListener) {\n this.#internalEventListeners.push(listener);\n }\n\n #removeInternalListener(listener: InternalListener) {\n this.#internalEventListeners.splice(\n this.#internalEventListeners.indexOf(listener),\n 1,\n );\n }\n\n #rejectPendingLatestBlock(error: unknown) {\n this.#pendingLatestBlock?.reject(error);\n this.#pendingLatestBlock = undefined;\n }\n}\n\n/**\n * Converts a number represented as a string in hexadecimal format into a native\n * number.\n *\n * @param hexInt - The hex string.\n * @returns The number.\n */\nfunction hexToInt(hexInt: string): number {\n return Number.parseInt(hexInt, 16);\n}\n"]}
1
+ {"version":3,"file":"PollingBlockTracker.js","sourceRoot":"","sources":["../src/PollingBlockTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider';\nimport SafeEventEmitter from '@metamask/safe-event-emitter';\nimport {\n createDeferredPromise,\n type DeferredPromise,\n getErrorMessage,\n type JsonRpcRequest,\n} from '@metamask/utils';\nimport getCreateRandomId from 'json-rpc-random-id';\n\nimport type { BlockTracker } from './BlockTracker';\nimport { projectLogger, createModuleLogger } from './logging-utils';\n\nconst log = createModuleLogger(projectLogger, 'polling-block-tracker');\nconst createRandomId = getCreateRandomId();\nconst sec = 1000;\n\nconst blockTrackerEvents: (string | symbol)[] = ['sync', 'latest'];\n\nexport interface PollingBlockTrackerOptions {\n provider?: SafeEventEmitterProvider;\n pollingInterval?: number;\n retryTimeout?: number;\n keepEventLoopActive?: boolean;\n setSkipCacheFlag?: boolean;\n blockResetDuration?: number;\n usePastBlocks?: boolean;\n}\n\ninterface ExtendedJsonRpcRequest extends JsonRpcRequest<[]> {\n skipCache?: boolean;\n}\n\ntype InternalListener = (value: string) => void;\n\nexport class PollingBlockTracker\n extends SafeEventEmitter\n implements BlockTracker\n{\n private _isRunning: boolean;\n\n private readonly _blockResetDuration: number;\n\n private readonly _usePastBlocks: boolean;\n\n private _currentBlock: string | null;\n\n private _blockResetTimeout?: ReturnType<typeof setTimeout>;\n\n private _pollingTimeout?: ReturnType<typeof setTimeout>;\n\n private readonly _provider: SafeEventEmitterProvider;\n\n private readonly _pollingInterval: number;\n\n private readonly _retryTimeout: number;\n\n private readonly _keepEventLoopActive: boolean;\n\n private readonly _setSkipCacheFlag: boolean;\n\n readonly #internalEventListeners: InternalListener[] = [];\n\n #pendingLatestBlock?: Omit<DeferredPromise<string>, 'resolve'>;\n\n #pendingFetch?: Omit<DeferredPromise<string>, 'resolve'>;\n\n constructor(opts: PollingBlockTrackerOptions = {}) {\n // parse + validate args\n if (!opts.provider) {\n throw new Error('PollingBlockTracker - no provider specified.');\n }\n\n super();\n\n // config\n this._blockResetDuration = opts.blockResetDuration || 20 * sec;\n this._usePastBlocks = opts.usePastBlocks || false;\n // state\n this._currentBlock = null;\n this._isRunning = false;\n\n // bind functions for internal use\n this._onNewListener = this._onNewListener.bind(this);\n this._onRemoveListener = this._onRemoveListener.bind(this);\n this._resetCurrentBlock = this._resetCurrentBlock.bind(this);\n\n // listen for handler changes\n this._setupInternalEvents();\n\n // config\n this._provider = opts.provider;\n this._pollingInterval = opts.pollingInterval || 20 * sec;\n this._retryTimeout = opts.retryTimeout || this._pollingInterval / 10;\n this._keepEventLoopActive =\n opts.keepEventLoopActive === undefined ? true : opts.keepEventLoopActive;\n this._setSkipCacheFlag = opts.setSkipCacheFlag || false;\n }\n\n async destroy() {\n this._cancelBlockResetTimeout();\n super.removeAllListeners();\n this._maybeEnd();\n }\n\n isRunning(): boolean {\n return this._isRunning;\n }\n\n getCurrentBlock(): string | null {\n return this._currentBlock;\n }\n\n async getLatestBlock(): Promise<string> {\n // return if available\n if (this._currentBlock) {\n return this._currentBlock;\n }\n\n if (this.#pendingLatestBlock) {\n return await this.#pendingLatestBlock.promise;\n }\n\n const { promise, resolve, reject } = createDeferredPromise<string>({\n suppressUnhandledRejection: true,\n });\n this.#pendingLatestBlock = { reject, promise };\n\n try {\n // If tracker isn't running, just fetch directly\n if (!this._isRunning) {\n const latestBlock = await this._fetchLatestBlock();\n this._newPotentialLatest(latestBlock);\n resolve(latestBlock);\n return latestBlock;\n }\n\n // If tracker is running, wait for next block with timeout\n const onLatestBlock = (value: string) => {\n this.#removeInternalListener(onLatestBlock);\n this.removeListener('latest', onLatestBlock);\n resolve(value);\n };\n\n this.#addInternalListener(onLatestBlock);\n this.once('latest', onLatestBlock);\n\n return await promise;\n } catch (error) {\n reject(error);\n throw error;\n } finally {\n this.#pendingLatestBlock = undefined;\n }\n }\n\n // dont allow module consumer to remove our internal event listeners\n removeAllListeners(eventName?: string | symbol) {\n // perform default behavior, preserve fn arity\n if (eventName) {\n super.removeAllListeners(eventName);\n } else {\n super.removeAllListeners();\n }\n\n // re-add internal events\n this._setupInternalEvents();\n // trigger stop check just in case\n this._onRemoveListener();\n\n return this;\n }\n\n private _setupInternalEvents(): void {\n // first remove listeners for idempotence\n this.removeListener('newListener', this._onNewListener);\n this.removeListener('removeListener', this._onRemoveListener);\n // then add them\n this.on('newListener', this._onNewListener);\n this.on('removeListener', this._onRemoveListener);\n }\n\n private _onNewListener(eventName: string | symbol): void {\n // `newListener` is called *before* the listener is added\n if (blockTrackerEvents.includes(eventName)) {\n // TODO: Handle dangling promise\n this._maybeStart();\n }\n }\n\n private _onRemoveListener(): void {\n // `removeListener` is called *after* the listener is removed\n if (this._getBlockTrackerEventCount() > 0) {\n return;\n }\n this._maybeEnd();\n }\n\n private _maybeStart() {\n if (this._isRunning) {\n return;\n }\n\n this._isRunning = true;\n // cancel setting latest block to stale\n this._cancelBlockResetTimeout();\n this._start();\n this.emit('_started');\n }\n\n private _maybeEnd() {\n if (!this._isRunning) {\n return;\n }\n\n this._isRunning = false;\n this._setupBlockResetTimeout();\n this._end();\n this.#rejectPendingLatestBlock(new Error('Block tracker destroyed'));\n this.emit('_ended');\n }\n\n private _getBlockTrackerEventCount(): number {\n return (\n blockTrackerEvents\n .map((eventName) => this.listeners(eventName))\n .flat()\n // internal listeners are not included in the count\n .filter((listener) =>\n this.#internalEventListeners.every(\n (internalListener) => !Object.is(internalListener, listener),\n ),\n ).length\n );\n }\n\n private _shouldUseNewBlock(newBlock: string) {\n const currentBlock = this._currentBlock;\n if (!currentBlock) {\n return true;\n }\n const newBlockInt = hexToInt(newBlock);\n const currentBlockInt = hexToInt(currentBlock);\n\n return (\n (this._usePastBlocks && newBlockInt < currentBlockInt) ||\n newBlockInt > currentBlockInt\n );\n }\n\n private _newPotentialLatest(newBlock: string): void {\n if (!this._shouldUseNewBlock(newBlock)) {\n return;\n }\n this._setCurrentBlock(newBlock);\n }\n\n private _setCurrentBlock(newBlock: string): void {\n const oldBlock = this._currentBlock;\n this._currentBlock = newBlock;\n this.emit('latest', newBlock);\n this.emit('sync', { oldBlock, newBlock });\n }\n\n private _setupBlockResetTimeout(): void {\n // clear any existing timeout\n this._cancelBlockResetTimeout();\n // clear latest block when stale\n this._blockResetTimeout = setTimeout(\n this._resetCurrentBlock,\n this._blockResetDuration,\n );\n\n // nodejs - dont hold process open\n if (this._blockResetTimeout.unref) {\n this._blockResetTimeout.unref();\n }\n }\n\n private _cancelBlockResetTimeout(): void {\n if (this._blockResetTimeout) {\n clearTimeout(this._blockResetTimeout);\n }\n }\n\n private _resetCurrentBlock(): void {\n this._currentBlock = null;\n }\n\n async checkForLatestBlock() {\n await this._updateLatestBlock();\n return await this.getLatestBlock();\n }\n\n private _start() {\n // Intentionally not awaited as this starts the polling via a timeout chain.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this._updateAndQueue();\n }\n\n private _end() {\n this._clearPollingTimeout();\n }\n\n private async _updateLatestBlock(): Promise<void> {\n // fetch + set latest block\n const latestBlock = await this._fetchLatestBlock();\n this._newPotentialLatest(latestBlock);\n }\n\n private async _fetchLatestBlock(): Promise<string> {\n // If there's already a pending fetch, reuse it\n if (this.#pendingFetch) {\n return await this.#pendingFetch.promise;\n }\n\n // Create a new deferred promise for this request\n const { promise, resolve, reject } = createDeferredPromise<string>({\n suppressUnhandledRejection: true,\n });\n this.#pendingFetch = { reject, promise };\n\n try {\n const req: ExtendedJsonRpcRequest = {\n jsonrpc: '2.0',\n id: createRandomId(),\n method: 'eth_blockNumber',\n params: [] as [],\n };\n if (this._setSkipCacheFlag) {\n req.skipCache = true;\n }\n\n log('Making request', req);\n const result = await this._provider.request<[], string>(req);\n log('Got result', result);\n resolve(result);\n return result;\n } catch (error) {\n log('Encountered error fetching block', getErrorMessage(error));\n reject(error);\n this.#rejectPendingLatestBlock(error);\n throw error;\n } finally {\n this.#pendingFetch = undefined;\n }\n }\n\n /**\n * The core polling function that runs after each interval.\n * Updates the latest block and then queues the next update.\n */\n private async _updateAndQueue() {\n let interval = this._pollingInterval;\n\n try {\n await this._updateLatestBlock();\n } catch (error: unknown) {\n try {\n this.emit('error', error);\n } catch {\n console.error(`Error updating latest block: ${getErrorMessage(error)}`);\n }\n\n interval = this._retryTimeout;\n }\n\n if (!this._isRunning) {\n return;\n }\n\n this._clearPollingTimeout();\n\n const timeoutRef = setTimeout(() => {\n // Intentionally not awaited as this just continues the polling loop.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this._updateAndQueue();\n }, interval);\n\n if (timeoutRef.unref && !this._keepEventLoopActive) {\n timeoutRef.unref();\n }\n\n this._pollingTimeout = timeoutRef;\n\n this.emit('_waitingForNextIteration');\n }\n\n _clearPollingTimeout() {\n if (this._pollingTimeout) {\n clearTimeout(this._pollingTimeout);\n this._pollingTimeout = undefined;\n }\n }\n\n #addInternalListener(listener: InternalListener) {\n this.#internalEventListeners.push(listener);\n }\n\n #removeInternalListener(listener: InternalListener) {\n this.#internalEventListeners.splice(\n this.#internalEventListeners.indexOf(listener),\n 1,\n );\n }\n\n #rejectPendingLatestBlock(error: unknown) {\n this.#pendingLatestBlock?.reject(error);\n this.#pendingLatestBlock = undefined;\n }\n}\n\n/**\n * Converts a number represented as a string in hexadecimal format into a native\n * number.\n *\n * @param hexInt - The hex string.\n * @returns The number.\n */\nfunction hexToInt(hexInt: string): number {\n return Number.parseInt(hexInt, 16);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/eth-block-tracker",
3
- "version": "12.0.0",
3
+ "version": "12.0.1",
4
4
  "description": "A block tracker for the Ethereum blockchain. Keeps track of the latest block",
5
5
  "repository": {
6
6
  "type": "git",