Skip to content

feat(wallet-cli): add daemon JSON-RPC socket transport#9108

Draft
sirtimid wants to merge 2 commits into
sirtimid/wallet-cli-persistencefrom
sirtimid/wallet-cli-daemon-transport
Draft

feat(wallet-cli): add daemon JSON-RPC socket transport#9108
sirtimid wants to merge 2 commits into
sirtimid/wallet-cli-persistencefrom
sirtimid/wallet-cli-daemon-transport

Conversation

@sirtimid

Copy link
Copy Markdown
Member

Explanation

@metamask/wallet-cli runs a background daemon that hosts a @metamask/wallet instance; the CLI talks to it over a Unix socket. This PR adds that transport layer. It is purely additive plumbing — no mm subcommand consumes it yet (commands land in a follow-up), so there is no user-visible behavior change.

  • socket-linewriteLine/readLine for newline-delimited framing over a net.Socket, with an optional read timeout and listener cleanup.
  • daemon-clientsendCommand opens a connection, writes one JSON-RPC request, reads one response, and closes; it correlates the response id with the request and retries once on transient connection errors (ECONNREFUSED/ECONNRESET). pingDaemon is a lightweight getStatus health probe that distinguishes "no daemon" (absent) from "daemon present but unreachable", classifying the latter by failure mode (refused / timeout / permission / protocol / other).
  • rpc-socket-serverstartRpcSocketServer listens on a Unix socket and dispatches one JSON-RPC request per connection to a handler map. It intercepts a built-in shutdown method, enforces one-request-per-connection, times out idle connections, and returns a close() handle.
  • daemon-spawnensureDaemon spawns a detached daemon process and polls until the socket is responsive, refusing to take over a wedged or foreign-owned socket. Resolves the entry point from dist (prod) or src via tsx (dev).
  • stop-daemonstopDaemon escalates from a graceful shutdown RPC through SIGTERM to SIGKILL, then removes the PID and socket files best-effort.
  • promptsconfirmPurge wraps the ESM-only @inquirer/confirm via dynamic import.
  • types — adds RpcHandler, RpcHandlerMap, DaemonStatusInfo, and DaemonSpawnConfig.

Adds @inquirer/confirm and @metamask/rpc-errors dependencies. Every daemon module is covered to the package's 100% coverage thresholds, plus a socket-integration.test.ts that exercises the client and server together over a real Unix socket (framing, id correlation, the one-request-per-connection invariant, and real shutdown timing).

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

🤖 Generated with Claude Code

sirtimid and others added 2 commits June 12, 2026 12:56
Add the daemon's IPC transport layer for `@metamask/wallet-cli`. This is
purely additive plumbing — no `mm` subcommand consumes it yet (commands
land in a later slice), so there is no user-visible behavior change.

- socket-line: newline-delimited read/write framing over a `net.Socket`.
- daemon-client: `sendCommand` (one request per connection, id-correlated,
  retries once on transient connection errors) and `pingDaemon` (a
  `getStatus` health probe that classifies unreachable daemons by failure
  mode: refused / timeout / permission / protocol / other).
- rpc-socket-server: `startRpcSocketServer` listens on a Unix socket and
  dispatches one JSON-RPC request per connection to a handler map, with a
  built-in `shutdown` method and idle-connection timeout.
- daemon-spawn: `ensureDaemon` spawns a detached daemon and polls until the
  socket is responsive, refusing to take over a wedged or foreign socket.
- stop-daemon: `stopDaemon` escalates from a graceful `shutdown` RPC through
  SIGTERM to SIGKILL, then cleans up the PID and socket files.
- prompts: `confirmPurge` wraps the ESM-only `@inquirer/confirm`.
- types: add `RpcHandler`, `RpcHandlerMap`, `DaemonStatusInfo`, and
  `DaemonSpawnConfig`.

Adds `@inquirer/confirm` and `@metamask/rpc-errors` dependencies. All daemon
modules are covered to the package's 100% thresholds, plus an end-to-end
socket integration test exercising both halves over a real Unix socket.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​inquirer/​confirm@​6.1.11001009895100

View full report

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.

1 participant