@ledgerhq/live-common 34.43.0-nightly.2 → 34.43.0

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 (176) hide show
  1. package/lib/appSupportsQuitApp.d.ts +0 -1
  2. package/lib/appSupportsQuitApp.d.ts.map +1 -1
  3. package/lib/appSupportsQuitApp.js +0 -1
  4. package/lib/appSupportsQuitApp.js.map +1 -1
  5. package/lib/appSupportsQuitApp.test.js +3 -28
  6. package/lib/appSupportsQuitApp.test.js.map +1 -1
  7. package/lib/bridge/generic-alpaca/alpaca/index.d.ts +1 -1
  8. package/lib/bridge/generic-alpaca/alpaca/index.d.ts.map +1 -1
  9. package/lib/bridge/generic-alpaca/alpaca/index.js.map +1 -1
  10. package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +6 -2
  11. package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -1
  12. package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -1
  13. package/lib/bridge/generic-alpaca/signOperation.js.map +1 -1
  14. package/lib/bridge/generic-alpaca/utils.d.ts +2 -2
  15. package/lib/bridge/generic-alpaca/utils.d.ts.map +1 -1
  16. package/lib/bridge/generic-alpaca/utils.js +1 -1
  17. package/lib/bridge/generic-alpaca/utils.js.map +1 -1
  18. package/lib/deviceSDK/hooks/__tests__/filterIgnoredFirmwareUpdates.test.d.ts +2 -0
  19. package/lib/deviceSDK/hooks/__tests__/filterIgnoredFirmwareUpdates.test.d.ts.map +1 -0
  20. package/lib/deviceSDK/hooks/__tests__/filterIgnoredFirmwareUpdates.test.js +114 -0
  21. package/lib/deviceSDK/hooks/__tests__/filterIgnoredFirmwareUpdates.test.js.map +1 -0
  22. package/lib/deviceSDK/hooks/filterIgnoredFirmwareUpdates.d.ts +11 -0
  23. package/lib/deviceSDK/hooks/filterIgnoredFirmwareUpdates.d.ts.map +1 -0
  24. package/lib/deviceSDK/hooks/filterIgnoredFirmwareUpdates.js +26 -0
  25. package/lib/deviceSDK/hooks/filterIgnoredFirmwareUpdates.js.map +1 -0
  26. package/lib/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.d.ts +12 -0
  27. package/lib/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.d.ts.map +1 -0
  28. package/lib/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.js +24 -0
  29. package/lib/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.js.map +1 -0
  30. package/lib/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.test.d.ts +2 -0
  31. package/lib/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.test.d.ts.map +1 -0
  32. package/lib/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.test.js +118 -0
  33. package/lib/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.test.js.map +1 -0
  34. package/lib/deviceSDK/hooks/useGetLatestAvailableFirmware.d.ts +3 -1
  35. package/lib/deviceSDK/hooks/useGetLatestAvailableFirmware.d.ts.map +1 -1
  36. package/lib/deviceSDK/hooks/useGetLatestAvailableFirmware.js +7 -3
  37. package/lib/deviceSDK/hooks/useGetLatestAvailableFirmware.js.map +1 -1
  38. package/lib/e2e/index.d.ts +2 -1
  39. package/lib/e2e/index.d.ts.map +1 -1
  40. package/lib/e2e/speculos.d.ts.map +1 -1
  41. package/lib/e2e/speculos.js +15 -45
  42. package/lib/e2e/speculos.js.map +1 -1
  43. package/lib/e2e/speculosCI.d.ts.map +1 -1
  44. package/lib/e2e/speculosCI.js +4 -22
  45. package/lib/e2e/speculosCI.js.map +1 -1
  46. package/lib/env.react.d.ts +1 -1
  47. package/lib/env.react.d.ts.map +1 -1
  48. package/lib/families/solana/bridge/mock-data.d.ts.map +1 -1
  49. package/lib/families/solana/bridge/mock-data.js +316 -46
  50. package/lib/families/solana/bridge/mock-data.js.map +1 -1
  51. package/lib/families/solana/bridge/mock.js +2 -2
  52. package/lib/families/solana/bridge/mock.js.map +1 -1
  53. package/lib/featureFlags/defaultFeatures.d.ts.map +1 -1
  54. package/lib/featureFlags/defaultFeatures.js +4 -0
  55. package/lib/featureFlags/defaultFeatures.js.map +1 -1
  56. package/lib/featureFlags/useFeature.d.ts +1 -1
  57. package/lib/featureFlags/useFeature.d.ts.map +1 -1
  58. package/lib-es/appSupportsQuitApp.d.ts +0 -1
  59. package/lib-es/appSupportsQuitApp.d.ts.map +1 -1
  60. package/lib-es/appSupportsQuitApp.js +0 -1
  61. package/lib-es/appSupportsQuitApp.js.map +1 -1
  62. package/lib-es/appSupportsQuitApp.test.js +1 -6
  63. package/lib-es/appSupportsQuitApp.test.js.map +1 -1
  64. package/lib-es/bridge/generic-alpaca/alpaca/index.d.ts +1 -1
  65. package/lib-es/bridge/generic-alpaca/alpaca/index.d.ts.map +1 -1
  66. package/lib-es/bridge/generic-alpaca/alpaca/index.js.map +1 -1
  67. package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +6 -2
  68. package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -1
  69. package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -1
  70. package/lib-es/bridge/generic-alpaca/signOperation.js.map +1 -1
  71. package/lib-es/bridge/generic-alpaca/utils.d.ts +2 -2
  72. package/lib-es/bridge/generic-alpaca/utils.d.ts.map +1 -1
  73. package/lib-es/bridge/generic-alpaca/utils.js +1 -1
  74. package/lib-es/bridge/generic-alpaca/utils.js.map +1 -1
  75. package/lib-es/deviceSDK/hooks/__tests__/filterIgnoredFirmwareUpdates.test.d.ts +2 -0
  76. package/lib-es/deviceSDK/hooks/__tests__/filterIgnoredFirmwareUpdates.test.d.ts.map +1 -0
  77. package/lib-es/deviceSDK/hooks/__tests__/filterIgnoredFirmwareUpdates.test.js +112 -0
  78. package/lib-es/deviceSDK/hooks/__tests__/filterIgnoredFirmwareUpdates.test.js.map +1 -0
  79. package/lib-es/deviceSDK/hooks/filterIgnoredFirmwareUpdates.d.ts +11 -0
  80. package/lib-es/deviceSDK/hooks/filterIgnoredFirmwareUpdates.d.ts.map +1 -0
  81. package/lib-es/deviceSDK/hooks/filterIgnoredFirmwareUpdates.js +22 -0
  82. package/lib-es/deviceSDK/hooks/filterIgnoredFirmwareUpdates.js.map +1 -0
  83. package/lib-es/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.d.ts +12 -0
  84. package/lib-es/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.d.ts.map +1 -0
  85. package/lib-es/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.js +20 -0
  86. package/lib-es/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.js.map +1 -0
  87. package/lib-es/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.test.d.ts +2 -0
  88. package/lib-es/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.test.d.ts.map +1 -0
  89. package/lib-es/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.test.js +116 -0
  90. package/lib-es/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.test.js.map +1 -0
  91. package/lib-es/deviceSDK/hooks/useGetLatestAvailableFirmware.d.ts +3 -1
  92. package/lib-es/deviceSDK/hooks/useGetLatestAvailableFirmware.d.ts.map +1 -1
  93. package/lib-es/deviceSDK/hooks/useGetLatestAvailableFirmware.js +7 -3
  94. package/lib-es/deviceSDK/hooks/useGetLatestAvailableFirmware.js.map +1 -1
  95. package/lib-es/e2e/index.d.ts +2 -1
  96. package/lib-es/e2e/index.d.ts.map +1 -1
  97. package/lib-es/e2e/speculos.d.ts.map +1 -1
  98. package/lib-es/e2e/speculos.js +15 -45
  99. package/lib-es/e2e/speculos.js.map +1 -1
  100. package/lib-es/e2e/speculosCI.d.ts.map +1 -1
  101. package/lib-es/e2e/speculosCI.js +4 -22
  102. package/lib-es/e2e/speculosCI.js.map +1 -1
  103. package/lib-es/env.react.d.ts +1 -1
  104. package/lib-es/env.react.d.ts.map +1 -1
  105. package/lib-es/families/solana/bridge/mock-data.d.ts.map +1 -1
  106. package/lib-es/families/solana/bridge/mock-data.js +316 -46
  107. package/lib-es/families/solana/bridge/mock-data.js.map +1 -1
  108. package/lib-es/families/solana/bridge/mock.js +3 -3
  109. package/lib-es/families/solana/bridge/mock.js.map +1 -1
  110. package/lib-es/featureFlags/defaultFeatures.d.ts.map +1 -1
  111. package/lib-es/featureFlags/defaultFeatures.js +4 -0
  112. package/lib-es/featureFlags/defaultFeatures.js.map +1 -1
  113. package/lib-es/featureFlags/useFeature.d.ts +1 -1
  114. package/lib-es/featureFlags/useFeature.d.ts.map +1 -1
  115. package/package.json +48 -48
  116. package/src/appSupportsQuitApp.test.ts +1 -7
  117. package/src/appSupportsQuitApp.ts +0 -1
  118. package/src/bridge/generic-alpaca/alpaca/index.ts +3 -3
  119. package/src/bridge/generic-alpaca/alpaca/network/network-alpaca.ts +8 -3
  120. package/src/bridge/generic-alpaca/signOperation.ts +1 -1
  121. package/src/bridge/generic-alpaca/utils.ts +10 -3
  122. package/src/deviceSDK/hooks/__tests__/filterIgnoredFirmwareUpdates.test.ts +132 -0
  123. package/src/deviceSDK/hooks/filterIgnoredFirmwareUpdates.ts +27 -0
  124. package/src/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.test.ts +192 -0
  125. package/src/deviceSDK/hooks/getIgnoredOSUpdatesForDeviceModelAndPlatform.ts +28 -0
  126. package/src/deviceSDK/hooks/useGetLatestAvailableFirmware.ts +9 -2
  127. package/src/e2e/speculos.ts +21 -77
  128. package/src/e2e/speculosCI.ts +10 -32
  129. package/src/families/solana/bridge/mock-data.ts +316 -52
  130. package/src/families/solana/bridge/mock.ts +3 -3
  131. package/src/featureFlags/defaultFeatures.ts +4 -0
  132. package/lib/modularDrawer/__mocks__/accounts.mock.d.ts +0 -18
  133. package/lib/modularDrawer/__mocks__/accounts.mock.d.ts.map +0 -1
  134. package/lib/modularDrawer/__mocks__/accounts.mock.js +0 -48
  135. package/lib/modularDrawer/__mocks__/accounts.mock.js.map +0 -1
  136. package/lib/utils/__tests__/composeHooks.test.d.ts +0 -2
  137. package/lib/utils/__tests__/composeHooks.test.d.ts.map +0 -1
  138. package/lib/utils/__tests__/composeHooks.test.js +0 -35
  139. package/lib/utils/__tests__/composeHooks.test.js.map +0 -1
  140. package/lib/utils/__tests__/getAccountTuplesForCurrency.test.d.ts +0 -2
  141. package/lib/utils/__tests__/getAccountTuplesForCurrency.test.d.ts.map +0 -1
  142. package/lib/utils/__tests__/getAccountTuplesForCurrency.test.js +0 -104
  143. package/lib/utils/__tests__/getAccountTuplesForCurrency.test.js.map +0 -1
  144. package/lib/utils/composeHooks.d.ts +0 -11
  145. package/lib/utils/composeHooks.d.ts.map +0 -1
  146. package/lib/utils/composeHooks.js +0 -25
  147. package/lib/utils/composeHooks.js.map +0 -1
  148. package/lib/utils/getAccountTuplesForCurrency.d.ts +0 -8
  149. package/lib/utils/getAccountTuplesForCurrency.d.ts.map +0 -1
  150. package/lib/utils/getAccountTuplesForCurrency.js +0 -19
  151. package/lib/utils/getAccountTuplesForCurrency.js.map +0 -1
  152. package/lib-es/modularDrawer/__mocks__/accounts.mock.d.ts +0 -18
  153. package/lib-es/modularDrawer/__mocks__/accounts.mock.d.ts.map +0 -1
  154. package/lib-es/modularDrawer/__mocks__/accounts.mock.js +0 -42
  155. package/lib-es/modularDrawer/__mocks__/accounts.mock.js.map +0 -1
  156. package/lib-es/utils/__tests__/composeHooks.test.d.ts +0 -2
  157. package/lib-es/utils/__tests__/composeHooks.test.d.ts.map +0 -1
  158. package/lib-es/utils/__tests__/composeHooks.test.js +0 -33
  159. package/lib-es/utils/__tests__/composeHooks.test.js.map +0 -1
  160. package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.d.ts +0 -2
  161. package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.d.ts.map +0 -1
  162. package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.js +0 -102
  163. package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.js.map +0 -1
  164. package/lib-es/utils/composeHooks.d.ts +0 -11
  165. package/lib-es/utils/composeHooks.d.ts.map +0 -1
  166. package/lib-es/utils/composeHooks.js +0 -21
  167. package/lib-es/utils/composeHooks.js.map +0 -1
  168. package/lib-es/utils/getAccountTuplesForCurrency.d.ts +0 -8
  169. package/lib-es/utils/getAccountTuplesForCurrency.d.ts.map +0 -1
  170. package/lib-es/utils/getAccountTuplesForCurrency.js +0 -15
  171. package/lib-es/utils/getAccountTuplesForCurrency.js.map +0 -1
  172. package/src/modularDrawer/__mocks__/accounts.mock.ts +0 -43
  173. package/src/utils/__tests__/composeHooks.test.ts +0 -46
  174. package/src/utils/__tests__/getAccountTuplesForCurrency.test.ts +0 -138
  175. package/src/utils/composeHooks.ts +0 -26
  176. package/src/utils/getAccountTuplesForCurrency.ts +0 -34
