@ledgerhq/cryptoassets 13.33.0-nightly.20251122023607 → 13.33.0-nightly.20251125023817

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.
@@ -12,5 +12,11 @@
12
12
  "src/cal-client/**",
13
13
  "src/legacy/legacy-data.ts"
14
14
  ],
15
- "ignoreUnused": ["zod", "@reduxjs/toolkit", "@ledgerhq/logs", "@ledgerhq/types-live"]
15
+ "ignoreUnused": [
16
+ "zod",
17
+ "@reduxjs/toolkit",
18
+ "@ledgerhq/logs",
19
+ "@ledgerhq/errors",
20
+ "@ledgerhq/types-live"
21
+ ]
16
22
  }
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ledgerhq/cryptoassets
2
2
 
3
- ## 13.33.0-nightly.20251122023607
3
+ ## 13.33.0-nightly.20251125023817
4
4
 
5
5
  ### Minor Changes
6
6
 
@@ -17,6 +17,8 @@
17
17
 
18
18
  - [#12734](https://github.com/LedgerHQ/ledger-live/pull/12734) [`903ea9c`](https://github.com/LedgerHQ/ledger-live/commit/903ea9cdacf704a0119de2803a4f409b775391a5) Thanks [@semeano](https://github.com/semeano)! - Add Monad testnet
19
19
 
20
+ - [#12942](https://github.com/LedgerHQ/ledger-live/pull/12942) [`9251b77`](https://github.com/LedgerHQ/ledger-live/commit/9251b77fcb01709723842f19220a2a41a6fc8f3b) Thanks [@gre-ledger](https://github.com/gre-ledger)! - improve CryptoAssetsStore to return proper network errors
21
+
20
22
  - [#12754](https://github.com/LedgerHQ/ledger-live/pull/12754) [`02ef98f`](https://github.com/LedgerHQ/ledger-live/commit/02ef98faeb13c182ef255e06a43c39abeb55ecc7) Thanks [@gre-ledger](https://github.com/gre-ledger)! - cal-client useTokensData hook to use pageSize of 1000 by default to workaround Hedera problem (and possibly on other flows too) of missing token beyond top 100
21
23
 
22
24
  - [#12572](https://github.com/LedgerHQ/ledger-live/pull/12572) [`c0b5b9f`](https://github.com/LedgerHQ/ledger-live/commit/c0b5b9f4cdcb2ea3e15419cbf3d1a14f725c3e6a) Thanks [@gre-ledger](https://github.com/gre-ledger)! - Make legacy token initialization explicit instead of automatic. This prepares for the async migration by giving applications control over when tokens are loaded.
@@ -44,9 +46,9 @@
44
46
 
45
47
  - [#12728](https://github.com/LedgerHQ/ledger-live/pull/12728) [`938b970`](https://github.com/LedgerHQ/ledger-live/commit/938b970e15118dc706c759a3bec27dc01c3dd268) Thanks [@jonezque](https://github.com/jonezque)! - feat: canton links for new explorer
46
48
 
47
- - Updated dependencies [[`74a340b`](https://github.com/LedgerHQ/ledger-live/commit/74a340b258589c9c37476103029eb036b930616c), [`a6bc24e`](https://github.com/LedgerHQ/ledger-live/commit/a6bc24ee988b98bf82f807ac5ce731ba79813901), [`544721d`](https://github.com/LedgerHQ/ledger-live/commit/544721d198454526ef83516619d59c881ba34eb9), [`fe81926`](https://github.com/LedgerHQ/ledger-live/commit/fe81926afeb2df8e917e6bd1e4cbab13f09647fd), [`1c6f5f5`](https://github.com/LedgerHQ/ledger-live/commit/1c6f5f5843349b1955f7ca466f98cbe4ffcdaddf), [`927ae64`](https://github.com/LedgerHQ/ledger-live/commit/927ae64db0bb04af54e25623655a001a68e0f2d3), [`d5d838a`](https://github.com/LedgerHQ/ledger-live/commit/d5d838a23e00edd53293843781c559c41db4e854), [`903ea9c`](https://github.com/LedgerHQ/ledger-live/commit/903ea9cdacf704a0119de2803a4f409b775391a5), [`c40e9da`](https://github.com/LedgerHQ/ledger-live/commit/c40e9da68452fe9827b9435ff2d162291186be73), [`70049be`](https://github.com/LedgerHQ/ledger-live/commit/70049bed0cd0a8c7a9e4947a63af82061dad46c0), [`0d33751`](https://github.com/LedgerHQ/ledger-live/commit/0d33751bb2ae599d0d26ce6a8efdbe01757f12fb), [`5b41dd5`](https://github.com/LedgerHQ/ledger-live/commit/5b41dd56e024a5d03ba0e49084113c04887395db), [`aadcec6`](https://github.com/LedgerHQ/ledger-live/commit/aadcec66847b800f79452ba1df09149e0a1cb9e8), [`ed8532b`](https://github.com/LedgerHQ/ledger-live/commit/ed8532bad754ca2b5f1788c6e92f4646b775ec79), [`9659a34`](https://github.com/LedgerHQ/ledger-live/commit/9659a34d9998d5c4dff8618bf6cef7d16403680d), [`c70f6a8`](https://github.com/LedgerHQ/ledger-live/commit/c70f6a8370056b6fd8f236205471359d6f9b846f)]:
48
- - @ledgerhq/types-live@6.89.0-nightly.20251122023607
49
- - @ledgerhq/live-env@2.21.0-nightly.20251122023607
49
+ - Updated dependencies [[`74a340b`](https://github.com/LedgerHQ/ledger-live/commit/74a340b258589c9c37476103029eb036b930616c), [`a6bc24e`](https://github.com/LedgerHQ/ledger-live/commit/a6bc24ee988b98bf82f807ac5ce731ba79813901), [`544721d`](https://github.com/LedgerHQ/ledger-live/commit/544721d198454526ef83516619d59c881ba34eb9), [`fe81926`](https://github.com/LedgerHQ/ledger-live/commit/fe81926afeb2df8e917e6bd1e4cbab13f09647fd), [`1c6f5f5`](https://github.com/LedgerHQ/ledger-live/commit/1c6f5f5843349b1955f7ca466f98cbe4ffcdaddf), [`927ae64`](https://github.com/LedgerHQ/ledger-live/commit/927ae64db0bb04af54e25623655a001a68e0f2d3), [`d5d838a`](https://github.com/LedgerHQ/ledger-live/commit/d5d838a23e00edd53293843781c559c41db4e854), [`903ea9c`](https://github.com/LedgerHQ/ledger-live/commit/903ea9cdacf704a0119de2803a4f409b775391a5), [`c40e9da`](https://github.com/LedgerHQ/ledger-live/commit/c40e9da68452fe9827b9435ff2d162291186be73), [`70049be`](https://github.com/LedgerHQ/ledger-live/commit/70049bed0cd0a8c7a9e4947a63af82061dad46c0), [`0d33751`](https://github.com/LedgerHQ/ledger-live/commit/0d33751bb2ae599d0d26ce6a8efdbe01757f12fb), [`5b41dd5`](https://github.com/LedgerHQ/ledger-live/commit/5b41dd56e024a5d03ba0e49084113c04887395db), [`aadcec6`](https://github.com/LedgerHQ/ledger-live/commit/aadcec66847b800f79452ba1df09149e0a1cb9e8), [`b113920`](https://github.com/LedgerHQ/ledger-live/commit/b11392056bc334fc1813c473569ad3ae7be08045), [`ed8532b`](https://github.com/LedgerHQ/ledger-live/commit/ed8532bad754ca2b5f1788c6e92f4646b775ec79), [`9659a34`](https://github.com/LedgerHQ/ledger-live/commit/9659a34d9998d5c4dff8618bf6cef7d16403680d), [`c70f6a8`](https://github.com/LedgerHQ/ledger-live/commit/c70f6a8370056b6fd8f236205471359d6f9b846f)]:
50
+ - @ledgerhq/types-live@6.89.0-nightly.20251125023817
51
+ - @ledgerhq/live-env@2.21.0-nightly.20251125023817
50
52
 
51
53
  ## 13.32.0
52
54
 
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/cal-client/state-manager/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAExC;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,iBAAiB;IAC5D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;gBAE9C,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC;IAKpE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAO7D,4BAA4B,CAChC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAY/B,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAM5D,MAAM,IAAI,eAAe;CAG1B;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,GACvC,oBAAoB,CAEtB"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/cal-client/state-manager/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAGxC;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,iBAAiB;IAC5D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;gBAE9C,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC;IAKpE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAM7D,4BAA4B,CAChC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAW/B,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAM5D,MAAM,IAAI,eAAe;CAG1B;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,GACvC,oBAAoB,CAEtB"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createRtkCryptoAssetsStore = exports.RtkCryptoAssetsStore = void 0;
4
+ const errors_1 = require("@ledgerhq/errors");
4
5
  /**
5
6
  * Simple adapter that implements CryptoAssetsStore interface using RTK Query API directly.
6
7
  * The persistent caching is handled internally by the API's custom baseQuery.
@@ -15,7 +16,7 @@ class RtkCryptoAssetsStore {
15
16
  async findTokenById(id) {
16
17
  const result = await this.dispatch(this.api.endpoints.findTokenById.initiate({ id }));
17
18
  if (result.error)
18
- throw result.error;
19
+ throw remapRtkQueryError(result.error);
19
20
  return result.data;
20
21
  }
21
22
  async findTokenByAddressInCurrency(address, currencyId) {
@@ -24,13 +25,13 @@ class RtkCryptoAssetsStore {
24
25
  network: currencyId,
25
26
  }));
26
27
  if (result.error)
27
- throw result.error;
28
+ throw remapRtkQueryError(result.error);
28
29
  return result.data;
29
30
  }
30
31
  async getTokensSyncHash(currencyId) {
31
32
  const result = await this.dispatch(this.api.endpoints.getTokensSyncHash.initiate(currencyId));
32
33
  if (result.error)
33
- throw result.error;
34
+ throw remapRtkQueryError(result.error);
34
35
  return result.data;
35
36
  }
36
37
  getApi() {
@@ -42,4 +43,21 @@ function createRtkCryptoAssetsStore(api, dispatch) {
42
43
  return new RtkCryptoAssetsStore(api, dispatch);
43
44
  }
44
45
  exports.createRtkCryptoAssetsStore = createRtkCryptoAssetsStore;
46
+ function remapRtkQueryError(error) {
47
+ // see https://github.com/reduxjs/redux-toolkit/blob/39e7c8fb97e4e1da513d52925eda2898eb17426e/packages/toolkit/etc/rtk-query.api.md?plain=1#L208
48
+ if (typeof error.status === "number") {
49
+ const status = error.status;
50
+ if (status >= 400 && status < 500) {
51
+ return new errors_1.LedgerAPI4xx();
52
+ }
53
+ else if (status >= 500 && status < 600) {
54
+ return new errors_1.LedgerAPI5xx();
55
+ }
56
+ return new errors_1.NetworkDown();
57
+ }
58
+ else if (error.status === "FETCH_ERROR") {
59
+ return new errors_1.NetworkDown();
60
+ }
61
+ return new Error(error.error);
62
+ }
45
63
  //# sourceMappingURL=store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/cal-client/state-manager/store.ts"],"names":[],"mappings":";;;AAIA;;;GAGG;AACH,MAAa,oBAAoB;IACd,GAAG,CAAkB;IACrB,QAAQ,CAAiC;IAE1D,YAAY,GAAoB,EAAE,QAAwC;QACxE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAEtF,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,MAAM,CAAC,KAAK,CAAC;QACrC,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,4BAA4B,CAChC,OAAe,EACf,UAAkB;QAElB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAChC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,4BAA4B,CAAC,QAAQ,CAAC;YACvD,gBAAgB,EAAE,OAAO;YACzB,OAAO,EAAE,UAAU;SACpB,CAAC,CACH,CAAC;QAEF,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,MAAM,CAAC,KAAK,CAAC;QACrC,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,UAAkB;QACxC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QAC9F,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,MAAM,CAAC,KAAK,CAAC;QACrC,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;CACF;AAxCD,oDAwCC;AAED,SAAgB,0BAA0B,CACxC,GAAoB,EACpB,QAAwC;IAExC,OAAO,IAAI,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AACjD,CAAC;AALD,gEAKC"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/cal-client/state-manager/store.ts"],"names":[],"mappings":";;;AAGA,6CAA2E;AAE3E;;;GAGG;AACH,MAAa,oBAAoB;IACd,GAAG,CAAkB;IACrB,QAAQ,CAAiC;IAE1D,YAAY,GAAoB,EAAE,QAAwC;QACxE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACtF,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,4BAA4B,CAChC,OAAe,EACf,UAAkB;QAElB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAChC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,4BAA4B,CAAC,QAAQ,CAAC;YACvD,gBAAgB,EAAE,OAAO;YACzB,OAAO,EAAE,UAAU;SACpB,CAAC,CACH,CAAC;QACF,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,UAAkB;QACxC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QAC9F,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;CACF;AAtCD,oDAsCC;AAED,SAAgB,0BAA0B,CACxC,GAAoB,EACpB,QAAwC;IAExC,OAAO,IAAI,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AACjD,CAAC;AALD,gEAKC;AAED,SAAS,kBAAkB,CAAC,KAAiD;IAC3E,gJAAgJ;IAChJ,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5B,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;YAClC,OAAO,IAAI,qBAAY,EAAE,CAAC;QAC5B,CAAC;aAAM,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;YACzC,OAAO,IAAI,qBAAY,EAAE,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,oBAAW,EAAE,CAAC;IAC3B,CAAC;SAAM,IAAI,KAAK,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;QAC1C,OAAO,IAAI,oBAAW,EAAE,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/cal-client/state-manager/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAExC;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,iBAAiB;IAC5D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;gBAE9C,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC;IAKpE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAO7D,4BAA4B,CAChC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAY/B,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAM5D,MAAM,IAAI,eAAe;CAG1B;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,GACvC,oBAAoB,CAEtB"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/cal-client/state-manager/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAGxC;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,iBAAiB;IAC5D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;gBAE9C,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC;IAKpE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAM7D,4BAA4B,CAChC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAW/B,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAM5D,MAAM,IAAI,eAAe;CAG1B;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,GACvC,oBAAoB,CAEtB"}
@@ -1,3 +1,4 @@
1
+ import { NetworkDown, LedgerAPI4xx, LedgerAPI5xx } from "@ledgerhq/errors";
1
2
  /**
2
3
  * Simple adapter that implements CryptoAssetsStore interface using RTK Query API directly.
3
4
  * The persistent caching is handled internally by the API's custom baseQuery.
@@ -12,7 +13,7 @@ export class RtkCryptoAssetsStore {
12
13
  async findTokenById(id) {
13
14
  const result = await this.dispatch(this.api.endpoints.findTokenById.initiate({ id }));
14
15
  if (result.error)
15
- throw result.error;
16
+ throw remapRtkQueryError(result.error);
16
17
  return result.data;
17
18
  }
18
19
  async findTokenByAddressInCurrency(address, currencyId) {
@@ -21,13 +22,13 @@ export class RtkCryptoAssetsStore {
21
22
  network: currencyId,
22
23
  }));
23
24
  if (result.error)
24
- throw result.error;
25
+ throw remapRtkQueryError(result.error);
25
26
  return result.data;
26
27
  }
27
28
  async getTokensSyncHash(currencyId) {
28
29
  const result = await this.dispatch(this.api.endpoints.getTokensSyncHash.initiate(currencyId));
29
30
  if (result.error)
30
- throw result.error;
31
+ throw remapRtkQueryError(result.error);
31
32
  return result.data;
32
33
  }
33
34
  getApi() {
@@ -37,4 +38,21 @@ export class RtkCryptoAssetsStore {
37
38
  export function createRtkCryptoAssetsStore(api, dispatch) {
38
39
  return new RtkCryptoAssetsStore(api, dispatch);
39
40
  }
41
+ function remapRtkQueryError(error) {
42
+ // see https://github.com/reduxjs/redux-toolkit/blob/39e7c8fb97e4e1da513d52925eda2898eb17426e/packages/toolkit/etc/rtk-query.api.md?plain=1#L208
43
+ if (typeof error.status === "number") {
44
+ const status = error.status;
45
+ if (status >= 400 && status < 500) {
46
+ return new LedgerAPI4xx();
47
+ }
48
+ else if (status >= 500 && status < 600) {
49
+ return new LedgerAPI5xx();
50
+ }
51
+ return new NetworkDown();
52
+ }
53
+ else if (error.status === "FETCH_ERROR") {
54
+ return new NetworkDown();
55
+ }
56
+ return new Error(error.error);
57
+ }
40
58
  //# sourceMappingURL=store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/cal-client/state-manager/store.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,OAAO,oBAAoB;IACd,GAAG,CAAkB;IACrB,QAAQ,CAAiC;IAE1D,YAAY,GAAoB,EAAE,QAAwC;QACxE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAEtF,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,MAAM,CAAC,KAAK,CAAC;QACrC,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,4BAA4B,CAChC,OAAe,EACf,UAAkB;QAElB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAChC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,4BAA4B,CAAC,QAAQ,CAAC;YACvD,gBAAgB,EAAE,OAAO;YACzB,OAAO,EAAE,UAAU;SACpB,CAAC,CACH,CAAC;QAEF,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,MAAM,CAAC,KAAK,CAAC;QACrC,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,UAAkB;QACxC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QAC9F,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,MAAM,CAAC,KAAK,CAAC;QACrC,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;CACF;AAED,MAAM,UAAU,0BAA0B,CACxC,GAAoB,EACpB,QAAwC;IAExC,OAAO,IAAI,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AACjD,CAAC"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/cal-client/state-manager/store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE3E;;;GAGG;AACH,MAAM,OAAO,oBAAoB;IACd,GAAG,CAAkB;IACrB,QAAQ,CAAiC;IAE1D,YAAY,GAAoB,EAAE,QAAwC;QACxE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACtF,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,4BAA4B,CAChC,OAAe,EACf,UAAkB;QAElB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAChC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,4BAA4B,CAAC,QAAQ,CAAC;YACvD,gBAAgB,EAAE,OAAO;YACzB,OAAO,EAAE,UAAU;SACpB,CAAC,CACH,CAAC;QACF,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,UAAkB;QACxC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QAC9F,IAAI,MAAM,CAAC,KAAK;YAAE,MAAM,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;CACF;AAED,MAAM,UAAU,0BAA0B,CACxC,GAAoB,EACpB,QAAwC;IAExC,OAAO,IAAI,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAiD;IAC3E,gJAAgJ;IAChJ,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5B,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;YAClC,OAAO,IAAI,YAAY,EAAE,CAAC;QAC5B,CAAC;aAAM,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;YACzC,OAAO,IAAI,YAAY,EAAE,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,WAAW,EAAE,CAAC;IAC3B,CAAC;SAAM,IAAI,KAAK,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;QAC1C,OAAO,IAAI,WAAW,EAAE,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/cryptoassets",
3
- "version": "13.33.0-nightly.20251122023607",
3
+ "version": "13.33.0-nightly.20251125023817",
4
4
  "description": "Ledger crypto-assets list",
5
5
  "keywords": [
6
6
  "Ledger"
@@ -23,9 +23,10 @@
23
23
  "@reduxjs/toolkit": "2.8.2",
24
24
  "invariant": "2",
25
25
  "zod": "^3.22.4",
26
- "@ledgerhq/live-env": "^2.21.0-nightly.20251122023607",
27
- "@ledgerhq/types-live": "^6.89.0-nightly.20251122023607",
28
- "@ledgerhq/logs": "^6.13.0"
26
+ "@ledgerhq/live-env": "^2.21.0-nightly.20251125023817",
27
+ "@ledgerhq/types-live": "^6.89.0-nightly.20251125023817",
28
+ "@ledgerhq/logs": "^6.13.0",
29
+ "@ledgerhq/errors": "^6.27.0"
29
30
  },
30
31
  "devDependencies": {
31
32
  "@testing-library/react": "14.2.2",
@@ -0,0 +1,337 @@
1
+ /// <reference types="jest" />
2
+ import { RtkCryptoAssetsStore, createRtkCryptoAssetsStore } from "./store";
3
+ import { CryptoAssetsApi } from "./api";
4
+ import { NetworkDown, LedgerAPI4xx, LedgerAPI5xx } from "@ledgerhq/errors";
5
+ import type { TokenCurrency } from "@ledgerhq/types-cryptoassets";
6
+
7
+ // Mock the API
8
+ jest.mock("./api", () => ({
9
+ cryptoAssetsApi: {
10
+ endpoints: {
11
+ findTokenById: {
12
+ initiate: jest.fn(),
13
+ },
14
+ findTokenByAddressInCurrency: {
15
+ initiate: jest.fn(),
16
+ },
17
+ getTokensSyncHash: {
18
+ initiate: jest.fn(),
19
+ },
20
+ },
21
+ },
22
+ }));
23
+
24
+ describe("RtkCryptoAssetsStore", () => {
25
+ let mockApi: CryptoAssetsApi;
26
+ let mockDispatch: jest.Mock;
27
+ let store: RtkCryptoAssetsStore;
28
+
29
+ beforeEach(() => {
30
+ jest.clearAllMocks();
31
+
32
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
33
+ mockApi = {
34
+ endpoints: {
35
+ findTokenById: {
36
+ initiate: jest.fn(),
37
+ },
38
+ findTokenByAddressInCurrency: {
39
+ initiate: jest.fn(),
40
+ },
41
+ getTokensSyncHash: {
42
+ initiate: jest.fn(),
43
+ },
44
+ },
45
+ } as unknown as CryptoAssetsApi;
46
+
47
+ mockDispatch = jest.fn();
48
+ store = new RtkCryptoAssetsStore(mockApi, mockDispatch);
49
+ });
50
+
51
+ describe("remapRtkQueryError - error remapping", () => {
52
+ describe("4xx status codes", () => {
53
+ it("should remap 400 status to LedgerAPI4xx", async () => {
54
+ const mockError = { status: 400, error: "Bad Request" };
55
+ mockDispatch.mockResolvedValue({ error: mockError });
56
+
57
+ await expect(store.findTokenById("test-id")).rejects.toThrow(LedgerAPI4xx);
58
+ expect(mockDispatch).toHaveBeenCalled();
59
+ });
60
+
61
+ it("should remap 404 status to LedgerAPI4xx", async () => {
62
+ const mockError = { status: 404, error: "Not Found" };
63
+ mockDispatch.mockResolvedValue({ error: mockError });
64
+
65
+ await expect(store.findTokenById("test-id")).rejects.toThrow(LedgerAPI4xx);
66
+ });
67
+
68
+ it("should remap 499 status to LedgerAPI4xx", async () => {
69
+ const mockError = { status: 499, error: "Client Closed Request" };
70
+ mockDispatch.mockResolvedValue({ error: mockError });
71
+
72
+ await expect(store.findTokenById("test-id")).rejects.toThrow(LedgerAPI4xx);
73
+ });
74
+
75
+ it("should remap 4xx errors in findTokenByAddressInCurrency", async () => {
76
+ const mockError = { status: 401, error: "Unauthorized" };
77
+ mockDispatch.mockResolvedValue({ error: mockError });
78
+
79
+ await expect(store.findTokenByAddressInCurrency("0x123", "ethereum")).rejects.toThrow(
80
+ LedgerAPI4xx,
81
+ );
82
+ });
83
+
84
+ it("should remap 4xx errors in getTokensSyncHash", async () => {
85
+ const mockError = { status: 403, error: "Forbidden" };
86
+ mockDispatch.mockResolvedValue({ error: mockError });
87
+
88
+ await expect(store.getTokensSyncHash("ethereum")).rejects.toThrow(LedgerAPI4xx);
89
+ });
90
+ });
91
+
92
+ describe("5xx status codes", () => {
93
+ it("should remap 500 status to LedgerAPI5xx", async () => {
94
+ const mockError = { status: 500, error: "Internal Server Error" };
95
+ mockDispatch.mockResolvedValue({ error: mockError });
96
+
97
+ await expect(store.findTokenById("test-id")).rejects.toThrow(LedgerAPI5xx);
98
+ });
99
+
100
+ it("should remap 503 status to LedgerAPI5xx", async () => {
101
+ const mockError = { status: 503, error: "Service Unavailable" };
102
+ mockDispatch.mockResolvedValue({ error: mockError });
103
+
104
+ await expect(store.findTokenById("test-id")).rejects.toThrow(LedgerAPI5xx);
105
+ });
106
+
107
+ it("should remap 599 status to LedgerAPI5xx", async () => {
108
+ const mockError = { status: 599, error: "Network Timeout" };
109
+ mockDispatch.mockResolvedValue({ error: mockError });
110
+
111
+ await expect(store.findTokenById("test-id")).rejects.toThrow(LedgerAPI5xx);
112
+ });
113
+
114
+ it("should remap 5xx errors in findTokenByAddressInCurrency", async () => {
115
+ const mockError = { status: 502, error: "Bad Gateway" };
116
+ mockDispatch.mockResolvedValue({ error: mockError });
117
+
118
+ await expect(store.findTokenByAddressInCurrency("0x123", "ethereum")).rejects.toThrow(
119
+ LedgerAPI5xx,
120
+ );
121
+ });
122
+
123
+ it("should remap 5xx errors in getTokensSyncHash", async () => {
124
+ const mockError = { status: 504, error: "Gateway Timeout" };
125
+ mockDispatch.mockResolvedValue({ error: mockError });
126
+
127
+ await expect(store.getTokensSyncHash("ethereum")).rejects.toThrow(LedgerAPI5xx);
128
+ });
129
+ });
130
+
131
+ describe("other numeric status codes", () => {
132
+ it("should remap status < 400 to NetworkDown", async () => {
133
+ const mockError = { status: 200, error: "OK" };
134
+ mockDispatch.mockResolvedValue({ error: mockError });
135
+
136
+ await expect(store.findTokenById("test-id")).rejects.toThrow(NetworkDown);
137
+ });
138
+
139
+ it("should remap status 300-399 to NetworkDown", async () => {
140
+ const mockError = { status: 301, error: "Moved Permanently" };
141
+ mockDispatch.mockResolvedValue({ error: mockError });
142
+
143
+ await expect(store.findTokenById("test-id")).rejects.toThrow(NetworkDown);
144
+ });
145
+
146
+ it("should remap status >= 600 to NetworkDown", async () => {
147
+ const mockError = { status: 600, error: "Unknown Error" };
148
+ mockDispatch.mockResolvedValue({ error: mockError });
149
+
150
+ await expect(store.findTokenById("test-id")).rejects.toThrow(NetworkDown);
151
+ });
152
+
153
+ it("should remap status 0 to NetworkDown", async () => {
154
+ const mockError = { status: 0, error: "Network Error" };
155
+ mockDispatch.mockResolvedValue({ error: mockError });
156
+
157
+ await expect(store.findTokenById("test-id")).rejects.toThrow(NetworkDown);
158
+ });
159
+ });
160
+
161
+ describe("FETCH_ERROR status", () => {
162
+ it("should remap FETCH_ERROR to NetworkDown", async () => {
163
+ const mockError = { status: "FETCH_ERROR", error: "Failed to fetch" };
164
+ mockDispatch.mockResolvedValue({ error: mockError });
165
+
166
+ await expect(store.findTokenById("test-id")).rejects.toThrow(NetworkDown);
167
+ });
168
+
169
+ it("should remap FETCH_ERROR in findTokenByAddressInCurrency", async () => {
170
+ const mockError = { status: "FETCH_ERROR", error: "Network failure" };
171
+ mockDispatch.mockResolvedValue({ error: mockError });
172
+
173
+ await expect(store.findTokenByAddressInCurrency("0x123", "ethereum")).rejects.toThrow(
174
+ NetworkDown,
175
+ );
176
+ });
177
+
178
+ it("should remap FETCH_ERROR in getTokensSyncHash", async () => {
179
+ const mockError = { status: "FETCH_ERROR", error: "Connection failed" };
180
+ mockDispatch.mockResolvedValue({ error: mockError });
181
+
182
+ await expect(store.getTokensSyncHash("ethereum")).rejects.toThrow(NetworkDown);
183
+ });
184
+ });
185
+
186
+ describe("other string status codes", () => {
187
+ it("should remap other string status to generic Error with error message", async () => {
188
+ const mockError = { status: "PARSING_ERROR", error: "Failed to parse response" };
189
+ mockDispatch.mockResolvedValue({ error: mockError });
190
+
191
+ await expect(store.findTokenById("test-id")).rejects.toThrow("Failed to parse response");
192
+ await expect(store.findTokenById("test-id")).rejects.toThrow(Error);
193
+ });
194
+
195
+ it("should remap CUSTOM_ERROR to generic Error", async () => {
196
+ const mockError = { status: "CUSTOM_ERROR", error: "Custom error message" };
197
+ mockDispatch.mockResolvedValue({ error: mockError });
198
+
199
+ await expect(store.findTokenById("test-id")).rejects.toThrow("Custom error message");
200
+ });
201
+
202
+ it("should preserve error message in generic Error", async () => {
203
+ const errorMessage = "Something went wrong";
204
+ const mockError = { status: "UNKNOWN_STATUS", error: errorMessage };
205
+ mockDispatch.mockResolvedValue({ error: mockError });
206
+
207
+ await expect(store.findTokenById("test-id")).rejects.toThrow(errorMessage);
208
+ await expect(store.findTokenById("test-id")).rejects.toThrow(Error);
209
+ });
210
+ });
211
+ });
212
+
213
+ describe("successful operations", () => {
214
+ it("should return data when findTokenById succeeds", async () => {
215
+ const mockToken: TokenCurrency = {
216
+ type: "TokenCurrency",
217
+ id: "ethereum/erc20/usdc",
218
+ contractAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
219
+ name: "USD Coin",
220
+ ticker: "USDC",
221
+ units: [{ code: "USDC", name: "USD Coin", magnitude: 6 }],
222
+ tokenType: "erc20",
223
+ delisted: false,
224
+ disableCountervalue: false,
225
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
226
+ parentCurrency: {} as any,
227
+ };
228
+
229
+ mockDispatch.mockResolvedValue({ data: mockToken });
230
+
231
+ const result = await store.findTokenById("ethereum/erc20/usdc");
232
+ expect(result).toEqual(mockToken);
233
+ });
234
+
235
+ it("should return data when findTokenByAddressInCurrency succeeds", async () => {
236
+ const mockToken: TokenCurrency = {
237
+ type: "TokenCurrency",
238
+ id: "ethereum/erc20/usdc",
239
+ contractAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
240
+ name: "USD Coin",
241
+ ticker: "USDC",
242
+ units: [{ code: "USDC", name: "USD Coin", magnitude: 6 }],
243
+ tokenType: "erc20",
244
+ delisted: false,
245
+ disableCountervalue: false,
246
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
247
+ parentCurrency: {} as any,
248
+ };
249
+
250
+ mockDispatch.mockResolvedValue({ data: mockToken });
251
+
252
+ const result = await store.findTokenByAddressInCurrency(
253
+ "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
254
+ "ethereum",
255
+ );
256
+ expect(result).toEqual(mockToken);
257
+ });
258
+
259
+ it("should return data when getTokensSyncHash succeeds", async () => {
260
+ const mockHash = "abc123def456";
261
+ mockDispatch.mockResolvedValue({ data: mockHash });
262
+
263
+ const result = await store.getTokensSyncHash("ethereum");
264
+ expect(result).toBe(mockHash);
265
+ });
266
+
267
+ it("should return undefined when findTokenById returns undefined", async () => {
268
+ mockDispatch.mockResolvedValue({ data: undefined });
269
+
270
+ const result = await store.findTokenById("non-existent");
271
+ expect(result).toBeUndefined();
272
+ });
273
+ });
274
+
275
+ describe("createRtkCryptoAssetsStore", () => {
276
+ it("should create a new RtkCryptoAssetsStore instance", () => {
277
+ const createdStore = createRtkCryptoAssetsStore(mockApi, mockDispatch);
278
+ expect(createdStore).toBeInstanceOf(RtkCryptoAssetsStore);
279
+ });
280
+
281
+ it("should return the same API via getApi", () => {
282
+ const createdStore = createRtkCryptoAssetsStore(mockApi, mockDispatch);
283
+ expect(createdStore.getApi()).toBe(mockApi);
284
+ });
285
+ });
286
+
287
+ describe("getApi", () => {
288
+ it("should return the API instance", () => {
289
+ expect(store.getApi()).toBe(mockApi);
290
+ });
291
+ });
292
+
293
+ describe("error remapping edge cases", () => {
294
+ it("should handle boundary case status 399", async () => {
295
+ const mockError = { status: 399, error: "Client Error" };
296
+ mockDispatch.mockResolvedValue({ error: mockError });
297
+
298
+ await expect(store.findTokenById("test-id")).rejects.toThrow(NetworkDown);
299
+ });
300
+
301
+ it("should handle boundary case status 400", async () => {
302
+ const mockError = { status: 400, error: "Bad Request" };
303
+ mockDispatch.mockResolvedValue({ error: mockError });
304
+
305
+ await expect(store.findTokenById("test-id")).rejects.toThrow(LedgerAPI4xx);
306
+ });
307
+
308
+ it("should handle boundary case status 499", async () => {
309
+ const mockError = { status: 499, error: "Client Closed Request" };
310
+ mockDispatch.mockResolvedValue({ error: mockError });
311
+
312
+ await expect(store.findTokenById("test-id")).rejects.toThrow(LedgerAPI4xx);
313
+ });
314
+
315
+ it("should handle boundary case status 500", async () => {
316
+ const mockError = { status: 500, error: "Internal Server Error" };
317
+ mockDispatch.mockResolvedValue({ error: mockError });
318
+
319
+ await expect(store.findTokenById("test-id")).rejects.toThrow(LedgerAPI5xx);
320
+ });
321
+
322
+ it("should handle boundary case status 599", async () => {
323
+ const mockError = { status: 599, error: "Network Timeout" };
324
+ mockDispatch.mockResolvedValue({ error: mockError });
325
+
326
+ await expect(store.findTokenById("test-id")).rejects.toThrow(LedgerAPI5xx);
327
+ });
328
+
329
+ it("should handle empty error message", async () => {
330
+ const mockError = { status: "PARSING_ERROR", error: "" };
331
+ mockDispatch.mockResolvedValue({ error: mockError });
332
+
333
+ await expect(store.findTokenById("test-id")).rejects.toThrow(Error);
334
+ await expect(store.findTokenById("test-id")).rejects.toThrow("");
335
+ });
336
+ });
337
+ });
@@ -1,6 +1,7 @@
1
1
  import { TokenCurrency } from "@ledgerhq/types-cryptoassets";
2
2
  import { CryptoAssetsStore } from "@ledgerhq/types-live";
3
3
  import { CryptoAssetsApi } from "./api";
4
+ import { NetworkDown, LedgerAPI4xx, LedgerAPI5xx } from "@ledgerhq/errors";
4
5
 
5
6
  /**
6
7
  * Simple adapter that implements CryptoAssetsStore interface using RTK Query API directly.
@@ -17,8 +18,7 @@ export class RtkCryptoAssetsStore implements CryptoAssetsStore {
17
18
 
18
19
  async findTokenById(id: string): Promise<TokenCurrency | undefined> {
19
20
  const result = await this.dispatch(this.api.endpoints.findTokenById.initiate({ id }));
20
-
21
- if (result.error) throw result.error;
21
+ if (result.error) throw remapRtkQueryError(result.error);
22
22
  return result.data;
23
23
  }
24
24
 
@@ -32,14 +32,13 @@ export class RtkCryptoAssetsStore implements CryptoAssetsStore {
32
32
  network: currencyId,
33
33
  }),
34
34
  );
35
-
36
- if (result.error) throw result.error;
35
+ if (result.error) throw remapRtkQueryError(result.error);
37
36
  return result.data;
38
37
  }
39
38
 
40
39
  async getTokensSyncHash(currencyId: string): Promise<string> {
41
40
  const result = await this.dispatch(this.api.endpoints.getTokensSyncHash.initiate(currencyId));
42
- if (result.error) throw result.error;
41
+ if (result.error) throw remapRtkQueryError(result.error);
43
42
  return result.data;
44
43
  }
45
44
 
@@ -54,3 +53,19 @@ export function createRtkCryptoAssetsStore(
54
53
  ): RtkCryptoAssetsStore {
55
54
  return new RtkCryptoAssetsStore(api, dispatch);
56
55
  }
56
+
57
+ function remapRtkQueryError(error: { status: string | number; error: string }): Error {
58
+ // see https://github.com/reduxjs/redux-toolkit/blob/39e7c8fb97e4e1da513d52925eda2898eb17426e/packages/toolkit/etc/rtk-query.api.md?plain=1#L208
59
+ if (typeof error.status === "number") {
60
+ const status = error.status;
61
+ if (status >= 400 && status < 500) {
62
+ return new LedgerAPI4xx();
63
+ } else if (status >= 500 && status < 600) {
64
+ return new LedgerAPI5xx();
65
+ }
66
+ return new NetworkDown();
67
+ } else if (error.status === "FETCH_ERROR") {
68
+ return new NetworkDown();
69
+ }
70
+ return new Error(error.error);
71
+ }