@ledgerhq/live-common 34.46.0-nightly.4 → 34.46.0-nightly.5

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 (136) hide show
  1. package/lib/bridge/generic-alpaca/estimateMaxSpendable.d.ts.map +1 -1
  2. package/lib/bridge/generic-alpaca/estimateMaxSpendable.js +6 -4
  3. package/lib/bridge/generic-alpaca/estimateMaxSpendable.js.map +1 -1
  4. package/lib/bridge/generic-alpaca/getTransactionStatus.d.ts.map +1 -1
  5. package/lib/bridge/generic-alpaca/getTransactionStatus.js +2 -2
  6. package/lib/bridge/generic-alpaca/getTransactionStatus.js.map +1 -1
  7. package/lib/bridge/generic-alpaca/prepareTransaction.d.ts.map +1 -1
  8. package/lib/bridge/generic-alpaca/prepareTransaction.js +12 -12
  9. package/lib/bridge/generic-alpaca/prepareTransaction.js.map +1 -1
  10. package/lib/bridge/generic-alpaca/signOperation.d.ts.map +1 -1
  11. package/lib/bridge/generic-alpaca/signOperation.js +3 -4
  12. package/lib/bridge/generic-alpaca/signOperation.js.map +1 -1
  13. package/lib/bridge/generic-alpaca/tests/prepareTransaction.test.js +1 -1
  14. package/lib/bridge/generic-alpaca/tests/prepareTransaction.test.js.map +1 -1
  15. package/lib/bridge/generic-alpaca/utils.d.ts +0 -1
  16. package/lib/bridge/generic-alpaca/utils.d.ts.map +1 -1
  17. package/lib/bridge/generic-alpaca/utils.js +0 -1
  18. package/lib/bridge/generic-alpaca/utils.js.map +1 -1
  19. package/lib/currencies/index.d.ts +1 -1
  20. package/lib/currencies/index.d.ts.map +1 -1
  21. package/lib/currencies/index.js +1 -2
  22. package/lib/currencies/index.js.map +1 -1
  23. package/lib/currencies/sortByMarketcap.test.js +2 -1
  24. package/lib/currencies/sortByMarketcap.test.js.map +1 -1
  25. package/lib/e2e/enum/AppInfos.d.ts +1 -1
  26. package/lib/e2e/enum/AppInfos.d.ts.map +1 -1
  27. package/lib/e2e/enum/Provider.d.ts.map +1 -1
  28. package/lib/e2e/enum/Provider.js +2 -2
  29. package/lib/e2e/enum/Provider.js.map +1 -1
  30. package/lib/e2e/index.d.ts +2 -0
  31. package/lib/e2e/index.d.ts.map +1 -1
  32. package/lib/e2e/speculos.d.ts.map +1 -1
  33. package/lib/e2e/speculos.js +3 -4
  34. package/lib/e2e/speculos.js.map +1 -1
  35. package/lib/e2e/speculosCI.d.ts +4 -0
  36. package/lib/e2e/speculosCI.d.ts.map +1 -1
  37. package/lib/e2e/speculosCI.js +16 -6
  38. package/lib/e2e/speculosCI.js.map +1 -1
  39. package/lib/featureFlags/defaultFeatures.d.ts.map +1 -1
  40. package/lib/featureFlags/defaultFeatures.js +1 -0
  41. package/lib/featureFlags/defaultFeatures.js.map +1 -1
  42. package/lib/featureFlags/useFeature.d.ts +1 -1
  43. package/lib/featureFlags/useFeature.d.ts.map +1 -1
  44. package/lib/modularDrawer/data/entities/index.d.ts +68 -0
  45. package/lib/modularDrawer/data/entities/index.d.ts.map +1 -0
  46. package/lib/modularDrawer/data/entities/index.js +3 -0
  47. package/lib/modularDrawer/data/entities/index.js.map +1 -0
  48. package/lib/modularDrawer/data/state-manager/api.d.ts +152 -0
  49. package/lib/modularDrawer/data/state-manager/api.d.ts.map +1 -0
  50. package/lib/modularDrawer/data/state-manager/api.js +45 -0
  51. package/lib/modularDrawer/data/state-manager/api.js.map +1 -0
  52. package/lib/modularDrawer/hooks/__test__/useAssetsData.test.d.ts +5 -0
  53. package/lib/modularDrawer/hooks/__test__/useAssetsData.test.d.ts.map +1 -0
  54. package/lib/modularDrawer/hooks/__test__/useAssetsData.test.js +120 -0
  55. package/lib/modularDrawer/hooks/__test__/useAssetsData.test.js.map +1 -0
  56. package/lib/modularDrawer/hooks/useAssetsData.d.ts +13 -0
  57. package/lib/modularDrawer/hooks/useAssetsData.d.ts.map +1 -0
  58. package/lib/modularDrawer/hooks/useAssetsData.js +31 -0
  59. package/lib/modularDrawer/hooks/useAssetsData.js.map +1 -0
  60. package/lib-es/bridge/generic-alpaca/estimateMaxSpendable.d.ts.map +1 -1
  61. package/lib-es/bridge/generic-alpaca/estimateMaxSpendable.js +6 -4
  62. package/lib-es/bridge/generic-alpaca/estimateMaxSpendable.js.map +1 -1
  63. package/lib-es/bridge/generic-alpaca/getTransactionStatus.d.ts.map +1 -1
  64. package/lib-es/bridge/generic-alpaca/getTransactionStatus.js +2 -2
  65. package/lib-es/bridge/generic-alpaca/getTransactionStatus.js.map +1 -1
  66. package/lib-es/bridge/generic-alpaca/prepareTransaction.d.ts.map +1 -1
  67. package/lib-es/bridge/generic-alpaca/prepareTransaction.js +12 -12
  68. package/lib-es/bridge/generic-alpaca/prepareTransaction.js.map +1 -1
  69. package/lib-es/bridge/generic-alpaca/signOperation.d.ts.map +1 -1
  70. package/lib-es/bridge/generic-alpaca/signOperation.js +3 -4
  71. package/lib-es/bridge/generic-alpaca/signOperation.js.map +1 -1
  72. package/lib-es/bridge/generic-alpaca/tests/prepareTransaction.test.js +1 -1
  73. package/lib-es/bridge/generic-alpaca/tests/prepareTransaction.test.js.map +1 -1
  74. package/lib-es/bridge/generic-alpaca/utils.d.ts +0 -1
  75. package/lib-es/bridge/generic-alpaca/utils.d.ts.map +1 -1
  76. package/lib-es/bridge/generic-alpaca/utils.js +0 -1
  77. package/lib-es/bridge/generic-alpaca/utils.js.map +1 -1
  78. package/lib-es/currencies/index.d.ts +1 -1
  79. package/lib-es/currencies/index.d.ts.map +1 -1
  80. package/lib-es/currencies/index.js +1 -1
  81. package/lib-es/currencies/index.js.map +1 -1
  82. package/lib-es/currencies/sortByMarketcap.test.js +2 -1
  83. package/lib-es/currencies/sortByMarketcap.test.js.map +1 -1
  84. package/lib-es/e2e/enum/AppInfos.d.ts +1 -1
  85. package/lib-es/e2e/enum/AppInfos.d.ts.map +1 -1
  86. package/lib-es/e2e/enum/Provider.d.ts.map +1 -1
  87. package/lib-es/e2e/enum/Provider.js +2 -2
  88. package/lib-es/e2e/enum/Provider.js.map +1 -1
  89. package/lib-es/e2e/index.d.ts +2 -0
  90. package/lib-es/e2e/index.d.ts.map +1 -1
  91. package/lib-es/e2e/speculos.d.ts.map +1 -1
  92. package/lib-es/e2e/speculos.js +3 -4
  93. package/lib-es/e2e/speculos.js.map +1 -1
  94. package/lib-es/e2e/speculosCI.d.ts +4 -0
  95. package/lib-es/e2e/speculosCI.d.ts.map +1 -1
  96. package/lib-es/e2e/speculosCI.js +14 -5
  97. package/lib-es/e2e/speculosCI.js.map +1 -1
  98. package/lib-es/featureFlags/defaultFeatures.d.ts.map +1 -1
  99. package/lib-es/featureFlags/defaultFeatures.js +1 -0
  100. package/lib-es/featureFlags/defaultFeatures.js.map +1 -1
  101. package/lib-es/featureFlags/useFeature.d.ts +1 -1
  102. package/lib-es/featureFlags/useFeature.d.ts.map +1 -1
  103. package/lib-es/modularDrawer/data/entities/index.d.ts +68 -0
  104. package/lib-es/modularDrawer/data/entities/index.d.ts.map +1 -0
  105. package/lib-es/modularDrawer/data/entities/index.js +2 -0
  106. package/lib-es/modularDrawer/data/entities/index.js.map +1 -0
  107. package/lib-es/modularDrawer/data/state-manager/api.d.ts +152 -0
  108. package/lib-es/modularDrawer/data/state-manager/api.d.ts.map +1 -0
  109. package/lib-es/modularDrawer/data/state-manager/api.js +42 -0
  110. package/lib-es/modularDrawer/data/state-manager/api.js.map +1 -0
  111. package/lib-es/modularDrawer/hooks/__test__/useAssetsData.test.d.ts +5 -0
  112. package/lib-es/modularDrawer/hooks/__test__/useAssetsData.test.d.ts.map +1 -0
  113. package/lib-es/modularDrawer/hooks/__test__/useAssetsData.test.js +118 -0
  114. package/lib-es/modularDrawer/hooks/__test__/useAssetsData.test.js.map +1 -0
  115. package/lib-es/modularDrawer/hooks/useAssetsData.d.ts +13 -0
  116. package/lib-es/modularDrawer/hooks/useAssetsData.d.ts.map +1 -0
  117. package/lib-es/modularDrawer/hooks/useAssetsData.js +27 -0
  118. package/lib-es/modularDrawer/hooks/useAssetsData.js.map +1 -0
  119. package/package.json +46 -45
  120. package/src/bridge/generic-alpaca/estimateMaxSpendable.ts +11 -5
  121. package/src/bridge/generic-alpaca/getTransactionStatus.ts +2 -1
  122. package/src/bridge/generic-alpaca/prepareTransaction.ts +20 -16
  123. package/src/bridge/generic-alpaca/signOperation.ts +3 -2
  124. package/src/bridge/generic-alpaca/tests/prepareTransaction.test.ts +1 -1
  125. package/src/bridge/generic-alpaca/utils.ts +0 -2
  126. package/src/currencies/index.ts +0 -1
  127. package/src/currencies/sortByMarketcap.test.ts +2 -1
  128. package/src/e2e/enum/AppInfos.ts +1 -1
  129. package/src/e2e/enum/Provider.ts +2 -2
  130. package/src/e2e/speculos.ts +3 -4
  131. package/src/e2e/speculosCI.ts +18 -6
  132. package/src/featureFlags/defaultFeatures.ts +1 -0
  133. package/src/modularDrawer/data/entities/index.ts +79 -0
  134. package/src/modularDrawer/data/state-manager/api.ts +62 -0
  135. package/src/modularDrawer/hooks/__test__/useAssetsData.test.ts +139 -0
  136. package/src/modularDrawer/hooks/useAssetsData.ts +36 -0
