MetaMask / MetaMask/metamask-extension
[`MetamaskController` A.6] Extract `vault-management`
- Dominant language
- TypeScript
- Stars
- 13.2k
- Forks
- 5.6k
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 451
Description
**Sub-epic:** [#41736 — `MetamaskController` decomposition: `wallet-services` completion](https://github.com/MetaMask/metamask-extension/issues/41736)
**Files:**
- `app/scripts/lib/wallet-services/vault-management/index.ts` (new)
- `app/scripts/lib/wallet-services/vault-management/vault-management.test.ts` (new)
- `app/scripts/metamask-controller.js`
**Size:** XL
## Problem
Vault management is the largest domain cluster on `MetamaskController`: `KeyringController` wiring, vault lifecycle, per-controller state reset, and cross-controller coordination sit alongside unrelated wallet concerns. Extract them into `wallet-services/vault-management/` so the responsibility is named and independently testable.
Reconciliation required during extraction: audit every `messenger.call(...)` site against the target controller's registered actions. `KeyringController` core calls are already registered messenger actions, but a number of call sites target class methods across 7 extension-local controllers that are not yet registered. Those sites must be converted to direct controller injection with explicit upstream-registration TODOs. The implementer should verify the following checklist against `main` during the port and adjust as needed:
- Call sites targeting class methods on `AppStateController`, `AccountTreeController`, `SeedlessOnboardingController`, `SubscriptionController`, `ShieldController`, `ClaimsController`, `AddressBookController` — verify each method against its controller's registered actions in [`app/scripts/controller-init/messengers/`](https://github.com/MetaMask/metamask-extension/tree/main/app/scripts/controller-init/messengers) and inject directly with `// TODO: upstream action registration` where missing.
- Any `SnapController:clearState` reference — verify the real action name in `@metamask/snaps-controllers` (likely `clearSnapState`) and rename at the callsite.
**Verification sources:** [`app/scripts/controller-init/messengers/`](https://github.com/MetaMask/metamask-extension/tree/main/app/scripts/controller-init/messengers) (keyring + the 7 extension-local controller messenger files listed above), `@metamask/keyring-controller`, `@metamask/snaps-controllers`.
## Solution
1. Create `app/scripts/lib/wallet-services/vault-management/` with `index.ts` exporting a structural `VaultManagementMessenger` type and the extracted function bodies.
2. Port the corresponding method bodies from `metamask-controller.js` into the module, performing the per-controller reconciliation described above.
3. Make `VaultManagementDependencies` extensible — accept each directly-injected controller as an optional dep so tests can stub individually.
4. Full unit-test matrix (each public method × each direct-injection branch).
5. Export `VAULT_MANAGEMENT_ACTIONS` and `registerActions(messenger)`.
6. Delete the moved method bodies from `metamask-controller.js`.
7. Update `MetamaskController#getApi()` entries for vault management to delegate via messenger.
## Acceptance criteria
- [ ] `app/scripts/lib/wallet-services/vault-management/index.ts` exists and owns the extracted logic
- [ ] Every direct-injection site has an explicit `// TODO: upstream action registration` comment naming the upstream package
- [ ] Any `clearState` → `clearSnapState` rename is verified against `@metamask/snaps-controllers`
- [ ] Unit tests stub each directly-injected controller
- [ ] Module still compiles when only `messenger` is provided (tests skip direct-injection branches)
- [ ] Moved method bodies are removed from `app/scripts/metamask-controller.js`
- [ ] `getApi()` entries rewritten to call `messenger.call('Module:action', ...)` directly — no forwarding stub remains in `MetamaskController`
- [ ] `yarn test` green, `tsc` green, extension dev build boots
## Dependencies
Sequence **last** among A.1–A.6 — absorbs lessons from the smaller modules. No hard blockers.
Contributor guide
Research direction
Start with the vault-related methods in app/scripts/metamask-controller.js and compare their messenger actions with the files under app/scripts/controller-init/messengers/. Check the relevant KeyringController and SnapsController action names, then review the extraction tests and acceptance checklist. Done means the new module owns the logic, direct-injection branches are tested, API delegation is updated, and yarn test, tsc, and the extension build pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- backend-api-design, testing
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 32/100