@ledgerhq/cryptoassets 13.32.0-nightly.1 → 13.32.0-nightly.3
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.
- package/.turbo/turbo-build.log +1 -1
- package/.unimportedrc.json +3 -6
- package/CHANGELOG.md +27 -0
- package/lib/abandonseed.d.ts.map +1 -1
- package/lib/abandonseed.js +1 -0
- package/lib/abandonseed.js.map +1 -1
- package/lib/api-token-converter.d.ts +29 -0
- package/lib/api-token-converter.d.ts.map +1 -1
- package/lib/api-token-converter.js +101 -110
- package/lib/api-token-converter.js.map +1 -1
- package/lib/cal-client/entities/index.d.ts +125 -0
- package/lib/cal-client/entities/index.d.ts.map +1 -0
- package/lib/cal-client/entities/index.js +57 -0
- package/lib/cal-client/entities/index.js.map +1 -0
- package/lib/cal-client/hooks/index.d.ts +2 -0
- package/lib/cal-client/hooks/index.d.ts.map +1 -0
- package/lib/cal-client/hooks/index.js +18 -0
- package/lib/cal-client/hooks/index.js.map +1 -0
- package/lib/cal-client/hooks/useTokensData.d.ts +11 -0
- package/lib/cal-client/hooks/useTokensData.d.ts.map +1 -0
- package/lib/cal-client/hooks/useTokensData.js +35 -0
- package/lib/cal-client/hooks/useTokensData.js.map +1 -0
- package/lib/cal-client/state-manager/api.d.ts +842 -0
- package/lib/cal-client/state-manager/api.d.ts.map +1 -0
- package/lib/cal-client/state-manager/api.js +86 -0
- package/lib/cal-client/state-manager/api.js.map +1 -0
- package/lib/cal-client/state-manager/fields.d.ts +2 -0
- package/lib/cal-client/state-manager/fields.d.ts.map +1 -0
- package/lib/cal-client/state-manager/fields.js +24 -0
- package/lib/cal-client/state-manager/fields.js.map +1 -0
- package/lib/cal-client/state-manager/types.d.ts +36 -0
- package/lib/cal-client/state-manager/types.d.ts.map +1 -0
- package/lib/cal-client/state-manager/types.js +8 -0
- package/lib/cal-client/state-manager/types.js.map +1 -0
- package/lib/currencies.d.ts.map +1 -1
- package/lib/currencies.js +52 -0
- package/lib/currencies.js.map +1 -1
- package/lib-es/abandonseed.d.ts.map +1 -1
- package/lib-es/abandonseed.js +1 -0
- package/lib-es/abandonseed.js.map +1 -1
- package/lib-es/api-token-converter.d.ts +29 -0
- package/lib-es/api-token-converter.d.ts.map +1 -1
- package/lib-es/api-token-converter.js +99 -109
- package/lib-es/api-token-converter.js.map +1 -1
- package/lib-es/cal-client/entities/index.d.ts +125 -0
- package/lib-es/cal-client/entities/index.d.ts.map +1 -0
- package/lib-es/cal-client/entities/index.js +54 -0
- package/lib-es/cal-client/entities/index.js.map +1 -0
- package/lib-es/cal-client/hooks/index.d.ts +2 -0
- package/lib-es/cal-client/hooks/index.d.ts.map +1 -0
- package/lib-es/cal-client/hooks/index.js +2 -0
- package/lib-es/cal-client/hooks/index.js.map +1 -0
- package/lib-es/cal-client/hooks/useTokensData.d.ts +11 -0
- package/lib-es/cal-client/hooks/useTokensData.d.ts.map +1 -0
- package/lib-es/cal-client/hooks/useTokensData.js +31 -0
- package/lib-es/cal-client/hooks/useTokensData.js.map +1 -0
- package/lib-es/cal-client/state-manager/api.d.ts +842 -0
- package/lib-es/cal-client/state-manager/api.d.ts.map +1 -0
- package/lib-es/cal-client/state-manager/api.js +83 -0
- package/lib-es/cal-client/state-manager/api.js.map +1 -0
- package/lib-es/cal-client/state-manager/fields.d.ts +2 -0
- package/lib-es/cal-client/state-manager/fields.d.ts.map +1 -0
- package/lib-es/cal-client/state-manager/fields.js +21 -0
- package/lib-es/cal-client/state-manager/fields.js.map +1 -0
- package/lib-es/cal-client/state-manager/types.d.ts +36 -0
- package/lib-es/cal-client/state-manager/types.d.ts.map +1 -0
- package/lib-es/cal-client/state-manager/types.js +5 -0
- package/lib-es/cal-client/state-manager/types.js.map +1 -0
- package/lib-es/currencies.d.ts.map +1 -1
- package/lib-es/currencies.js +52 -0
- package/lib-es/currencies.js.map +1 -1
- package/package.json +6 -3
- package/src/abandonseed.ts +1 -0
- package/src/api-token-converter.test.ts +217 -221
- package/src/api-token-converter.ts +124 -140
- package/src/cal-client/MIGRATION_GUIDE.md +276 -0
- package/src/cal-client/README.md +125 -0
- package/src/cal-client/entities/index.ts +59 -0
- package/src/cal-client/hooks/__tests__/useTokensData.test.ts +222 -0
- package/src/cal-client/hooks/index.ts +1 -0
- package/src/cal-client/hooks/useTokensData.ts +47 -0
- package/src/cal-client/state-manager/api.ts +97 -0
- package/src/cal-client/state-manager/fields.ts +20 -0
- package/src/cal-client/state-manager/types.ts +39 -0
- package/src/currencies.ts +52 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for token unit
|
|
5
|
+
*/
|
|
6
|
+
export const TokenUnitSchema = z.object({
|
|
7
|
+
/** Code identifier for the unit */
|
|
8
|
+
code: z.string(),
|
|
9
|
+
/** Display name of the unit */
|
|
10
|
+
name: z.string(),
|
|
11
|
+
/** Magnitude (number of decimals) */
|
|
12
|
+
magnitude: z.number(),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export type TokenUnit = z.infer<typeof TokenUnitSchema>;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Zod schema for API token response
|
|
19
|
+
*/
|
|
20
|
+
export const ApiTokenResponseSchema = z.object({
|
|
21
|
+
/** Type of asset (token or currency) */
|
|
22
|
+
type: z.string(),
|
|
23
|
+
/** Unique identifier for the token */
|
|
24
|
+
id: z.string(),
|
|
25
|
+
/** Smart contract address */
|
|
26
|
+
contract_address: z.string(),
|
|
27
|
+
/** Token standard (e.g., erc20, bep20, spl) */
|
|
28
|
+
standard: z.string(),
|
|
29
|
+
/** Number of decimals */
|
|
30
|
+
decimals: z.number(),
|
|
31
|
+
/** Network identifier (e.g., arbitrum, ethereum) */
|
|
32
|
+
network: z.string(),
|
|
33
|
+
/** Network family (e.g., ethereum, solana) */
|
|
34
|
+
network_family: z.string(),
|
|
35
|
+
/** Whether the token is delisted */
|
|
36
|
+
delisted: z.boolean(),
|
|
37
|
+
/** Full name of the token */
|
|
38
|
+
name: z.string(),
|
|
39
|
+
/** Ticker symbol */
|
|
40
|
+
ticker: z.string(),
|
|
41
|
+
/** Array of unit representations */
|
|
42
|
+
units: z.array(TokenUnitSchema).min(1),
|
|
43
|
+
/** Symbol */
|
|
44
|
+
symbol: z.string(),
|
|
45
|
+
/** Chain ID */
|
|
46
|
+
chain_id: z.string(),
|
|
47
|
+
/** Token identifier */
|
|
48
|
+
token_identifier: z.string().optional(),
|
|
49
|
+
/** Network type */
|
|
50
|
+
network_type: z.string(),
|
|
51
|
+
/** Meta currency ID */
|
|
52
|
+
meta_currency_id: z.string(),
|
|
53
|
+
/** Blockchain name */
|
|
54
|
+
blockchain_name: z.string(),
|
|
55
|
+
/** Live signature */
|
|
56
|
+
live_signature: z.string().optional(),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export type ApiTokenResponse = z.infer<typeof ApiTokenResponseSchema>;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { renderHook } from "@testing-library/react";
|
|
6
|
+
import { useTokensData } from "../useTokensData";
|
|
7
|
+
import { useGetTokensDataInfiniteQuery } from "../../state-manager/api";
|
|
8
|
+
|
|
9
|
+
jest.mock("../../state-manager/api", () => ({
|
|
10
|
+
useGetTokensDataInfiniteQuery: jest.fn(),
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
const mockUseGetTokensDataInfiniteQuery = jest.mocked(useGetTokensDataInfiniteQuery);
|
|
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
|
+
};
|
|
28
|
+
|
|
29
|
+
describe("useAssetsData", () => {
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
jest.clearAllMocks();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("should return loading state when API is loading", () => {
|
|
35
|
+
mockUseGetTokensDataInfiniteQuery.mockReturnValue({
|
|
36
|
+
...defaultMockValues,
|
|
37
|
+
isLoading: true,
|
|
38
|
+
status: "pending",
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const { result } = renderHook(() =>
|
|
42
|
+
useTokensData({
|
|
43
|
+
networkFamily: ["ethereum"],
|
|
44
|
+
pageSize: 100,
|
|
45
|
+
output: ["id", "name", "ticker", "contract_address"],
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
expect(result.current.isLoading).toBe(true);
|
|
50
|
+
expect(result.current.data).toBe(undefined);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("should return combined data from multiple pages", () => {
|
|
54
|
+
const mockPages = [
|
|
55
|
+
{
|
|
56
|
+
tokens: [
|
|
57
|
+
{
|
|
58
|
+
id: "token-1",
|
|
59
|
+
name: "Token 1",
|
|
60
|
+
ticker: "T1",
|
|
61
|
+
contractAddress: "0x123",
|
|
62
|
+
parentCurrency: { id: "currency-1", name: "Currency 1" },
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: "token-2",
|
|
66
|
+
name: "Token 2",
|
|
67
|
+
ticker: "T2",
|
|
68
|
+
contractAddress: "0x456",
|
|
69
|
+
parentCurrency: { id: "currency-2", name: "Currency 2" },
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
pagination: { nextCursor: "cursor-2" },
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
tokens: [
|
|
76
|
+
{
|
|
77
|
+
id: "token-3",
|
|
78
|
+
name: "Token 3",
|
|
79
|
+
ticker: "T3",
|
|
80
|
+
contractAddress: "0x789",
|
|
81
|
+
parentCurrency: { id: "currency-3", name: "Currency 3" },
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
pagination: { nextCursor: undefined },
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
mockUseGetTokensDataInfiniteQuery.mockReturnValue({
|
|
89
|
+
...defaultMockValues,
|
|
90
|
+
data: { pages: mockPages, pageParams: [{ cursor: "" }, { cursor: "cursor-2" }] },
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const { result } = renderHook(() =>
|
|
94
|
+
useTokensData({
|
|
95
|
+
networkFamily: ["ethereum"],
|
|
96
|
+
pageSize: 100,
|
|
97
|
+
output: ["id", "name", "ticker", "contract_address"],
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
expect(result.current.data).toEqual({
|
|
102
|
+
tokens: [
|
|
103
|
+
{
|
|
104
|
+
id: "token-1",
|
|
105
|
+
name: "Token 1",
|
|
106
|
+
ticker: "T1",
|
|
107
|
+
contractAddress: "0x123",
|
|
108
|
+
parentCurrency: { id: "currency-1", name: "Currency 1" },
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: "token-2",
|
|
112
|
+
name: "Token 2",
|
|
113
|
+
ticker: "T2",
|
|
114
|
+
contractAddress: "0x456",
|
|
115
|
+
parentCurrency: { id: "currency-2", name: "Currency 2" },
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: "token-3",
|
|
119
|
+
name: "Token 3",
|
|
120
|
+
ticker: "T3",
|
|
121
|
+
contractAddress: "0x789",
|
|
122
|
+
parentCurrency: { id: "currency-3", name: "Currency 3" },
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
pagination: { nextCursor: undefined },
|
|
126
|
+
});
|
|
127
|
+
expect(result.current.isLoading).toBe(false);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("should return error when API has error", () => {
|
|
131
|
+
const mockError = new Error("API Error");
|
|
132
|
+
mockUseGetTokensDataInfiniteQuery.mockReturnValue({
|
|
133
|
+
...defaultMockValues,
|
|
134
|
+
data: undefined,
|
|
135
|
+
error: mockError,
|
|
136
|
+
isSuccess: false,
|
|
137
|
+
isError: true,
|
|
138
|
+
status: "error",
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const { result } = renderHook(() =>
|
|
142
|
+
useTokensData({
|
|
143
|
+
networkFamily: ["ethereum"],
|
|
144
|
+
pageSize: 100,
|
|
145
|
+
output: ["id", "name", "ticker", "contract_address"],
|
|
146
|
+
}),
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
expect(result.current.error).toBe(mockError);
|
|
150
|
+
expect(result.current.isLoading).toBe(false);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("should provide loadNext function when there's a nextCursor", () => {
|
|
154
|
+
const mockFetchNextPage = jest.fn();
|
|
155
|
+
const mockPages = [
|
|
156
|
+
{
|
|
157
|
+
tokens: [],
|
|
158
|
+
pagination: { nextCursor: "next-cursor-456" },
|
|
159
|
+
},
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
mockUseGetTokensDataInfiniteQuery.mockReturnValue({
|
|
163
|
+
...defaultMockValues,
|
|
164
|
+
data: { pages: mockPages, pageParams: [{ cursor: "" }] },
|
|
165
|
+
fetchNextPage: mockFetchNextPage,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const { result } = renderHook(() =>
|
|
169
|
+
useTokensData({
|
|
170
|
+
networkFamily: ["ethereum"],
|
|
171
|
+
pageSize: 100,
|
|
172
|
+
output: ["id", "name", "ticker", "contract_address"],
|
|
173
|
+
}),
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
expect(result.current.loadNext).toBeDefined();
|
|
177
|
+
result.current.loadNext?.();
|
|
178
|
+
|
|
179
|
+
expect(mockFetchNextPage).toHaveBeenCalled();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("should not provide loadNext function when there's no nextCursor", () => {
|
|
183
|
+
const mockPages = [
|
|
184
|
+
{
|
|
185
|
+
tokens: [],
|
|
186
|
+
pagination: { nextCursor: undefined },
|
|
187
|
+
},
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
mockUseGetTokensDataInfiniteQuery.mockReturnValue({
|
|
191
|
+
...defaultMockValues,
|
|
192
|
+
data: { pages: mockPages, pageParams: [{ cursor: "" }] },
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const { result } = renderHook(() =>
|
|
196
|
+
useTokensData({
|
|
197
|
+
networkFamily: ["ethereum"],
|
|
198
|
+
pageSize: 100,
|
|
199
|
+
output: ["id", "name", "ticker", "contract_address"],
|
|
200
|
+
}),
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
expect(result.current.loadNext).toBeUndefined();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it("should return undefined data when no pages exist", () => {
|
|
207
|
+
mockUseGetTokensDataInfiniteQuery.mockReturnValue({
|
|
208
|
+
...defaultMockValues,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const { result } = renderHook(() =>
|
|
212
|
+
useTokensData({
|
|
213
|
+
networkFamily: ["ethereum"],
|
|
214
|
+
pageSize: 100,
|
|
215
|
+
output: ["id", "name", "ticker", "contract_address"],
|
|
216
|
+
}),
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
expect(result.current.data).toBeUndefined();
|
|
220
|
+
expect(result.current.loadNext).toBeUndefined();
|
|
221
|
+
});
|
|
222
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./useTokensData";
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useGetTokensDataInfiniteQuery } from "../state-manager/api";
|
|
3
|
+
import { TokensDataWithPagination, GetTokensDataParams } from "../state-manager/types";
|
|
4
|
+
|
|
5
|
+
const emptyData = () => ({
|
|
6
|
+
tokens: [],
|
|
7
|
+
pagination: { nextCursor: "" },
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export function useTokensData(params: GetTokensDataParams) {
|
|
11
|
+
const {
|
|
12
|
+
data,
|
|
13
|
+
isLoading,
|
|
14
|
+
error,
|
|
15
|
+
fetchNextPage,
|
|
16
|
+
isSuccess,
|
|
17
|
+
refetch,
|
|
18
|
+
isFetching,
|
|
19
|
+
isError,
|
|
20
|
+
isFetchingNextPage,
|
|
21
|
+
} = useGetTokensDataInfiniteQuery(params);
|
|
22
|
+
|
|
23
|
+
const joinedPages = useMemo(() => {
|
|
24
|
+
return data?.pages.reduce<TokensDataWithPagination>((acc, page) => {
|
|
25
|
+
return {
|
|
26
|
+
tokens: [...acc.tokens, ...page.tokens],
|
|
27
|
+
pagination: {
|
|
28
|
+
nextCursor: page.pagination.nextCursor,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}, emptyData());
|
|
32
|
+
}, [data]);
|
|
33
|
+
|
|
34
|
+
const hasMore = Boolean(joinedPages?.pagination.nextCursor);
|
|
35
|
+
|
|
36
|
+
const isInitialLoading = isLoading || (isFetching && !isFetchingNextPage);
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
data: joinedPages,
|
|
40
|
+
isLoading: isInitialLoading,
|
|
41
|
+
error,
|
|
42
|
+
loadNext: hasMore ? fetchNextPage : undefined,
|
|
43
|
+
isSuccess,
|
|
44
|
+
isError,
|
|
45
|
+
refetch,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { createApi, fetchBaseQuery, FetchBaseQueryMeta } from "@reduxjs/toolkit/query/react";
|
|
2
|
+
import { ApiTokenResponse } from "../entities";
|
|
3
|
+
import { getEnv } from "@ledgerhq/live-env";
|
|
4
|
+
import { GetTokensDataParams, PageParam, TokensDataTags, TokensDataWithPagination } from "./types";
|
|
5
|
+
import { TOKEN_OUTPUT_FIELDS } from "./fields";
|
|
6
|
+
import { TokenCurrency } from "@ledgerhq/types-cryptoassets";
|
|
7
|
+
import { convertApiToken } from "../../api-token-converter";
|
|
8
|
+
|
|
9
|
+
function transformTokensResponse(
|
|
10
|
+
response: ApiTokenResponse[],
|
|
11
|
+
meta?: FetchBaseQueryMeta,
|
|
12
|
+
): TokensDataWithPagination {
|
|
13
|
+
const nextCursor = meta?.response?.headers.get("x-ledger-next") || undefined;
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
tokens: response.flatMap(token => {
|
|
17
|
+
const result = transformApiTokenToTokenCurrency(token);
|
|
18
|
+
return result ? [result] : [];
|
|
19
|
+
}),
|
|
20
|
+
pagination: {
|
|
21
|
+
nextCursor,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function transformApiTokenToTokenCurrency(token: ApiTokenResponse): TokenCurrency | undefined {
|
|
27
|
+
// convertApiToken handles all format reconciliation internally
|
|
28
|
+
const result = convertApiToken({
|
|
29
|
+
id: token.id,
|
|
30
|
+
contractAddress: token.contract_address,
|
|
31
|
+
name: token.name,
|
|
32
|
+
ticker: token.ticker,
|
|
33
|
+
units: token.units,
|
|
34
|
+
standard: token.standard,
|
|
35
|
+
tokenIdentifier: token.token_identifier,
|
|
36
|
+
delisted: token.delisted,
|
|
37
|
+
ledgerSignature: token.live_signature,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Add symbol if result exists
|
|
41
|
+
if (result && token.symbol) {
|
|
42
|
+
return {
|
|
43
|
+
...result,
|
|
44
|
+
symbol: token.symbol,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const cryptoAssetsApi = createApi({
|
|
52
|
+
reducerPath: "cryptoAssetsApi",
|
|
53
|
+
baseQuery: fetchBaseQuery({
|
|
54
|
+
baseUrl: "",
|
|
55
|
+
}),
|
|
56
|
+
tagTypes: [TokensDataTags.Tokens],
|
|
57
|
+
endpoints: build => ({
|
|
58
|
+
getTokensData: build.infiniteQuery<TokensDataWithPagination, GetTokensDataParams, PageParam>({
|
|
59
|
+
query: ({ pageParam, queryArg = {} }) => {
|
|
60
|
+
const { isStaging = false, output, networkFamily, pageSize = 100, limit, ref } = queryArg;
|
|
61
|
+
|
|
62
|
+
const params = {
|
|
63
|
+
output: output?.join(",") || TOKEN_OUTPUT_FIELDS.join(","),
|
|
64
|
+
...(pageParam?.cursor && { cursor: pageParam.cursor }),
|
|
65
|
+
...(networkFamily && { network_family: networkFamily }),
|
|
66
|
+
pageSize,
|
|
67
|
+
...(limit && { limit }),
|
|
68
|
+
...(ref && { ref }),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const baseUrl = isStaging ? getEnv("CAL_SERVICE_URL_STAGING") : getEnv("CAL_SERVICE_URL");
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
url: `${baseUrl}/v1/tokens`,
|
|
75
|
+
params,
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
providesTags: [TokensDataTags.Tokens],
|
|
79
|
+
transformResponse: transformTokensResponse,
|
|
80
|
+
infiniteQueryOptions: {
|
|
81
|
+
initialPageParam: {
|
|
82
|
+
cursor: "",
|
|
83
|
+
},
|
|
84
|
+
getNextPageParam: lastPage => {
|
|
85
|
+
if (lastPage.pagination.nextCursor) {
|
|
86
|
+
return {
|
|
87
|
+
cursor: lastPage.pagination.nextCursor,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return undefined;
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
}),
|
|
94
|
+
}),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
export const { useGetTokensDataInfiniteQuery } = cryptoAssetsApi;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const TOKEN_OUTPUT_FIELDS = [
|
|
2
|
+
"id",
|
|
3
|
+
"name",
|
|
4
|
+
"ticker",
|
|
5
|
+
"symbol",
|
|
6
|
+
"contract_address",
|
|
7
|
+
"standard",
|
|
8
|
+
"decimals",
|
|
9
|
+
"network",
|
|
10
|
+
"network_family",
|
|
11
|
+
"units",
|
|
12
|
+
"type",
|
|
13
|
+
"delisted",
|
|
14
|
+
"chain_id",
|
|
15
|
+
"token_identifier",
|
|
16
|
+
"network_type",
|
|
17
|
+
"meta_currency_id",
|
|
18
|
+
"blockchain_name",
|
|
19
|
+
"live_signature",
|
|
20
|
+
] as const;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { TokenCurrency } from "@ledgerhq/types-cryptoassets";
|
|
2
|
+
|
|
3
|
+
export enum TokensDataTags {
|
|
4
|
+
Tokens = "Tokens",
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Parameters for the getTokensData query
|
|
9
|
+
*
|
|
10
|
+
* @param networkFamily - Filter by network families (e.g., ["ethereum", "polygon"])
|
|
11
|
+
* @param isStaging - Use staging or production environment
|
|
12
|
+
* @param pageSize - Number of items per page (default: 100, options: 10, 100, 1000)
|
|
13
|
+
* @param output - Specify output fields (default: all fields, values: id, name, ticker, units, delisted)
|
|
14
|
+
* @param limit - Maximum number of assets to return
|
|
15
|
+
* @param ref - Reference to the source of the data Default: "branch:main" Examples:
|
|
16
|
+
* - ref=branch:main - Main branch HEAD
|
|
17
|
+
* - ref=tag:tokens-1.11.12 - specific tag
|
|
18
|
+
* - ref=commit:48188c6ca2888a9c50a0466d2442ec2f24cc2852 - specific commit
|
|
19
|
+
* - CAL reference to use
|
|
20
|
+
*/
|
|
21
|
+
export interface GetTokensDataParams {
|
|
22
|
+
networkFamily?: string[];
|
|
23
|
+
output?: string[];
|
|
24
|
+
limit?: number;
|
|
25
|
+
pageSize?: number;
|
|
26
|
+
ref?: string;
|
|
27
|
+
isStaging?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface PageParam {
|
|
31
|
+
cursor?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface TokensDataWithPagination {
|
|
35
|
+
tokens: TokenCurrency[];
|
|
36
|
+
pagination: {
|
|
37
|
+
nextCursor?: string;
|
|
38
|
+
};
|
|
39
|
+
}
|
package/src/currencies.ts
CHANGED
|
@@ -3487,6 +3487,37 @@ export const cryptocurrenciesById: Record<CryptoCurrencyId, CryptoCurrency> = {
|
|
|
3487
3487
|
],
|
|
3488
3488
|
explorerId: "btc_testnet",
|
|
3489
3489
|
},
|
|
3490
|
+
bitcoin_regtest: {
|
|
3491
|
+
type: "CryptoCurrency",
|
|
3492
|
+
id: "bitcoin_regtest",
|
|
3493
|
+
coinType: CoinType.BTC_TESTNET,
|
|
3494
|
+
name: "Bitcoin Regtest",
|
|
3495
|
+
managerAppName: "Bitcoin Test",
|
|
3496
|
+
ticker: "BTC",
|
|
3497
|
+
scheme: "regtest",
|
|
3498
|
+
color: "#00ff00",
|
|
3499
|
+
symbol: "Ƀ",
|
|
3500
|
+
units: bitcoinUnits.map(makeTestnetUnit),
|
|
3501
|
+
deviceTicker: "TEST",
|
|
3502
|
+
supportsSegwit: true,
|
|
3503
|
+
supportsNativeSegwit: true,
|
|
3504
|
+
isTestnetFor: "bitcoin",
|
|
3505
|
+
disableCountervalue: true,
|
|
3506
|
+
family: "bitcoin",
|
|
3507
|
+
blockAvgTime: 15 * 60,
|
|
3508
|
+
bitcoinLikeInfo: {
|
|
3509
|
+
P2PKH: 111,
|
|
3510
|
+
P2SH: 196,
|
|
3511
|
+
XPUBVersion: 0x043587cf,
|
|
3512
|
+
},
|
|
3513
|
+
explorerViews: [
|
|
3514
|
+
{
|
|
3515
|
+
tx: "https://live.blockcypher.com/btc-testnet/tx/$hash",
|
|
3516
|
+
address: "https://live.blockcypher.com/btc-testnet/address/$address",
|
|
3517
|
+
},
|
|
3518
|
+
],
|
|
3519
|
+
explorerId: "btc_testnet",
|
|
3520
|
+
},
|
|
3490
3521
|
ethereum_sepolia: {
|
|
3491
3522
|
type: "CryptoCurrency",
|
|
3492
3523
|
id: "ethereum_sepolia",
|
|
@@ -4788,6 +4819,27 @@ export const cryptocurrenciesById: Record<CryptoCurrencyId, CryptoCurrency> = {
|
|
|
4788
4819
|
},
|
|
4789
4820
|
],
|
|
4790
4821
|
},
|
|
4822
|
+
monad: {
|
|
4823
|
+
type: "CryptoCurrency",
|
|
4824
|
+
id: "monad",
|
|
4825
|
+
coinType: CoinType.ETH,
|
|
4826
|
+
name: "Monad",
|
|
4827
|
+
managerAppName: "Ethereum",
|
|
4828
|
+
ticker: "MON",
|
|
4829
|
+
scheme: "monad",
|
|
4830
|
+
color: "#836EF9",
|
|
4831
|
+
family: "evm",
|
|
4832
|
+
units: ethereumUnits("MON", "MON"),
|
|
4833
|
+
ethereumLikeInfo: {
|
|
4834
|
+
chainId: 143,
|
|
4835
|
+
},
|
|
4836
|
+
explorerViews: [
|
|
4837
|
+
{
|
|
4838
|
+
tx: "https://monadexplorer.com/tx/$hash",
|
|
4839
|
+
address: "https://monadexplorer.com/address/$address",
|
|
4840
|
+
},
|
|
4841
|
+
],
|
|
4842
|
+
},
|
|
4791
4843
|
};
|
|
4792
4844
|
|
|
4793
4845
|
const cryptocurrenciesByScheme: Record<string, CryptoCurrency> = {};
|