MetaMask / MetaMask/core

Expose replacement implementations of `QueryClient` APIs in UI

Open
#8,531 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.