@metamask/eth-block-tracker 13.0.0 → 14.0.0

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/CHANGELOG.md CHANGED
@@ -7,342 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ## [13.0.0]
10
+ ## [14.0.0]
11
11
 
12
12
  ### Changed
13
13
 
14
- - **BREAKING:** Distribute separate CommonJS and ESM files ([#351](https://github.com/MetaMask/eth-block-tracker/pull/351))
15
- - Use the `exports` field of `package.json`, breaking some previously valid imports.
14
+ - **BREAKING:** Update minimum Node.js version from `^18.16.0` to `^18.18.0` ([#6865](https://github.com/MetaMask/core/pull/6865))
15
+ - This package was migrated from `MetaMask/eth-block-tracker` to the
16
+ `MetaMask/core` monorepo ([#6865](https://github.com/MetaMask/core/pull/6865))
17
+ - See [`MetaMask/eth-block-tracker`](https://github.com/MetaMask/eth-block-tracker/blob/main/CHANGELOG.md)
18
+ for the original changelog.
16
19
 
17
- ## [12.2.1]
18
-
19
- ### Fixed
20
-
21
- - `PollingBlockTracker.checkForLatestBlock()` and `getLatestBlock()` now clear the cached block after `blockReset` duration when called and the `PollingBlockTracker` is not polling. ([#348](https://github.com/MetaMask/eth-block-tracker/pull/348))
22
-
23
- ## [12.2.0]
24
-
25
- ### Changed
26
-
27
- - `PollingBlockTracker.getLatestBlock()` now accepts an optional parameter `useCache` ([#340](https://github.com/MetaMask/eth-block-tracker/pull/340))
28
- - This option defaults to `true`, but when `false`, it ignores the cached block number and instead updates and returns a new block number, ensuring that the frequency of requests is limited to the `pollingInterval` period
29
-
30
- ## [12.1.0]
31
-
32
- ### Changed
33
-
34
- - Bump `@metamask/eth-json-rpc-provider` from `^4.1.5` to `^5.0.0` ([#334](https://github.com/MetaMask/eth-block-tracker/pull/334))
35
-
36
- ## [12.0.1]
37
-
38
- ### Fixed
39
-
40
- - Fixed hanging `getLatestBlock()` promises when block tracker is stopped before request completion ([#320](https://github.com/MetaMask/eth-block-tracker/pull/320))
41
- - Pending `getLatestBlock()` requests are now properly rejected with "Block tracker destroyed" error when the tracker is stopped
42
-
43
- ## [12.0.0]
44
-
45
- ### Changed
46
-
47
- - Errors that occur while polling are no longer wrapped ([#310](https://github.com/MetaMask/eth-block-tracker/pull/310))
48
-
49
- ### Removed
50
-
51
- - **BREAKING:** Remove `SubscribeBlockTracker` ([#309](https://github.com/MetaMask/eth-block-tracker/pull/309))
52
- - Although we continue to maintain this, we have not used it internally for quite some time. In general we have found a polling-based approval to be reliable than a subscription-based approach. We recommend using `PollingBlockTracker` instead.
53
-
54
- ### Fixed
55
-
56
- - Fix `PollingBlockTracker.getLatestBlock` so that it throws an error encountered while making the request instead of hanging, regardless of whether the request occurs inside or outside of a polling loop ([#313](https://github.com/MetaMask/eth-block-tracker/pull/313))
57
- - Fix `PollingBlockTracker.getLatestBlock` so that if invoked while a previous invocation is pending, it will throw if that invocation also throws ([#313](https://github.com/MetaMask/eth-block-tracker/pull/313))
58
-
59
- ## [11.0.4]
60
-
61
- ### Changed
62
-
63
- - Bump `@metamask/utils` from `^9.1.0` to `^11.0.1` ([#297](https://github.com/MetaMask/eth-block-tracker/pull/297))
64
-
65
- ## [11.0.3]
66
-
67
- ### Fixed
68
-
69
- - Avoid risk of infinite retry loops when fetching new blocks ([#284](https://github.com/MetaMask/eth-block-tracker/pull/284))
70
- - When the provider returns an error and `PollingBlockTracker` or `SubscribeBlockTracker` is destroyed, the promise returned by the `getLatestBlock` method will be rejected.
71
-
72
- ## [11.0.2]
73
-
74
- ### Fixed
75
-
76
- - Bump `@metamask/eth-json-rpc-provider` from `^4.1.1` to `^4.1.5` ([#273](https://github.com/MetaMask/eth-block-tracker/pull/273))
77
-
78
- ## [11.0.1]
79
-
80
- ### Changed
81
-
82
- - Bump `@metamask/eth-json-rpc-provider` from `^4.1.0` to `^4.1.1` ([#261](https://github.com/MetaMask/eth-block-tracker/pull/261))
83
- - Bump `@metamask/safe-event-emitter` from `^3.0.0` to `^3.1.1` ([#261](https://github.com/MetaMask/eth-block-tracker/pull/261))
84
- - Bump `@metamask/utils` from `^8.1.0` to `^9.1.0` ([#261](https://github.com/MetaMask/eth-block-tracker/pull/261))
85
-
86
- ## [11.0.0]
87
-
88
- ### Changed
89
-
90
- - **BREAKING**: Adapt to EIP-1193 provider changes by using `request` method of provider instead of `sendAsync` ([#252](https://github.com/MetaMask/eth-block-tracker/pull/252))
91
- - This change included in `10.1.0` was mistakenly categorised as a non-breaking change.
92
- - This requires provider object to have the `request` method. You need to upgrade to minimum `4.1.0` of `@metamask/eth-json-rpc-provider` so that the `request` method is available.
93
-
94
- ## [10.1.0] [DEPRECATED]
95
-
96
- ### Changed
97
-
98
- - Adapt to EIP-1193 provider changes ([#252](https://github.com/MetaMask/eth-block-tracker/pull/252))
99
- - Deprecated `sendAsync` method is replaced with `request` method
100
- - Bump `@metamask/eth-json-rpc-provider` from `^4.0.0` to `^4.1.0` ([#252](https://github.com/MetaMask/eth-block-tracker/pull/252))
101
-
102
- ## [10.0.0]
103
-
104
- ### Changed
105
-
106
- - BREAKING: Drop support for Node.js v16; add support for Node.js v20, v22 ([#245](https://github.com/MetaMask/eth-block-tracker/pull/245))
107
- - Update `@metamask/eth-json-rpc-provider` from `^3.0.2` to `^4.0.0` ([#247](https://github.com/MetaMask/eth-block-tracker/pull/247))
108
-
109
- ## [9.0.3]
110
-
111
- ### Fixed
112
-
113
- - Update dependency `@metamask/eth-json-rpc-engine` from `^7.1.1` to `^8.0.2` ([#235](https://github.com/MetaMask/eth-block-tracker/pull/235))
114
- - Update dependency `@metamask/eth-json-rpc-provider` from `^2.3.1` to `^3.0.2` ([#235](https://github.com/MetaMask/eth-block-tracker/pull/235))
115
-
116
- ## [9.0.2]
117
-
118
- ### Fixed
119
-
120
- - Put back missing empty `params` to `eth_blockNumber` call removed in 9.0.1 ([#198](https://github.com/MetaMask/eth-block-tracker/pull/198))
121
-
122
- ## [9.0.1]
123
-
124
- ### Fixed
125
-
126
- - Concurrency fix: Prevent multiple simultaneous polling loops ([#208](https://github.com/MetaMask/eth-block-tracker/pull/208))
127
- - Bump `@metamask/eth-json-rpc-provider` from `^2.1.0` to `^2.3.1` ([#198](https://github.com/MetaMask/eth-block-tracker/pull/198)) ([#217](https://github.com/MetaMask/eth-block-tracker/pull/217))
128
-
129
- ## [9.0.0]
130
-
131
- ### Changed
132
-
133
- - Rename package from `eth-block-tracker` to `@metamask/eth-block-tracker` ([#183](https://github.com/MetaMask/eth-block-tracker/pull/183))
134
-
135
- ## [8.1.0]
136
-
137
- ### Changed
138
-
139
- - Typescript: Add `checkForLatestBlock` function to `BlockTracker` interface ([#184](https://github.com/MetaMask/eth-block-tracker/pull/184))
140
-
141
- ## [8.0.0]
142
-
143
- ### Changed
144
-
145
- - Bump @metamask/utils from ^5.0.2 to ^8.1.0 ([#178](https://github.com/MetaMask/eth-block-tracker/pull/178))
146
- - **BREAKING**: Bump @metamask/eth-json-rpc-provider from ^1.0.0 to ^2.1.0 ([#174](https://github.com/MetaMask/eth-block-tracker/pull/174))
147
- - **BREAKING**: Increase minimum Node.js version to 16 ([#173](https://github.com/MetaMask/eth-block-tracker/pull/173))
148
-
149
- ## [7.2.0]
150
-
151
- ### Added
152
-
153
- - Typescript: Export `BlockTracker` interface ([#168](https://github.com/MetaMask/eth-block-tracker/pull/168))
154
-
155
- ### Changed
156
-
157
- - Dependency Updates: ([#165](https://github.com/MetaMask/eth-block-tracker/pull/165))
158
- - Bump pify from ^3.0.0 to ^5.0.0
159
- - Bump @metamask/utils from ^5.0.1 to ^5.0.2
160
-
161
- ## [7.1.0]
162
-
163
- ### Added
164
-
165
- - Add `usePastBlocks` to constructor ([#151](https://github.com/MetaMask/eth-block-tracker/pull/151))
166
- - Optional flag. When set to true, it allows blocks less than the current block number to be cached and returned.
167
-
168
- ## [7.0.1]
169
-
170
- ### Changed
171
-
172
- - Dependency updates:
173
- - Bump @metamask/utils from 5.0.1 to 5.0.2
174
- - [#141](https://github.com/MetaMask/eth-block-tracker/pull/141)
175
- - [#144](https://github.com/MetaMask/eth-block-tracker/pull/144)
176
- - Bump @metamask/safe-event-emitter from 2.0.0 to 3.0.0 ([#143](https://github.com/MetaMask/eth-block-tracker/pull/143))
177
-
178
- ## [7.0.0]
179
-
180
- ### Changed
181
-
182
- - **BREAKING:** The type of the `provider` option for `PollingBlockTracker` and `SubscribeBlockTracker` has changed ([#130](https://github.com/MetaMask/eth-block-tracker/pull/130))
183
- - The `provider` option must be compatible with the `SafeEventEmitterProvider` type from `@metamask/eth-json-rpc-middleware`.
184
- - The new provider type should be mostly equivalent, except that it's now expected to have a `send` method. We don't use that `send` method in this package though.
185
-
186
- ### Removed
187
-
188
- - **BREAKING:** Remove the `Provider` exported type ([#130](https://github.com/MetaMask/eth-block-tracker/pull/130))
189
- - We now use `@metamask/eth-json-rpc-provider` for this instead, so there was no need to re-export it.
190
-
191
- ## [6.1.0]
192
-
193
- ### Added
194
-
195
- - Add back Provider type that was accidentally removed in 6.0.0 ([#117](https://github.com/MetaMask/eth-block-tracker/pull/117))
196
-
197
- ### Fixed
198
-
199
- - Align Provider type with `eth-json-rpc-middleware` to prevent typecasting ([#117](https://github.com/MetaMask/eth-block-tracker/pull/117))
200
-
201
- ## [6.0.0]
202
-
203
- ### Added
204
-
205
- - Add logging ([#112](https://github.com/MetaMask/eth-block-tracker/pull/112))
206
- - You will not be able to see log messages by default, but you can turn them on for this library by setting the `DEBUG` environment variable to `metamask:eth-block-tracker:*` or `metamask:*`.
207
- - Add `destroy` method to block tracker classes ([#106](https://github.com/MetaMask/eth-block-tracker/pull/106))
208
- - Update PollingBlockTracker to support new `blockResetDuration` option ([#103](https://github.com/MetaMask/eth-block-tracker/pull/103))
209
- - Expose types that represent options to PollingBlockTracker and SubscribeBlockTracker constructors ([#103](https://github.com/MetaMask/eth-block-tracker/pull/103))
210
-
211
- ### Changed
212
-
213
- - **BREAKING:** Require Node >= 14 ([#113](https://github.com/MetaMask/eth-block-tracker/pull/113))
214
- - **BREAKING:** Make BaseBlockTracker abstract ([#103](https://github.com/MetaMask/eth-block-tracker/pull/103))
215
- - If you are using this class directly, you must only use PollingBlockTracker or SubscribeBlockTracker.
216
- - **BREAKING:** Make options for BaseBlockTracker required ([#103](https://github.com/MetaMask/eth-block-tracker/pull/103))
217
- - Subclasses must pass a set of options to `super` in their constructors.
218
- - Make argument to `removeAllListeners` in BaseBlockTracker optional ([#103](https://github.com/MetaMask/eth-block-tracker/pull/103))
219
- - **BREAKING:** Update signatures for `_start` and `_end` in BaseBlockTracker ([#103](https://github.com/MetaMask/eth-block-tracker/pull/103))
220
- - Subclasses must provide an implementation for both of these methods; they are no longer no-ops.
221
- - Both methods must return a promise.
222
- - Update SubscribeBlockTracker to not pass empty `newHeads` parameter to `eth_subscribe` call ([#108](https://github.com/MetaMask/eth-block-tracker/pull/108))
223
- - This change was made because OpenEthereum does not support this parameter. While we've done our best to confirm that this will not be a breaking change for other Ethereum implementations, you will want to confirm no breakages for yours.
224
-
225
- ### Security
226
-
227
- - Add `@lavamoat/allow-scripts` to ensure that install scripts are opt-in for dependencies ([#97](https://github.com/MetaMask/eth-block-tracker/pull/97))
228
-
229
- ## [5.0.1] - 2021-03-25
230
-
231
- ### Fixed
232
-
233
- - Add missing `types` field to `package.json` ([#75](https://github.com/MetaMask/eth-block-tracker/pull/75))
234
-
235
- ## [5.0.0] - 2021-03-25
236
-
237
- ### Changed
238
-
239
- - **(BREAKING)** Refactor exports ([#71](https://github.com/MetaMask/eth-block-tracker/pull/71))
240
- - **(BREAKING)** Target ES2017, remove ES5 builds ([#71](https://github.com/MetaMask/eth-block-tracker/pull/71))
241
- - Migrate to TypeScript ([#71](https://github.com/MetaMask/eth-block-tracker/pull/71))
242
- - Update various dependencies ([#44](https://github.com/MetaMask/eth-block-tracker/pull/44), [#49](https://github.com/MetaMask/eth-block-tracker/pull/49), [#54](https://github.com/MetaMask/eth-block-tracker/pull/54), [#59](https://github.com/MetaMask/eth-block-tracker/pull/59), [#61](https://github.com/MetaMask/eth-block-tracker/pull/61), [#62](https://github.com/MetaMask/eth-block-tracker/pull/62), [#63](https://github.com/MetaMask/eth-block-tracker/pull/63), [#70](https://github.com/MetaMask/eth-block-tracker/pull/70), [#72](https://github.com/MetaMask/eth-block-tracker/pull/72))
243
-
244
- ### Removed
245
-
246
- - Remove unused production dependencies ([#60](https://github.com/MetaMask/eth-block-tracker/pull/60), [#68](https://github.com/MetaMask/eth-block-tracker/pull/68))
247
-
248
- ## [4.4.3] - 2019-08-30
249
-
250
- ### Added
251
-
252
- - Add SubscribeBlockTracker
253
-
254
- ### Changed
255
-
256
- - Change events so that they now only return the block number (internal polling is done via `eth_blockNumber`)
257
- - Add `retryTimeout` and `keepEventLoopActive` to constructor
258
- - Update block trackers to inherit from `safe-event-emitter` rather than EventEmitter
259
-
260
- ### Removed
261
-
262
- - Remove `block` event
263
- - Please use `latest` or `sync`.
264
-
265
- ## [4.0.0] - 2018-04-26
266
-
267
- ### Added
268
-
269
- - Add isRunning method
270
- - Add `error` event
271
-
272
- ### Changed
273
-
274
- - Significantly rewrite `eth-block-tracker` (primarily due to optimizing network IO)
275
- - Rename `awaitCurrentBlock` to `getLatestBlock`
276
-
277
- ### Removed
278
-
279
- - Remove `stop`/`start` methods from BlockTrackers
280
- - BlockTrackers now automatically start and stop based on listener count for the `latest` and `sync` events. You can force a stop by calling the `EventEmitter` method `removeAllListeners`.
281
- - Remove tx body from block
282
- - Remove getTrackingBlock
283
- - Remove start/stop
284
- - Remove test/util/testBlockMiddleware
285
-
286
- ## [3.0.0] - 2018-04-16
287
-
288
- ### Changed
289
-
290
- - Update published version so main module now exports unprocessed source
291
- - Module includes dist:
292
- - Bundle: `dist/EthBlockTracker.js`
293
- - ES5 source: `dist/es5/`
294
- - Rename `lib` to `src`
295
- - Update RpcBlockTracker to be a normal `EventEmitter`
296
- - It no longer provides a callback to event handlers.
297
-
298
- ### Fixed
299
-
300
- - Fix `awaitCurrentBlock` return value
301
-
302
- ## [2.0.0] - 2017-06-14
303
-
304
- ### Added
305
-
306
- - Expose EventEmitter interface (via `async-eventemitter`)
307
- - Add `getTrackingBlock`, `getCurrentBlock`, `start`, and `stop`
308
- - Add events: `block`, `latest`, `sync`
309
-
310
- ## [1.0.0] - 2017-02-03
311
-
312
- ### Added
313
-
314
- - Add RpcBlockTracker
315
-
316
- [Unreleased]: https://github.com/MetaMask/eth-block-tracker/compare/v13.0.0...HEAD
317
- [13.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v12.2.1...v13.0.0
318
- [12.2.1]: https://github.com/MetaMask/eth-block-tracker/compare/v12.2.0...v12.2.1
319
- [12.2.0]: https://github.com/MetaMask/eth-block-tracker/compare/v12.1.0...v12.2.0
320
- [12.1.0]: https://github.com/MetaMask/eth-block-tracker/compare/v12.0.1...v12.1.0
321
- [12.0.1]: https://github.com/MetaMask/eth-block-tracker/compare/v12.0.0...v12.0.1
322
- [12.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v11.0.4...v12.0.0
323
- [11.0.4]: https://github.com/MetaMask/eth-block-tracker/compare/v11.0.3...v11.0.4
324
- [11.0.3]: https://github.com/MetaMask/eth-block-tracker/compare/v11.0.2...v11.0.3
325
- [11.0.2]: https://github.com/MetaMask/eth-block-tracker/compare/v11.0.1...v11.0.2
326
- [11.0.1]: https://github.com/MetaMask/eth-block-tracker/compare/v11.0.0...v11.0.1
327
- [11.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v10.1.0...v11.0.0
328
- [10.1.0]: https://github.com/MetaMask/eth-block-tracker/compare/v10.0.0...v10.1.0
329
- [10.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v9.0.3...v10.0.0
330
- [9.0.3]: https://github.com/MetaMask/eth-block-tracker/compare/v9.0.2...v9.0.3
331
- [9.0.2]: https://github.com/MetaMask/eth-block-tracker/compare/v9.0.1...v9.0.2
332
- [9.0.1]: https://github.com/MetaMask/eth-block-tracker/compare/v9.0.0...v9.0.1
333
- [9.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v8.1.0...v9.0.0
334
- [8.1.0]: https://github.com/MetaMask/eth-block-tracker/compare/v8.0.0...v8.1.0
335
- [8.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v7.2.0...v8.0.0
336
- [7.2.0]: https://github.com/MetaMask/eth-block-tracker/compare/v7.1.0...v7.2.0
337
- [7.1.0]: https://github.com/MetaMask/eth-block-tracker/compare/v7.0.1...v7.1.0
338
- [7.0.1]: https://github.com/MetaMask/eth-block-tracker/compare/v7.0.0...v7.0.1
339
- [7.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v6.1.0...v7.0.0
340
- [6.1.0]: https://github.com/MetaMask/eth-block-tracker/compare/v6.0.0...v6.1.0
341
- [6.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v5.0.1...v6.0.0
342
- [5.0.1]: https://github.com/MetaMask/eth-block-tracker/compare/v5.0.0...v5.0.1
343
- [5.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v4.4.3...v5.0.0
344
- [4.4.3]: https://github.com/MetaMask/eth-block-tracker/compare/v4.0.0...v4.4.3
345
- [4.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v3.0.0...v4.0.0
346
- [3.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v2.0.0...v3.0.0
347
- [2.0.0]: https://github.com/MetaMask/eth-block-tracker/compare/v1.0.0...v2.0.0
348
- [1.0.0]: https://github.com/MetaMask/eth-block-tracker/releases/tag/v1.0.0
20
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/eth-block-tracker@14.0.0...HEAD
21
+ [14.0.0]: https://github.com/MetaMask/core/releases/tag/@metamask/eth-block-tracker@14.0.0
package/README.md CHANGED
@@ -1,6 +1,4 @@
1
- # @metamask/eth-block-tracker
2
-
3
- <table><tr><td><p align="center"><b>⚠️ PLEASE READ ⚠️</b></p><p align="center">This package is currently being migrated to our <a href="https://github.com/MetaMask/core"><code>core</code></a> monorepo. Please do not make any commits to this repository while this migration is taking place, as they will not be transferred over.</p></td></tr></table>
1
+ # `@metamask/eth-block-tracker`
4
2
 
5
3
  This module walks the Ethereum blockchain, keeping track of the latest block. It uses a web3 provider as a data source and will continuously poll for the next block.
6
4
 
@@ -90,46 +88,4 @@ blockTracker.on('error', (err) => console.error(err));
90
88
 
91
89
  ## Contributing
92
90
 
93
- ### Setup
94
-
95
- - Install the current LTS version of [Node.js](https://nodejs.org)
96
- - If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm install` will install the latest version and running `nvm use` will automatically choose the right node version for you.
97
- - Install [Yarn](https://yarnpkg.com) v4 via [Corepack](https://github.com/nodejs/corepack?tab=readme-ov-file#how-to-install)
98
- - Run `yarn install` to install dependencies and run any required post-install scripts
99
-
100
- ### Testing and Linting
101
-
102
- Run `yarn test` to run the tests once. To run tests on file changes, run `yarn test:watch`.
103
-
104
- Run `yarn lint` to run the linter, or run `yarn lint:fix` to run the linter and fix any automatically fixable issues.
105
-
106
- ### Release & Publishing
107
-
108
- The project follows the same release process as the other libraries in the MetaMask organization. The GitHub Actions [`action-create-release-pr`](https://github.com/MetaMask/action-create-release-pr) and [`action-publish-release`](https://github.com/MetaMask/action-publish-release) are used to automate the release process; see those repositories for more information about how they work.
109
-
110
- 1. Choose a release version.
111
- - The release version should be chosen according to SemVer. Analyze the changes to see whether they include any breaking changes, new features, or deprecations, then choose the appropriate SemVer version. See [the SemVer specification](https://semver.org/) for more information.
112
-
113
- 2. If this release is backporting changes onto a previous release, then ensure there is a major version branch for that version (e.g. `1.x` for a `v1` backport release).
114
- - The major version branch should be set to the most recent release with that major version. For example, when backporting a `v1.0.2` release, you'd want to ensure there was a `1.x` branch that was set to the `v1.0.1` tag.
115
-
116
- 3. Trigger the [`workflow_dispatch`](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#workflow_dispatch) event [manually](https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow) for the `Create Release Pull Request` action to create the release PR.
117
- - For a backport release, the base branch should be the major version branch that you ensured existed in step 2. For a normal release, the base branch should be the main branch for that repository (which should be the default value).
118
- - This should trigger the [`action-create-release-pr`](https://github.com/MetaMask/action-create-release-pr) workflow to create the release PR.
119
-
120
- 4. Update the changelog to move each change entry into the appropriate change category ([See here](https://keepachangelog.com/en/1.0.0/#types) for the full list of change categories, and the correct ordering), and edit them to be more easily understood by users of the package.
121
- - 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.).
122
- - Try to explain each change in terms that users of the package would understand (e.g. avoid referencing internal variables/concepts).
123
- - Consolidate related changes into one change entry if it makes it easier to explain.
124
- - Run `yarn auto-changelog validate --rc --prettier` to check that the changelog is correctly formatted.
125
-
126
- 5. Review and QA the release.
127
- - If changes are made to the base branch, the release branch will need to be updated with these changes and review/QA will need to restart again. As such, it's probably best to avoid merging other PRs into the base branch while review is underway.
128
-
129
- 6. Squash & Merge the release.
130
- - This should trigger the [`action-publish-release`](https://github.com/MetaMask/action-publish-release) workflow to tag the final release commit and publish the release on GitHub.
131
-
132
- 7. Publish the release on npm.
133
- - Be very careful to use a clean local environment to publish the release, and follow exactly the same steps used during CI.
134
- - Use `npm publish --dry-run` to examine the release contents to ensure the correct files are included. Compare to previous releases if necessary (e.g. using `https://unpkg.com/browse/[package name]@[package version]/`).
135
- - Once you are confident the release contents are correct, publish the release using `npm publish`.
91
+ This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme).
@@ -303,7 +303,7 @@ class PollingBlockTracker extends safe_event_emitter_1.default {
303
303
  try {
304
304
  this.emit('error', error);
305
305
  }
306
- catch (_a) {
306
+ catch {
307
307
  console.error(`Error updating latest block: ${(0, utils_1.getErrorMessage)(error)}`);
308
308
  }
309
309
  interval = this._retryTimeout;
@@ -336,8 +336,7 @@ _PollingBlockTracker_internalEventListeners = new WeakMap(), _PollingBlockTracke
336
336
  }, _PollingBlockTracker_removeInternalListener = function _PollingBlockTracker_removeInternalListener(listener) {
337
337
  __classPrivateFieldGet(this, _PollingBlockTracker_internalEventListeners, "f").splice(__classPrivateFieldGet(this, _PollingBlockTracker_internalEventListeners, "f").indexOf(listener), 1);
338
338
  }, _PollingBlockTracker_rejectPendingLatestBlock = function _PollingBlockTracker_rejectPendingLatestBlock(error) {
339
- var _a;
340
- (_a = __classPrivateFieldGet(this, _PollingBlockTracker_pendingLatestBlock, "f")) === null || _a === void 0 ? void 0 : _a.reject(error);
339
+ __classPrivateFieldGet(this, _PollingBlockTracker_pendingLatestBlock, "f")?.reject(error);
341
340
  __classPrivateFieldSet(this, _PollingBlockTracker_pendingLatestBlock, undefined, "f");
342
341
  };
343
342
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"PollingBlockTracker.cjs","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 type PollingBlockTrackerOptions = {\n provider?: SafeEventEmitterProvider;\n pollingInterval?: number;\n retryTimeout?: number;\n keepEventLoopActive?: boolean;\n setSkipCacheFlag?: boolean;\n blockResetDuration?: number;\n usePastBlocks?: boolean;\n};\n\ntype ExtendedJsonRpcRequest = {\n skipCache?: boolean;\n} & JsonRpcRequest<[]>;\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({\n useCache = true,\n }: { useCache?: boolean } = {}): Promise<string> {\n // return if available\n if (this._currentBlock && useCache) {\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 if (this._isRunning) {\n try {\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 } else {\n // If tracker isn't running, just fetch directly\n try {\n const latestBlock = await this._updateLatestBlock();\n resolve(latestBlock);\n return latestBlock;\n } catch (error) {\n reject(error);\n throw error;\n } finally {\n // We want to rate limit calls to this method if we made a direct fetch\n // for the block number because the BlockTracker was not running. We\n // achieve this by delaying the unsetting of the #pendingLatestBlock promise.\n setTimeout(() => {\n this.#pendingLatestBlock = undefined;\n }, this._pollingInterval);\n }\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 /**\n * Checks for the latest block, updates the internal state, and returns the\n * value immediately rather than waiting for the next polling interval.\n *\n * @deprecated Use {@link getLatestBlock} instead.\n * @returns A promise that resolves to the latest block number.\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<string> {\n // fetch + set latest block\n const latestBlock = await this._fetchLatestBlock();\n this._newPotentialLatest(latestBlock);\n\n if (!this._isRunning) {\n // Ensure the one-time update is eventually reset once it's stale\n this._setupBlockResetTimeout();\n }\n\n // _newPotentialLatest() ensures that this._currentBlock is not null\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this._currentBlock!;\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.cjs","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 type PollingBlockTrackerOptions = {\n provider?: SafeEventEmitterProvider;\n pollingInterval?: number;\n retryTimeout?: number;\n keepEventLoopActive?: boolean;\n setSkipCacheFlag?: boolean;\n blockResetDuration?: number;\n usePastBlocks?: boolean;\n};\n\ntype ExtendedJsonRpcRequest = {\n skipCache?: boolean;\n} & JsonRpcRequest<[]>;\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({\n useCache = true,\n }: { useCache?: boolean } = {}): Promise<string> {\n // return if available\n if (this._currentBlock && useCache) {\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 if (this._isRunning) {\n try {\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 } else {\n // If tracker isn't running, just fetch directly\n try {\n const latestBlock = await this._updateLatestBlock();\n resolve(latestBlock);\n return latestBlock;\n } catch (error) {\n reject(error);\n throw error;\n } finally {\n // We want to rate limit calls to this method if we made a direct fetch\n // for the block number because the BlockTracker was not running. We\n // achieve this by delaying the unsetting of the #pendingLatestBlock promise.\n setTimeout(() => {\n this.#pendingLatestBlock = undefined;\n }, this._pollingInterval);\n }\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 /**\n * Checks for the latest block, updates the internal state, and returns the\n * value immediately rather than waiting for the next polling interval.\n *\n * @deprecated Use {@link getLatestBlock} instead.\n * @returns A promise that resolves to the latest block number.\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<string> {\n // fetch + set latest block\n const latestBlock = await this._fetchLatestBlock();\n this._newPotentialLatest(latestBlock);\n\n if (!this._isRunning) {\n // Ensure the one-time update is eventually reset once it's stale\n this._setupBlockResetTimeout();\n }\n\n // _newPotentialLatest() ensures that this._currentBlock is not null\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this._currentBlock!;\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"]}
@@ -11,7 +11,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
11
11
  };
12
12
  var _PollingBlockTracker_instances, _PollingBlockTracker_internalEventListeners, _PollingBlockTracker_pendingLatestBlock, _PollingBlockTracker_pendingFetch, _PollingBlockTracker_addInternalListener, _PollingBlockTracker_removeInternalListener, _PollingBlockTracker_rejectPendingLatestBlock;
13
13
  function $importDefault(module) {
14
- if (module === null || module === void 0 ? void 0 : module.__esModule) {
14
+ if (module?.__esModule) {
15
15
  return module.default;
16
16
  }
17
17
  return module;
@@ -304,7 +304,7 @@ export class PollingBlockTracker extends SafeEventEmitter {
304
304
  try {
305
305
  this.emit('error', error);
306
306
  }
307
- catch (_a) {
307
+ catch {
308
308
  console.error(`Error updating latest block: ${getErrorMessage(error)}`);
309
309
  }
310
310
  interval = this._retryTimeout;
@@ -336,8 +336,7 @@ _PollingBlockTracker_internalEventListeners = new WeakMap(), _PollingBlockTracke
336
336
  }, _PollingBlockTracker_removeInternalListener = function _PollingBlockTracker_removeInternalListener(listener) {
337
337
  __classPrivateFieldGet(this, _PollingBlockTracker_internalEventListeners, "f").splice(__classPrivateFieldGet(this, _PollingBlockTracker_internalEventListeners, "f").indexOf(listener), 1);
338
338
  }, _PollingBlockTracker_rejectPendingLatestBlock = function _PollingBlockTracker_rejectPendingLatestBlock(error) {
339
- var _a;
340
- (_a = __classPrivateFieldGet(this, _PollingBlockTracker_pendingLatestBlock, "f")) === null || _a === void 0 ? void 0 : _a.reject(error);
339
+ __classPrivateFieldGet(this, _PollingBlockTracker_pendingLatestBlock, "f")?.reject(error);
341
340
  __classPrivateFieldSet(this, _PollingBlockTracker_pendingLatestBlock, undefined, "f");
342
341
  };
343
342
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"PollingBlockTracker.mjs","sourceRoot":"","sources":["../src/PollingBlockTracker.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AACA,OAAO,gBAAgB,qCAAqC;AAC5D,OAAO,EACL,qBAAqB,EAErB,eAAe,EAEhB,wBAAwB;AACzB,OAAO,kBAAiB,2BAA2B;;AAGnD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,4BAAwB;AAEpE,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,uBAAuB,CAAC,CAAC;AACvE,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;AAC3C,MAAM,GAAG,GAAG,IAAI,CAAC;AAEjB,MAAM,kBAAkB,GAAwB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAkBnE,MAAM,OAAO,mBACX,SAAQ,gBAAgB;IA+BxB,YAAY,OAAmC,EAAE;QAC/C,wBAAwB;QACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;SACjE;QAED,KAAK,EAAE,CAAC;;QAZD,sDAA8C,EAAE,EAAC;QAE1D,0DAA+D;QAE/D,oDAAyD;QAUvD,SAAS;QACT,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,kBAAkB,IAAI,EAAE,GAAG,GAAG,CAAC;QAC/D,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,aAAa,IAAI,KAAK,CAAC;QAClD,QAAQ;QACR,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAExB,kCAAkC;QAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3D,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE7D,6BAA6B;QAC7B,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAE5B,SAAS;QACT,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,eAAe,IAAI,EAAE,GAAG,GAAG,CAAC;QACzD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;QACrE,IAAI,CAAC,oBAAoB;YACvB,IAAI,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC;QAC3E,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,IAAI,KAAK,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAChC,KAAK,CAAC,kBAAkB,EAAE,CAAC;QAC3B,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,EACnB,QAAQ,GAAG,IAAI,MACW,EAAE;QAC5B,sBAAsB;QACtB,IAAI,IAAI,CAAC,aAAa,IAAI,QAAQ,EAAE;YAClC,OAAO,IAAI,CAAC,aAAa,CAAC;SAC3B;QAED,IAAI,uBAAA,IAAI,+CAAoB,EAAE;YAC5B,OAAO,MAAM,uBAAA,IAAI,+CAAoB,CAAC,OAAO,CAAC;SAC/C;QAED,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,qBAAqB,CAAS;YACjE,0BAA0B,EAAE,IAAI;SACjC,CAAC,CAAC;QACH,uBAAA,IAAI,2CAAuB,EAAE,MAAM,EAAE,OAAO,EAAE,MAAA,CAAC;QAE/C,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB,IAAI;gBACF,0DAA0D;gBAC1D,MAAM,aAAa,GAAG,CAAC,KAAa,EAAE,EAAE;oBACtC,uBAAA,IAAI,mFAAwB,MAA5B,IAAI,EAAyB,aAAa,CAAC,CAAC;oBAC5C,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;oBAC7C,OAAO,CAAC,KAAK,CAAC,CAAC;gBACjB,CAAC,CAAC;gBAEF,uBAAA,IAAI,gFAAqB,MAAzB,IAAI,EAAsB,aAAa,CAAC,CAAC;gBACzC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;gBAEnC,OAAO,MAAM,OAAO,CAAC;aACtB;YAAC,OAAO,KAAK,EAAE;gBACd,MAAM,CAAC,KAAK,CAAC,CAAC;gBACd,MAAM,KAAK,CAAC;aACb;oBAAS;gBACR,uBAAA,IAAI,2CAAuB,SAAS,MAAA,CAAC;aACtC;SACF;aAAM;YACL,gDAAgD;YAChD,IAAI;gBACF,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACpD,OAAO,CAAC,WAAW,CAAC,CAAC;gBACrB,OAAO,WAAW,CAAC;aACpB;YAAC,OAAO,KAAK,EAAE;gBACd,MAAM,CAAC,KAAK,CAAC,CAAC;gBACd,MAAM,KAAK,CAAC;aACb;oBAAS;gBACR,uEAAuE;gBACvE,oEAAoE;gBACpE,6EAA6E;gBAC7E,UAAU,CAAC,GAAG,EAAE;oBACd,uBAAA,IAAI,2CAAuB,SAAS,MAAA,CAAC;gBACvC,CAAC,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;aAC3B;SACF;IACH,CAAC;IAED,oEAAoE;IACpE,kBAAkB,CAAC,SAA2B;QAC5C,8CAA8C;QAC9C,IAAI,SAAS,EAAE;YACb,KAAK,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;SACrC;aAAM;YACL,KAAK,CAAC,kBAAkB,EAAE,CAAC;SAC5B;QAED,yBAAyB;QACzB,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,kCAAkC;QAClC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,oBAAoB;QAC1B,yCAAyC;QACzC,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QACxD,IAAI,CAAC,cAAc,CAAC,gBAAgB,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC9D,gBAAgB;QAChB,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC5C,IAAI,CAAC,EAAE,CAAC,gBAAgB,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACpD,CAAC;IAEO,cAAc,CAAC,SAA0B;QAC/C,yDAAyD;QACzD,IAAI,kBAAkB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;YAC1C,gCAAgC;YAChC,IAAI,CAAC,WAAW,EAAE,CAAC;SACpB;IACH,CAAC;IAEO,iBAAiB;QACvB,6DAA6D;QAC7D,IAAI,IAAI,CAAC,0BAA0B,EAAE,GAAG,CAAC,EAAE;YACzC,OAAO;SACR;QACD,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAEO,WAAW;QACjB,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB,OAAO;SACR;QAED,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,uCAAuC;QACvC,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAChC,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxB,CAAC;IAEO,SAAS;QACf,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YACpB,OAAO;SACR;QAED,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,uBAAA,IAAI,qFAA0B,MAA9B,IAAI,EAA2B,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC;QACrE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtB,CAAC;IAEO,0BAA0B;QAChC,OAAO,CACL,kBAAkB;aACf,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;aAC7C,IAAI,EAAE;YACP,mDAAmD;aAClD,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CACnB,uBAAA,IAAI,mDAAwB,CAAC,KAAK,CAChC,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAC7D,CACF,CAAC,MAAM,CACX,CAAC;IACJ,CAAC;IAEO,kBAAkB,CAAC,QAAgB;QACzC,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC;QACxC,IAAI,CAAC,YAAY,EAAE;YACjB,OAAO,IAAI,CAAC;SACb;QACD,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,eAAe,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;QAE/C,OAAO,CACL,CAAC,IAAI,CAAC,cAAc,IAAI,WAAW,GAAG,eAAe,CAAC;YACtD,WAAW,GAAG,eAAe,CAC9B,CAAC;IACJ,CAAC;IAEO,mBAAmB,CAAC,QAAgB;QAC1C,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE;YACtC,OAAO;SACR;QACD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAEO,gBAAgB,CAAC,QAAgB;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC;QACpC,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5C,CAAC;IAEO,uBAAuB;QAC7B,6BAA6B;QAC7B,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAChC,gCAAgC;QAChC,IAAI,CAAC,kBAAkB,GAAG,UAAU,CAClC,IAAI,CAAC,kBAAkB,EACvB,IAAI,CAAC,mBAAmB,CACzB,CAAC;QAEF,kCAAkC;QAClC,IAAI,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE;YACjC,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;SACjC;IACH,CAAC;IAEO,wBAAwB;QAC9B,IAAI,IAAI,CAAC,kBAAkB,EAAE;YAC3B,YAAY,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;SACvC;IACH,CAAC;IAEO,kBAAkB;QACxB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,mBAAmB;QACvB,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAChC,OAAO,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;IACrC,CAAC;IAEO,MAAM;QACZ,4EAA4E;QAC5E,mEAAmE;QACnE,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAEO,IAAI;QACV,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAEO,KAAK,CAAC,kBAAkB;QAC9B,2BAA2B;QAC3B,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACnD,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAEtC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YACpB,iEAAiE;YACjE,IAAI,CAAC,uBAAuB,EAAE,CAAC;SAChC;QAED,oEAAoE;QACpE,oEAAoE;QACpE,OAAO,IAAI,CAAC,aAAc,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,iBAAiB;QAC7B,+CAA+C;QAC/C,IAAI,uBAAA,IAAI,yCAAc,EAAE;YACtB,OAAO,MAAM,uBAAA,IAAI,yCAAc,CAAC,OAAO,CAAC;SACzC;QAED,iDAAiD;QACjD,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,qBAAqB,CAAS;YACjE,0BAA0B,EAAE,IAAI;SACjC,CAAC,CAAC;QACH,uBAAA,IAAI,qCAAiB,EAAE,MAAM,EAAE,OAAO,EAAE,MAAA,CAAC;QAEzC,IAAI;YACF,MAAM,GAAG,GAA2B;gBAClC,OAAO,EAAE,KAAK;gBACd,EAAE,EAAE,cAAc,EAAE;gBACpB,MAAM,EAAE,iBAAiB;gBACzB,MAAM,EAAE,EAAQ;aACjB,CAAC;YACF,IAAI,IAAI,CAAC,iBAAiB,EAAE;gBAC1B,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;aACtB;YAED,GAAG,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAa,GAAG,CAAC,CAAC;YAC7D,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YAC1B,OAAO,CAAC,MAAM,CAAC,CAAC;YAChB,OAAO,MAAM,CAAC;SACf;QAAC,OAAO,KAAK,EAAE;YACd,GAAG,CAAC,kCAAkC,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;YAChE,MAAM,CAAC,KAAK,CAAC,CAAC;YACd,uBAAA,IAAI,qFAA0B,MAA9B,IAAI,EAA2B,KAAK,CAAC,CAAC;YACtC,MAAM,KAAK,CAAC;SACb;gBAAS;YACR,uBAAA,IAAI,qCAAiB,SAAS,MAAA,CAAC;SAChC;IACH,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,eAAe;QAC3B,IAAI,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAErC,IAAI;YACF,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;SACjC;QAAC,OAAO,KAAc,EAAE;YACvB,IAAI;gBACF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;aAC3B;YAAC,WAAM;gBACN,OAAO,CAAC,KAAK,CAAC,gCAAgC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;aACzE;YAED,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC;SAC/B;QAED,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YACpB,OAAO;SACR;QAED,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAE5B,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE;YACjC,qEAAqE;YACrE,mEAAmE;YACnE,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC,EAAE,QAAQ,CAAC,CAAC;QAEb,IAAI,UAAU,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE;YAClD,UAAU,CAAC,KAAK,EAAE,CAAC;SACpB;QAED,IAAI,CAAC,eAAe,GAAG,UAAU,CAAC;QAElC,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IACxC,CAAC;IAED,oBAAoB;QAClB,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACnC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;SAClC;IACH,CAAC;CAiBF;sTAfsB,QAA0B;IAC7C,uBAAA,IAAI,mDAAwB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC9C,CAAC,qGAEuB,QAA0B;IAChD,uBAAA,IAAI,mDAAwB,CAAC,MAAM,CACjC,uBAAA,IAAI,mDAAwB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAC9C,CAAC,CACF,CAAC;AACJ,CAAC,yGAEyB,KAAc;;IACtC,MAAA,uBAAA,IAAI,+CAAoB,0CAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,uBAAA,IAAI,2CAAuB,SAAS,MAAA,CAAC;AACvC,CAAC;AAGH;;;;;;GAMG;AACH,SAAS,QAAQ,CAAC,MAAc;IAC9B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC","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 type PollingBlockTrackerOptions = {\n provider?: SafeEventEmitterProvider;\n pollingInterval?: number;\n retryTimeout?: number;\n keepEventLoopActive?: boolean;\n setSkipCacheFlag?: boolean;\n blockResetDuration?: number;\n usePastBlocks?: boolean;\n};\n\ntype ExtendedJsonRpcRequest = {\n skipCache?: boolean;\n} & JsonRpcRequest<[]>;\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({\n useCache = true,\n }: { useCache?: boolean } = {}): Promise<string> {\n // return if available\n if (this._currentBlock && useCache) {\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 if (this._isRunning) {\n try {\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 } else {\n // If tracker isn't running, just fetch directly\n try {\n const latestBlock = await this._updateLatestBlock();\n resolve(latestBlock);\n return latestBlock;\n } catch (error) {\n reject(error);\n throw error;\n } finally {\n // We want to rate limit calls to this method if we made a direct fetch\n // for the block number because the BlockTracker was not running. We\n // achieve this by delaying the unsetting of the #pendingLatestBlock promise.\n setTimeout(() => {\n this.#pendingLatestBlock = undefined;\n }, this._pollingInterval);\n }\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 /**\n * Checks for the latest block, updates the internal state, and returns the\n * value immediately rather than waiting for the next polling interval.\n *\n * @deprecated Use {@link getLatestBlock} instead.\n * @returns A promise that resolves to the latest block number.\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<string> {\n // fetch + set latest block\n const latestBlock = await this._fetchLatestBlock();\n this._newPotentialLatest(latestBlock);\n\n if (!this._isRunning) {\n // Ensure the one-time update is eventually reset once it's stale\n this._setupBlockResetTimeout();\n }\n\n // _newPotentialLatest() ensures that this._currentBlock is not null\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this._currentBlock!;\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.mjs","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 type PollingBlockTrackerOptions = {\n provider?: SafeEventEmitterProvider;\n pollingInterval?: number;\n retryTimeout?: number;\n keepEventLoopActive?: boolean;\n setSkipCacheFlag?: boolean;\n blockResetDuration?: number;\n usePastBlocks?: boolean;\n};\n\ntype ExtendedJsonRpcRequest = {\n skipCache?: boolean;\n} & JsonRpcRequest<[]>;\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({\n useCache = true,\n }: { useCache?: boolean } = {}): Promise<string> {\n // return if available\n if (this._currentBlock && useCache) {\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 if (this._isRunning) {\n try {\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 } else {\n // If tracker isn't running, just fetch directly\n try {\n const latestBlock = await this._updateLatestBlock();\n resolve(latestBlock);\n return latestBlock;\n } catch (error) {\n reject(error);\n throw error;\n } finally {\n // We want to rate limit calls to this method if we made a direct fetch\n // for the block number because the BlockTracker was not running. We\n // achieve this by delaying the unsetting of the #pendingLatestBlock promise.\n setTimeout(() => {\n this.#pendingLatestBlock = undefined;\n }, this._pollingInterval);\n }\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 /**\n * Checks for the latest block, updates the internal state, and returns the\n * value immediately rather than waiting for the next polling interval.\n *\n * @deprecated Use {@link getLatestBlock} instead.\n * @returns A promise that resolves to the latest block number.\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<string> {\n // fetch + set latest block\n const latestBlock = await this._fetchLatestBlock();\n this._newPotentialLatest(latestBlock);\n\n if (!this._isRunning) {\n // Ensure the one-time update is eventually reset once it's stale\n this._setupBlockResetTimeout();\n }\n\n // _newPotentialLatest() ensures that this._currentBlock is not null\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this._currentBlock!;\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,14 +1,18 @@
1
1
  {
2
2
  "name": "@metamask/eth-block-tracker",
3
- "version": "13.0.0",
3
+ "version": "14.0.0",
4
4
  "description": "A block tracker for the Ethereum blockchain. Keeps track of the latest block",
5
- "homepage": "https://github.com/MetaMask/eth-block-tracker#readme",
5
+ "keywords": [
6
+ "MetaMask",
7
+ "Ethereum"
8
+ ],
9
+ "homepage": "https://github.com/MetaMask/core/tree/main/packages/eth-block-tracker#readme",
6
10
  "bugs": {
7
- "url": "https://github.com/MetaMask/eth-block-tracker/issues"
11
+ "url": "https://github.com/MetaMask/core/issues"
8
12
  },
9
13
  "repository": {
10
14
  "type": "git",
11
- "url": "https://github.com/MetaMask/eth-block-tracker.git"
15
+ "url": "https://github.com/MetaMask/core.git"
12
16
  },
13
17
  "license": "MIT",
14
18
  "sideEffects": false,
@@ -29,77 +33,49 @@
29
33
  "module": "./dist/index.mjs",
30
34
  "types": "./dist/index.d.cts",
31
35
  "files": [
32
- "dist"
36
+ "dist",
37
+ "dist/"
33
38
  ],
34
39
  "scripts": {
35
- "build": "ts-bridge --project tsconfig.build.json --clean",
36
- "build:clean": "rimraf dist && yarn build",
40
+ "build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
37
41
  "build:docs": "typedoc",
38
- "lint": "yarn lint:eslint && yarn lint:constraints && yarn lint:misc --check && yarn lint:dependencies --check && yarn lint:changelog",
39
- "lint:changelog": "auto-changelog validate --prettier",
40
- "lint:constraints": "yarn constraints",
41
- "lint:dependencies": "depcheck && yarn dedupe --check",
42
- "lint:dependencies:fix": "depcheck && yarn dedupe",
43
- "lint:eslint": "eslint . --cache",
44
- "lint:fix": "yarn lint:eslint --fix && yarn lint:constraints --fix && yarn lint:misc --write && yarn lint:dependencies:fix && yarn lint:changelog",
45
- "lint:misc": "prettier '**/*.json' '**/*.md' '**/*.yml' '!.yarnrc.yml' --ignore-path .gitignore --no-error-on-unmatched-pattern",
46
- "prepack": "./scripts/prepack.sh",
47
- "test": "jest && attw --pack",
48
- "test:watch": "jest --watch"
42
+ "changelog:update": "../../scripts/update-changelog.sh @metamask/eth-block-tracker",
43
+ "changelog:validate": "../../scripts/validate-changelog.sh @metamask/eth-block-tracker",
44
+ "lint": "yarn lint:eslint && yarn lint:misc --check && yarn lint:dependencies",
45
+ "lint:dependencies": "depcheck",
46
+ "lint:eslint": "eslint . --cache --ext js,ts",
47
+ "lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write && yarn lint:dependencies",
48
+ "lint:misc": "prettier '**/*.json' '**/*.md' '!CHANGELOG.md' '**/*.yml' '!.yarnrc.yml' --ignore-path .gitignore --no-error-on-unmatched-pattern",
49
+ "publish:preview": "yarn npm publish --tag preview",
50
+ "since-latest-release": "../../scripts/since-latest-release.sh",
51
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter",
52
+ "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache",
53
+ "test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
54
+ "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
49
55
  },
50
56
  "dependencies": {
51
- "@metamask/eth-json-rpc-provider": "^5.0.0",
52
- "@metamask/safe-event-emitter": "^3.1.1",
53
- "@metamask/utils": "^11.0.1",
57
+ "@metamask/eth-json-rpc-provider": "^5.0.1",
58
+ "@metamask/safe-event-emitter": "^3.0.0",
59
+ "@metamask/utils": "^11.8.1",
54
60
  "json-rpc-random-id": "^1.0.1"
55
61
  },
56
62
  "devDependencies": {
57
- "@arethetypeswrong/cli": "^0.15.3",
58
- "@jest/types": "^27.5.1",
59
- "@lavamoat/allow-scripts": "^3.0.4",
60
63
  "@metamask/auto-changelog": "^3.4.4",
61
- "@metamask/eslint-config": "^14.0.0",
62
- "@metamask/eslint-config-jest": "^14.0.0",
63
- "@metamask/eslint-config-nodejs": "^14.0.0",
64
- "@metamask/eslint-config-typescript": "^14.0.0",
65
- "@metamask/json-rpc-engine": "^10.0.0",
66
- "@ts-bridge/cli": "^0.6.3",
64
+ "@metamask/json-rpc-engine": "^10.1.1",
67
65
  "@types/jest": "^27.4.1",
68
66
  "@types/json-rpc-random-id": "^1.0.1",
69
- "@types/node": "^18.18",
70
- "@yarnpkg/types": "^4.0.1",
71
- "depcheck": "^1.4.3",
72
- "eslint": "^9.11.0",
73
- "eslint-config-prettier": "^9.1.0",
74
- "eslint-import-resolver-typescript": "^3.6.3",
75
- "eslint-plugin-import-x": "^4.3.0",
76
- "eslint-plugin-jest": "^28.8.3",
77
- "eslint-plugin-jsdoc": "^50.2.4",
78
- "eslint-plugin-n": "^17.10.3",
79
- "eslint-plugin-prettier": "^5.2.1",
80
- "eslint-plugin-promise": "^7.1.0",
67
+ "deepmerge": "^4.2.2",
81
68
  "jest": "^27.5.1",
82
- "prettier": "^3.3.3",
83
- "prettier-plugin-packagejson": "^2.5.8",
84
- "rimraf": "^3.0.2",
85
69
  "ts-jest": "^27.1.4",
86
- "ts-node": "^10.9.1",
87
70
  "typedoc": "^0.24.8",
88
- "typescript": "~5.2.2",
89
- "typescript-eslint": "^8.7.0"
71
+ "typedoc-plugin-missing-exports": "^2.0.0",
72
+ "typescript": "~5.2.2"
90
73
  },
91
- "packageManager": "yarn@4.5.3",
92
74
  "engines": {
93
- "node": "^18.16 || ^20 || >=22"
75
+ "node": "^18.18 || >=20"
94
76
  },
95
77
  "publishConfig": {
96
78
  "access": "public",
97
79
  "registry": "https://registry.npmjs.org/"
98
- },
99
- "lavamoat": {
100
- "allowScripts": {
101
- "@lavamoat/preinstall-always-fail": false,
102
- "eslint-plugin-import-x>unrs-resolver": false
103
- }
104
80
  }
105
81
  }