feat(messenger): add getRegisteredActionTypes accessor#9271
Merged
Conversation
ad9e23f to
41944f4
Compare
Add a public, read-only `getRegisteredActionTypes()` method to the `Messenger` class that returns every action type the messenger can call directly — actions registered on it plus actions delegated into it. This gives consumers a way to discover a messenger's callable action surface (needed by an upcoming `mm daemon list` command in `@metamask/wallet-cli`). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
41944f4 to
c14f260
Compare
| * Get the types of all actions that this messenger can call directly. | ||
| * | ||
| * This includes actions registered on this messenger as well as actions that | ||
| * have been delegated into it from another messenger. It does not include |
Member
There was a problem hiding this comment.
Suggested change
| * have been delegated into it from another messenger. It does not include | |
| * have been delegated to it from another messenger. It does not include |
nit
| * Get the types of all actions that this messenger can call directly. | ||
| * | ||
| * This includes actions registered on this messenger as well as actions that | ||
| * have been delegated into it from another messenger. It does not include |
Member
There was a problem hiding this comment.
I don't follow the last line: "It does not include actions this messenger has delegated out to other messengers". Can you elaborate on that?
Member
Author
There was a problem hiding this comment.
Actually that line is misleading and I removed it 2a4dfbf Thanks!
FrederikBolding
approved these changes
Jun 29, 2026
pull Bot
pushed a commit
to dmrazzy/core
that referenced
this pull request
Jul 1, 2026
…MetaMask#9339) ## What `mm daemon call <Controller>:<method>` can dispatch **any** registered messenger action, but a consumer had no way to see what's callable — and the surface grows silently as controllers are wired. This adds `mm daemon list` to enumerate it. - **`listActions` RPC handler** in the daemon, backed by the live messenger's `getRegisteredActionTypes()` (landed in MetaMask#9271), so the list can never drift from what `call` actually accepts — no hand-kept catalog to rot. - **`mm daemon list` command** renders an indented, counted list on a TTY, and a bare, sorted, newline-delimited list when piped (so it pipes cleanly into `grep`/`fzf`). - **README** usage section refreshed: documents `list`, frames the surface as evolving (not a stability contract), links out to each controller's TypeDoc/README for exhaustive detail, and drops the stale `@deprecated AccountsController:listAccounts` example (fixed to `KeyringController:getState`). ## Testing - New `list.test.ts` and a `listActions` handler test in `daemon-entry.test.ts`; package stays at 100% coverage. - `build`, `test`, `lint`, and `changelog:validate` all pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > CLI-only discovery and error-message refactors; no changes to wallet auth, key handling, or messenger dispatch semantics beyond a read-only introspection RPC. > > **Overview** > Adds **`mm daemon list`** so users can see which messenger actions the running wallet daemon accepts via `daemon call`, without maintaining a static catalog. > > The daemon exposes a new **`listActions`** JSON-RPC handler that returns `messenger.getRegisteredActionTypes()`, keeping discovery aligned with what `call` can dispatch. The CLI sorts actions lexicographically: on a TTY it prints a counted, indented list with usage hints; when piped it emits a bare newline-delimited list for `grep`/`fzf`. > > **`mm daemon call`** now shares centralized socket and JSON-RPC error handling via `makeDaemonConnectionError`, `formatJsonRpcError`, and `isStringArray` in `daemon/utils`, including clearer messages for `ECONNRESET` and permission errors. README and changelog document `list` and refresh `call` examples. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e9a0545. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation
Adds a public, read-only accessor
Messenger.getRegisteredActionTypes()that returns the action types a messenger cancall()directly — actions registered on it plus actions delegated into it from a child messenger. It returns[...this.#actions.keys()].There is no public way to enumerate a messenger's callable actions today.
Why
string[]and notAction['type'][]The first instinct is to type the return as the messenger's action-type union for nicer caller types. That's not safe here: it would make
Actionappear in a covariant (return) position — the first such member on the class. Every existingAction-dependent method (call,registerActionHandler) deliberately keepsActionbehind a bounded generic to avoid this. A covariantActionmember breaks assigning a messenger to a narrower-typed one (e.g. passing a controller's full messenger to a service typed against only a subset of its actions) — a pattern consumers rely on (@metamask/perps-controllerdoes exactly this and fails to compile with the union return). No union-derived return type avoids this; only a constant return type does.string[]is sufficient for the consumer below, which just lists/prints the types.Why
@metamask/wallet-cliis gaining anmm daemon listcommand to enumerate the actions on the wallet's root messenger (sibling to the existingmm daemon call <Controller>:<method>). That needs a public accessor on the messenger, which this PR adds. The command itself is a separate wallet-cli follow-up.Notes for reviewers
🤖 Generated with Claude Code
Note
Low Risk
Additive read-only API with no change to
callor registration behavior; return type is intentionally loose to preserve existing messenger assignability patterns.Overview
Adds
Messenger.getRegisteredActionTypes(), a read-only API that lists action types the instance cancall()directly—local registrations plus actions delegated into that messenger. It returns[...this.#actions.keys()]asstring[](not the messenger’s action-type union) so callers can enumerate actions without introducing a covariantActionreturn that would break assigning messengers to narrower action typings.Unit tests cover empty messengers, register/unregister, and delegated actions.
packages/messenger/CHANGELOG.mddocuments the addition.Reviewed by Cursor Bugbot for commit 832a804. Bugbot is set up for automated code reviews on this repo. Configure here.