Skip to content

refactor!: Add consolidated legacy method middleware#8583

Open
rekmarks wants to merge 22 commits intomainfrom
rekm/v2-permitted-handlers
Open

refactor!: Add consolidated legacy method middleware#8583
rekmarks wants to merge 22 commits intomainfrom
rekm/v2-permitted-handlers

Conversation

@rekmarks
Copy link
Copy Markdown
Member

@rekmarks rekmarks commented Apr 24, 2026

Explanation

Consolidates the bespoke makeMethodMiddlewareMaker implementations from the
MetaMask extension and mobile clients into a single legacy createMethodMiddleware
exported from @metamask/json-rpc-engine, and removes the unused permitted
method handlers from @metamask/permission-controller.

@metamask/json-rpc-engine

  • Adds a legacy createMethodMiddleware that builds a JsonRpcEngine middleware
    from a record of handlers keyed by method name. Hooks are validated against the
    union of hookNames declared by the handlers (rejecting both missing and
    extraneous hooks), and incoming requests are dispatched by method.
  • Handlers may declare actionNames and receive a per-handler delegated
    Messenger as the sixth argument to implementation, mirroring the v2
    createMethodMiddleware.
  • The legacy and v2 versions share their hook selection / validation and
    messenger delegation utilities (assertExpectedHooks, selectHooks,
    createHandlerMessenger).
  • The legacy export is deprecated in favor of the v2 createMethodMiddleware.
    It exists only to give the extension and mobile clients a consolidated
    migration target before they move to JsonRpcEngineV2.

@metamask/eip1193-permission-middleware (BREAKING)

  • Reshapes the per-method exports (getPermissionsHandler,
    requestPermissionsHandler, revokePermissionsHandler) into the new
    MethodHandler format and consolidates them into a single methodHandlers
    export keyed by method name. The individual handler exports are removed.

@metamask/multichain-api-middleware (BREAKING)

  • Reshapes the per-method exports (walletCreateSession, walletGetSession,
    walletInvokeMethod, walletRevokeSession) into the new MethodHandler
    format and consolidates them into a single methodHandlers export keyed by
    method name. The individual handler exports are removed.

@metamask/permission-controller (BREAKING)

  • Removes the permitted RPC method handler modules (getPermissions,
    requestPermissions, revokePermissions) and the related
    permissionRpcMethods and PermittedHandlerExport exports. These were unused
    in practice. Replacement types are available in
    @metamask/[email protected].

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

High Risk
Breaking export and typing changes across multiple published packages plus new middleware dispatch/validation logic could impact downstream integrations and runtime hook wiring.

Overview
Adds a deprecated legacy createMethodMiddleware export to @metamask/json-rpc-engine that dispatches JSON-RPC requests by req.method, enforces exact hook sets (missing/extraneous), and optionally delegates a per-handler Messenger when actionNames are declared; shared utilities (selectHooks, assertExpectedHooks, createHandlerMessenger) are centralized in v2/utils and v2 middleware is updated to support no-messenger/no-hooks handlers.

Introduces breaking API reshapes in @metamask/eip1193-permission-middleware and @metamask/multichain-api-middleware by replacing per-method exports with a single methodHandlers map keyed by method name, updating handlers to the new MethodHandler typing, and adding construction tests via createMethodMiddleware.

Removes @metamask/permission-controller permitted RPC method modules/exports and related types, and tightens a couple of behaviors: wallet_invokeMethod now returns invalidParams when params isn’t an object, and wallet_createSession makes trackSessionCreatedEvent a required hook (nullable to disable).

Reviewed by Cursor Bugbot for commit 846bfc4. Bugbot is set up for automated code reviews on this repo. Configure here.

rekmarks and others added 3 commits April 24, 2026 13:32
Add `createMethodMiddlewareFactory` to the legacy (v1) surface,
consolidating the near-identical `makeMethodMiddlewareMaker`
implementations from metamask-extension and metamask-mobile. The new
export is deprecated in favor of the v2 `createMethodMiddleware`.

Extract `selectHooks` and `assertExpectedHooks` into a shared
`hookUtils.ts` module used by both v1 and v2. v2 now performs the same
strict missing/extraneous hook validation as v1 at middleware
construction time.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
@rekmarks rekmarks changed the title refactor!: Consolidate legacy method middleware implementation refactor!: Add consolidated legacy method middleware Apr 24, 2026
@rekmarks

This comment was marked as resolved.

cursor[bot]

This comment was marked as resolved.

Comment thread packages/permission-controller/CHANGELOG.md Outdated
Comment thread packages/json-rpc-engine/src/v2/index.ts
Comment thread packages/json-rpc-engine/src/createMethodMiddleware.ts Outdated
Comment thread packages/json-rpc-engine/src/createMethodMiddleware.test.ts Outdated
rekmarks and others added 4 commits April 27, 2026 09:50
…thod middleware

