@ledgerhq/cryptoassets 13.31.1-nightly.0 → 13.32.0-nightly.2

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 (83) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.unimportedrc.json +3 -6
  3. package/CHANGELOG.md +29 -0
  4. package/lib/abandonseed.d.ts.map +1 -1
  5. package/lib/abandonseed.js +1 -0
  6. package/lib/abandonseed.js.map +1 -1
  7. package/lib/cal-client/entities/index.d.ts +125 -0
  8. package/lib/cal-client/entities/index.d.ts.map +1 -0
  9. package/lib/cal-client/entities/index.js +57 -0
  10. package/lib/cal-client/entities/index.js.map +1 -0
  11. package/lib/cal-client/hooks/index.d.ts +2 -0
  12. package/lib/cal-client/hooks/index.d.ts.map +1 -0
  13. package/lib/cal-client/hooks/index.js +18 -0
  14. package/lib/cal-client/hooks/index.js.map +1 -0
  15. package/lib/cal-client/hooks/useTokensData.d.ts +11 -0
  16. package/lib/cal-client/hooks/useTokensData.d.ts.map +1 -0
  17. package/lib/cal-client/hooks/useTokensData.js +35 -0
  18. package/lib/cal-client/hooks/useTokensData.js.map +1 -0
  19. package/lib/cal-client/state-manager/api.d.ts +842 -0
  20. package/lib/cal-client/state-manager/api.d.ts.map +1 -0
  21. package/lib/cal-client/state-manager/api.js +87 -0
  22. package/lib/cal-client/state-manager/api.js.map +1 -0
  23. package/lib/cal-client/state-manager/fields.d.ts +2 -0
  24. package/lib/cal-client/state-manager/fields.d.ts.map +1 -0
  25. package/lib/cal-client/state-manager/fields.js +24 -0
  26. package/lib/cal-client/state-manager/fields.js.map +1 -0
  27. package/lib/cal-client/state-manager/types.d.ts +36 -0
  28. package/lib/cal-client/state-manager/types.d.ts.map +1 -0
  29. package/lib/cal-client/state-manager/types.js +8 -0
  30. package/lib/cal-client/state-manager/types.js.map +1 -0
  31. package/lib/currencies.d.ts.map +1 -1
  32. package/lib/currencies.js +52 -0
  33. package/lib/currencies.js.map +1 -1
  34. package/lib/legacy/legacy-store.d.ts.map +1 -1
  35. package/lib/legacy/legacy-store.js +5 -0
  36. package/lib/legacy/legacy-store.js.map +1 -1
  37. package/lib-es/abandonseed.d.ts.map +1 -1
  38. package/lib-es/abandonseed.js +1 -0
  39. package/lib-es/abandonseed.js.map +1 -1
  40. package/lib-es/cal-client/entities/index.d.ts +125 -0
  41. package/lib-es/cal-client/entities/index.d.ts.map +1 -0
  42. package/lib-es/cal-client/entities/index.js +54 -0
  43. package/lib-es/cal-client/entities/index.js.map +1 -0
  44. package/lib-es/cal-client/hooks/index.d.ts +2 -0
  45. package/lib-es/cal-client/hooks/index.d.ts.map +1 -0
  46. package/lib-es/cal-client/hooks/index.js +2 -0
  47. package/lib-es/cal-client/hooks/index.js.map +1 -0
  48. package/lib-es/cal-client/hooks/useTokensData.d.ts +11 -0
  49. package/lib-es/cal-client/hooks/useTokensData.d.ts.map +1 -0
  50. package/lib-es/cal-client/hooks/useTokensData.js +31 -0
  51. package/lib-es/cal-client/hooks/useTokensData.js.map +1 -0
  52. package/lib-es/cal-client/state-manager/api.d.ts +842 -0
  53. package/lib-es/cal-client/state-manager/api.d.ts.map +1 -0
  54. package/lib-es/cal-client/state-manager/api.js +84 -0
  55. package/lib-es/cal-client/state-manager/api.js.map +1 -0
  56. package/lib-es/cal-client/state-manager/fields.d.ts +2 -0
  57. package/lib-es/cal-client/state-manager/fields.d.ts.map +1 -0
  58. package/lib-es/cal-client/state-manager/fields.js +21 -0
  59. package/lib-es/cal-client/state-manager/fields.js.map +1 -0
  60. package/lib-es/cal-client/state-manager/types.d.ts +36 -0
  61. package/lib-es/cal-client/state-manager/types.d.ts.map +1 -0
  62. package/lib-es/cal-client/state-manager/types.js +5 -0
  63. package/lib-es/cal-client/state-manager/types.js.map +1 -0
  64. package/lib-es/currencies.d.ts.map +1 -1
  65. package/lib-es/currencies.js +52 -0
  66. package/lib-es/currencies.js.map +1 -1
  67. package/lib-es/legacy/legacy-store.d.ts.map +1 -1
  68. package/lib-es/legacy/legacy-store.js +6 -1
  69. package/lib-es/legacy/legacy-store.js.map +1 -1
  70. package/package.json +7 -4
  71. package/src/abandonseed.ts +1 -0
  72. package/src/cal-client/MIGRATION_GUIDE.md +276 -0
  73. package/src/cal-client/README.md +125 -0
  74. package/src/cal-client/entities/index.ts +59 -0
  75. package/src/cal-client/hooks/__tests__/useTokensData.test.ts +222 -0
  76. package/src/cal-client/hooks/index.ts +1 -0
  77. package/src/cal-client/hooks/useTokensData.ts +47 -0
  78. package/src/cal-client/state-manager/api.ts +97 -0
  79. package/src/cal-client/state-manager/fields.ts +20 -0
  80. package/src/cal-client/state-manager/types.ts +39 -0
  81. package/src/currencies.ts +52 -0
  82. package/src/legacy/legacy-store.ts +7 -1
  83. package/src/legacy/legacy.test.ts +93 -0
