feat: add @metamask/wallet-cli package scaffold#9065
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
All alerts resolved. Learn more about Socket for GitHub. This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored. Ignoring alerts on:
|
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@SocketSecurity ignore npm/jake@10.9.4 All three are transitive dependencies of Research:
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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 c85b8d2. Configure here.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
c8b4c43 to
f5ed2fa
Compare
Add an oclif-based `mm` CLI package (`@metamask/wallet-cli`) for `@metamask/wallet`, plus its monorepo registration. This is the initial scaffold: a buildable/lintable/testable package with the `bin/run.mjs` launcher and daemon path helpers, but no subcommands yet. - `packages/wallet-cli/`: package manifest, tsconfigs, jest config (100% coverage thresholds), README, CHANGELOG, MIT LICENSE, the `mm` bin launcher, and `src/daemon/paths.ts` (+test) / `types.ts` (`DaemonPaths`). - Register the workspace: add to `TOOLS` in `yarn.config.cjs` (library `exports`/`build:docs`-exempt), ESLint overrides for `src`/`bin`, root `tsconfig.json`/`tsconfig.build.json` project references, `CODEOWNERS`, `teams.json`, and the generated root README dependency graph. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The oclif ESM scaffold ships `bin/run.mjs`, but `bin/run.cmd` invoked `node "%~dp0\run"` (an extensionless path inherited from the older oclif template that shipped a `bin/run` file). Node's CJS entry resolution does not append `.mjs`, so `run.cmd` failed with a missing-module error on Windows while the `mm` bin shim (which targets `run.mjs`) worked. Point the launcher at `run.mjs` so the Windows entrypoint matches the file the package actually ships. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restore the LICENSE pointer file, LICENSE.MIT, and LICENSE.APACHE2 introduced by the package-initialization PR (#9079) and set the manifest license back to (MIT OR Apache-2.0); the CLI scaffold should not change the package's licensing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Collapse duplicate ranges introduced by the @oclif/core addition so `yarn dedupe --check` (lint:dependencies CI task) passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
94090fe to
5ef15ec
Compare
…aMask#9067) ## Explanation `@metamask/wallet-cli` runs a background daemon that hosts a `@metamask/wallet` instance. For controller state to survive daemon restarts, it needs durable local storage. This PR adds that persistence layer. It is purely additive and not yet wired into a daemon process — the daemon entry point that consumes it lands in a follow-up. - **`KeyValueStore`** — a synchronous `better-sqlite3`-backed key-value store (a single `kv` table with a TEXT key and a JSON-serialized TEXT value). Corrupt rows fail loud (a descriptive, key-scoped error) rather than returning garbage. - **`loadState(store)`** — rehydrates persisted state into the `{ [controllerName]: { [property]: value } }` shape accepted by the `Wallet` constructor's `state` option. - **`subscribeToChanges(messenger, controllerMetadata, store, log?)`** — subscribes to every `<Controller>:stateChanged` event and writes persist-flagged top-level properties through to the store (applying `StateDeriver` persist functions, and deleting a key when its property is removed from state). It returns an unsubscribe handle; teardown is owned by the caller (a `dispose()` handle in a later PR), so there is no package-level teardown event. ### `better-sqlite3` native addon `better-sqlite3` ships a native C addon. The monorepo runs Yarn with `enableScripts: false`, so the addon is not built during `yarn install`. To handle this: - a `test:prepare` step (`scripts/install-binaries.sh`) fetches a matching prebuild via `prebuild-install` before tests run; - `engines.node` is set to `>=20` (better-sqlite3 v12 only ships prebuilt binaries for Node 20+); - `@metamask/wallet-cli` is excluded from the Node 18.x CI test matrix; - `yarn.config.cjs` exempts the package from the standard `test`-script and `engines.node` constraints accordingly. ## References - Closes MetaMask#8682 - Builds on MetaMask#9065 (the `@metamask/wallet-cli` package scaffold). This PR targets that branch and should merge after it. ## 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/processes/updating-changelogs.md) - [ ] I've introduced [breaking changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > New durable state path can diverge from in-memory state on disk write failures (logged only today); native addon and Node 20+ requirement affect install and CI. > > **Overview** > Adds **SQLite-backed persistence** in `@metamask/wallet-cli` so wallet controller state can survive restarts (not yet wired into the daemon). > > A synchronous **`KeyValueStore`** (`better-sqlite3`, JSON values in a `kv` table) is the storage backend. **`loadState`** rebuilds `{ controllerName: { property: value } }` for `Wallet` construction, honoring only properties still marked `persist` in controller metadata so stale rows are not resurrected. **`subscribeToChanges`** listens on `<Controller>:stateChanged`, writes persist-flagged top-level fields from Immer patches (including `StateDeriver` transforms and deletes when properties are removed), logs write failures without stopping the process, and returns an unsubscribe handle. > > **`better-sqlite3`** is added with **`engines.node` `>=20`**, a **`test:prepare`** / **`install-binaries.sh`** prebuild step (monorepo `enableScripts: false`), CI matrix exclusion for Node 18 on this package, and **`yarn.config.cjs`** exceptions for the custom test script and engines field. Dependencies on `@metamask/wallet`, `@metamask/base-controller`, and `immer` are added with matching tsconfig project references. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b9854de. 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>
…#9226) ## Explanation Adds the wallet factory and daemon entry point for `@metamask/wallet-cli`, after the scaffold (MetaMask#9065), persistence (MetaMask#9067), and transport (MetaMask#9108) slices: - **`wallet-factory.ts`** — `createWallet()` builds a `@metamask/wallet` `Wallet` over the SQLite `KeyValueStore`, hydrates it from persisted state, imports the SRP on first run, and returns `{ wallet, dispose }`. `dispose` (idempotent, resilient) runs unsubscribe → `wallet.destroy()` → `store.close()`. - **`daemon-entry.ts`** — the daemon process: claims the PID slot, builds the wallet, serves the messenger over the owner-only Unix socket, and tears down via `dispose` on shutdown. It uses the current `@metamask/wallet` `instanceOptions` API — `storageService` (in-memory adapter), `connectivityController` (`AlwaysOnlineAdapter`), and `remoteFeatureFlagController`. `NetworkController` and `TransactionController` slots are left as TODOs until they're wired on `main`. Supersedes draft MetaMask#8847 (the `{ wallet, dispose }` refactor), folded in here on top of `main`. Closes MetaMask#8779. ## Checklist - [x] `build`, `test` (100% coverage on both new files), `lint`, `changelog:validate`, and `constraints` pass. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Touches keyring/SRP import, encrypted vault persistence, and exposes the full wallet messenger over a Unix socket with only filesystem permissions as the access boundary. > > **Overview** > Adds **`createWallet`** and **`daemon-entry`** so the CLI can run a long-lived background wallet process backed by SQLite persistence. > > **`createWallet`** opens a `KeyValueStore`, hydrates controller state (via a short-lived metadata probe `Wallet`), wires headless `instanceOptions` (in-memory `storageService`, `AlwaysOnlineAdapter`, Infura + remote feature flags), subscribes persistence, runs **`wallet.init()`** (startup aborts if any step fails), imports the SRP on first run when no vault exists, and returns **`{ wallet, dispose }`** with ordered, idempotent teardown. First-run failures can delete on-disk DB files. > > **`daemon-entry`** validates required env vars, **removes password/SRP from `process.env`** after capture, locks the data dir to **`0o700`**, runs **`claimDaemonSlot`** (stale socket/PID cleanup, refuse live siblings), claims the daemon with an **exclusive PID write before opening the DB**, builds the wallet, and serves **`getStatus`** plus a **`call`** RPC that forwards arbitrary messenger actions. Shutdown/SIG handlers coalesce teardown and only remove PID files the process owns. > > Also adds **`remote-feature-flag-controller`** and **`storage-service`** dependencies and a small **`Readonly`** typing tweak in persistence subscriptions. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 180ffc1. 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>
…oke test (MetaMask#9255) ## Explanation The final landing slice for `@metamask/wallet-cli`, after the scaffold (MetaMask#9065), persistence (MetaMask#9067), transport (MetaMask#9108), and factory (MetaMask#9226) slices. It adds the user-facing command surface so the package is runnable: - **`src/commands/daemon/{start,stop,status,purge,call}.ts`** (+ tests) — the `mm daemon` command suite over the daemon layers already on `main`: `start` spawns the daemon and reports its socket, `status`/`stop` ping and tear it down, `purge` deletes the daemon state files, and `call` dispatches an arbitrary `Controller:method` messenger action. - **`bin/dev.mjs` + `bin/dev.cmd`** — the dev-mode launchers deferred from the scaffold slice, run via the `tsx` loader (`knip` `ignoreDependencies: ['tsx']`). - **`wallet-factory.e2e.test.ts`** — a smoke test that feeds the wired `instanceOptions` into a **real** `Wallet` (no mock) against `:memory:`, imports the SRP, and dispatches a messenger action — closing the gap flagged in MetaMask#9226 review. Offline/CI-safe (neither construction nor `wallet.init()` reaches the network). - **`src/test/run-command.ts`** + a README **Usage** section. ## Checklist - [x] `build`, `test` (100% coverage), `lint`, and `changelog:validate` pass. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > New CLI paths accept wallet secrets and can invoke arbitrary messenger actions over a local socket; `purge` deletes persisted wallet state, though safeguards limit deletion when the daemon is still responsive. > > **Overview** > Adds the runnable **`mm daemon`** command surface on top of the existing spawn/client/stop layers: **`start`** (Infura/password/SRP via flags or env), **`stop`**, **`status`** (orphan-PID and stale-PID warnings), **`purge`** (confirm/`--force`, whitelist-only file deletion, refuses purge while the daemon still responds), and **`call`** (JSON-RPC `call` with optional JSON-array args and timeout, TTY vs piped JSON output). > > Also ships **`bin/dev.mjs`/`dev.cmd`** (oclif dev mode via **`tsx`**), a **`runCommand`** oclif test harness, a **real `Wallet` `:memory:` e2e** for `createWallet`, Jest **Web Crypto polyfill** environment for KeyringController tests, README **Usage**, and knip/tsconfig tweaks for **`wallet-cli`**. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 15fbe92. 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>

Explanation
This adds
@metamask/wallet-cli— an oclif-basedmmCLI for@metamask/wallet, intended to run the wallet as a background daemon and dispatch messenger actions to it.This first PR is the package scaffold only: a buildable, lintable, and testable package with the
mmbinary launcher (bin/run.mjs) and a couple of pure daemon path helpers, but no subcommands yet. oclif rendersmm --help/mm --versioneven with no commands registered, so the package is exercisable end to end. Functionality is added incrementally in follow-up PRs (SQLite persistence, the Unix-socket daemon transport, theWalletfactory, and thedaemonsubcommands) so each stays small and self-contained.Because the package is a CLI tool rather than a published library, it is registered in the
TOOLSlist inyarn.config.cjs— which exempts it from the libraryexports/main/typesandbuild:docsconstraints — matching how@metamask/messenger-cliis handled. The remaining changes outsidepackages/wallet-cli/are the standard new-package registration: ESLint overrides, roottsconfigproject references,CODEOWNERS,teams.json, and the generated root README dependency graph.References
N/A
Checklist
getDaemonPathshelper is covered to 100%)Note
Low Risk
New CLI package and lint/yarn config only; no wallet runtime, daemon, or messenger integration in this diff.
Overview
Introduces
@metamask/wallet-cli, an oclif-basedmmCLI aimed at running@metamask/walletas a background daemon. This PR is scaffold only:bin/run.mjs/run.cmd, oclif metadata pointing at./dist/commands, and@oclif/coreas a runtime dependency—no subcommands yet (help/version still work via oclif).The package is reshaped as a tool, not a library: library
main/types/ fullexportsand typedoc tooling are removed; publishedfilesincludebin/;yarn.config.cjsadds it toTOOLS(same pattern asmessenger-cli). AddsgetDaemonPathsplusDaemonPathstypes for socket, PID, log, and DB paths under a data dir, with a unit test. Placeholdergreeterindexis deleted.Repo wiring: ESLint overrides for wallet-cli src, tests, and bin;
tsconfigincludes./bin; changelog Unreleased entry.Reviewed by Cursor Bugbot for commit 5ef15ec. Bugbot is set up for automated code reviews on this repo. Configure here.