@ledgerhq/live-common 34.55.0-nightly.20251216024112 → 34.55.0-nightly.20251217023943

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 (107) hide show
  1. package/lib/apps/listApps.d.ts.map +1 -1
  2. package/lib/apps/listApps.js +10 -0
  3. package/lib/apps/listApps.js.map +1 -1
  4. package/lib/apps/polyfill.d.ts +2 -2
  5. package/lib/apps/polyfill.d.ts.map +1 -1
  6. package/lib/apps/types.d.ts +4 -0
  7. package/lib/apps/types.d.ts.map +1 -1
  8. package/lib/apps/types.js.map +1 -1
  9. package/lib/dada-client/hooks/useAssetsData.d.ts +1 -0
  10. package/lib/dada-client/hooks/useAssetsData.d.ts.map +1 -1
  11. package/lib/dada-client/hooks/useAssetsData.js +3 -0
  12. package/lib/dada-client/hooks/useAssetsData.js.map +1 -1
  13. package/lib/dada-client/hooks/useInterestRatesByCurrencies.d.ts +1 -5
  14. package/lib/dada-client/hooks/useInterestRatesByCurrencies.d.ts.map +1 -1
  15. package/lib/dada-client/hooks/useMarketByCurrencies.d.ts +1 -4
  16. package/lib/dada-client/hooks/useMarketByCurrencies.d.ts.map +1 -1
  17. package/lib/dada-client/utils/errorUtils.d.ts +28 -0
  18. package/lib/dada-client/utils/errorUtils.d.ts.map +1 -0
  19. package/lib/dada-client/utils/errorUtils.js +53 -0
  20. package/lib/dada-client/utils/errorUtils.js.map +1 -0
  21. package/lib/e2e/index.d.ts +1 -0
  22. package/lib/e2e/index.d.ts.map +1 -1
  23. package/lib/e2e/swap.js +2 -2
  24. package/lib/e2e/swap.js.map +1 -1
  25. package/lib/env.react.d.ts +1 -1
  26. package/lib/env.react.d.ts.map +1 -1
  27. package/lib/hw/actions/app.d.ts +2 -0
  28. package/lib/hw/actions/app.d.ts.map +1 -1
  29. package/lib/hw/actions/app.js +8 -2
  30. package/lib/hw/actions/app.js.map +1 -1
  31. package/lib/hw/actions/manager.d.ts +2 -0
  32. package/lib/hw/actions/manager.d.ts.map +1 -1
  33. package/lib/hw/actions/manager.js +6 -0
  34. package/lib/hw/actions/manager.js.map +1 -1
  35. package/lib/hw/connectApp.d.ts +4 -0
  36. package/lib/hw/connectApp.d.ts.map +1 -1
  37. package/lib/hw/connectApp.js.map +1 -1
  38. package/lib/hw/connectAppEventMapper.d.ts +1 -0
  39. package/lib/hw/connectAppEventMapper.d.ts.map +1 -1
  40. package/lib/hw/connectAppEventMapper.js +12 -0
  41. package/lib/hw/connectAppEventMapper.js.map +1 -1
  42. package/lib/modularDrawer/utils/getLoadingStatus.d.ts +1 -1
  43. package/lib/modularDrawer/utils/getLoadingStatus.d.ts.map +1 -1
  44. package/lib/socket/index.d.ts.map +1 -1
  45. package/lib/socket/index.js +28 -0
  46. package/lib/socket/index.js.map +1 -1
  47. package/lib-es/apps/listApps.d.ts.map +1 -1
  48. package/lib-es/apps/listApps.js +10 -0
  49. package/lib-es/apps/listApps.js.map +1 -1
  50. package/lib-es/apps/polyfill.d.ts +2 -2
  51. package/lib-es/apps/polyfill.d.ts.map +1 -1
  52. package/lib-es/apps/types.d.ts +4 -0
  53. package/lib-es/apps/types.d.ts.map +1 -1
  54. package/lib-es/apps/types.js.map +1 -1
  55. package/lib-es/dada-client/hooks/useAssetsData.d.ts +1 -0
  56. package/lib-es/dada-client/hooks/useAssetsData.d.ts.map +1 -1
  57. package/lib-es/dada-client/hooks/useAssetsData.js +3 -0
  58. package/lib-es/dada-client/hooks/useAssetsData.js.map +1 -1
  59. package/lib-es/dada-client/hooks/useInterestRatesByCurrencies.d.ts +1 -5
  60. package/lib-es/dada-client/hooks/useInterestRatesByCurrencies.d.ts.map +1 -1
  61. package/lib-es/dada-client/hooks/useMarketByCurrencies.d.ts +1 -4
  62. package/lib-es/dada-client/hooks/useMarketByCurrencies.d.ts.map +1 -1
  63. package/lib-es/dada-client/utils/errorUtils.d.ts +28 -0
  64. package/lib-es/dada-client/utils/errorUtils.d.ts.map +1 -0
  65. package/lib-es/dada-client/utils/errorUtils.js +45 -0
  66. package/lib-es/dada-client/utils/errorUtils.js.map +1 -0
  67. package/lib-es/e2e/index.d.ts +1 -0
  68. package/lib-es/e2e/index.d.ts.map +1 -1
  69. package/lib-es/e2e/swap.js +2 -2
  70. package/lib-es/e2e/swap.js.map +1 -1
  71. package/lib-es/env.react.d.ts +1 -1
  72. package/lib-es/env.react.d.ts.map +1 -1
  73. package/lib-es/hw/actions/app.d.ts +2 -0
  74. package/lib-es/hw/actions/app.d.ts.map +1 -1
  75. package/lib-es/hw/actions/app.js +8 -2
  76. package/lib-es/hw/actions/app.js.map +1 -1
  77. package/lib-es/hw/actions/manager.d.ts +2 -0
  78. package/lib-es/hw/actions/manager.d.ts.map +1 -1
  79. package/lib-es/hw/actions/manager.js +6 -0
  80. package/lib-es/hw/actions/manager.js.map +1 -1
  81. package/lib-es/hw/connectApp.d.ts +4 -0
  82. package/lib-es/hw/connectApp.d.ts.map +1 -1
  83. package/lib-es/hw/connectApp.js.map +1 -1
  84. package/lib-es/hw/connectAppEventMapper.d.ts +1 -0
  85. package/lib-es/hw/connectAppEventMapper.d.ts.map +1 -1
  86. package/lib-es/hw/connectAppEventMapper.js +12 -0
  87. package/lib-es/hw/connectAppEventMapper.js.map +1 -1
  88. package/lib-es/modularDrawer/utils/getLoadingStatus.d.ts +1 -1
  89. package/lib-es/modularDrawer/utils/getLoadingStatus.d.ts.map +1 -1
  90. package/lib-es/socket/index.d.ts.map +1 -1
  91. package/lib-es/socket/index.js +28 -0
  92. package/lib-es/socket/index.js.map +1 -1
  93. package/package.json +76 -76
  94. package/src/apps/listApps.ts +11 -0
  95. package/src/apps/types.ts +5 -0
  96. package/src/dada-client/hooks/useAssetsData.ts +4 -0
  97. package/src/dada-client/utils/__test__/errorUtils.test.ts +222 -0
  98. package/src/dada-client/utils/errorUtils.ts +57 -0
  99. package/src/e2e/swap.ts +2 -2
  100. package/src/hw/actions/app.ts +12 -3
  101. package/src/hw/actions/manager.ts +13 -0
  102. package/src/hw/connectApp.ts +5 -0
  103. package/src/hw/connectAppEventMapper.ts +12 -0
  104. package/src/modularDrawer/utils/getLoadingStatus.ts +1 -1
  105. package/src/platform/react.ts +1 -1
  106. package/src/socket/index.ts +35 -0
  107. package/src/wallet-api/react.ts +1 -1