@@ -21,6 +21,14 @@ function uniqueId(): string {
21
21
  return timestamp + randomString;
22
22
  }
23
23
 
24
+ function slugify(name: string): string {
25
+ return name
26
+ .toLowerCase()
27
+ .trim()
28
+ .replace(/[^a-z0-9]+/g, "-")
29
+ .replace(/^-+|-+$/g, "");
30
+ }
31
+
24
32
  /**
25
33
  * Helper function to make API requests with error handling
26
34
  */
@@ -58,10 +66,14 @@ async function githubApiRequest<T = unknown>({
58
66
  }
59
67
  }
60
68
 
61
- function waitForSpeculosReady(url: string, { interval = 2000, timeout = 300_000 } = {}) {
69
+ export function waitForSpeculosReady(
70
+ deviceId: string,
71
+ { interval = 2_000, timeout = 150_000 } = {},
72
+ ) {
62
73
  return new Promise((resolve, reject) => {
63
74
  const startTime = Date.now();
64
75
  let currentRequest: ReturnType<typeof https.get> | null = null;
76
+ const url = getSpeculosAddress(deviceId);
65
77
 
66
78
  function cleanup() {
67
79
  if (currentRequest) {
@@ -151,22 +163,22 @@ function createStartPayload(deviceParams: DeviceParams, runId: string) {
151
163
  export async function createSpeculosDeviceCI(
152
164
  deviceParams: DeviceParams,
153
165
  ): Promise<SpeculosDevice | undefined> {
166
+ const runId = `${slugify(deviceParams.appName)}-${uniqueId()}`;
154
167
  try {
155
- const runId = uniqueId();
156
- console.warn("Creating remote speculos:", runId);
157
168
  const data = createStartPayload(deviceParams, runId);
158
169
  await githubApiRequest({ urlSuffix: START_WORKFLOW_ID, data });
159
- await waitForSpeculosReady(getSpeculosAddress(runId));
160
-
161
170
  return {
162
171
  id: runId,
163
172
  port: speculosPort,
164
173
  };
165
174
  } catch (e: unknown) {
166
- console.error(e);
167
175
  console.warn(
168
176
  `Creating remote speculos ${deviceParams.appName}:${deviceParams.appVersion} failed with ${String(e)}`,
169
177
  );
178
+ return {
179
+ id: runId,
180
+ port: 0,
181
+ };
170
182
  }
171
183
  }
172
184
 
@@ -625,6 +625,7 @@ export const DEFAULT_FEATURES: Features = {
625
625
  },
626
626
  },
627
627
  lldModularDrawerBackendData: DEFAULT_FEATURE,
628
+ llmModularDrawerBackendData: DEFAULT_FEATURE,
628
629
  llmModularDrawer: {
629
630
  ...DEFAULT_FEATURE,
630
631
  params: {
@@ -0,0 +1,79 @@
1
+ import type { CryptoOrTokenCurrency } from "@ledgerhq/types-cryptoassets";
2
+ import type { ApiAsset } from "@ledgerhq/cryptoassets";
3
+ import { PartialMarketItemResponse } from "@ledgerhq/live-common/market/utils/types";
4
+
5
+ // Types for crypto asset metadata
6
+ export interface CryptoAssetMeta {
7
+ /** Asset identifier */
8
+ id: string;
9
+ /** Asset ticker symbol */
10
+ ticker: string;
11
+ /** Asset display name */
12
+ name: string;
13
+ /** Map of network IDs to their corresponding asset IDs */
14
+ assetsIds: Record<string, string>;
15
+ }
16
+
17
+ // Types for network information
18
+ export interface NetworkInfo {
19
+ /** Network identifier */
20
+ id: string;
21
+ /** Network display name */
22
+ name: string;
23
+ }
24
+
25
+ // Types for interest rate data
26
+ export interface InterestRate {
27
+ /** Currency identifier */
28
+ currencyId: string;
29
+ /** Interest rate value */
30
+ rate: number;
31
+ /** Type of rate (NRR, APR, APY, etc.) */
32
+ type: string;
33
+ /** Timestamp when the rate was fetched */
34
+ fetchAt: string;
35
+ }
36
+
37
+ // Types for currency ordering
38
+ export interface CurrenciesOrder {
39
+ /** Sorting key (e.g., "marketCap") */
40
+ key: string;
41
+ /** Sort order (e.g., "desc") */
42
+ order: string;
43
+ /** Ordered list of currency IDs */
44
+ currenciesIds: string[];
45
+ /** Ordered list of meta-currency IDs */
46
+ metaCurrencyIds: string[];
47
+ }
48
+
49
+ // Types for raw API response (before transformation)
50
+ export interface RawApiResponse {
51
+ /** Grouped crypto assets by meta-currency */
52
+ cryptoAssets: Record<string, CryptoAssetMeta>;
53
+ /** Network information */
54
+ networks: Record<string, NetworkInfo>;
55
+ /** Raw crypto currencies and token currencies from API */
56
+ cryptoOrTokenCurrencies: Record<string, ApiAsset>;
57
+ /** Interest rates for various currencies */
58
+ interestRates: Record<string, InterestRate>;
59
+ /** Market data for currencies */
60
+ markets: Record<string, PartialMarketItemResponse>;
61
+ /** Currency ordering information */
62
+ currenciesOrder: CurrenciesOrder;
63
+ }
64
+
65
+ // Types for transformed API response (after transformation)
66
+ export interface AssetsData {
67
+ /** Grouped crypto assets by meta-currency */
68
+ cryptoAssets: Record<string, CryptoAssetMeta>;
69
+ /** Network information */
70
+ networks: Record<string, NetworkInfo>;
71
+ /** Transformed crypto currencies and token currencies compatible with Ledger Live */
72
+ cryptoOrTokenCurrencies: Record<string, CryptoOrTokenCurrency>;
73
+ /** Interest rates for various currencies */
74
+ interestRates: Record<string, InterestRate>;
75
+ /** Market data for currencies */
76
+ markets: Record<string, PartialMarketItemResponse>;
77
+ /** Currency ordering information */
78
+ currenciesOrder: CurrenciesOrder;
79
+ }
@@ -0,0 +1,62 @@
1
+ import { createApi, fetchBaseQuery, FetchBaseQueryMeta } from "@reduxjs/toolkit/query/react";
2
+ import { convertApiAssets } from "@ledgerhq/cryptoassets";
3
+ import { AssetsData, RawApiResponse } from "../entities";
4
+ import { getEnv } from "@ledgerhq/live-env";
5
+
6
+ export enum AssetsDataTags {
7
+ Assets = "Assets",
8
+ }
9
+
10
+ export interface GetAssetsDataParams {
11
+ cursor?: string;
12
+ search?: string;
13
+ currencyIds?: string[];
14
+ }
15
+
16
+ export interface AssetsDataWithPagination extends AssetsData {
17
+ pagination: {
18
+ nextCursor?: string;
19
+ };
20
+ }
21
+
22
+ function transformAssetsResponse(
23
+ response: RawApiResponse,
24
+ meta?: FetchBaseQueryMeta,
25
+ ): AssetsDataWithPagination {
26
+ const enrichedCryptoOrTokenCurrencies = convertApiAssets(response.cryptoOrTokenCurrencies);
27
+
28
+ const nextCursor = meta?.response?.headers.get("x-ledger-next") || undefined;
29
+
30
+ return {
31
+ ...response,
32
+ cryptoOrTokenCurrencies: enrichedCryptoOrTokenCurrencies,
33
+ pagination: {
34
+ nextCursor,
35
+ },
36
+ };
37
+ }
38
+
39
+ export const assetsDataApi = createApi({
40
+ reducerPath: "assetsDataApi",
41
+ baseQuery: fetchBaseQuery({
42
+ baseUrl: __DEV__ ? getEnv("DADA_API_STAGING") : getEnv("DADA_API_PROD"),
43
+ }),
44
+ tagTypes: [AssetsDataTags.Assets],
45
+ 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 }),
53
+ pageSize: 100,
54
+ },
55
+ }),
56
+ providesTags: [AssetsDataTags.Assets],
57
+ transformResponse: transformAssetsResponse,
58
+ }),
59
+ }),
60
+ });
61
+
62
+ export const { useGetAssetsDataQuery } = assetsDataApi;
@@ -0,0 +1,139 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+
5
+ import { renderHook } from "@testing-library/react";
6
+ import { useAssetsData } from "../useAssetsData";
7
+ import { useGetAssetsDataQuery } from "../../data/state-manager/api";
8
+
9
+ jest.mock("../../data/state-manager/api", () => ({
10
+ useGetAssetsDataQuery: jest.fn(),
11
+ }));
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);
22
+
23
+ describe("useAssetsData", () => {
24
+ beforeEach(() => {
25
+ jest.clearAllMocks();
26
+ });
27
+
28
+ it("should return loading state when API is loading", () => {
29
+ mockUseGetAssetsDataQuery.mockReturnValue({
30
+ data: undefined,
31
+ isLoading: true,
32
+ error: undefined,
33
+ refetch: jest.fn(),
34
+ isFetching: false,
35
+ isSuccess: false,
36
+ isError: false,
37
+ currentData: undefined,
38
+ });
39
+
40
+ const { result } = renderHook(() => useAssetsData({}));
41
+
42
+ expect(result.current.isLoading).toBe(true);
43
+ expect(result.current.data).toBe(undefined);
44
+ expect(result.current.hasMore).toBe(false);
45
+ });
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,
61
+ });
62
+
63
+ const { result } = renderHook(() => useAssetsData({}));
64
+
65
+ expect(result.current.data).toBe(mockData);
66
+ expect(result.current.isLoading).toBe(false);
67
+ expect(result.current.hasMore).toBe(true);
68
+ });
69
+
70
+ it("should return error when API has error", () => {
71
+ const mockError = new Error("API Error");
72
+ mockUseGetAssetsDataQuery.mockReturnValue({
73
+ data: undefined,
74
+ isLoading: false,
75
+ error: mockError,
76
+ refetch: jest.fn(),
77
+ isFetching: false,
78
+ isSuccess: false,
79
+ isError: true,
80
+ currentData: undefined,
81
+ });
82
+
83
+ const { result } = renderHook(() => useAssetsData({}));
84
+
85
+ expect(result.current.error).toBe(mockError);
86
+ expect(result.current.isLoading).toBe(false);
87
+ });
88
+
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 },
105
+ },
106
+ });
107
+
108
+ const { result } = renderHook(() => useAssetsData({}));
109
+
110
+ result.current.loadNext();
111
+
112
+ expect(mockSetCursor).toHaveBeenCalledWith(nextCursor);
113
+ });
114
+
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: [],
129
+ pagination: { nextCursor: undefined },
130
+ },
131
+ });
132
+
133
+ const { result } = renderHook(() => useAssetsData({}));
134
+
135
+ result.current.loadNext();
136
+
137
+ expect(mockSetCursor).not.toHaveBeenCalled();
138
+ });
139
+ });
@@ -0,0 +1,36 @@
1
+ import { useState, useCallback } from "react";
2
+ import { useGetAssetsDataQuery } from "../data/state-manager/api";
3
+
4
+ export function useAssetsData({
5
+ search,
6
+ currencyIds,
7
+ }: {
8
+ search?: string;
9
+ currencyIds?: string[];
10
+ }) {
11
+ const [cursor, setCursor] = useState<string | undefined>(undefined);
12
+ const { data, error, isLoading, isSuccess } = useGetAssetsDataQuery({
13
+ cursor,
14
+ search,
15
+ currencyIds,
16
+ });
17
+
18
+ const loadNext = useCallback(() => {
19
+ const nextCursor = data?.pagination?.nextCursor;
20
+ if (nextCursor) {
21
+ setCursor(nextCursor);
22
+ }
23
+ }, [data?.pagination?.nextCursor]);
24
+
25
+ const hasMore = Boolean(data?.pagination?.nextCursor);
26
+
27
+ return {
28
+ data,
29
+ error,
30
+ isLoading,
31
+ isSuccess,
32
+ hasMore,
33
+ cursor,
34
+ loadNext,
35
+ };
36
+ }