Skip to content

Epic: Remove global ExtraDependencies from all thunks #30770

Description

@peter-sanderson

Goal

Remove the global ExtraDependencies contract from thunk implementations. Every thunk should expose only the state and injected dependencies it actually consumes, so unit tests can construct minimal stores without the full global dependency graph or as any casts.

The end state is that ExtraDependencies is not used by thunks, tests, feature middleware, or feature packages. It may remain only at composition roots while the application store is assembled. Dependency-bearing thunks must declare a named <ThunkName>Deps type directly above the thunk and compose nested thunk contracts with &. Dependency-free thunks keep the explicit void third generic.

Inventory baseline

A scan of develop currently finds approximately 345 createThunk call sites:

  • suite-common/wallet-core: 106
  • suite-common/trading: 83
  • packages/suite: 43
  • suite-common/walletconnect: 16
  • suite-common/connect-popup: 9
  • Suite Native packages: approximately 60
  • Remaining Suite and Suite Common feature packages: approximately 28

There are also explicit ExtraDependencies annotations in vanilla thunks, middleware APIs, test mocks, and store setup. Counts should be refreshed after the prerequisite PRs land.

Conventions

  • Use type <ThunkName>Deps = ... directly above every dependency-bearing thunk.
  • Compose reusable service dependency contracts and child-thunk contracts with intersections (&).
  • Use direct state contracts such as DeviceRootState; do not infer state with Parameters<typeof selector>[0].
  • Declare a named <ThunkName>State where a thunk reads state.
  • Use the explicit third generic void when a thunk needs neither state nor injected dependencies.
  • Do not use ExtraDependencies, CustomThunkAPI, as any, or full dependency mocks as a shortcut.
  • Parent thunks must include the state/dependency contracts of child thunks they dispatch.
  • Update tests to pass only the state slices and dependencies required by the thunk under test.

Work already implemented / in progress

Conversion plan

Vanilla thunks

  • Convert remaining desktop Suite vanilla thunks in packages/suite/src/actions: staking (Cardano, Ethereum, Solana), stake orchestration, protocol/suite leftovers, modal callbacks, and any newly added call sites.
  • Convert remaining suite/* vanilla thunks: metadata labeling/provider flows, metadata migration modal dispatch, device flows, and any desktop-update/receive leftovers after refactor(suite): narrow vanilla thunk dependencies #30733.
  • Convert any remaining Suite Common and Suite Native vanilla thunks; replace explicit global dispatch/get-extra annotations with local state and <ThunkName>Deps contracts.

RTK thunks — Suite Common

  • Convert wallet-core foundation: accounts, discovery, device lifecycle, blockchain, explorer, settings, UI events, fiat rates, and token management.
  • Convert wallet-core transaction construction: fees, transactions, Bitcoin/Cardano/Ethereum/Solana/Ripple/Stellar/Tron send flows, signing, pushing, replacement, and nested orchestration.
  • Convert wallet-core earn flows: staking, stablecoin yield approval/deposit/wrap, Stellar token operations, and related tests.
  • Convert suite-common/trading buy and shared flows: initial data, address/payment request creation, nonce/refund/purchase helpers, trade watching, and verification.
  • Convert suite-common/trading exchange flows: quote selection, approval, DEX prefetch/watch/sign/send, and exchange request/confirmation orchestration.
  • Convert suite-common/trading sell flows: quote selection, request handling, confirmation, signing, sending, and trade watching.
  • Convert WalletConnect and adapters: session lifecycle plus Bitcoin, Ethereum, Solana, Stellar, and Tron request thunks.
  • Convert Connect integration packages: connect-init, connect-popup, and all nested picker, permission, verification, and cancellation flows.
  • Convert remaining small Suite Common packages: firmware, authenticity, message-system, token-definitions, toast notifications, THP, feedback, geolocation, and future call sites.

RTK thunks — Desktop Suite

  • Convert desktop Bluetooth thunks and storage-related child dispatch chains.
  • Convert Suite shell/device/settings/router/recovery/metadata/labeling thunks, including application reset, auto-eject, device forget, language, wallet selection, and navigation.
  • Convert wallet send and transaction UI thunks: form drafts, metadata labels, signing/pushing, graph updates, exports, wrap/unwrap, and Tron cancellation.
  • Convert desktop trading wrapper thunks for buy, exchange, and sell.
  • Convert desktop stablecoin-yield wrapper thunks: deposit, withdraw, claim, cancellation, and child flow composition.

RTK thunks — Suite Native

  • Convert Native application/state infrastructure: app-init, analytics-redux, biometrics, device, graph, firmware, Bluetooth, and account import/check-backup packages.
  • Convert Native wallet flows: blockchain, send, transaction management, receive, Stellar token management, and staking.
  • Convert Native earn and trading packages: module-earn, module-trading, trading-state, and their middleware/tests.
  • Convert remaining Native feature packages and refresh the inventory to include thunks added while this epic is active.

Infrastructure, middleware, and tests

  • Make app-level dispatch/store typing accept thunks with narrower state/extra contracts without losing .unwrap(), .abort(), action metadata, or payload inference in desktop and Native consumers.
  • Make createSingleInstanceThunk and any other thunk factories support the same named selective contracts and explicit-void behavior.
  • Parameterize middleware helpers over their actual dependency contracts; remove ExtraDependencies from feature middleware and middleware tests.
  • Split the global dependency mocks into small reusable dependency fixtures and migrate tests away from extraDependenciesCommonMock, desktop/native full mocks, Partial<ExtraDependencies>, and casts.
  • Add/adjust type tests proving omitted RTK config remains backward compatible during migration, explicit void means no dependencies, named selective contracts reject undeclared access, and parent/child composition remains sound.
  • After every createThunk call site has an explicit state/dependency contract, remove the legacy DefaultThunkAPI/CustomThunkAPI fallback. An omitted third generic must mean no state or injected dependencies (extra: Record<never, never>), so accessing injected dependencies requires an explicit { extra: <ThunkName>Deps } contract.
  • Add ESLint enforcement that production thunk implementations may not import or reference the global ExtraDependencies or CustomThunkAPI; allow only explicitly documented composition-root/store files.
  • Add ESLint enforcement for thunk contracts: every dependency-bearing vanilla or RTK thunk must use a named <ThunkName>Deps type declared directly above it; dependency-free RTK thunks must use explicit void. Reject inline dependency object types and omitted third generics once migration is complete.
  • Document the thunk dependency/state conventions and the approved composition-root allowlist in the Redux contribution guidance.
  • Final audit: verify ExtraDependencies from suite-common/redux-utils is unused everywhere except the minimal desktop/Native composition roots, remove obsolete global mocks/types where possible, run repository-wide type-check/lint/tests, and ensure ESLint prevents regressions.

Metadata

Metadata

Labels

Type

No type

Projects

Status
🏃‍♀️ In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions