@ledgerhq/live-common 34.54.0-nightly.20251127103328 → 34.54.0-nightly.20251128023740

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 (80) hide show
  1. package/lib/e2e/data/deviceLabelsData.d.ts.map +1 -1
  2. package/lib/e2e/data/deviceLabelsData.js +1 -0
  3. package/lib/e2e/data/deviceLabelsData.js.map +1 -1
  4. package/lib/e2e/enum/Device.d.ts +1 -0
  5. package/lib/e2e/enum/Device.d.ts.map +1 -1
  6. package/lib/e2e/enum/Device.js +1 -0
  7. package/lib/e2e/enum/Device.js.map +1 -1
  8. package/lib/e2e/families/cardano.d.ts.map +1 -1
  9. package/lib/e2e/families/cardano.js +29 -14
  10. package/lib/e2e/families/cardano.js.map +1 -1
  11. package/lib/e2e/index.d.ts +4 -3
  12. package/lib/e2e/index.d.ts.map +1 -1
  13. package/lib/e2e/index.js +21 -1
  14. package/lib/e2e/index.js.map +1 -1
  15. package/lib/e2e/speculos.d.ts.map +1 -1
  16. package/lib/e2e/speculos.js +31 -4
  17. package/lib/e2e/speculos.js.map +1 -1
  18. package/lib/e2e/speculosAppVersion.d.ts.map +1 -1
  19. package/lib/e2e/speculosAppVersion.js +6 -2
  20. package/lib/e2e/speculosAppVersion.js.map +1 -1
  21. package/lib/e2e/swap.d.ts.map +1 -1
  22. package/lib/e2e/swap.js +7 -6
  23. package/lib/e2e/swap.js.map +1 -1
  24. package/lib/featureFlags/defaultFeatures.d.ts.map +1 -1
  25. package/lib/featureFlags/defaultFeatures.js +6 -1
  26. package/lib/featureFlags/defaultFeatures.js.map +1 -1
  27. package/lib/featureFlags/useFeature.d.ts +1 -1
  28. package/lib/load/speculos.d.ts.map +1 -1
  29. package/lib/load/speculos.js +1 -0
  30. package/lib/load/speculos.js.map +1 -1
  31. package/lib-es/e2e/data/deviceLabelsData.d.ts.map +1 -1
  32. package/lib-es/e2e/data/deviceLabelsData.js +1 -0
  33. package/lib-es/e2e/data/deviceLabelsData.js.map +1 -1
  34. package/lib-es/e2e/enum/Device.d.ts +1 -0
  35. package/lib-es/e2e/enum/Device.d.ts.map +1 -1
  36. package/lib-es/e2e/enum/Device.js +1 -0
  37. package/lib-es/e2e/enum/Device.js.map +1 -1
  38. package/lib-es/e2e/families/cardano.d.ts.map +1 -1
  39. package/lib-es/e2e/families/cardano.js +29 -14
  40. package/lib-es/e2e/families/cardano.js.map +1 -1
  41. package/lib-es/e2e/index.d.ts +4 -3
  42. package/lib-es/e2e/index.d.ts.map +1 -1
  43. package/lib-es/e2e/index.js +16 -0
  44. package/lib-es/e2e/index.js.map +1 -1
  45. package/lib-es/e2e/speculos.d.ts.map +1 -1
  46. package/lib-es/e2e/speculos.js +31 -4
  47. package/lib-es/e2e/speculos.js.map +1 -1
  48. package/lib-es/e2e/speculosAppVersion.d.ts.map +1 -1
  49. package/lib-es/e2e/speculosAppVersion.js +6 -2
  50. package/lib-es/e2e/speculosAppVersion.js.map +1 -1
  51. package/lib-es/e2e/swap.d.ts.map +1 -1
  52. package/lib-es/e2e/swap.js +7 -6
  53. package/lib-es/e2e/swap.js.map +1 -1
  54. package/lib-es/featureFlags/defaultFeatures.d.ts.map +1 -1
  55. package/lib-es/featureFlags/defaultFeatures.js +6 -1
  56. package/lib-es/featureFlags/defaultFeatures.js.map +1 -1
  57. package/lib-es/featureFlags/useFeature.d.ts +1 -1
  58. package/lib-es/load/speculos.d.ts.map +1 -1
  59. package/lib-es/load/speculos.js +1 -0
  60. package/lib-es/load/speculos.js.map +1 -1
  61. package/package.json +53 -53
  62. package/src/e2e/data/deviceLabelsData.ts +1 -0
  63. package/src/e2e/enum/Device.ts +1 -0
  64. package/src/e2e/families/cardano.ts +32 -14
  65. package/src/e2e/index.ts +20 -0
  66. package/src/e2e/speculos.ts +35 -4
  67. package/src/e2e/speculosAppVersion.ts +8 -2
  68. package/src/e2e/swap.ts +8 -7
  69. package/src/featureFlags/defaultFeatures.ts +6 -1
  70. package/src/load/speculos.ts +1 -0
  71. package/lib/families/evm/shouldUseReceiveOptions.d.ts +0 -3
  72. package/lib/families/evm/shouldUseReceiveOptions.d.ts.map +0 -1
  73. package/lib/families/evm/shouldUseReceiveOptions.js +0 -5
  74. package/lib/families/evm/shouldUseReceiveOptions.js.map +0 -1
  75. package/lib-es/families/evm/shouldUseReceiveOptions.d.ts +0 -3
  76. package/lib-es/families/evm/shouldUseReceiveOptions.d.ts.map +0 -1
  77. package/lib-es/families/evm/shouldUseReceiveOptions.js +0 -3
  78. package/lib-es/families/evm/shouldUseReceiveOptions.js.map +0 -1
  79. package/src/families/evm/shouldUseReceiveOptions.test.ts +0 -25
  80. package/src/families/evm/shouldUseReceiveOptions.ts +0 -4