@@ -0,0 +1,192 @@
1
+ import { type Feature_OnboardingIgnoredOSUpdates } from "@ledgerhq/types-live";
2
+ import { DeviceModelId } from "@ledgerhq/types-devices";
3
+ import { getIgnoredOSUpdatesForDeviceModelAndPlatform } from "./getIgnoredOSUpdatesForDeviceModelAndPlatform";
4
+
5
+ describe("getIgnoredOSUpdatesForDeviceModelAndPlatform", () => {
6
+ const mockConfig: Feature_OnboardingIgnoredOSUpdates["params"] = {
7
+ ios: {
8
+ [DeviceModelId.nanoS]: ["1.6.0", "1.6.1"],
9
+ [DeviceModelId.nanoX]: ["2.0.0"],
10
+ [DeviceModelId.nanoSP]: ["1.0.0", "1.0.1", "1.0.2"],
11
+ },
12
+ android: {
13
+ [DeviceModelId.nanoS]: ["1.5.0"],
14
+ [DeviceModelId.nanoX]: ["2.1.0", "2.1.1"],
15
+ },
16
+ macos: {
17
+ [DeviceModelId.nanoX]: ["2.2.0"],
18
+ },
19
+ windows: {
20
+ [DeviceModelId.stax]: ["3.0.0"],
21
+ },
22
+ linux: {
23
+ [DeviceModelId.europa]: ["4.0.0", "4.0.1"],
24
+ },
25
+ };
26
+
27
+ describe("when config is undefined", () => {
28
+ it("should return empty array", () => {
29
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
30
+ undefined,
31
+ DeviceModelId.nanoS,
32
+ "ios",
33
+ );
34
+ expect(result).toEqual([]);
35
+ });
36
+ });
37
+
38
+ describe("when config is null", () => {
39
+ it("should return empty array", () => {
40
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
41
+ null as unknown as Feature_OnboardingIgnoredOSUpdates["params"],
42
+ DeviceModelId.nanoS,
43
+ "ios",
44
+ );
45
+ expect(result).toEqual([]);
46
+ });
47
+ });
48
+
49
+ describe("when platform does not exist in config", () => {
50
+ it("should return empty array", () => {
51
+ const configWithoutPlatform: Feature_OnboardingIgnoredOSUpdates["params"] = {
52
+ ios: { [DeviceModelId.nanoS]: ["1.6.0"] },
53
+ };
54
+
55
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
56
+ configWithoutPlatform,
57
+ DeviceModelId.nanoS,
58
+ "android",
59
+ );
60
+ expect(result).toEqual([]);
61
+ });
62
+ });
63
+
64
+ describe("when device model does not exist for platform", () => {
65
+ it("should return empty array", () => {
66
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
67
+ mockConfig,
68
+ DeviceModelId.stax,
69
+ "ios",
70
+ );
71
+ expect(result).toEqual([]);
72
+ });
73
+ });
74
+
75
+ describe("when device model exists but has no ignored updates", () => {
76
+ it("should return empty array", () => {
77
+ const configWithEmptyArray: Feature_OnboardingIgnoredOSUpdates["params"] = {
78
+ ios: {
79
+ [DeviceModelId.nanoS]: [],
80
+ },
81
+ };
82
+
83
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
84
+ configWithEmptyArray,
85
+ DeviceModelId.nanoS,
86
+ "ios",
87
+ );
88
+ expect(result).toEqual([]);
89
+ });
90
+ });
91
+
92
+ describe("when device model exists and has ignored updates", () => {
93
+ it("should return the ignored updates for iOS", () => {
94
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
95
+ mockConfig,
96
+ DeviceModelId.nanoS,
97
+ "ios",
98
+ );
99
+ expect(result).toEqual(["1.6.0", "1.6.1"]);
100
+ });
101
+
102
+ it("should return the ignored updates for Android", () => {
103
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
104
+ mockConfig,
105
+ DeviceModelId.nanoX,
106
+ "android",
107
+ );
108
+ expect(result).toEqual(["2.1.0", "2.1.1"]);
109
+ });
110
+
111
+ it("should return multiple ignored updates", () => {
112
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
113
+ mockConfig,
114
+ DeviceModelId.nanoSP,
115
+ "ios",
116
+ );
117
+ expect(result).toEqual(["1.0.0", "1.0.1", "1.0.2"]);
118
+ });
119
+
120
+ it("should return ignored updates for macOS", () => {
121
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
122
+ mockConfig,
123
+ DeviceModelId.nanoX,
124
+ "macos",
125
+ );
126
+ expect(result).toEqual(["2.2.0"]);
127
+ });
128
+
129
+ it("should return ignored updates for Windows", () => {
130
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
131
+ mockConfig,
132
+ DeviceModelId.stax,
133
+ "windows",
134
+ );
135
+ expect(result).toEqual(["3.0.0"]);
136
+ });
137
+
138
+ it("should return ignored updates for Linux", () => {
139
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
140
+ mockConfig,
141
+ DeviceModelId.europa,
142
+ "linux",
143
+ );
144
+ expect(result).toEqual(["4.0.0", "4.0.1"]);
145
+ });
146
+ });
147
+
148
+ describe("edge cases", () => {
149
+ it("should handle empty config object", () => {
150
+ const emptyConfig: Feature_OnboardingIgnoredOSUpdates["params"] = {};
151
+
152
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
153
+ emptyConfig,
154
+ DeviceModelId.nanoS,
155
+ "ios",
156
+ );
157
+ expect(result).toEqual([]);
158
+ });
159
+
160
+ it("should handle config with empty platform objects", () => {
161
+ const configWithEmptyPlatforms: Feature_OnboardingIgnoredOSUpdates["params"] = {
162
+ ios: {},
163
+ android: {},
164
+ macos: {},
165
+ windows: {},
166
+ linux: {},
167
+ };
168
+
169
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
170
+ configWithEmptyPlatforms,
171
+ DeviceModelId.nanoS,
172
+ "ios",
173
+ );
174
+ expect(result).toEqual([]);
175
+ });
176
+
177
+ it("should handle undefined device model entries", () => {
178
+ const configWithUndefined: Feature_OnboardingIgnoredOSUpdates["params"] = {
179
+ ios: {
180
+ [DeviceModelId.nanoS]: undefined as unknown as string[],
181
+ },
182
+ };
183
+
184
+ const result = getIgnoredOSUpdatesForDeviceModelAndPlatform(
185
+ configWithUndefined,
186
+ DeviceModelId.nanoS,
187
+ "ios",
188
+ );
189
+ expect(result).toEqual([]);
190
+ });
191
+ });
192
+ });
@@ -0,0 +1,28 @@
1
+ import type {
2
+ Feature_OnboardingIgnoredOSUpdates,
3
+ Platform,
4
+ IgnoredOSUpdates,
5
+ } from "@ledgerhq/types-live";
6
+ import type { DeviceModelId } from "@ledgerhq/types-devices";
7
+
8
+ /**
9
+ * Extracts the ignored OS updates for a specific device model and platform from the configuration
10
+ *
11
+ * @param ignoredOSUpdatesConfig The configuration object containing ignored OS updates per platform and device model
12
+ * @param deviceModelId The device model identifier
13
+ * @param platform The platform to get updates for
14
+ * @returns Array of firmware versions that should be ignored for the given device model and platform
15
+ */
16
+ export const getIgnoredOSUpdatesForDeviceModelAndPlatform = (
17
+ ignoredOSUpdatesConfig: Feature_OnboardingIgnoredOSUpdates["params"] | undefined,
18
+ deviceModelId: DeviceModelId,
19
+ platform: Platform,
20
+ ): IgnoredOSUpdates => {
21
+ // No ignored OS updates configuration
22
+ if (!ignoredOSUpdatesConfig) return [];
23
+ // No configuration for the specified platform
24
+ const configForPlatform = ignoredOSUpdatesConfig[platform];
25
+ if (!configForPlatform) return [];
26
+ // Return the ignored OS updates for the specified device model, empty array if not configured for that model
27
+ return configForPlatform[deviceModelId] ?? [];
28
+ };
@@ -5,11 +5,14 @@ import {
5
5
  getLatestAvailableFirmwareAction as defaultGetLatestAvailableFirmwareAction,
6
6
  initialState,
7
7
  } from "../actions/getLatestAvailableFirmware";
