@ledgerhq/live-common 34.47.0-nightly.0 → 34.47.0-nightly.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/lib/__tests__/test-helpers/environment.js +2 -0
  2. package/lib/__tests__/test-helpers/environment.js.map +1 -1
  3. package/lib/families/canton/config.d.ts.map +1 -1
  4. package/lib/families/canton/config.js +35 -1
  5. package/lib/families/canton/config.js.map +1 -1
  6. package/lib/modularDrawer/data/state-manager/api.d.ts +729 -24
  7. package/lib/modularDrawer/data/state-manager/api.d.ts.map +1 -1
  8. package/lib/modularDrawer/data/state-manager/api.js +29 -11
  9. package/lib/modularDrawer/data/state-manager/api.js.map +1 -1
  10. package/lib/modularDrawer/hooks/__test__/useAssetsData.test.js +129 -73
  11. package/lib/modularDrawer/hooks/__test__/useAssetsData.test.js.map +1 -1
  12. package/lib/modularDrawer/hooks/useAssetsData.d.ts +4 -5
  13. package/lib/modularDrawer/hooks/useAssetsData.d.ts.map +1 -1
  14. package/lib/modularDrawer/hooks/useAssetsData.js +34 -15
  15. package/lib/modularDrawer/hooks/useAssetsData.js.map +1 -1
  16. package/lib-es/__tests__/test-helpers/environment.js +2 -0
  17. package/lib-es/__tests__/test-helpers/environment.js.map +1 -1
  18. package/lib-es/families/canton/config.d.ts.map +1 -1
  19. package/lib-es/families/canton/config.js +35 -1
  20. package/lib-es/families/canton/config.js.map +1 -1
  21. package/lib-es/modularDrawer/data/state-manager/api.d.ts +729 -24
  22. package/lib-es/modularDrawer/data/state-manager/api.d.ts.map +1 -1
  23. package/lib-es/modularDrawer/data/state-manager/api.js +28 -10
  24. package/lib-es/modularDrawer/data/state-manager/api.js.map +1 -1
  25. package/lib-es/modularDrawer/hooks/__test__/useAssetsData.test.js +130 -74
  26. package/lib-es/modularDrawer/hooks/__test__/useAssetsData.test.js.map +1 -1
  27. package/lib-es/modularDrawer/hooks/useAssetsData.d.ts +4 -5
  28. package/lib-es/modularDrawer/hooks/useAssetsData.d.ts.map +1 -1
  29. package/lib-es/modularDrawer/hooks/useAssetsData.js +36 -17
  30. package/lib-es/modularDrawer/hooks/useAssetsData.js.map +1 -1
  31. package/package.json +39 -39
  32. package/src/__tests__/test-helpers/environment.ts +2 -0
  33. package/src/families/canton/config.ts +36 -1
  34. package/src/modularDrawer/data/state-manager/api.ts +32 -11
  35. package/src/modularDrawer/hooks/__test__/useAssetsData.test.ts +136 -75
  36. package/src/modularDrawer/hooks/useAssetsData.ts +40 -17
@@ -8,11 +8,14 @@ export enum AssetsDataTags {
8
8
  }
9
9
 
10
10
  export interface GetAssetsDataParams {
11
- cursor?: string;
12
11
  search?: string;
13
12
  currencyIds?: string[];
14
13
  }
15
14
 