@@ -22,7 +22,7 @@ function validateTransactionData(tx: Transaction, events: string[]) {
22
22
 
23
23
  async function sendCardanoTouchDevices(tx: Transaction) {
24
24
  await waitFor(DeviceLabels.REVIEW_TRANSACTION);
25
- const events = await pressUntilTextFound(DeviceLabels.TO);
25
+ const events = await pressUntilTextFound(DeviceLabels.AMOUNT);
26
26
  validateTransactionData(tx, events);
27
27
  await pressAndRelease(DeviceLabels.TAP_TO_CONTINUE);
28
28
  await waitFor(DeviceLabels.FEES);
@@ -77,18 +77,22 @@ export async function sendCardano(tx: Transaction) {
77
77
  return sendCardanoButtonDevice(tx);
78
78
  }
79
79
 
80
+ const TOUCH_DELEGATE_STEPS = [
81
+ [DeviceLabels.REVIEW_TRANSACTION, "swipe"],
82
+ [DeviceLabels.TAP_TO_CONTINUE, "tap"],
83
+ [DeviceLabels.REGISTER, "swipe"],
84
+ [DeviceLabels.TAP_TO_CONTINUE, "tap"],
85
+ [DeviceLabels.CONFIRM, "confirm"],
86
+ [DeviceLabels.DELEGATE_STAKE, "swipe"],
87
+ [DeviceLabels.TAP_TO_CONTINUE, "tap"],
88
+ [DeviceLabels.CONFIRM, "confirm"],
89
+ [DeviceLabels.HOLD_TO_SIGN, "hold"],
90
+ ] as const;
91
+
80
92
  const DELEGATE_STEPS_CONFIG = {
81
- [DeviceModelId.stax || DeviceModelId.europa]: [
82
- [DeviceLabels.REVIEW_TRANSACTION, "swipe"],
83
- [DeviceLabels.TAP_TO_CONTINUE, "tap"],
84
- [DeviceLabels.REGISTER, "swipe"],
85
- [DeviceLabels.TAP_TO_CONTINUE, "tap"],
86
- [DeviceLabels.CONFIRM, "confirm"],
87
- [DeviceLabels.DELEGATE_STAKE, "swipe"],
88
- [DeviceLabels.TAP_TO_CONTINUE, "tap"],
89
- [DeviceLabels.CONFIRM, "confirm"],
90
- [DeviceLabels.HOLD_TO_SIGN, "hold"],
91
- ] as const,
93
+ [DeviceModelId.stax]: TOUCH_DELEGATE_STEPS,
94
+ [DeviceModelId.europa]: TOUCH_DELEGATE_STEPS,
95
+ [DeviceModelId.apex]: TOUCH_DELEGATE_STEPS,
92
96
  [DeviceModelId.nanoS]: [
93
97
  [DeviceLabels.NEW_ORDINARY, "right"],
94
98
  [DeviceLabels.TRANSACTION_FEE, "both"],
@@ -115,8 +119,22 @@ const DELEGATE_STEPS_CONFIG = {
115
119
  ] as const,
116
120
  };
117
121
 
122
+ function getConfirmButtonCoords(): { x: number; y: number } {
123
+ const speculosModel = getSpeculosModel();
124
+
125
+ switch (speculosModel) {
126
+ case DeviceModelId.stax:
127
+ return { x: 152, y: 532 };
128
+ case DeviceModelId.apex:
129
+ return { x: 114, y: 305 };
130
+ case DeviceModelId.europa:
131
+ default:
132
+ return { x: 186, y: 446 };
133
+ }
134
+ }
135
+
118
136
  async function delegateTouchDevicesAction(label: DeviceLabels) {
119
- const CONFIRM_BUTTON_COORDS = { x: 139, y: 532 };
137
+ const CONFIRM_BUTTON_COORDS = getConfirmButtonCoords();
120
138
  await waitFor(label);
121
139
  switch (label) {
122
140
  case DeviceLabels.TAP_TO_CONTINUE:
@@ -164,7 +182,7 @@ async function executeDelegateStep(label: DeviceLabels, action: ActionType) {
164
182
  export async function delegateCardano() {
165
183
  const speculosModel = getSpeculosModel();
166
184
  const steps =
167
- speculosModel === DeviceModelId.stax || speculosModel === DeviceModelId.europa
185
+ isTouchDevice() && DELEGATE_STEPS_CONFIG[speculosModel]
168
186
  ? DELEGATE_STEPS_CONFIG[speculosModel]
169
187
  : speculosModel === DeviceModelId.nanoS
170
188
  ? DELEGATE_STEPS_CONFIG[DeviceModelId.nanoS]
package/src/e2e/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { EnvName } from "@ledgerhq/live-env";
2
2
  import { Feature, FeatureId } from "@ledgerhq/types-live";
3
3
  import { getFeature, DEFAULT_FEATURES } from "../featureFlags";
4
+ import axios, { AxiosError } from "axios";
4
5
 
5
6
  export const getAllFeatureFlags = (
6
7
  appLanguage?: string,
@@ -53,3 +54,22 @@ export const formatEnvData = (data: { [key in EnvName]: unknown }) => {
53
54
  }
54
55
  return allureData;
55
56
  };
57
+
58
+ export const sanitizeError = (error: unknown): Error => {
59
+ if (!axios.isAxiosError(error)) {
60
+ return error instanceof Error ? error : new Error(String(error ?? "Unknown error"));
61
+ }
62
+
63
+ const err = error as AxiosError;
64
+ const sanitized = new Error(err.message || "Axios request failed");
65
+
66
+ Object.assign(sanitized, {
67
+ name: err.name,
68
+ code: err.code,
69
+ url: err.config?.url,
70
+ method: err.config?.method,
71
+ status: err.response?.status,
72
+ });
73
+
74
+ return sanitized;
75
+ };
@@ -49,6 +49,7 @@ import {
49
49
  swipeRight,
50
50
  } from "./deviceInteraction/TouchDeviceSimulator";
51
51
  import { withDeviceController } from "./deviceInteraction/DeviceController";
52
+ import { sanitizeError } from ".";
52
53
 
53
54
  const isSpeculosRemote = process.env.REMOTE_SPECULOS === "true";
54
55
 
@@ -428,7 +429,7 @@ export async function startSpeculos(
428
429
  };
429
430
  });
430
431
  } catch (e: unknown) {
431
- console.error(e);
432
+ console.error(sanitizeError(e));
432
433
  log("engine", `test ${testName} failed with ${String(e)}`);
433
434
  }
434
435
  }
@@ -610,7 +611,7 @@ export async function takeScreenshot(port?: number): Promise<Buffer | undefined>
610
611
  );
611
612
  return response.data;
612
613
  } catch (error) {
613
- console.error("Error downloading speculos screenshot:", error);
614
+ console.error("Error downloading speculos screenshot:", sanitizeError(error));
614
615
  }
615
616
  }