8
+ import { filterIgnoredFirmwareUpdates } from "./filterIgnoredFirmwareUpdates";
9
+ import type { IgnoredOSUpdates } from "@ledgerhq/types-live";
8
10
 
9
11
  export type UseGetLatestAvailableFirmwareArgs = {
10
12
  getLatestAvailableFirmwareAction?: typeof defaultGetLatestAvailableFirmwareAction;
11
13
  deviceId: string;
12
14
  isHookEnabled?: boolean;
15
+ ignoredOSUpdates?: IgnoredOSUpdates;
13
16
  };
14
17
 
15
18
  /**
@@ -30,6 +33,7 @@ export const useGetLatestAvailableFirmware = ({
30
33
  getLatestAvailableFirmwareAction = defaultGetLatestAvailableFirmwareAction,
31
34
  deviceId,
32
35
  isHookEnabled = true,
36
+ ignoredOSUpdates,
33
37
  }: UseGetLatestAvailableFirmwareArgs): {
34
38
  state: GetLatestAvailableFirmwareActionState;
35
39
  } => {
@@ -47,7 +51,10 @@ export const useGetLatestAvailableFirmware = ({
47
51
  const subscription = getLatestAvailableFirmwareAction({
48
52
  deviceId,
49
53
  }).subscribe({
50
- next: setState,
54
+ next: newValue => {
55
+ const filteredValue = filterIgnoredFirmwareUpdates(newValue, ignoredOSUpdates);
56
+ setState(filteredValue);
57
+ },
51
58
  error: (error: unknown) => {
52
59
  // Error from an action should be handled like an event and should not reach here
53
60
  log("useGetLatestAvailableFirmware", "Unknown error", error);
@@ -57,7 +64,7 @@ export const useGetLatestAvailableFirmware = ({
57
64
  return () => {
58
65
  subscription.unsubscribe();
59
66
  };
60
- }, [deviceId, getLatestAvailableFirmwareAction, isHookEnabled]);
67
+ }, [deviceId, getLatestAvailableFirmwareAction, ignoredOSUpdates, isHookEnabled]);
61
68
 
62
69
  return { state };
63
70
  };
@@ -11,7 +11,7 @@ import { createSpeculosDeviceCI, releaseSpeculosDeviceCI } from "./speculosCI";
11
11
  import type { AppCandidate } from "@ledgerhq/coin-framework/bot/types";
12
12
  import { DeviceModelId } from "@ledgerhq/devices";
13
13
  import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
14
- import axios, { AxiosError, AxiosResponse } from "axios";
14
+ import axios from "axios";
15
15
  import { getEnv } from "@ledgerhq/live-env";
16
16
  import { getCryptoCurrencyById } from "../currencies";
17
17
  import { DeviceLabels } from "../e2e/enum/DeviceLabels";
@@ -415,59 +415,13 @@ interface ResponseData {
415
415
  events: Event[];
416
416
  }
417
417
 
418
- function getSpeculosAddress(): string {
419
- const speculosAddress = process.env.SPECULOS_ADDRESS;
420
- return speculosAddress || "http://127.0.0.1";
421
- }
422
-
423
- async function retryAxiosRequest<T>(
424
- requestFn: () => Promise<AxiosResponse<T>>,
425
- maxRetries: number = 5,
426
- baseDelay: number = 1000,
427
- retryableStatusCodes: number[] = [500, 502, 503, 504],
428
- ): Promise<AxiosResponse<T>> {
429
- let lastError: AxiosError | Error;
430
-
431
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
432
- try {
433
- return await requestFn();
434
- } catch (error) {
435
- lastError = error as AxiosError | Error;
436
-
437
- const isRetryable =
438
- axios.isAxiosError(error) &&
439
- error.response &&
440
- retryableStatusCodes.includes(error.response.status);
441
-
442
- const isNetworkError = axios.isAxiosError(error) && !error.response;
443
-
444
- if ((isRetryable || isNetworkError) && attempt < maxRetries) {
445
- const delay = baseDelay * (attempt + 1);
446
- console.warn(
447
- `Axios request failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms...`,
448
- {
449
- status: axios.isAxiosError(error) ? error.response?.status : "network error",
450
- message: error.message,
451
- },
452
- );
453
- await new Promise(resolve => setTimeout(resolve, delay));
454
- continue;
455
- }
456
-
457
- throw lastError;
458
- }
459
- }
460
-
461
- throw lastError!;
462
- }
463
-
464
418
  export async function waitFor(text: string, maxAttempts = 15): Promise<string[]> {
465
419
  const port = getEnv("SPECULOS_API_PORT");
466
- const address = getSpeculosAddress();
420
+ const address = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
467
421
  const url = `${address}:${port}/events?stream=false&currentscreenonly=true`;
468
422
 
469
423
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
470
- const { data } = await retryAxiosRequest(() => axios.get<ResponseData>(url));
424
+ const { data } = await axios.get<ResponseData>(url);
471
425
  const texts = data.events.map(event => event.text);
472
426
 
473
427
  if (texts?.some(t => t?.toLowerCase().includes(text.toLowerCase()))) {
@@ -482,12 +436,10 @@ export async function waitFor(text: string, maxAttempts = 15): Promise<string[]>
482
436
 
483
437
  export async function pressBoth() {
484
438
  const speculosApiPort = getEnv("SPECULOS_API_PORT");
485
- const speculosAddress = getSpeculosAddress();
486
- await retryAxiosRequest(() =>
487
- axios.post(`${speculosAddress}:${speculosApiPort}/button/both`, {
488
- action: "press-and-release",
489
- }),
490
- );
439
+ const speculosAddress = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
440
+ await axios.post(`${speculosAddress}:${speculosApiPort}/button/both`, {
441
+ action: "press-and-release",
442
+ });
491
443
  }
492
444
 
493
445
  export async function pressUntilTextFound(
@@ -513,33 +465,27 @@ export async function pressUntilTextFound(
513
465
  }
514
466
 
515
467
  async function fetchCurrentScreenTexts(speculosApiPort: number): Promise<string> {
516
- const speculosAddress = getSpeculosAddress();
517
- const response = await retryAxiosRequest(() =>
518
- axios.get<ResponseData>(
519
- `${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=true`,
520
- ),
468
+ const speculosAddress = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
469
+ const response = await axios.get<ResponseData>(
470
+ `${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=true`,
521
471
  );
522
472
  return response.data.events.map(event => event.text).join("");
523
473
  }
524
474
 
525
475
  async function fetchAllEvents(speculosApiPort: number): Promise<string[]> {
526
- const speculosAddress = getSpeculosAddress();
527
- const response = await retryAxiosRequest(() =>
528
- axios.get<ResponseData>(
529
- `${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=false`,
530
- ),
476
+ const speculosAddress = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
477
+ const response = await axios.get<ResponseData>(
478
+ `${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=false`,
531
479
  );
532
480
  return response.data.events.map(event => event.text);
533
481
  }
534
482
 
535
483
  export async function pressRightButton(): Promise<void> {
536
484
  const speculosApiPort = getEnv("SPECULOS_API_PORT");
537
- const speculosAddress = getSpeculosAddress();
538
- await retryAxiosRequest(() =>
539
- axios.post(`${speculosAddress}:${speculosApiPort}/button/right`, {
540
- action: "press-and-release",
541
- }),
542
- );
485
+ const speculosAddress = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
486
+ await axios.post(`${speculosAddress}:${speculosApiPort}/button/right`, {
487
+ action: "press-and-release",
488
+ });
543
489
  }
544
490
 
545
491
  export function containsSubstringInEvent(targetString: string, events: string[]): boolean {
@@ -557,14 +503,12 @@ export function containsSubstringInEvent(targetString: string, events: string[])
557
503
  }
558
504
 
559
505
  export async function takeScreenshot(port?: number): Promise<Buffer | undefined> {
560
- const speculosAddress = getSpeculosAddress();
506
+ const speculosAddress = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
561
507
  const speculosApiPort = port ?? getEnv("SPECULOS_API_PORT");
562
508
  try {
563
- const response = await retryAxiosRequest(() =>
564
- axios.get(`${speculosAddress}:${speculosApiPort}/screenshot`, {
565
- responseType: "arraybuffer",
566
- }),
567
- );
509
+ const response = await axios.get(`${speculosAddress}:${speculosApiPort}/screenshot`, {
510
+ responseType: "arraybuffer",
511
+ });
568
512
  return response.data;
569
513
  } catch (error) {
570
514
  console.error("Error downloading speculos screenshot:", error);
@@ -61,44 +61,22 @@ async function githubApiRequest<T = unknown>({
61
61
  function waitForSpeculosReady(url: string, { interval = 2000, timeout = 300_000 } = {}) {
62
62
  return new Promise((resolve, reject) => {
63
63
  const startTime = Date.now();
64
- let currentRequest: ReturnType<typeof https.get> | null = null;
65
-
66
- function cleanup() {
67
- if (currentRequest) {
68
- currentRequest.destroy();
69
- currentRequest = null;
70
- }
71
- }
72
64
 
73
65
  function check() {
74
- cleanup();
75
-
76
- currentRequest = https.get(url, { timeout: 10000 }, res => {
77
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 400) {
78
- process.env.SPECULOS_ADDRESS = url;
79
- cleanup();
80
- console.warn(`Speculos is ready at ${url}`);
81
- resolve(true);
82
- } else {
83
- console.warn(`Speculos not ready yet, status: ${res.statusCode}`);
84
- retry();
85
- }
86
- });
87
-
88
- currentRequest.on("error", error => {
89
- console.error(`Request error: ${error.message}`);
90
- retry();
91
- });
92
-
93
- currentRequest.on("timeout", () => {
94
- console.error("Request timeout");
95
- retry();
96
- });
66
+ https
67
+ .get(url, res => {
68
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 400) {
69
+ process.env.SPECULOS_ADDRESS = url;
70
+ resolve(true);
71
+ } else {
72
+ retry();
73
+ }
74
+ })
75
+ .on("error", retry);
97
76
  }
98
77
 
99
78
  function retry() {
100
79
  if (Date.now() - startTime >= timeout) {
101
- cleanup();
102
80
  reject(new Error(`Timeout: ${url} did not become available within ${timeout}ms`));
103
81
  } else {
104
82
  setTimeout(check, interval);