Skip to content

Commit 18af7ab

Browse files
feat: Add support for data services extending BaseDataService (MetaMask#27921)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Replace the default `QueryClient` with a custom `QueryClient` from `createUIQueryClient`. This establishes the query client required for using the `BaseDataService` pattern from the core repo, which handles cache syncing. Existing UI-only queries should work as they did previously. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** https://consensyssoftware.atlassian.net/browse/WPC-445 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Moderate risk because it changes how the global React Query `QueryClient` is constructed and introduces messenger-backed call/subscribe plumbing that could affect caching and network behavior across the app. > > **Overview** > Switches `ReactQueryService` to build its `queryClient` via `@metamask/react-data-query`’s `createUIQueryClient`, passing an Engine messenger adapter to support data services and cache syncing while keeping the existing default query options. > > Adds a `DATA_SERVICES` registry (currently empty) for wiring in available data services, updates unit tests to validate the new client defaults and cache clearing behavior, and adds the new `@metamask/react-data-query` dependency (plus lockfile updates). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 088a264. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 2324e7c commit 18af7ab

5 files changed

Lines changed: 78 additions & 12 deletions

File tree

app/constants/data-services.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// A list of all names of data services available in the client.
2+
export const DATA_SERVICES: string[] = [];

app/core/ReactQueryService/ReactQueryService.test.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import {
77
import { addEventListener as addNetInfoEventListener } from '@react-native-community/netinfo';
88
import { ReactQueryService } from './ReactQueryService';
99

10-
jest.mock('@tanstack/react-query', () => ({
11-
QueryClient: jest.fn().mockImplementation(() => ({ clear: jest.fn() })),
10+
jest.mock('@tanstack/query-core', () => ({
11+
...jest.requireActual('@tanstack/query-core'),
1212
focusManager: { setFocused: jest.fn() },
1313
onlineManager: { setEventListener: jest.fn() },
1414
}));
@@ -43,14 +43,15 @@ describe('ReactQueryService', () => {
4343

4444
describe('constructor', () => {
4545
it('creates a QueryClient with expected default options', () => {
46-
expect(QueryClient).toHaveBeenCalledWith({
47-
defaultOptions: {
48-
queries: {
49-
staleTime: 1000 * 60 * 5,
50-
retry: 2,
51-
cacheTime: 1000 * 60 * 60 * 24,
52-
},
46+
// @ts-expect-error Accessing private property.
47+
expect(service.queryClient.defaultOptions).toStrictEqual({
48+
queries: {
49+
staleTime: 1000 * 60 * 5,
50+
retry: 2,
51+
cacheTime: 1000 * 60 * 60 * 24,
52+
queryFn: expect.any(Function),
5353
},
54+
mutations: undefined,
5455
});
5556
});
5657

@@ -169,9 +170,11 @@ describe('ReactQueryService', () => {
169170
});
170171

171172
it('clears the query client cache', () => {
173+
const spy = jest.spyOn(service.queryClient, 'clear');
174+
172175
service.destroy();
173176

174-
expect(service.queryClient.clear).toHaveBeenCalled();
177+
expect(spy).toHaveBeenCalled();
175178
});
176179
});
177180
});

app/core/ReactQueryService/ReactQueryService.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,29 @@ import {
88
addEventListener as addNetInfoEventListener,
99
type NetInfoState,
1010
} from '@react-native-community/netinfo';
11+
import { createUIQueryClient } from '@metamask/react-data-query';
12+
import { Json } from '@metamask/utils';
13+
import { MessengerActions, MessengerEvents } from '@metamask/messenger';
14+
import Engine from '../Engine/Engine';
15+
import { RootMessenger } from '../Engine/types';
16+
import { DATA_SERVICES } from '../../constants/data-services';
17+
18+
type ActionType = MessengerActions<RootMessenger>['type'];
19+
type EventType = MessengerEvents<RootMessenger>['type'];
20+
21+
type JsonSubscriptionCallback = (data: Json) => void;
22+
23+
const adapter = {
24+
call: async (method: string, ...params: Json[]) =>
25+
// @ts-expect-error Target requires 1 element(s) but source may have fewer.
26+
Engine.controllerMessenger.call(method as ActionType, ...params) as Json,
27+
subscribe: (event: string, callback: JsonSubscriptionCallback) => {
28+
Engine.controllerMessenger.subscribe(event as EventType, callback);
29+
},
30+
unsubscribe: (event: string, callback: JsonSubscriptionCallback) => {
31+
Engine.controllerMessenger.unsubscribe(event as EventType, callback);
32+
},
33+
};
1134

1235
export class ReactQueryService {
1336
queryClient: QueryClient;
@@ -16,7 +39,7 @@ export class ReactQueryService {
1639
#netInfoUnsubscribe?: () => void;
1740

1841
constructor() {
19-
this.queryClient = new QueryClient({
42+
this.queryClient = createUIQueryClient(DATA_SERVICES, adapter, {
2043
defaultOptions: {
2144
queries: {
2245
// Mobile users often trigger re-renders or navigate back/forth frequently.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@
281281
"@metamask/profile-metrics-controller": "^3.1.0",
282282
"@metamask/profile-sync-controller": "^28.0.0",
283283
"@metamask/ramps-controller": "^12.0.1",
284+
"@metamask/react-data-query": "^0.2.0",
284285
"@metamask/react-native-acm": "1.2.0",
285286
"@metamask/react-native-actionsheet": "2.4.2",
286287
"@metamask/react-native-button": "^3.0.0",

yarn.lock

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7883,6 +7883,19 @@ __metadata:
78837883
languageName: node
78847884
linkType: hard
78857885

7886+
"@metamask/base-data-service@npm:^0.1.0":
7887+
version: 0.1.1
7888+
resolution: "@metamask/base-data-service@npm:0.1.1"
7889+
dependencies:
7890+
"@metamask/controller-utils": "npm:^11.19.0"
7891+
"@metamask/messenger": "npm:^1.0.0"
7892+
"@metamask/utils": "npm:^11.9.0"
7893+
"@tanstack/query-core": "npm:^4.43.0"
7894+
fast-deep-equal: "npm:^3.1.3"
7895+
checksum: 10/b746cfaad6625d61e0d5e3202488d1f3139ef1e4b8f04c7b07a3e0fbe474c1307c73bacb1cf5d9288e946719137c52f1bc1fd40e9e44800f65b8729bbed7311d
7896+
languageName: node
7897+
linkType: hard
7898+
78867899
"@metamask/bitcoin-wallet-snap@npm:^1.10.0":
78877900
version: 1.10.0
78887901
resolution: "@metamask/bitcoin-wallet-snap@npm:1.10.0"
@@ -8890,6 +8903,13 @@ __metadata:
88908903
languageName: node
88918904
linkType: hard
88928905

8906+
"@metamask/messenger@npm:^1.0.0":
8907+
version: 1.0.0
8908+
resolution: "@metamask/messenger@npm:1.0.0"
8909+
checksum: 10/ab1219a922d5acc86f2b1b557d79c75ca0c5f42572f50da8a2337bc5c8feb1ae95c0aaa2d2ee55b677acd4401fb2cc9c2dbacca7513edcddf20d88fb73fa7bea
8910+
languageName: node
8911+
linkType: hard
8912+
88938913
"@metamask/metamask-eth-abis@npm:3.1.1, @metamask/metamask-eth-abis@npm:^3.1.1":
88948914
version: 3.1.1
88958915
resolution: "@metamask/metamask-eth-abis@npm:3.1.1"
@@ -9433,6 +9453,22 @@ __metadata:
94339453
languageName: node
94349454
linkType: hard
94359455

9456+
"@metamask/react-data-query@npm:^0.2.0":
9457+
version: 0.2.0
9458+
resolution: "@metamask/react-data-query@npm:0.2.0"
9459+
dependencies:
9460+
"@metamask/base-data-service": "npm:^0.1.0"
9461+
"@metamask/utils": "npm:^11.9.0"
9462+
"@tanstack/query-core": "npm:^4.43.0"
9463+
"@tanstack/react-query": "npm:^4.43.0"
9464+
peerDependencies:
9465+
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
9466+
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
9467+
react-native: "*"
9468+
checksum: 10/c54a9943bb68ad46ad9964864d4ee81604e61216ebed00026a1a4681a1e1091b6e413b9812d25e38d028493f3c75e91c8102b9d1c0232f409cd6f1dd4d22b211
9469+
languageName: node
9470+
linkType: hard
9471+
94369472
"@metamask/react-native-acm@npm:1.2.0":
94379473
version: 1.2.0
94389474
resolution: "@metamask/react-native-acm@npm:1.2.0"
@@ -17427,7 +17463,7 @@ __metadata:
1742717463
languageName: node
1742817464
linkType: hard
1742917465

17430-
"@tanstack/query-core@npm:4.43.0":
17466+
"@tanstack/query-core@npm:4.43.0, @tanstack/query-core@npm:^4.43.0":
1743117467
version: 4.43.0
1743217468
resolution: "@tanstack/query-core@npm:4.43.0"
1743317469
checksum: 10/c2a5a151c7adaea8311e01a643255f31946ae3164a71567ba80048242821ae14043f13f5516b695baebe5ea7e4b2cf717fd60908a929d18a5c5125fee925ff67
@@ -35612,6 +35648,7 @@ __metadata:
3561235648
"@metamask/profile-sync-controller": "npm:^28.0.0"
3561335649
"@metamask/providers": "npm:^18.3.1"
3561435650
"@metamask/ramps-controller": "npm:^12.0.1"
35651+
"@metamask/react-data-query": "npm:^0.2.0"
3561535652
"@metamask/react-native-acm": "npm:1.2.0"
3561635653
"@metamask/react-native-actionsheet": "npm:2.4.2"
3561735654
"@metamask/react-native-button": "npm:^3.0.0"

0 commit comments

Comments
 (0)