@@ -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 { findCryptoCurrencyById } from "../../currencies";
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
+ const parentCurrency = findCryptoCurrencyById(token.network);
28
+ if (!parentCurrency) {
29
+ return undefined;
30
+ }
31
+
32
+ return {
33
+ type: "TokenCurrency",
34
+ id: token.id,
35
+ ledgerSignature: token.live_signature,
36
+ contractAddress: token.contract_address,
37
+ parentCurrency,
38
+ tokenType: token.standard,
39
+ name: token.name,
40
+ ticker: token.ticker,
41
+ units: token.units.map(unit => ({
42
+ code: unit.code,
43
+ name: unit.name,
44
+ magnitude: unit.magnitude,
45
+ })),
46
+ delisted: token.delisted,
47
+ symbol: token.symbol,
48
+ };
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> = {};
@@ -1,6 +1,6 @@
1
1
  import type { TokenCurrency } from "@ledgerhq/types-cryptoassets";
2
2
  import type { CryptoAssetsStore } from "@ledgerhq/types-live";
3
- import { tokensById, tokensByCurrencyAddress } from "./legacy-state";
3
+ import { tokensById, tokensByCurrencyAddress, tokensByCryptoCurrency } from "./legacy-state";
4
4
 
5
5
  function findTokenById(id: string): TokenCurrency | undefined {
6
6
  return tokensById[id];
@@ -13,6 +13,11 @@ function findTokenByAddressInCurrency(
13
13
  return tokensByCurrencyAddress[currencyId + ":" + address.toLowerCase()];
14
14
  }
15
15
 
16
+ function getTokensSyncHash(currencyId: string): Promise<string> {
17
+ const tokens = tokensByCryptoCurrency[currencyId];
18
+ return Promise.resolve("legacy_" + tokens?.length);
19
+ }
20
+
16
21
  /**
17
22
  * Legacy CryptoAssetsStore adapter that wraps the legacy token lookup functions
18
23
  * and provides the CryptoAssetsStore interface expected by the rest of the codebase.
@@ -20,4 +25,5 @@ function findTokenByAddressInCurrency(
20
25
  export const legacyCryptoAssetsStore: CryptoAssetsStore = {
21
26
  findTokenById,
22
27
  findTokenByAddressInCurrency,
28
+ getTokensSyncHash,
23
29
  };
@@ -30,6 +30,7 @@ import {
30
30
  tokensByCurrencyAddress,
31
31
  tokenListHashes,
32
32
  } from "./legacy-state";
33
+ import { legacyCryptoAssetsStore } from "./legacy-store";
33
34
  import type { TokenCurrency } from "@ledgerhq/types-cryptoassets";
34
35
  import type {
35
36
  ERC20Token,
@@ -567,6 +568,98 @@ describe("Legacy Data", () => {
567
568
  });
568
569
  });
569
570
 
571
+ describe("legacyCryptoAssetsStore", () => {
572
+ beforeEach(() => {
573
+ __clearAllLists();
574
+ });
575
+
576
+ it("should find token by id", () => {
577
+ const erc20Token: ERC20Token = [
578
+ "ethereum",
579
+ "test_token",
580
+ "TEST",
581
+ 18,
582
+ "Test Token",
583
+ "signature",
584
+ "0x123",
585
+ false,
586
+ false,
587
+ ];
588
+
589
+ addTokens([convertERC20(erc20Token)].filter(Boolean) as TokenCurrency[]);
590
+
591
+ const token = legacyCryptoAssetsStore.findTokenById("ethereum/erc20/test_token");
592
+
593
+ expect(token).toMatchObject({ ticker: "TEST" });
594
+ });
595
+
596
+ it("should find token by address in currency", () => {
597
+ const erc20Token: ERC20Token = [
598
+ "ethereum",
599
+ "test_token",
600
+ "TEST",
601
+ 18,
602
+ "Test Token",
603
+ "signature",
604
+ "0xABC123",
605
+ false,
606
+ false,
607
+ ];
608
+
609
+ addTokens([convertERC20(erc20Token)].filter(Boolean) as TokenCurrency[]);
610
+
611
+ const token = legacyCryptoAssetsStore.findTokenByAddressInCurrency("0xabc123", "ethereum");
612
+
613
+ expect(token).toMatchObject({ ticker: "TEST" });
614
+ });
615
+
616
+ it("should return undefined for non-existent token by address", () => {
617
+ const token = legacyCryptoAssetsStore.findTokenByAddressInCurrency("0xnonexistent", "ethereum");
618
+
619
+ expect(token).toBeUndefined();
620
+ });
621
+
622
+ it("should return sync hash for currency with tokens", async () => {
623
+ const erc20Token1: ERC20Token = [
624
+ "ethereum",
625
+ "test_token1",
626
+ "TEST1",
627
+ 18,
628
+ "Test Token 1",
629
+ "signature1",
630
+ "0x123",
631
+ false,
632
+ false,
633
+ ];
634
+
635
+ const erc20Token2: ERC20Token = [
636
+ "ethereum",
637
+ "test_token2",
638
+ "TEST2",
639
+ 18,
640
+ "Test Token 2",
641
+ "signature2",
642
+ "0x456",
643
+ false,
644
+ false,
645
+ ];
646
+
647
+ addTokens(
648
+ [convertERC20(erc20Token1), convertERC20(erc20Token2)].filter(Boolean) as TokenCurrency[],
649
+ );
650
+
651
+ const hash = await legacyCryptoAssetsStore.getTokensSyncHash("ethereum");
652
+
653
+ expect(hash).toBe("legacy_2");
654
+ });
655
+
656
+ it("should return sync hash for currency with no tokens", async () => {
657
+ const hash = await legacyCryptoAssetsStore.getTokensSyncHash("bitcoin");
658
+
659
+ expect(hash).toBe("legacy_undefined");
660
+ });
661
+ });
662
+
570
663
  describe("Legacy State", () => {
571
664
  it("should export all state objects", () => {
572
665
  expect(tokensArray).toBeDefined();