Allow `Messenger<string, never>` in the no-actions branch of
`CreateMethodMiddlewareFactoryOptions` so callers may still pass a
no-op root messenger when handlers declare no actions.

Pre-select hooks per handler at curried-call time and store them on a
`ResolvedHandler` entry, mirroring v2's dispatch shape and removing
`selectHooks` from the per-request path.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
@rekmarks

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

Comment thread packages/json-rpc-engine/src/createMethodMiddleware.ts Outdated
Comment thread packages/json-rpc-engine/src/createMethodMiddleware.test.ts Outdated
Comment thread packages/json-rpc-engine/src/createMethodMiddleware.test.ts Outdated
Comment thread packages/json-rpc-engine/src/createMethodMiddleware.ts Outdated
Overload createMethodMiddleware (v1 and v2) so messenger is optional when
handlers do not use messenger actions. Move actionNames/root validation
into createHandlerMessenger; add tests for no-messenger and missing-root
cases.

Made-with: Cursor
Add a fifth generic to MethodHandlerImplementation and MethodHandler so
callers can type non-standard JSON-RPC request fields (e.g. origin) without
widening JsonRpcEngine types. Extras are optionalized on the request
parameter so middleware can pass a plain JsonRpcRequest. Add a test and
changelog note.

Made-with: Cursor
@rekmarks rekmarks marked this pull request as ready for review April 28, 2026 21:21
@rekmarks rekmarks requested a review from a team as a code owner April 28, 2026 21:21
@rekmarks rekmarks requested a review from a team as a code owner April 28, 2026 21:21
@rekmarks
Copy link
Copy Markdown
Member Author

@cursor review

@rekmarks
Copy link
Copy Markdown
Member Author

@metamaskbot publish-preview

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 45a82ea. Configure here.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 86dd857. Configure here.

Comment thread packages/multichain-api-middleware/src/handlers/wallet-createSession.ts Outdated
const middleware = createMethodMiddleware({
handlers: { callAction: messengerHandler },
messenger: rootMessenger,
hooks: {},
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm unsure exactly why but the inference does not work as well as in the v2 version, for example here if you add extraneous hooks you do not get a type error.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed here: f43f664

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wonder why we aren't using this package in the clients 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Great question. Didn't realize that. @jiexi do you know the status of this package?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The package is used in mobile, but its integration was overlooked in the extension. It can be added there once the other changes in this PR have been integrated.

Comment thread packages/multichain-api-middleware/src/handlers/wallet-invokeMethod.ts Outdated
rekmarks and others added 3 commits April 29, 2026 08:46
Type the `hooks` property as `Record<string, never>` (rather than
collapsing to `unknown` via `UnionToIntersection<never>`) when no
handler declares hooks. This forces callers to spell out `hooks: {}`
and prevents TypeScript from co-resolving the shared `Handlers` generic
in a way that also relaxes the `messenger` requirement.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
Comment on lines +191 to +192
| readonly HandlerActions<Handlers[keyof Handlers]>['type'][]
| undefined,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ahh i see. Because it's too early to type this in AnyMethodHandler itself. fun

Comment thread packages/multichain-api-middleware/CHANGELOG.md
@jiexi
Copy link
Copy Markdown
Member

jiexi commented Apr 29, 2026

nit with the naming of the handler type. For example

type RevokePermissionsHandler = MethodHandler<...>;

export const revokePermissions = {
  ...
} satisfies RevokePermissionsHandler;

export const revokePermissionsHandler = {
  [MethodNames.RevokePermissions]: revokePermissions,
}

This is awkward to me because on first read, revokePermissions should be called revokePermissionsHandler to me, especially since it satisfies RevokePermissionsHandler. But the pattern in this PR has been to define revokePermissionsHandler as the Record<string, MethodHandler> object. I'm not sure what to rename the existing revokePermissionsHandler / the type for revokePermissionsHandler though

Comment thread packages/json-rpc-engine/src/v2/utils.ts Outdated
Comment thread packages/json-rpc-engine/src/v2/utils.ts
Comment thread packages/json-rpc-engine/src/createMethodMiddleware.test.ts Outdated
jiexi
jiexi previously approved these changes Apr 29, 2026
Rename the per-method handler constants to `<methodName>Handler` (e.g.
`getPermissions` → `getPermissionsHandler`, `walletCreateSession` →
`walletCreateSessionHandler`) and export their corresponding type
aliases. Drop the per-file `Record<methodName, handler>` wrappers; the
consolidated `methodHandlers` map is now built directly in each
package's index, using computed property keys from a `MethodNames`
const object (or the existing enum, in `eip1193-permission-middleware`)
to satisfy the naming-convention lint rule.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
@rekmarks
Copy link
Copy Markdown
Member Author

@metamaskbot publish-preview

@rekmarks rekmarks enabled auto-merge April 29, 2026 22:50
@rekmarks rekmarks disabled auto-merge April 29, 2026 22:50
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.

3 participants