MetaMask / MetaMask/metamask-extension
[`MetamaskController` A.5] Extract `transaction-lifecycle`
- 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/transaction-lifecycle/index.ts` (new)
- `app/scripts/lib/wallet-services/transaction-lifecycle/transaction-lifecycle.test.ts` (new)
- `app/scripts/metamask-controller.js`
**Size:** L
## Problem
Transaction lifecycle logic lives inline on `MetamaskController`: `addTransaction`, `approveTransaction`, `stopTransaction`, `speedUpTransaction`, `estimateGas`, `isAtomicBatchSupported`, network-client lookup, and related wiring sit alongside unrelated wallet concerns. Extract them into `wallet-services/transaction-lifecycle/` so the responsibility is named and independently testable.
Reconciliation required during extraction: audit every `messenger.call(...)` site against `@metamask/transaction-controller` registered actions. At least one platform overload (extension-vs-mobile shape) needs refactoring during the port — confirm the exact callsite by reading the `MetamaskController` method bodies before starting.
**Verification sources:** [`app/scripts/controller-init/messengers/transaction-controller-messenger.ts`](https://github.com/MetaMask/metamask-extension/blob/main/app/scripts/controller-init/messengers/transaction-controller-messenger.ts), `@metamask/transaction-controller`.
## Solution
1. Create `app/scripts/lib/wallet-services/transaction-lifecycle/` with `index.ts` exporting a structural `TransactionLifecycleMessenger` type and the extracted function bodies.
2. Port the corresponding method bodies from `metamask-controller.js` into the module, performing the per-action audit described above.
3. Refactor the platform overload so the extracted module is platform-neutral.
4. Export `TRANSACTION_LIFECYCLE_ACTIONS` and `registerActions(messenger)`.
5. Add structural unit tests against a stub messenger.
6. Delete the moved method bodies from `metamask-controller.js`.
7. Update `MetamaskController#getApi()` entries for transaction lifecycle to delegate via messenger.
## Acceptance criteria
- [ ] `app/scripts/lib/wallet-services/transaction-lifecycle/index.ts` exists and owns the extracted logic
- [ ] Platform overload refactored; extracted module is platform-neutral
- [ ] Every `messenger.call(...)` site matches a real registered action, or is replaced with direct controller injection plus an explicit upstream-registration TODO
- [ ] Full unit-test coverage against structural messenger
- [ ] 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
None.
Contributor guide
Research direction
Start by reading the transaction lifecycle methods in app/scripts/metamask-controller.js and the registered actions in app/scripts/controller-init/messengers/transaction-controller-messenger.ts. Then compare each messenger.call(...) with @metamask/transaction-controller while reviewing the named new module and test paths. Done means the logic is extracted, tested against a structural messenger, getApi() delegates directly, and yarn test, tsc, and the extension build pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- api, backend
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100