MetaMask / MetaMask/metamask-extension

[State Sync Redesign] Epic 2: Background cleanup

Open
#40,061 0 comments 0 reactions 0 assignees View on GitHub
INVALID-ISSUE-TEMPLATE team-extension-platform
Dominant language
TypeScript
Stars
13.2k
Forks
5.6k
Avg merge
2d 5h
Merged PRs (30d)
451

Description

Modernize MetamaskController's state delivery path: replace `ComposableObservableStore` and the `@metamask/obs-store` dependency with direct messenger subscriptions. Completes the BaseController V2 migration on the background side for controller `stateChange` routing — these layers were necessary when controllers had no standardized state management but have been redundant since V2. `MetamaskController` retains its `EventEmitter` base for events emitted during early app load before controllers and their messengers are guaranteed to be initialized.

## Key Benefits

- **Completes BaseController V2 migration for controller `stateChange` routing**: removes 4 legacy V1-era broadcast layers
- **MetamaskController state-broadcast cleanup**: `updateStructure` x2, `ComposableObservableStore` x2, `PatchStore`, `publicConfigStore` removed
- **Zero-touch controller addition**: 6 manual steps to 2; `ControllerRegistry` becomes canonical registry
- **3 bug classes eliminated**: unbounded UI starvation (debounce with no `maxWait`), listener leaks (per-controller subscriptions without cleanup accounting), untyped event subscriptions (silent mismatches)
- **`forceUpdateMetamaskState` RPC elimination**: replace full-state fetch implementation with lightweight sync primitive that waits for next push update (~109 round-trips removed)
- **Remove `@metamask/obs-store` dependency** (~8KB bundle reduction)

## ADR Option

A1 (background cleanup)

## Phase

A1 (background cleanup) — together with Epic 1

## Dependencies

Epic 1 (transport must not go through memStore; per-controller messenger subscriptions in `setupControllerConnection` replace `memStore.subscribe(sendUpdate)`)

## Enables

Epic 3 (A2 phase — UI-controller subscriptions). Epic 3 depends on both Epic 1 and Epic 2 completing (A1 phase complete).

## Blocked by

Epic 3 only for Issue 2.7 (`@metamask/obs-store` removal requires no Redux consumers via obs-store)

## Issues

- [ ] 2.1: Migrate MetaMetrics to direct messenger subscriptions — #40052
- [ ] 2.2: Migrate `_onStateUpdate` to direct messenger subscriptions — #40053
- [ ] 2.3: Simplify `getState()` to iterate `ControllerRegistry` — #40054
- [ ] 2.4: Replace `this.memStore` with direct messenger subscriptions — #40055
- [ ] 2.5: Replace `this.store` with direct persistence subscriptions — #40056
- [ ] 2.7: Remove `@metamask/obs-store` dependency — #40058
- [ ] 2.8: Replace `forceUpdateMetamaskState` implementation with push-based sync primitive — TBD

## Critical path

2.1 → 2.4 → 2.7

2.8 depends on Epic 1 (reliable push pipeline)

## Validation criteria

- [ ] Persistence works across extension restarts (2.5 — E2E)
- [ ] Vault backup/restore works (2.5 — E2E)
- [ ] MetaMetrics traits still reported correctly (2.1)
- [ ] Dapp provider state notifications still work (2.2, `_notifyChainChange`)
- [ ] `@metamask/obs-store` not in `node_modules` (2.7)
- [ ] `forceUpdateMetamaskState` no longer makes background RPC call (2.8)
- [ ] No regression in E2E test suite

Contributor guide

Open the contributing guide

Research direction

Start with MetamaskController, ControllerRegistry, and setupControllerConnection, then review the linked subtasks for _onStateUpdate, memStore, store, and forceUpdateMetamaskState. Done means the listed background cleanup is complete, persistence and state notifications still work, and the validation criteria—including removal of @metamask/obs-store and no regression in E2E tests—are satisfied.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.