15
+ export interface PageParam {
16
+ cursor?: string;
17
+ }
18
+
16
19
  export interface AssetsDataWithPagination extends AssetsData {
17
20
  pagination: {
18
21
  nextCursor?: string;
@@ -43,20 +46,38 @@ export const assetsDataApi = createApi({
43
46
  }),
44
47
  tagTypes: [AssetsDataTags.Assets],
45
48
  endpoints: build => ({
46
- getAssetsData: build.query<AssetsDataWithPagination, GetAssetsDataParams>({
47
- query: ({ cursor, search, currencyIds: _currencyIds }) => ({
48
- url: "assets",
49
- params: {
50
- ...(cursor && { cursor }),
51
- ...(search && { search }),
52
- // ...(currencyIds && currencyIds.length > 0 && { currencyIds }),
49
+ getAssetsData: build.infiniteQuery<AssetsDataWithPagination, GetAssetsDataParams, PageParam>({
50
+ query: ({ pageParam, queryArg }) => {
51
+ const params = {
53
52
  pageSize: 100,
54
- },
55
- }),
53
+ ...(pageParam?.cursor && { cursor: pageParam.cursor }),
54
+ // ...(queryArg?.currencyIds && queryArg?.currencyIds.length > 0 && { currencyIds: queryArg.currencyIds }),
55
+ ...(queryArg?.search && { search: queryArg.search }),
56
+ };
57
+
58
+ return {
59
+ url: "assets",
60
+ params,
61
+ };
62
+ },
56
63
  providesTags: [AssetsDataTags.Assets],
57
64
  transformResponse: transformAssetsResponse,
65
+ infiniteQueryOptions: {
66
+ initialPageParam: {
67
+ cursor: "",
68
+ },
69
+ getNextPageParam: lastPage => {
70
+ if (lastPage.pagination.nextCursor) {
71
+ return {
72
+ cursor: lastPage.pagination.nextCursor,
73
+ };
74
+ } else {
75
+ return undefined;
76
+ }
77
+ },
78
+ },
58
79
  }),
59
80
  }),
60
81
  });
61
82
 
62
- export const { useGetAssetsDataQuery } = assetsDataApi;
83
+ export const { useGetAssetsDataInfiniteQuery } = assetsDataApi;
@@ -4,21 +4,27 @@
4
4
 
5
5
  import { renderHook } from "@testing-library/react";
6
6
  import { useAssetsData } from "../useAssetsData";
7
- import { useGetAssetsDataQuery } from "../../data/state-manager/api";
7
+ import { useGetAssetsDataInfiniteQuery } from "../../data/state-manager/api";
8
8
 
9
9
  jest.mock("../../data/state-manager/api", () => ({
10
- useGetAssetsDataQuery: jest.fn(),
10
+ useGetAssetsDataInfiniteQuery: jest.fn(),
11
11
  }));
12
12
 
13
- const mockSetCursor = jest.fn();
14
- jest.mock("react", () => ({
15
- ...jest.requireActual("react"),
16
- useState: jest.fn(() => [undefined, mockSetCursor]),
17
- useCallback: jest.fn(fn => fn),
18
- useMemo: jest.fn(fn => fn()),
19
- }));
20
-
21
- const mockUseGetAssetsDataQuery = jest.mocked(useGetAssetsDataQuery);
13
+ const mockuseGetAssetsDataInfiniteQuery = jest.mocked(useGetAssetsDataInfiniteQuery);
14
+
15
+ const defaultMockValues = {
16
+ data: undefined,
17
+ isLoading: false,
18
+ error: undefined,
19
+ fetchNextPage: jest.fn(),
20
+ isSuccess: true,
21
+ isFetching: false,
22
+ isError: false,
23
+ fetchPreviousPage: jest.fn(),
24
+ isFetchingPreviousPage: false,
25
+ refetch: jest.fn(),
26
+ status: "success",
27
+ };
22
28
 
23
29
  describe("useAssetsData", () => {
24
30
  beforeEach(() => {
@@ -26,58 +32,92 @@ describe("useAssetsData", () => {
26
32
  });
27
33
 
28
34
  it("should return loading state when API is loading", () => {
29
- mockUseGetAssetsDataQuery.mockReturnValue({
30
- data: undefined,
35
+ mockuseGetAssetsDataInfiniteQuery.mockReturnValue({
36
+ ...defaultMockValues,
31
37
  isLoading: true,
32
- error: undefined,
33
- refetch: jest.fn(),
34
- isFetching: false,
35
- isSuccess: false,
36
- isError: false,
37
- currentData: undefined,
38
+ status: "pending",
38
39
  });
39
40
 
40
41
  const { result } = renderHook(() => useAssetsData({}));
41
42
 
42
43
  expect(result.current.isLoading).toBe(true);
43
44
  expect(result.current.data).toBe(undefined);
44
- expect(result.current.hasMore).toBe(false);
45
45
  });
46
46
 
47
- it("should return data and hasMore when API returns data", () => {
48
- const mockData = {
49
- assetsData: [],
50
- pagination: { nextCursor: "test-cursor" },
51
- };
52
- mockUseGetAssetsDataQuery.mockReturnValue({
53
- data: mockData,
54
- isLoading: false,
55
- error: undefined,
56
- refetch: jest.fn(),
57
- isFetching: false,
58
- isSuccess: true,
59
- isError: false,
60
- currentData: mockData,
47
+ it("should return combined data from multiple pages", () => {
48
+ const mockPages = [
49
+ {
50
+ cryptoAssets: { bitcoin: { id: "bitcoin", name: "Bitcoin" } },
51
+ networks: { bitcoin: { id: "bitcoin", name: "Bitcoin" } },
52
+ cryptoOrTokenCurrencies: { bitcoin: { id: "bitcoin" } },
53
+ interestRates: {},
54
+ markets: {},
55
+ currenciesOrder: {
56
+ currenciesIds: ["bitcoin"],
57
+ metaCurrencyIds: ["bitcoin"],
58
+ key: "marketCap",
59
+ order: "desc",
60
+ },
61
+ pagination: { nextCursor: "cursor-2" },
62
+ },
63
+ {
64
+ cryptoAssets: { ethereum: { id: "ethereum", name: "Ethereum" } },
65
+ networks: { ethereum: { id: "ethereum", name: "Ethereum" } },
66
+ cryptoOrTokenCurrencies: { ethereum: { id: "ethereum" } },
67
+ interestRates: {},
68
+ markets: {},
69
+ currenciesOrder: {
70
+ currenciesIds: ["ethereum"],
71
+ metaCurrencyIds: ["ethereum"],
72
+ key: "marketCap",
73
+ order: "desc",
74
+ },
75
+ pagination: { nextCursor: undefined },
76
+ },
77
+ ];
78
+
79
+ mockuseGetAssetsDataInfiniteQuery.mockReturnValue({
80
+ ...defaultMockValues,
81
+ data: { pages: mockPages, pageParams: [{ cursor: "" }, { cursor: "cursor-2" }] },
61
82
  });
62
83
 
63
84
  const { result } = renderHook(() => useAssetsData({}));
64
85
 
65
- expect(result.current.data).toBe(mockData);
86
+ expect(result.current.data).toEqual({
87
+ cryptoAssets: {
88
+ bitcoin: { id: "bitcoin", name: "Bitcoin" },
89
+ ethereum: { id: "ethereum", name: "Ethereum" },
90
+ },
91
+ networks: {
92
+ bitcoin: { id: "bitcoin", name: "Bitcoin" },
93
+ ethereum: { id: "ethereum", name: "Ethereum" },
94
+ },
95
+ cryptoOrTokenCurrencies: {
96
+ bitcoin: { id: "bitcoin" },
97
+ ethereum: { id: "ethereum" },
98
+ },
99
+ interestRates: {},
100
+ markets: {},
101
+ currenciesOrder: {
102
+ currenciesIds: ["bitcoin", "ethereum"],
103
+ metaCurrencyIds: ["bitcoin", "ethereum"],
104
+ key: "marketCap",
105
+ order: "desc",
106
+ },
107
+ pagination: { nextCursor: undefined },
108
+ });
66
109
  expect(result.current.isLoading).toBe(false);
67
- expect(result.current.hasMore).toBe(true);
68
110
  });
69
111
 
70
112
  it("should return error when API has error", () => {
71
113
  const mockError = new Error("API Error");
72
- mockUseGetAssetsDataQuery.mockReturnValue({
114
+ mockuseGetAssetsDataInfiniteQuery.mockReturnValue({
115
+ ...defaultMockValues,
73
116
  data: undefined,
74
- isLoading: false,
75
117
  error: mockError,
76
- refetch: jest.fn(),
77
- isFetching: false,
78
118
  isSuccess: false,
79
119
  isError: true,
80
- currentData: undefined,
120
+ status: "error",
81
121
  });
82
122
 
83
123
  const { result } = renderHook(() => useAssetsData({}));
@@ -86,54 +126,75 @@ describe("useAssetsData", () => {
86
126
  expect(result.current.isLoading).toBe(false);
87
127
  });
88
128
 
89
- it("should call setCursor when loadNext is called and there's a nextCursor", () => {
90
- const nextCursor = "next-cursor-456";
91
- mockUseGetAssetsDataQuery.mockReturnValue({
92
- data: {
93
- assetsData: [],
94
- pagination: { nextCursor },
95
- },
96
- isLoading: false,
97
- error: undefined,
98
- refetch: jest.fn(),
99
- isFetching: false,
100
- isSuccess: true,
101
- isError: false,
102
- currentData: {
103
- assetsData: [],
104
- pagination: { nextCursor },
129
+ it("should provide loadNext function when there's a nextCursor", () => {
130
+ const mockFetchNextPage = jest.fn();
131
+ const mockPages = [
132
+ {
133
+ cryptoAssets: {},
134
+ networks: {},
135
+ cryptoOrTokenCurrencies: {},
136
+ interestRates: {},
137
+ markets: {},
138
+ currenciesOrder: {
139
+ currenciesIds: [],
140
+ metaCurrencyIds: [],
141
+ key: "marketCap",
142
+ order: "desc",
143
+ },
144
+ pagination: { nextCursor: "next-cursor-456" },
105
145
  },
146
+ ];
147
+
148
+ mockuseGetAssetsDataInfiniteQuery.mockReturnValue({
149
+ ...defaultMockValues,
150
+ data: { pages: mockPages, pageParams: [{ cursor: "" }] },
151
+ fetchNextPage: mockFetchNextPage,
106
152
  });
107
153
 
108
154
  const { result } = renderHook(() => useAssetsData({}));
109
155
 
110
- result.current.loadNext();
156
+ expect(result.current.loadNext).toBeDefined();
157
+ result.current.loadNext?.();
111
158
 
112
- expect(mockSetCursor).toHaveBeenCalledWith(nextCursor);
159
+ expect(mockFetchNextPage).toHaveBeenCalled();
113
160
  });
114
161
 
115
- it("should not call setCursor when there's no nextCursor", () => {
116
- mockUseGetAssetsDataQuery.mockReturnValue({
117
- data: {
118
- assetsData: [],
119
- pagination: { nextCursor: undefined },
120
- },
121
- isLoading: false,
122
- error: undefined,
123
- refetch: jest.fn(),
124
- isFetching: false,
125
- isSuccess: true,
126
- isError: false,
127
- currentData: {
128
- assetsData: [],
162
+ it("should not provide loadNext function when there's no nextCursor", () => {
163
+ const mockPages = [
164
+ {
165
+ cryptoAssets: {},
166
+ networks: {},
167
+ cryptoOrTokenCurrencies: {},
168
+ interestRates: {},
169
+ markets: {},
170
+ currenciesOrder: {
171
+ currenciesIds: [],
172
+ metaCurrencyIds: [],
173
+ key: "marketCap",
174
+ order: "desc",
175
+ },
129
176
  pagination: { nextCursor: undefined },
130
177
  },
178
+ ];
179
+
180
+ mockuseGetAssetsDataInfiniteQuery.mockReturnValue({
181
+ ...defaultMockValues,
182
+ data: { pages: mockPages, pageParams: [{ cursor: "" }] },
131
183
  });
132
184
 
133
185
  const { result } = renderHook(() => useAssetsData({}));
134
186
 
135
- result.current.loadNext();
187
+ expect(result.current.loadNext).toBeUndefined();
188
+ });
189
+
190
+ it("should return undefined data when no pages exist", () => {
191
+ mockuseGetAssetsDataInfiniteQuery.mockReturnValue({
192
+ ...defaultMockValues,
193
+ });
194
+
195
+ const { result } = renderHook(() => useAssetsData({}));
136
196
 
137
- expect(mockSetCursor).not.toHaveBeenCalled();
197
+ expect(result.current.data).toBeUndefined();
198
+ expect(result.current.loadNext).toBeUndefined();
138
199
  });
139
200
  });
@@ -1,5 +1,20 @@
1
- import { useState, useCallback } from "react";
2
- import { useGetAssetsDataQuery } from "../data/state-manager/api";
1
+ import { useMemo } from "react";
2
+ import { AssetsDataWithPagination, useGetAssetsDataInfiniteQuery } from "../data/state-manager/api";
3
+
4
+ const emptyData = () => ({
5
+ cryptoAssets: {},
6
+ networks: {},
7
+ cryptoOrTokenCurrencies: {},
8
+ interestRates: {},
9
+ markets: {},
10
+ currenciesOrder: {
11
+ currenciesIds: [],
12
+ metaCurrencyIds: [],
13
+ key: "",
14
+ order: "",
15
+ },
16
+ pagination: { nextCursor: "" },
17
+ });
3
18
 
4
19
  export function useAssetsData({
5
20
  search,
@@ -8,29 +23,37 @@ export function useAssetsData({
8
23
  search?: string;
9
24
  currencyIds?: string[];
10
25
  }) {
11
- const [cursor, setCursor] = useState<string | undefined>(undefined);
12
- const { data, error, isLoading, isSuccess } = useGetAssetsDataQuery({
13
- cursor,
26
+ const { data, isLoading, error, fetchNextPage, isSuccess } = useGetAssetsDataInfiniteQuery({
14
27
  search,
15
28
  currencyIds,
16
29
  });
17
30
 
18
- const loadNext = useCallback(() => {
19
- const nextCursor = data?.pagination?.nextCursor;
20
- if (nextCursor) {
21
- setCursor(nextCursor);
22
- }
23
- }, [data?.pagination?.nextCursor]);
31
+ const joinedPages = useMemo(() => {
32
+ return data?.pages.reduce<AssetsDataWithPagination>((acc, page) => {
33
+ Object.assign(acc.cryptoAssets, page.cryptoAssets);
34
+ Object.assign(acc.networks, page.networks);
35
+ Object.assign(acc.cryptoOrTokenCurrencies, page.cryptoOrTokenCurrencies);
36
+ Object.assign(acc.interestRates, page.interestRates);
37
+ Object.assign(acc.markets, page.markets);
38
+
39
+ acc.currenciesOrder.currenciesIds.push(...page.currenciesOrder.currenciesIds);
40
+ acc.currenciesOrder.metaCurrencyIds.push(...page.currenciesOrder.metaCurrencyIds);
41
+
42
+ acc.currenciesOrder.key = page.currenciesOrder.key;
43
+ acc.currenciesOrder.order = page.currenciesOrder.order;
44
+ acc.pagination.nextCursor = page.pagination.nextCursor;
24
45
 
25
- const hasMore = Boolean(data?.pagination?.nextCursor);
46
+ return acc;
47
+ }, emptyData());
48
+ }, [data]);
49
+
50
+ const hasMore = Boolean(joinedPages?.pagination.nextCursor);
26
51
 
27
52
  return {
28
- data,
29
- error,
53
+ data: joinedPages,
30
54
  isLoading,
55
+ error,
56
+ loadNext: hasMore ? fetchNextPage : undefined,
31
57
  isSuccess,
32
- hasMore,
33
- cursor,
34
- loadNext,
35
58
  };
36
59
  }