From e9f2a2a5c8d858bca444d09e6e4725edccb05963 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Fri, 4 Sep 2026 14:59:26 -0600 Subject: [PATCH 1/3] Move FakeBlockTracker to eth-block-tracker (as MockPollingBlockTracker) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `FakeBlockTracker` is a class defined in a top-level test helper file which provides a mock implementation of the `PollingBlockTracker` class in `eth-block-tracker`. Because this file uses types from `eth-block-tracker`, any package that wants to use `FakeBlockTracker` needs to depend on this package. `controller-utils` is such a package, and so it and `eth-block-tracker` are actually circular. That will create a problem when we try to add typechecking to all packages in CI. To address this and prevent future issues, we move `FakeBlockTracker` — now `MockPollingBlockTracker` — into `eth-block-tracker`, and we change all callsites to match. --- README.md | 1 + package.json | 3 -- packages/assets-controllers/package.json | 1 + .../src/NftDetectionController.test.ts | 4 +-- .../assets-controllers/tsconfig.build.json | 3 ++ packages/assets-controllers/tsconfig.json | 3 ++ packages/eth-block-tracker/jest.config.cjs | 6 ++++ .../src/MockPollingBlockTracker.ts | 36 +++++++++---------- packages/eth-block-tracker/src/index.ts | 1 + .../tests/NetworkController.test.ts | 4 +-- packages/network-controller/tests/helpers.ts | 7 ++-- packages/transaction-controller/package.json | 2 +- .../src/TransactionController.test.ts | 6 ++-- yarn.lock | 6 ++-- 14 files changed, 44 insertions(+), 39 deletions(-) rename tests/fake-block-tracker.ts => packages/eth-block-tracker/src/MockPollingBlockTracker.ts (55%) diff --git a/README.md b/README.md index 217db0a052c..c68b300cb33 100644 --- a/README.md +++ b/README.md @@ -310,6 +310,7 @@ linkStyle default opacity:0.5 assets_controllers --> remote_feature_flag_controller; assets_controllers --> storage_service; assets_controllers --> transaction_controller; + assets_controllers --> eth_block_tracker; assets_controllers --> eth_json_rpc_provider; authenticated_user_storage --> base_data_service; authenticated_user_storage --> controller_utils; diff --git a/package.json b/package.json index c69c3f0e098..e68ff7b4cfc 100644 --- a/package.json +++ b/package.json @@ -72,9 +72,6 @@ "@metamask/eslint-config-jest": "^15.0.0", "@metamask/eslint-config-nodejs": "^15.0.0", "@metamask/eslint-config-typescript": "^15.0.0", - "@metamask/eth-block-tracker": "^15.0.1", - "@metamask/eth-json-rpc-provider": "^6.0.1", - "@metamask/json-rpc-engine": "^10.5.0", "@metamask/network-controller": "^36.0.0", "@metamask/skills": "^0.1.0", "@metamask/utils": "^11.12.0", diff --git a/packages/assets-controllers/package.json b/packages/assets-controllers/package.json index 70ed4ff8408..ebbf0ae47c6 100644 --- a/packages/assets-controllers/package.json +++ b/packages/assets-controllers/package.json @@ -102,6 +102,7 @@ "@babel/runtime": "^7.23.9", "@metamask/account-api": "^2.0.0", "@metamask/auto-changelog": "^6.1.0", + "@metamask/eth-block-tracker": "^15.0.1", "@metamask/eth-json-rpc-provider": "^6.0.1", "@metamask/ethjs-provider-http": "^0.3.0", "@metamask/keyring-internal-api": "^12.0.0", diff --git a/packages/assets-controllers/src/NftDetectionController.test.ts b/packages/assets-controllers/src/NftDetectionController.test.ts index d767473299f..8260fd9e5e1 100644 --- a/packages/assets-controllers/src/NftDetectionController.test.ts +++ b/packages/assets-controllers/src/NftDetectionController.test.ts @@ -4,6 +4,7 @@ import { ChainId, InfuraNetworkType, } from '@metamask/controller-utils'; +import { MockPollingBlockTracker } from '@metamask/eth-block-tracker'; import { MockInternalProvider } from '@metamask/eth-json-rpc-provider'; import { MOCK_ANY_NAMESPACE, Messenger } from '@metamask/messenger'; import type { @@ -26,7 +27,6 @@ import { getDefaultPreferencesState } from '@metamask/preferences-controller'; import type { PreferencesState } from '@metamask/preferences-controller'; import nock from 'nock'; -import { FakeBlockTracker } from '../../../tests/fake-block-tracker.js'; import { jestAdvanceTime } from '../../../tests/helpers.js'; import { createMockInternalAccount } from '../../accounts-controller/tests/mocks.js'; import { @@ -781,7 +781,7 @@ describe('NftDetectionController', () => { type: NetworkClientType.Custom, }, provider, - blockTracker: new FakeBlockTracker({ provider }), + blockTracker: new MockPollingBlockTracker({ provider }), destroy: () => { // do nothing }, diff --git a/packages/assets-controllers/tsconfig.build.json b/packages/assets-controllers/tsconfig.build.json index 4c91e33d6f9..b4fbab67758 100644 --- a/packages/assets-controllers/tsconfig.build.json +++ b/packages/assets-controllers/tsconfig.build.json @@ -65,6 +65,9 @@ }, { "path": "../eth-json-rpc-provider/tsconfig.build.json" + }, + { + "path": "../eth-block-tracker/tsconfig.build.json" } ], "include": ["../../types", "./src"], diff --git a/packages/assets-controllers/tsconfig.json b/packages/assets-controllers/tsconfig.json index bf85cfc88ab..82befc583d4 100644 --- a/packages/assets-controllers/tsconfig.json +++ b/packages/assets-controllers/tsconfig.json @@ -64,6 +64,9 @@ }, { "path": "../eth-json-rpc-provider" + }, + { + "path": "../eth-block-tracker" } ], "include": ["../../types", "./src", "../../tests"] diff --git a/packages/eth-block-tracker/jest.config.cjs b/packages/eth-block-tracker/jest.config.cjs index ed2bf4de9b6..8e2133092fe 100644 --- a/packages/eth-block-tracker/jest.config.cjs +++ b/packages/eth-block-tracker/jest.config.cjs @@ -14,6 +14,12 @@ module.exports = merge(baseConfig, { // The display name when running multiple projects displayName, + // An array of regexp pattern strings used to skip coverage collection + coveragePathIgnorePatterns: [ + // This file is tested indirectly in other packages' test suites. + '.*/MockPollingBlockTracker\\.ts', + ], + // An object that configures minimum threshold enforcement for coverage results coverageThreshold: { global: { diff --git a/tests/fake-block-tracker.ts b/packages/eth-block-tracker/src/MockPollingBlockTracker.ts similarity index 55% rename from tests/fake-block-tracker.ts rename to packages/eth-block-tracker/src/MockPollingBlockTracker.ts index 735ac706874..5dea4325b37 100644 --- a/tests/fake-block-tracker.ts +++ b/packages/eth-block-tracker/src/MockPollingBlockTracker.ts @@ -1,23 +1,32 @@ -import { PollingBlockTracker } from '@metamask/eth-block-tracker'; import type { InternalProvider } from '@metamask/eth-json-rpc-provider'; import type { ContextConstraint, MiddlewareContext, } from '@metamask/json-rpc-engine/v2'; +import { Hex } from '@metamask/utils'; + +import { PollingBlockTracker } from './PollingBlockTracker.js'; /** * Acts like a PollingBlockTracker, but doesn't start the polling loop or * make any requests. */ -export class FakeBlockTracker< +export class MockPollingBlockTracker< Context extends ContextConstraint = MiddlewareContext, > extends PollingBlockTracker { - #latestBlockNumber = '0x0'; + latestBlockNumber: Hex; + + constructor({ + provider, + latestBlockNumber = '0x0', + }: { + provider: InternalProvider; + latestBlockNumber?: Hex; + }) { + super({ provider }); + + this.latestBlockNumber = latestBlockNumber; - constructor({ provider }: { provider: InternalProvider }) { - super({ - provider, - }); // Don't start the polling loop // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -26,20 +35,11 @@ export class FakeBlockTracker< }; } - /** - * Sets the number of the block that the block tracker will always return. - * - * @param latestBlockNumber - The block number to use. - */ - mockLatestBlockNumber(latestBlockNumber: string): void { - this.#latestBlockNumber = latestBlockNumber; - } - override async getLatestBlock(): Promise { - return this.#latestBlockNumber; + return this.latestBlockNumber; } override async checkForLatestBlock(): Promise { - return this.#latestBlockNumber; + return this.latestBlockNumber; } } diff --git a/packages/eth-block-tracker/src/index.ts b/packages/eth-block-tracker/src/index.ts index 32370f265de..ef158239f66 100644 --- a/packages/eth-block-tracker/src/index.ts +++ b/packages/eth-block-tracker/src/index.ts @@ -1,2 +1,3 @@ export * from './PollingBlockTracker.js'; export type * from './BlockTracker.js'; +export { MockPollingBlockTracker } from './MockPollingBlockTracker.js'; diff --git a/packages/network-controller/tests/NetworkController.test.ts b/packages/network-controller/tests/NetworkController.test.ts index 63b1f66b943..0b318595ca2 100644 --- a/packages/network-controller/tests/NetworkController.test.ts +++ b/packages/network-controller/tests/NetworkController.test.ts @@ -10,6 +10,7 @@ import { toHex, } from '@metamask/controller-utils'; import { PollingBlockTrackerOptions } from '@metamask/eth-block-tracker'; +import { MockPollingBlockTracker } from '@metamask/eth-block-tracker'; import type { MockInternalProviderStub } from '@metamask/eth-json-rpc-provider'; import { MockInternalProvider } from '@metamask/eth-json-rpc-provider'; import { rpcErrors } from '@metamask/rpc-errors'; @@ -20,7 +21,6 @@ import { when, resetAllWhenMocks, WhenMock } from 'jest-when'; import { inspect, isDeepStrictEqual, promisify } from 'util'; import { v4 as uuidV4 } from 'uuid'; -import { FakeBlockTracker } from '../../../tests/fake-block-tracker.js'; import { NetworkStatus } from '../src/constants.js'; import * as createAutoManagedNetworkClientModule from '../src/create-auto-managed-network-client.js'; import type { AutoManagedNetworkClient } from '../src/create-auto-managed-network-client.js'; @@ -16874,7 +16874,7 @@ function buildFakeClient( rpcUrl: 'https://test.network', }, provider, - blockTracker: new FakeBlockTracker({ + blockTracker: new MockPollingBlockTracker({ provider, }), destroy: (): void => { diff --git a/packages/network-controller/tests/helpers.ts b/packages/network-controller/tests/helpers.ts index 4dabb860d5c..55fcbd27b53 100644 --- a/packages/network-controller/tests/helpers.ts +++ b/packages/network-controller/tests/helpers.ts @@ -9,7 +9,7 @@ import { NetworksTicker, toHex, } from '@metamask/controller-utils'; -import type { InternalProvider } from '@metamask/eth-json-rpc-provider'; +import { MockPollingBlockTracker } from '@metamask/eth-block-tracker'; import { MockInternalProvider } from '@metamask/eth-json-rpc-provider'; import type { MockInternalProviderStub } from '@metamask/eth-json-rpc-provider'; import { Messenger, MOCK_ANY_NAMESPACE } from '@metamask/messenger'; @@ -21,7 +21,6 @@ import type { import type { CaipChainId, Hex } from '@metamask/utils'; import { v4 as uuidV4 } from 'uuid'; -import { FakeBlockTracker } from '../../../tests/fake-block-tracker.js'; import { buildTestObject } from '../../../tests/helpers.js'; import type { AutoManagedNetworkClient } from '../src/create-auto-managed-network-client.js'; import { NetworkController } from '../src/index.js'; @@ -236,9 +235,7 @@ function buildFakeNetworkClient({ return { configuration, provider, - blockTracker: new FakeBlockTracker({ - provider: provider as unknown as InternalProvider, - }), + blockTracker: new MockPollingBlockTracker({ provider }), destroy: (): void => { // do nothing }, diff --git a/packages/transaction-controller/package.json b/packages/transaction-controller/package.json index ef52e5fd18a..afafd1620f1 100644 --- a/packages/transaction-controller/package.json +++ b/packages/transaction-controller/package.json @@ -83,7 +83,7 @@ "@babel/runtime": "^7.23.9", "@metamask/auto-changelog": "^6.1.0", "@metamask/connectivity-controller": "^0.3.0", - "@metamask/eth-block-tracker": "^15.0.0", + "@metamask/eth-block-tracker": "^15.0.1", "@metamask/eth-json-rpc-provider": "^6.0.1", "@metamask/ethjs-provider-http": "^0.3.0", "@types/bn.js": "^5.1.5", diff --git a/packages/transaction-controller/src/TransactionController.test.ts b/packages/transaction-controller/src/TransactionController.test.ts index 1224db2bb45..b32d8f575f5 100644 --- a/packages/transaction-controller/src/TransactionController.test.ts +++ b/packages/transaction-controller/src/TransactionController.test.ts @@ -15,6 +15,7 @@ import { ORIGIN_METAMASK, InfuraNetworkType, } from '@metamask/controller-utils'; +import { MockPollingBlockTracker } from '@metamask/eth-block-tracker'; import type { InternalProvider } from '@metamask/eth-json-rpc-provider'; import { MockInternalProvider } from '@metamask/eth-json-rpc-provider'; import HttpProvider from '@metamask/ethjs-provider-http'; @@ -43,7 +44,6 @@ import assert from 'assert'; // eslint-disable-next-line import-x/namespace import * as uuidModule from 'uuid'; -import { FakeBlockTracker } from '../../../tests/fake-block-tracker.js'; import { flushPromises, jestAdvanceTime } from '../../../tests/helpers.js'; import { buildCustomNetworkClientConfiguration, @@ -198,9 +198,7 @@ function buildMockBlockTracker( latestBlockNumber: string, provider: InternalProvider, ): BlockTracker { - const fakeBlockTracker = new FakeBlockTracker({ provider }); - fakeBlockTracker.mockLatestBlockNumber(latestBlockNumber); - return fakeBlockTracker; + return new MockPollingBlockTracker({ provider, latestBlockNumber }); } /** diff --git a/yarn.lock b/yarn.lock index c7da4f0c294..7c23689ac07 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5886,6 +5886,7 @@ __metadata: "@metamask/contract-metadata": "npm:^2.4.0" "@metamask/controller-utils": "npm:^12.3.0" "@metamask/core-backend": "npm:^9.1.1" + "@metamask/eth-block-tracker": "npm:^15.0.1" "@metamask/eth-json-rpc-provider": "npm:^6.0.1" "@metamask/eth-query": "npm:^4.0.0" "@metamask/ethjs-provider-http": "npm:^0.3.0" @@ -6523,9 +6524,6 @@ __metadata: "@metamask/eslint-config-jest": "npm:^15.0.0" "@metamask/eslint-config-nodejs": "npm:^15.0.0" "@metamask/eslint-config-typescript": "npm:^15.0.0" - "@metamask/eth-block-tracker": "npm:^15.0.1" - "@metamask/eth-json-rpc-provider": "npm:^6.0.1" - "@metamask/json-rpc-engine": "npm:^10.5.0" "@metamask/network-controller": "npm:^36.0.0" "@metamask/skills": "npm:^0.1.0" "@metamask/utils": "npm:^11.12.0" @@ -9193,7 +9191,7 @@ __metadata: "@metamask/connectivity-controller": "npm:^0.3.0" "@metamask/controller-utils": "npm:^12.3.0" "@metamask/core-backend": "npm:^9.1.1" - "@metamask/eth-block-tracker": "npm:^15.0.0" + "@metamask/eth-block-tracker": "npm:^15.0.1" "@metamask/eth-json-rpc-provider": "npm:^6.0.1" "@metamask/ethjs-provider-http": "npm:^0.3.0" "@metamask/gas-fee-controller": "npm:^26.3.2" From 4bc8f8c6940a15c120c11c9d7dfd3b1d913539b0 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Wed, 9 Sep 2026 13:25:01 -0600 Subject: [PATCH 2/3] Fix type error --- .../src/MultichainTransactionsController.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/multichain-transactions-controller/src/MultichainTransactionsController.ts b/packages/multichain-transactions-controller/src/MultichainTransactionsController.ts index 92fd043768b..9792b7a9946 100644 --- a/packages/multichain-transactions-controller/src/MultichainTransactionsController.ts +++ b/packages/multichain-transactions-controller/src/MultichainTransactionsController.ts @@ -313,6 +313,10 @@ export class MultichainTransactionsController extends BaseController< } chainUpdates.forEach(({ chain, entry }) => { + // Using `@ts-ignore` instead of `@ts-expect-error` since this error + // comes and goes after unrelated changes. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore: TS2589: Type instantiation is excessively deep and possibly infinite. state.nonEvmTransactions[account.id][chain as CaipChainId] = entry; }); }); From 53fde542b47f83ef28b9dc330db5b3d9c206e122 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Wed, 9 Sep 2026 14:04:19 -0600 Subject: [PATCH 3/3] Align dependencies --- packages/assets-controllers/package.json | 2 +- yarn.lock | 26 +----------------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/packages/assets-controllers/package.json b/packages/assets-controllers/package.json index 9438046926b..9e35cea0876 100644 --- a/packages/assets-controllers/package.json +++ b/packages/assets-controllers/package.json @@ -102,7 +102,7 @@ "@babel/runtime": "^7.23.9", "@metamask/account-api": "^2.0.0", "@metamask/auto-changelog": "^6.1.0", - "@metamask/eth-block-tracker": "^15.0.1", + "@metamask/eth-block-tracker": "^16.0.0", "@metamask/eth-json-rpc-provider": "^7.0.0", "@metamask/ethjs-provider-http": "^0.3.0", "@metamask/keyring-internal-api": "^12.0.0", diff --git a/yarn.lock b/yarn.lock index df410dcf6cc..7be9de280d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5909,7 +5909,7 @@ __metadata: "@metamask/contract-metadata": "npm:^2.4.0" "@metamask/controller-utils": "npm:^13.0.0" "@metamask/core-backend": "npm:^10.0.0" - "@metamask/eth-block-tracker": "npm:^15.0.1" + "@metamask/eth-block-tracker": "npm:^16.0.0" "@metamask/eth-json-rpc-provider": "npm:^7.0.0" "@metamask/eth-query": "npm:^4.0.0" "@metamask/ethjs-provider-http": "npm:^0.3.0" @@ -6902,18 +6902,6 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-block-tracker@npm:^15.0.1": - version: 15.0.1 - resolution: "@metamask/eth-block-tracker@npm:15.0.1" - dependencies: - "@metamask/eth-json-rpc-provider": "npm:^6.0.0" - "@metamask/safe-event-emitter": "npm:^3.0.0" - "@metamask/utils": "npm:^11.9.0" - json-rpc-random-id: "npm:^1.0.1" - checksum: 10/8c0e0f5bde00fb40aa240fc562c29d0ce84156402132705d387c95453c6f265b3b738c9b649510771965d8b5b8036c2bdc6406142ff634383bf60df3741bdbfe - languageName: node - linkType: hard - "@metamask/eth-block-tracker@npm:^16.0.0, @metamask/eth-block-tracker@workspace:packages/eth-block-tracker": version: 0.0.0-use.local resolution: "@metamask/eth-block-tracker@workspace:packages/eth-block-tracker" @@ -7024,18 +7012,6 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-json-rpc-provider@npm:^6.0.0": - version: 6.0.1 - resolution: "@metamask/eth-json-rpc-provider@npm:6.0.1" - dependencies: - "@metamask/json-rpc-engine": "npm:^10.2.4" - "@metamask/rpc-errors": "npm:^7.0.2" - "@metamask/utils": "npm:^11.9.0" - nanoid: "npm:^3.3.8" - checksum: 10/06078a9e43b02f35387a3ccfe09733c7eeac2a732dee1f1be53254fc05719e230776b8512b13702a178fb692088fc7da46f727c5064550d65f51ac59d44f9d83 - languageName: node - linkType: hard - "@metamask/eth-json-rpc-provider@npm:^7.0.0, @metamask/eth-json-rpc-provider@workspace:packages/eth-json-rpc-provider": version: 0.0.0-use.local resolution: "@metamask/eth-json-rpc-provider@workspace:packages/eth-json-rpc-provider"