Expose replacement implementations of `QueryClient` APIs in UI
- Dominant language
- TypeScript
- Stars
- 413
- Forks
- 308
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 253
Description
Tracks follow-up work after the initial guard implementation ([#8530](https://github.com/MetaMask/core/issues/8530)) and ADR-level alignment on PR #131.
---
## Subissues
**Replacement: optimistic-update alternative for data-service-backed state** (`setQueryData` / `setQueriesData`)
#8530 throws on these for data-service keys. This ticket designs and ships a sanctioned alternative so feature teams can still do optimistic UI updates. Options (pending [ADR 0020 PR #131](https://github.com/MetaMask/decisions/pull/131) resolution):
- Messenger-dispatched primitive: `dataService.setOptimisticCacheData(queryKey, updater)` that writes to the background cache and propagates via `cacheUpdated` → `hydrate()`. Loses synchronous-write semantics; cold-path MV3 SW wake-up (100–300ms) makes worst case materially slower than the canonical pattern.
- Sanctioned UI facade with explicit rollback on mutation failure. Preserves synchronous-write semantics.
- Explicit ADR statement that optimistic updates for data-service keys are out of scope under Option A.
File after PR #131 alignment on which option to pursue.
---
**Replacement: route-loader integration for data-service keys** (`ensureQueryData` / `ensureInfiniteQueryData`)
#8530 throws on these for data-service keys. This ticket designs and ships a sanctioned loader-compatible alternative. Extension is mid-transition to `react-router` v6 data-router (`createHashRouter` + `RouterProvider`), where `loader: () => queryClient.ensureQueryData(...)` is the natural pattern. Options (pending PR #131 resolution):
- `ensureDataServiceQueryData(routeMessenger, queryKey)` — dispatches to the service via the route messenger, awaits cache population. Composes with the [UI messengers ADR](https://github.com/MetaMask/decisions/commit/072811e9a0d0a2b1536ed58ee4262b9efa3d9f02) `RouteMessenger` authorization boundary. Requires route-messenger-manager or closure-injected handle (UI messengers ADR Option 1B).
- Block loaders from consuming data-service keys; treat route data loading as React-side only (`useSuspenseQuery` in route component).
File after PR #131 alignment on which option to pursue.
---
`getQueryCache()` facade**
`client.getQueryCache().build/.add/.remove` bypasses all instance-shadowing from #8530. Two design options:
- Shadow `getQueryCache` to return a facade that gates mutating methods by key prefix
- Stop returning a raw `QueryClient` from `createUIQueryClient` — return a narrower facade (breaking API change)
File after Layer 1 (#8530) is validated and a design option is chosen.
---
## Dependencies
**Blocked on:** [#8530](https://github.com/MetaMask/core/issues/8530) (Layer 1 guards)
**Blocked on (replacements):** [ADR 0020 PR #131](https://github.com/MetaMask/decisions/pull/131) resolution
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reading blocked issue #8530 and ADR 0020 PR #131 to understand the guard design and pending alignment. Review the createUIQueryClient API and the react-router v6 createHashRouter/RouterProvider transition described here. Done means choosing and shipping sanctioned replacements for optimistic updates, route loaders, and getQueryCache mutations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100