Skip to content

Conversation

@rekmarks
Copy link
Member

@rekmarks rekmarks commented Nov 5, 2025

Explanation

Migrates @metamask/eth-json-rpc-middleware to the JsonRpcEngineV2 conventions in a total overhaul of the package. The semantics of each middleware should be the same as before.

One potential behavioral difference is that request cloning within middleware now occurs with klona instead of klona/full. This is because klona/full copies property descriptors such that cloned requests are immutable but not frozen in the Object.isFrozen() sense. This is unlikely to make a difference in practice to us, since our request objects have historically been "plain" objects.

As with all #6327-related work up to this point, json-rpc-engine received minor refactors to facilitate the use of the new abstractions in situ.

Incidentally, all lint rule exceptions have been removed and all lint warnings and errors have been resolved for eth-json-rpc-middleware.

Several other packages are changed to support or in consequence of the migration:

  • network-controller
    • The NetworkClient is migrated to JsonRpcEngineV2.
    • The RpcService now uses Readonly<JsonRpcRequest> internally for request objects received via its request() method, since the "fetch" middleware now passes it deeply frozen request objects directly.
  • message-manager and signature-controller
    • Minor changes to types in order to harmonize them with the new conventions.

References

Checklist


Note

Migrates @metamask/eth-json-rpc-middleware and the NetworkClient to JsonRpcEngineV2, updates RPC request handling to use deeply frozen Readonly requests, and aligns related types and docs.

  • eth-json-rpc-middleware:
    • Migrate all middleware to JsonRpcEngineV2 (block-cache, block-ref, block-ref-rewrite, block-tracker-inspector, inflight-cache, retryOnEmpty, fetch, wallet, etc.).
    • Add providerAsMiddlewareV2; keep legacy adapter for backward compatibility.
    • Adopt MiddlewareContext (e.g., origin, skipCache) and immutable request/results; tests updated accordingly.
    • Normalize/validation utils adjusted to avoid mutation; new tests for read-only data.
    • Dependencies: add @metamask/message-manager, deep-freeze-strict (+ types).
  • network-controller:
    • Migrate NetworkClient pipeline to V2; compose V2 middleware; use providerFromMiddlewareV2.
    • RpcService.request now accepts Readonly<JsonRpcRequest>; add tests for frozen requests.
    • Minor: destroy signature relaxed; internal composition helpers updated.
  • message-manager & signature-controller:
    • Rename OriginalRequestMessageRequest and allow string id; update types/usages.
  • json-rpc-engine:
    • Docs: add migration guidance; minor typing/compat helpers updates.
  • Tooling/Meta:
    • Remove package-specific ESLint overrides; tweak coverage threshold; update changelogs.

Written by Cursor Bugbot for commit ae42d6d. This will update automatically on new commits. Configure here.