@@ -20,6 +20,7 @@ import { shouldUpgrade } from "../../apps";
20
20
  import { AppOp, SkippedAppOp } from "../../apps/types";
21
21
  import perFamilyAccount from "../../generated/account";
22
22
  import type { Account, DeviceInfo, FirmwareUpdateContext } from "@ledgerhq/types-live";
23
+ import { DeviceId } from "@ledgerhq/client-ids/ids";
23
24
  import type { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
24
25
  import { getImplementation, ImplementationType } from "./implementations";
25
26
  import { getDefaultAccountName } from "@ledgerhq/live-wallet/accountName";
@@ -44,6 +45,7 @@ export type State = {
44
45
  allowManagerGranted: boolean;
45
46
  device: Device | null | undefined;
46
47
  deviceInfo?: DeviceInfo | null | undefined;
48
+ deviceId: DeviceId | null | undefined;
47
49
  latestFirmware?: FirmwareUpdateContext | null | undefined;
48
50
  error: Error | null | undefined;
49
51
  derivation:
@@ -144,6 +146,7 @@ const getInitialState = (device?: Device | null | undefined, request?: AppReques
144
146
  allowManagerGranted: false,
145
147
  device: null,
146
148
  deviceInfo: null,
149
+ deviceId: null,
147
150
  latestFirmware: null,
148
151
  opened: false,
149
152
  appAndVersion: null,
@@ -311,6 +314,12 @@ const reducer = (state: State, e: Event): State => {
311
314
  listedApps: state.listedApps,
312
315
  };
313
316
 
317
+ case "device-id":
318
+ return {
319
+ ...state,
320
+ deviceId: e.deviceId,
321
+ };
322
+
314
323
  case "app-not-installed":
315
324
  return {
316
325
  ...getInitialState(state.device, state.request),
@@ -460,9 +469,9 @@ export const createAction = (
460
469
  () => inferCommandParams(appRequest), // for now i don't have better
461
470
  // eslint-disable-next-line react-hooks/exhaustive-deps
462
471
  [
463
- appRequest.appName, // eslint-disable-next-line react-hooks/exhaustive-deps
464
- appRequest.account && appRequest.account.id, // eslint-disable-next-line react-hooks/exhaustive-deps
465
- appRequest.currency && appRequest.currency.id,
472
+ appRequest.appName,
473
+ appRequest.account?.id,
474
+ appRequest.currency?.id,
466
475
  appRequest.dependencies,
467
476
  ],
468
477
  );
@@ -10,6 +10,7 @@ import type { Action, Device } from "./types";
10
10
  import { currentMode } from "./app";
11
11
  import { getImplementation } from "./implementations";
12
12
  import { getLatestFirmwareForDeviceUseCase } from "../../device/use-cases/getLatestFirmwareForDeviceUseCase";
13
+ import { DeviceId } from "@ledgerhq/client-ids/ids";
13
14
 
14
15
  type State = {
15
16
  isLoading: boolean;
@@ -19,6 +20,7 @@ type State = {
19
20
  allowManagerGranted: boolean;
20
21
  device: Device | null | undefined;
21
22
  deviceInfo: DeviceInfo | null | undefined;
23
+ deviceId: DeviceId | null | undefined;
22
24
  result: ListAppsResult | null | undefined;
23
25
  error: Error | null | undefined;
24
26
  isLocked: boolean;
@@ -62,6 +64,10 @@ type Event =
62
64
  | {
63
65
  type: "deviceChange";
64
66
  device: Device | null | undefined;
67
+ }
68
+ | {
69
+ type: "device-id";
70
+ deviceId: DeviceId;
65
71
  };
66
72
 
67
73
  const mapResult = ({ deviceInfo, device, result }): Result | null | undefined =>
@@ -82,6 +88,7 @@ const getInitialState = (device?: Device | null | undefined): State => ({
82
88
  allowManagerGranted: false,
83
89
  device,
84
90
  deviceInfo: null,
91
+ deviceId: null,
85
92
  result: null,
86
93
  error: null,
87
94
  });
@@ -151,6 +158,12 @@ const reducer = (state: State, e: Event): State => {
151
158
  allowManagerGranted: true,
152
159
  };
153
160
 
161
+ case "device-id":
162
+ return {
163
+ ...state,
164
+ deviceId: e.deviceId,
165
+ };
166
+
154
167
  case "result":
155
168
  return {
156
169
  ...state,
@@ -39,6 +39,7 @@ import {
39
39
  } from "@ledgerhq/device-management-kit";
40
40
  import { ConnectAppDeviceAction } from "@ledgerhq/live-dmk-shared";
41
41
  import { ConnectAppEventMapper } from "./connectAppEventMapper";
42
+ import { DeviceId } from "@ledgerhq/client-ids/ids";
42
43
 
43
44
  export type RequiresDerivation = {
44
45
  currencyId: string;
@@ -84,6 +85,10 @@ export type ConnectAppEvent =
84
85
  | {
85
86
  type: "device-permission-granted";
86
87
  }
88
+ | {
89
+ type: "device-id";
90
+ deviceId: DeviceId;
91
+ }
87
92
  | {
88
93
  type: "app-not-installed";
89
94
  appNames: string[];
@@ -28,6 +28,7 @@ import {
28
28
  LatestFirmwareVersionRequired,
29
29
  UnsupportedFeatureError,
30
30
  } from "@ledgerhq/errors";
31
+ import { DeviceId } from "@ledgerhq/client-ids/ids";
31
32
 
32
33
  import type { SkippedAppOp } from "../apps/types";
33
34
  import { SkipReason } from "../apps/types";
@@ -40,6 +41,7 @@ export class ConnectAppEventMapper {
40
41
  private permissionRequested: boolean = false;
41
42
  private lastSeenDeviceSent: boolean = false;
42
43
  private installPlan: InstallPlan | null = null;
44
+ private deviceId: string | undefined = undefined;
43
45
  private eventSubject = new Subject<ConnectAppEvent>();
44
46
 
45
47
  constructor(
@@ -162,6 +164,16 @@ export class ConnectAppEventMapper {
162
164
  if (intermediateValue.installPlan !== null) {
163
165
  this.handleInstallPlan(intermediateValue.installPlan);
164
166
  }
167
+ if (intermediateValue.deviceId) {
168
+ const deviceIdString = Buffer.from(intermediateValue.deviceId).toString("hex");
169
+ if (deviceIdString !== this.deviceId) {
170
+ this.deviceId = deviceIdString;
171
+ this.eventSubject.next({
172
+ type: "device-id",
173
+ deviceId: DeviceId.fromString(deviceIdString),
174
+ });
175
+ }
176
+ }
165
177
  break;
166
178
  }
167
179
  }
@@ -1,6 +1,6 @@
1
1
  import { LoadingStatus } from "../../deposit/type";
2
2
  import { SerializedError } from "@reduxjs/toolkit";
3
- import { FetchBaseQueryError } from "@reduxjs/toolkit/query";
3
+ import { FetchBaseQueryError } from "@reduxjs/toolkit/query/react";
4
4
 
5
5
  export const getLoadingStatus = ({
6
6
  isLoading,
@@ -1,7 +1,7 @@
1
1
  import { useCallback, useMemo } from "react";
2
2
  import { useDispatch } from "react-redux";
3
3
  import { ThunkDispatch, UnknownAction } from "@reduxjs/toolkit";
4
- import { InfiniteData } from "@reduxjs/toolkit/query";
4
+ import { InfiniteData } from "@reduxjs/toolkit/query/react";
5
5
  import { AccountLike } from "@ledgerhq/types-live";
6
6
  import { makeRe } from "minimatch";
7
7
  import type {
@@ -14,6 +14,8 @@ import {
14
14
  import { cancelDeviceAction } from "../hw/deviceAccess";
15
15
  import { getEnv } from "@ledgerhq/live-env";
16
16
  import type { SocketEvent } from "@ledgerhq/types-live";
17
+ import { sha3_256 } from "@noble/hashes/sha3";
18
+ import { DeviceId } from "@ledgerhq/client-ids/ids";
17
19
 
18
20
  const LOG_TYPE = "socket";
19
21
  const ALLOW_SECURE_CHANNEL_DELAY = 500;
@@ -51,6 +53,7 @@ export function createDeviceSocket(
51
53
  let correctlyFinished = false; // the socket logic reach a normal termination
52
54
  let inBulkMode = false; // we have an array of apdus to exchange, without the need of more WS messages.
53
55
  let allowSecureChannelTimeout: NodeJS.Timeout | null = null; // allows to delay/cancel the user confirmation event
56
+ let deviceIdCaptured = false; // track if we've already captured the device id
54
57
  const ws = new WS(url);
55
58
 
56
59
  ws.onopen = () => {
@@ -127,6 +130,10 @@ export function createDeviceSocket(
127
130
  }, ALLOW_SECURE_CHANNEL_DELAY);
128
131
  }
129
132
 
133
+ // Detect GetCertificate APDU to extract device ID
134
+ const shouldCaptureDeviceId =
135
+ !deviceIdCaptured && apdu.slice(0, 2).toString("hex") === "e052";
136
+
130
137
  const r = await transport.exchange(apdu);
131
138
 
132
139
  if (allowSecureChannelTimeout) {
@@ -170,6 +177,34 @@ export function createDeviceSocket(
170
177
  });
171
178
  }
172
179
 
180
+ // Extract device ID from GetCertificate response
181
+ if (shouldCaptureDeviceId && status === StatusCodes.OK) {
182
+ try {
183
+ const responseData = r.slice(0, r.length - 2);
184
+ const headerLength = responseData[0];
185
+ const publicKeyLengthOffset = 1 + headerLength;
186
+ const publicKeyLength = responseData[publicKeyLengthOffset];
187
+ const publicKeyOffset = publicKeyLengthOffset + 1;
188
+ const publicKey = responseData.slice(
189
+ publicKeyOffset,
190
+ publicKeyOffset + publicKeyLength,
191
+ );
192
+
193
+ // Compute device ID as SHA3-256 hash of the public key
194
+ const deviceIdHash = sha3_256(publicKey);
195
+ const deviceIdString = Buffer.from(deviceIdHash).toString("hex");
196
+ const deviceId = DeviceId.fromString(deviceIdString);
197
+ deviceIdCaptured = true;
198
+
199
+ o.next({
200
+ type: "device-id",
201
+ deviceId,
202
+ });
203
+ } catch (err) {
204
+ tracer.trace("Failed to extract device ID from GetCertificate response", { err });
205
+ }
206
+ }
207
+
173
208
  const data = r.slice(0, r.length - 2);
174
209
  o.next({
175
210
  type: "exchange",
@@ -16,7 +16,7 @@ import { UserRefusedOnDevice } from "@ledgerhq/errors";
16
16
  import { WalletState } from "@ledgerhq/live-wallet/store";
17
17
  import { endpoints as calEndpoints } from "@ledgerhq/cryptoassets/cal-client/state-manager/api";
18
18
  import { ThunkDispatch, UnknownAction } from "@reduxjs/toolkit";
19
- import { InfiniteData } from "@reduxjs/toolkit/query";
19
+ import { InfiniteData } from "@reduxjs/toolkit/query/react";
20
20
  import type {
21
21
  TokensDataWithPagination,
22
22
  PageParam,