616
617
 
@@ -668,12 +669,42 @@ export const activateLedgerSync = withDeviceController(({ getButtonsController }
668
669
  }
669
670
  });
670
671
 
672
+ const getSettingsToggle1Coordinates = () => {
673
+ const deviceModel = getSpeculosModel();
674
+
675
+ switch (deviceModel) {
676
+ case DeviceModelId.stax:
677
+ return { x: 345, y: 136 };
678
+ case DeviceModelId.europa:
679
+ return { x: 420, y: 140 };
680
+ case DeviceModelId.apex:
681
+ return { x: 263, y: 100 };
682
+ default:
683
+ return { x: 420, y: 140 };
684
+ }
685
+ };
686
+
687
+ const getSettingsCogwheelCoordinates = () => {
688
+ const deviceModel = getSpeculosModel();
689
+
690
+ switch (deviceModel) {
691
+ case DeviceModelId.stax:
692
+ return { x: 362, y: 43 };
693
+ case DeviceModelId.europa:
694
+ return { x: 400, y: 80 };
695
+ case DeviceModelId.apex:
696
+ return { x: 253, y: 58 };
697
+ default:
698
+ return { x: 400, y: 80 };
699
+ }
700
+ };
701
+
671
702
  export const activateExpertMode = withDeviceController(({ getButtonsController }) => async () => {
672
703
  const buttons = getButtonsController();
673
704
 
674
705
  if (isTouchDevice()) {
675
706
  await goToSettings();
676
- const SettingsToggle1Coordinates = { x: 344, y: 136 };
707
+ const SettingsToggle1Coordinates = getSettingsToggle1Coordinates();
677
708
  await pressAndRelease(
678
709
  DeviceLabels.SETTINGS_TOGGLE_1,
679
710
  SettingsToggle1Coordinates.x,
@@ -698,7 +729,7 @@ export const goToSettings = withDeviceController(({ getButtonsController }) => a
698
729
  const buttons = getButtonsController();
699
730
 
700
731
  if (isTouchDevice()) {
701
- const SettingsCogwheelCoordinates = { x: 400, y: 75 };
732
+ const SettingsCogwheelCoordinates = getSettingsCogwheelCoordinates();
702
733
  await pressAndRelease(
703
734
  DeviceLabels.SETTINGS,
704
735
  SettingsCogwheelCoordinates.x,
@@ -3,6 +3,7 @@ import { version } from "../../package.json";
3
3
  import { getEnv } from "@ledgerhq/live-env";
4
4
  import { DeviceModelId } from "@ledgerhq/devices";
5
5
  import { Device as CryptoWallet } from "./enum/Device";
6
+ import { sanitizeError } from "./index";
6
7
  import * as fs from "fs";
7
8
  import * as path from "path";
8
9
 
@@ -18,6 +19,8 @@ export function getSpeculosModel(): DeviceModelId {
18
19
  case CryptoWallet.FLEX.name:
19
20
  case DeviceModelId.europa:
20
21
  return DeviceModelId.europa;
22
+ case CryptoWallet.NANO_GEN_5.name:
23
+ return DeviceModelId.apex;
21
24
  case CryptoWallet.LNSP.name:
22
25
  default:
23
26
  return DeviceModelId.nanoSP;
@@ -26,7 +29,9 @@ export function getSpeculosModel(): DeviceModelId {
26
29
 
27
30
  export function isTouchDevice(): boolean {
28
31
  const model = getSpeculosModel();
29
- return model === DeviceModelId.stax || model === DeviceModelId.europa;
32
+ return (
33
+ model === DeviceModelId.stax || model === DeviceModelId.europa || model === DeviceModelId.apex
34
+ );
30
35
  }
31
36
 
32
37
  function getDeviceTargetId(device: DeviceModelId): number {
@@ -36,6 +41,7 @@ function getDeviceTargetId(device: DeviceModelId): number {
36
41
  [DeviceModelId.nanoSP]: CryptoWallet.LNSP.targetId,
37
42
  [DeviceModelId.stax]: CryptoWallet.STAX.targetId,
38
43
  [DeviceModelId.europa]: CryptoWallet.FLEX.targetId,
44
+ [DeviceModelId.apex]: CryptoWallet.NANO_GEN_5.targetId,
39
45
  };
40
46
  return modelToTargetIdMap[device];
41
47
  }
@@ -73,7 +79,7 @@ export async function createNanoAppJsonFile(nanoAppFilePath: string): Promise<vo
73
79
  }
74
80
  fs.writeFileSync(jsonFilePath, JSON.stringify(appCatalog, null, 2), "utf8");
75
81
  } catch (error) {
76
- console.error("Unable to create app version file:", error);
82
+ console.error("Unable to create app version file:", sanitizeError(error));
77
83
  }
78
84
  }
79
85
 
package/src/e2e/swap.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { Account } from "./enum/Account";
2
+ import { sanitizeError } from "./index";
2
3
  import axios from "axios";
3
4
 
4
5
  export async function getMinimumSwapAmount(AccountFrom: Account, AccountTo: Account) {
5
6
  try {
6
7
  const requestConfig = {
7
8
  method: "GET",
8
- url: `https://swap-stg.ledger-test.com/v5/quote`,
9
+ url: "https://swap-stg.ledger-test.com/v5/quote",
9
10
  params: {
10
11
  from: AccountFrom.currency.id,
11
12
  to: AccountTo.currency.id,
@@ -21,9 +22,7 @@ export async function getMinimumSwapAmount(AccountFrom: Account, AccountTo: Acco
21
22
  tradeType: "INPUT",
22
23
  uniswapOrderType: "uniswapxv1",
23
24
  },
24
- headers: {
25
- accept: "application/json",
26
- },
25
+ headers: { accept: "application/json" },
27
26
  };
28
27
 
29
28
  const { data } = await axios(requestConfig);
@@ -38,8 +37,10 @@ export async function getMinimumSwapAmount(AccountFrom: Account, AccountTo: Acco
38
37
  }
39
38
 
40
39
  return Math.max(...minimumAmounts);
41
- } catch (error) {
42
- console.error("Error fetching swap minimum amount:", error);
43
- throw error;
40
+ } catch (error: any) {
41
+ const sanitizedError = sanitizeError(error);
42
+ console.error("Error fetching swap minimum amount:", sanitizedError);
43
+ // throw the sanitized error, not the original circular Axios error
44
+ throw sanitizedError;
44
45
  }
45
46
  }
@@ -703,7 +703,12 @@ export const DEFAULT_FEATURES: Features = {
703
703
  supportDeviceApex: DEFAULT_FEATURE,
704
704
  llmSyncOnboardingIncr1: DEFAULT_FEATURE,
705
705
  lldSyncOnboardingIncr1: DEFAULT_FEATURE,
706
- noah: DEFAULT_FEATURE,
706
+ noah: {
707
+ ...DEFAULT_FEATURE,
708
+ params: {
709
+ activeCurrencyIds: [],
710
+ },
711
+ },
707
712
  newSendFlow: DEFAULT_FEATURE,
708
713
  cantonSkipPreapprovalStep: DEFAULT_FEATURE,
709
714
  lldSessionReplay: {
@@ -28,6 +28,7 @@ export { closeAllSpeculosDevices, releaseSpeculosDevice, createSpeculosDevice };
28
28
  export type { SpeculosTransport };
29
29
 
30
30
  const modelMapPriority: Record<string, number> = {
31
+ apex_p: 7,
31
32
  flex: 6,
32
33
  stax: 5,
33
34
  nanos: 4,
@@ -1,3 +0,0 @@
1
- declare const shouldUseReceiveOptions: (currencyId: string | undefined) => boolean;
2
- export default shouldUseReceiveOptions;
3
- //# sourceMappingURL=shouldUseReceiveOptions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shouldUseReceiveOptions.d.ts","sourceRoot":"","sources":["../../../src/families/evm/shouldUseReceiveOptions.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,uBAAuB,eAAgB,MAAM,GAAG,SAAS,YACkB,CAAC;AAElF,eAAe,uBAAuB,CAAC"}
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const shouldUseReceiveOptions = (currencyId) => !!(currencyId && ["ethereum/erc20/usd__coin", "ethereum"].includes(currencyId));
4
- exports.default = shouldUseReceiveOptions;
5
- //# sourceMappingURL=shouldUseReceiveOptions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shouldUseReceiveOptions.js","sourceRoot":"","sources":["../../../src/families/evm/shouldUseReceiveOptions.ts"],"names":[],"mappings":";;AAAA,MAAM,uBAAuB,GAAG,CAAC,UAA8B,EAAE,EAAE,CACjE,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,0BAA0B,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;AAElF,kBAAe,uBAAuB,CAAC"}
@@ -1,3 +0,0 @@
1
- declare const shouldUseReceiveOptions: (currencyId: string | undefined) => boolean;
2
- export default shouldUseReceiveOptions;
3
- //# sourceMappingURL=shouldUseReceiveOptions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shouldUseReceiveOptions.d.ts","sourceRoot":"","sources":["../../../src/families/evm/shouldUseReceiveOptions.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,uBAAuB,eAAgB,MAAM,GAAG,SAAS,YACkB,CAAC;AAElF,eAAe,uBAAuB,CAAC"}
@@ -1,3 +0,0 @@
1
- const shouldUseReceiveOptions = (currencyId) => !!(currencyId && ["ethereum/erc20/usd__coin", "ethereum"].includes(currencyId));
2
- export default shouldUseReceiveOptions;
3
- //# sourceMappingURL=shouldUseReceiveOptions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shouldUseReceiveOptions.js","sourceRoot":"","sources":["../../../src/families/evm/shouldUseReceiveOptions.ts"],"names":[],"mappings":"AAAA,MAAM,uBAAuB,GAAG,CAAC,UAA8B,EAAE,EAAE,CACjE,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,0BAA0B,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;AAElF,eAAe,uBAAuB,CAAC"}
@@ -1,25 +0,0 @@
1
- import shouldUseReceiveOptions from "./shouldUseReceiveOptions";
2
-
3
- describe("shouldUseReceiveOptions", () => {
4
- it("returns true for 'ethereum/erc20/usd__coin'", () => {
5
- expect(shouldUseReceiveOptions("ethereum/erc20/usd__coin")).toBe(true);
6
- });
7
-
8
- it("returns true for 'ethereum'", () => {
9
- expect(shouldUseReceiveOptions("ethereum")).toBe(true);
10
- });
11
-
12
- it("returns false for undefined", () => {
13
- expect(shouldUseReceiveOptions(undefined)).toBe(false);
14
- });
15
-
16
- it("returns false for empty string", () => {
17
- expect(shouldUseReceiveOptions("")).toBe(false);
18
- });
19
-
20
- it("returns false for other currency ids", () => {
21
- expect(shouldUseReceiveOptions("bitcoin")).toBe(false);
22
- expect(shouldUseReceiveOptions("ethereum/erc20/other_token")).toBe(false);
23
- expect(shouldUseReceiveOptions("usd__coin")).toBe(false);
24
- });
25
- });
@@ -1,4 +0,0 @@
1
- const shouldUseReceiveOptions = (currencyId: string | undefined) =>
2
- !!(currencyId && ["ethereum/erc20/usd__coin", "ethereum"].includes(currencyId));
3
-
4
- export default shouldUseReceiveOptions;