@rekmarks rekmarks force-pushed the rekm/ejrpc-rewrite-2 branch 3 times, most recently from 8bf6c31 to a345102 Compare November 5, 2025 20:41
@rekmarks

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@rekmarks

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@rekmarks rekmarks force-pushed the rekm/ejrpc-rewrite-2 branch from 1e01c22 to 50e1c81 Compare November 6, 2025 03:27
rekmarks added a commit that referenced this pull request Nov 6, 2025
… methods (#7061)

## Explanation

Adds a `MiddlewareContext` parameter to `InternalProvider.request()` and
`JsonRpcServer.handle()`. This is essentially a missing feature from the
`JsonRpcEngineV2` implementation / migration, since callers are no
longer able to add non-JSON-RPC properties to request objects and
instead need to use the `context` object.

As part of this, permit specifying a plain object as the context to
avoid forcing callers to import `MiddlewareContext` whenever they want
to make a JSON-RPC call with some particular context. Also
opportunistically fixes a bug with the static `isInstance` methods of V2
engine classes, where we wouldn't walk the prototype chain when checking
for the symbol property.

## References

- Related to #6327

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/contributing.md#updating-changelogs),
highlighting breaking changes as necessary
- ~I've prepared draft pull requests for clients and consumer packages
to resolve any breaking changes~
- These changes are non-breaking, and will in any event be exhaustively
covered via preview builds through #7065.



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a context option to
`InternalProvider.request()`/`JsonRpcServer.handle()`, enables passing
plain-object contexts across the V2 engine, makes `PollingBlockTracker`
context-generic, and narrows Network Controller’s `Provider` type;
updates tests/docs accordingly.
> 
> - **JSON-RPC Engine (v2)**:
> - Add `HandleOptions` with `context` (accepts `MiddlewareContext` or
plain object) and forward it through `handle()` and
`JsonRpcServer.handle()`.
> - Enhance `MiddlewareContext` (construct from KeyValues object,
`isInstance`) and export `InferKeyValues`; add shared `isInstance` util;
minor server refactor (static request coercion).
>   - Update README and tests for context passing and utils.
> - **eth-json-rpc-provider**:
> - Make `InternalProvider` generic over `Context`; `request()` accepts
`{ context }` and forwards to engine.
>   - Update tests and CHANGELOG.
> - **eth-block-tracker**:
> - Genericize `PollingBlockTracker` with `Context`; type provider as
`InternalProvider<Context>`; update CHANGELOG.
> - **Network Controller**:
> - Narrow `Provider` to `InternalProvider<MiddlewareContext<{ origin:
string; skipCache: boolean } & Record<string, unknown>>>`.
> - Type updates in `create-network-client`, tests, and helpers; update
CHANGELOG.
> - **Tests/Utilities**:
> - Update fakes (`FakeProvider`, `FakeBlockTracker`) and consumers to
new generic/context types.
> - Bridge controller test now uses `@metamask/network-controller`
`Provider`.
> - **Deps**:
>   - Add `@metamask/network-controller` to root `package.json`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c853283. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Base automatically changed from rekm/jrpce-internal-provider-context to main November 6, 2025 20:38
@rekmarks rekmarks force-pushed the rekm/ejrpc-rewrite-2 branch 2 times, most recently from 7e2d0c0 to 78988ea Compare November 6, 2025 21:27
@rekmarks rekmarks force-pushed the rekm/ejrpc-rewrite-2 branch from 78988ea to 536ed51 Compare November 6, 2025 21:28
@rekmarks
Copy link
Member Author

rekmarks commented Nov 7, 2025

@metamaskbot publish-preview

@MetaMask MetaMask deleted a comment from github-actions bot Nov 7, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Nov 7, 2025

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/account-tree-controller": "2.0.0-preview-5a558267",
  "@metamask-previews/accounts-controller": "34.0.0-preview-5a558267",
  "@metamask-previews/address-book-controller": "7.0.0-preview-5a558267",
  "@metamask-previews/analytics-controller": "0.0.0-preview-5a558267",
  "@metamask-previews/announcement-controller": "8.0.0-preview-5a558267",
  "@metamask-previews/app-metadata-controller": "2.0.0-preview-5a558267",
  "@metamask-previews/approval-controller": "8.0.0-preview-5a558267",
  "@metamask-previews/assets-controllers": "87.1.0-preview-5a558267",
  "@metamask-previews/base-controller": "9.0.0-preview-5a558267",
  "@metamask-previews/bridge-controller": "59.0.0-preview-5a558267",
  "@metamask-previews/bridge-status-controller": "59.0.0-preview-5a558267",
  "@metamask-previews/build-utils": "3.0.4-preview-5a558267",
  "@metamask-previews/chain-agnostic-permission": "1.2.2-preview-5a558267",
  "@metamask-previews/composable-controller": "12.0.0-preview-5a558267",
  "@metamask-previews/controller-utils": "11.15.0-preview-5a558267",
  "@metamask-previews/core-backend": "4.0.0-preview-5a558267",
  "@metamask-previews/delegation-controller": "1.0.0-preview-5a558267",
  "@metamask-previews/earn-controller": "9.0.0-preview-5a558267",
  "@metamask-previews/eip-5792-middleware": "2.0.0-preview-5a558267",
  "@metamask-previews/eip-7702-internal-rpc-middleware": "0.1.0-preview-5a558267",
  "@metamask-previews/eip1193-permission-middleware": "1.0.2-preview-5a558267",
  "@metamask-previews/ens-controller": "18.0.0-preview-5a558267",
  "@metamask-previews/error-reporting-service": "3.0.0-preview-5a558267",
  "@metamask-previews/eth-block-tracker": "14.0.0-preview-5a558267",
  "@metamask-previews/eth-json-rpc-middleware": "21.0.0-preview-5a558267",
  "@metamask-previews/eth-json-rpc-provider": "5.0.1-preview-5a558267",
  "@metamask-previews/foundryup": "1.0.1-preview-5a558267",
  "@metamask-previews/gas-fee-controller": "25.0.0-preview-5a558267",
  "@metamask-previews/gator-permissions-controller": "0.4.0-preview-5a558267",
  "@metamask-previews/json-rpc-engine": "10.1.1-preview-5a558267",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.8-preview-5a558267",
  "@metamask-previews/keyring-controller": "24.0.0-preview-5a558267",
  "@metamask-previews/logging-controller": "7.0.0-preview-5a558267",
  "@metamask-previews/message-manager": "14.0.0-preview-5a558267",
  "@metamask-previews/messenger": "0.3.0-preview-5a558267",
  "@metamask-previews/multichain-account-service": "2.1.0-preview-5a558267",
  "@metamask-previews/multichain-api-middleware": "1.2.4-preview-5a558267",
  "@metamask-previews/multichain-network-controller": "2.0.0-preview-5a558267",
  "@metamask-previews/multichain-transactions-controller": "6.0.0-preview-5a558267",
  "@metamask-previews/name-controller": "9.0.0-preview-5a558267",
  "@metamask-previews/network-controller": "25.0.0-preview-5a558267",
  "@metamask-previews/network-enablement-controller": "3.1.0-preview-5a558267",
  "@metamask-previews/notification-services-controller": "19.0.0-preview-5a558267",
  "@metamask-previews/permission-controller": "12.1.0-preview-5a558267",
  "@metamask-previews/permission-log-controller": "5.0.0-preview-5a558267",
  "@metamask-previews/phishing-controller": "15.0.0-preview-5a558267",
  "@metamask-previews/polling-controller": "15.0.0-preview-5a558267",
  "@metamask-previews/preferences-controller": "21.0.0-preview-5a558267",
  "@metamask-previews/profile-sync-controller": "26.0.0-preview-5a558267",
  "@metamask-previews/rate-limit-controller": "7.0.0-preview-5a558267",
  "@metamask-previews/remote-feature-flag-controller": "2.0.0-preview-5a558267",
  "@metamask-previews/sample-controllers": "3.0.0-preview-5a558267",
  "@metamask-previews/seedless-onboarding-controller": "6.1.0-preview-5a558267",
  "@metamask-previews/selected-network-controller": "25.0.0-preview-5a558267",
  "@metamask-previews/shield-controller": "2.0.0-preview-5a558267",
  "@metamask-previews/signature-controller": "36.0.0-preview-5a558267",
  "@metamask-previews/subscription-controller": "3.3.0-preview-5a558267",
  "@metamask-previews/token-search-discovery-controller": "4.0.0-preview-5a558267",
  "@metamask-previews/transaction-controller": "61.1.0-preview-5a558267",
  "@metamask-previews/transaction-pay-controller": "3.1.0-preview-5a558267",
  "@metamask-previews/user-operation-controller": "40.0.0-preview-5a558267"
}

@rekmarks rekmarks marked this pull request as ready for review November 7, 2025 08:26
@rekmarks rekmarks requested review from a team as code owners November 7, 2025 08:26
}
],
"include": ["../../types", "./src", "./test", "./types"]
"include": ["../../types", "./src", "./test"]
Copy link
Member Author

@rekmarks rekmarks Nov 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no ./types directory.

headers,
},
);
const jsonRpcResponse = await rpcService.request(klona(request), {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I naively cloned this, but I'm questioning whether we actually need to. The request is not mutated in rpc-service.ts. Can we just pass the frozen request?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can: 92a672c

"@metamask/eth-json-rpc-provider": "^5.0.1",
"@metamask/eth-sig-util": "^8.2.0",
"@metamask/json-rpc-engine": "^10.1.1",
"@metamask/message-manager": "^14.0.0",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type-only import, but the types appear in the public interface.

@rekmarks rekmarks force-pushed the rekm/ejrpc-rewrite-2 branch from 3225e4a to eb33694 Compare November 8, 2025 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants