@onekeyfe/hd-core 1.2.0-alpha.53 → 1.2.0-alpha.54

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 (251) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +0 -78
  2. package/__tests__/DeviceCommands.test.ts +0 -45
  3. package/__tests__/DeviceEventRegistration.test.ts +0 -6
  4. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +3 -198
  5. package/__tests__/connectSettings.test.ts +47 -5
  6. package/__tests__/device-initialize-timeout.test.ts +56 -0
  7. package/__tests__/device-lifecycle-events.test.ts +3 -105
  8. package/__tests__/firmware-update/check-all-firmware-release.test.ts +175 -0
  9. package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
  10. package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
  11. package/__tests__/firmware-update/firmware-preparation-error.test.ts +27 -0
  12. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +200 -0
  13. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
  14. package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +294 -0
  15. package/__tests__/firmware-update/firmware-update-plan.test.ts +593 -0
  16. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +213 -0
  17. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +59 -31
  18. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +58 -0
  19. package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
  20. package/__tests__/get-device-state.test.ts +12 -132
  21. package/__tests__/homescreen.test.ts +1 -41
  22. package/__tests__/logBlockEvent.test.ts +1 -1
  23. package/__tests__/method-protocol-support.test.ts +0 -19
  24. package/__tests__/open-wallet-session.test.ts +33 -446
  25. package/__tests__/protocol-v2-unlock-policy.test.ts +35 -201
  26. package/__tests__/protocol-v2.test.ts +1034 -1378
  27. package/__tests__/protocolV2UiInteraction.test.ts +0 -63
  28. package/__tests__/public-pro2-api-boundary.test.ts +0 -1
  29. package/__tests__/search-devices.test.ts +3 -12
  30. package/dist/api/BaseMethod.d.ts +1 -3
  31. package/dist/api/BaseMethod.d.ts.map +1 -1
  32. package/dist/api/CheckAllFirmwareRelease.d.ts +1 -2
  33. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  34. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  35. package/dist/api/FirmwareUpdateV2.d.ts +11 -0
  36. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  37. package/dist/api/FirmwareUpdateV3.d.ts +7 -3
  38. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  39. package/dist/api/FirmwareUpdateV4.d.ts +25 -11
  40. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  41. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  42. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  43. package/dist/api/SearchDevices.d.ts.map +1 -1
  44. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  45. package/dist/api/device/DeviceUnlock.d.ts +2 -2
  46. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  47. package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
  48. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  49. package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
  50. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
  51. package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
  52. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
  53. package/dist/api/firmware/FirmwarePreparationError.d.ts +3 -0
  54. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +1 -0
  55. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +9 -0
  56. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  57. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
  58. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
  59. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +25 -0
  60. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
  61. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +32 -0
  62. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
  63. package/dist/api/firmware/getBinary.d.ts +7 -0
  64. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  65. package/dist/api/firmware/progressThrottle.d.ts +3 -0
  66. package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
  67. package/dist/api/firmware/updateBootloader.d.ts +2 -0
  68. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  69. package/dist/api/firmware/uploadFirmware.d.ts +9 -1
  70. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  71. package/dist/api/helpers/protocolV2FileWrite.d.ts +0 -2
  72. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  73. package/dist/api/index.d.ts +0 -2
  74. package/dist/api/index.d.ts.map +1 -1
  75. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  76. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  77. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  78. package/dist/core/deviceEventRegistration.d.ts +0 -2
  79. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  80. package/dist/core/index.d.ts.map +1 -1
  81. package/dist/data-manager/DataManager.d.ts +2 -4
  82. package/dist/data-manager/DataManager.d.ts.map +1 -1
  83. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  84. package/dist/device/Device.d.ts +6 -29
  85. package/dist/device/Device.d.ts.map +1 -1
  86. package/dist/device/DeviceCommands.d.ts +4 -4
  87. package/dist/device/DeviceCommands.d.ts.map +1 -1
  88. package/dist/device/DevicePool.d.ts.map +1 -1
  89. package/dist/events/device.d.ts +0 -4
  90. package/dist/events/device.d.ts.map +1 -1
  91. package/dist/events/logBlockEvent.d.ts.map +1 -1
  92. package/dist/events/ui-promise.d.ts +2 -4
  93. package/dist/events/ui-promise.d.ts.map +1 -1
  94. package/dist/events/ui-request.d.ts +2 -31
  95. package/dist/events/ui-request.d.ts.map +1 -1
  96. package/dist/events/ui-response.d.ts +2 -10
  97. package/dist/events/ui-response.d.ts.map +1 -1
  98. package/dist/index.d.ts +231 -214
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +3497 -2559
  101. package/dist/inject.d.ts +1 -6
  102. package/dist/inject.d.ts.map +1 -1
  103. package/dist/lowLevelInject.d.ts.map +1 -1
  104. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  105. package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
  106. package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
  107. package/dist/protocols/protocol-v2/uiInteraction.d.ts +4 -7
  108. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  109. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +3 -1
  110. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  111. package/dist/protocols/protocol-v2/unlockRetry.d.ts +10 -0
  112. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
  113. package/dist/protocols/protocol-v2/walletSession.d.ts +1 -5
  114. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  115. package/dist/topLevelInject.d.ts.map +1 -1
  116. package/dist/types/api/checkAllFirmwareRelease.d.ts +4 -2
  117. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  118. package/dist/types/api/deviceUnlock.d.ts +1 -5
  119. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  120. package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
  121. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  122. package/dist/types/api/export.d.ts +4 -2
  123. package/dist/types/api/export.d.ts.map +1 -1
  124. package/dist/types/api/firmwareUpdate.d.ts +70 -2
  125. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  126. package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
  127. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
  128. package/dist/types/api/firmwareUpdatePlan.d.ts +28 -0
  129. package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
  130. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
  131. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
  132. package/dist/types/api/index.d.ts +10 -7
  133. package/dist/types/api/index.d.ts.map +1 -1
  134. package/dist/types/api/protocolV2.d.ts +0 -3
  135. package/dist/types/api/protocolV2.d.ts.map +1 -1
  136. package/dist/types/device.d.ts.map +1 -1
  137. package/dist/types/params.d.ts +0 -1
  138. package/dist/types/params.d.ts.map +1 -1
  139. package/dist/types/settings.d.ts +13 -22
  140. package/dist/types/settings.d.ts.map +1 -1
  141. package/dist/utils/deviceFeaturesCompat.d.ts +1 -0
  142. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
  143. package/dist/utils/deviceFeaturesUtils.d.ts +0 -4
  144. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  145. package/dist/utils/homescreen.d.ts +0 -4
  146. package/dist/utils/homescreen.d.ts.map +1 -1
  147. package/dist/utils/index.d.ts +1 -1
  148. package/dist/utils/index.d.ts.map +1 -1
  149. package/dist/utils/patch.d.ts +1 -1
  150. package/dist/utils/patch.d.ts.map +1 -1
  151. package/dist/utils/pro2Wallpaper.d.ts +0 -10
  152. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  153. package/package.json +4 -4
  154. package/src/api/BaseMethod.ts +10 -8
  155. package/src/api/CheckAllFirmwareRelease.ts +57 -54
  156. package/src/api/FirmwareUpdate.ts +15 -7
  157. package/src/api/FirmwareUpdateV2.ts +316 -126
  158. package/src/api/FirmwareUpdateV3.ts +265 -63
  159. package/src/api/FirmwareUpdateV4.ts +965 -566
  160. package/src/api/GetPassphraseState.ts +1 -7
  161. package/src/api/OpenWalletSession.ts +17 -54
  162. package/src/api/SearchDevices.ts +1 -3
  163. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +11 -32
  164. package/src/api/device/DeviceUnlock.ts +3 -8
  165. package/src/api/device/DeviceUpdateBootloader.ts +122 -6
  166. package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
  167. package/src/api/firmware/FirmwareHostBinding.ts +100 -0
  168. package/src/api/firmware/FirmwarePreparationError.ts +12 -0
  169. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +83 -16
  170. package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
  171. package/src/api/firmware/FirmwareUpdatePlan.ts +772 -0
  172. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +415 -0
  173. package/src/api/firmware/progressThrottle.ts +44 -0
  174. package/src/api/firmware/updateBootloader.ts +19 -4
  175. package/src/api/firmware/uploadFirmware.ts +144 -39
  176. package/src/api/helpers/protocolV2FileWrite.ts +4 -11
  177. package/src/api/index.ts +0 -2
  178. package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -3
  179. package/src/api/protocol-v2/helpers.ts +0 -1
  180. package/src/core/deviceEventRegistration.ts +0 -4
  181. package/src/core/index.ts +83 -167
  182. package/src/data/messages/messages-protocol-v2.json +0 -25
  183. package/src/data-manager/DataManager.ts +38 -67
  184. package/src/data-manager/connectSettings.ts +11 -0
  185. package/src/device/Device.ts +42 -258
  186. package/src/device/DeviceCommands.ts +1 -7
  187. package/src/device/DevicePool.ts +2 -7
  188. package/src/events/device.ts +0 -4
  189. package/src/events/logBlockEvent.ts +0 -1
  190. package/src/events/ui-promise.ts +2 -4
  191. package/src/events/ui-request.ts +2 -36
  192. package/src/events/ui-response.ts +2 -12
  193. package/src/index.ts +5 -0
  194. package/src/inject.ts +24 -60
  195. package/src/lowLevelInject.ts +8 -7
  196. package/src/protocols/protocol-v2/features.ts +3 -10
  197. package/src/protocols/protocol-v2/lockedError.ts +10 -0
  198. package/src/protocols/protocol-v2/uiInteraction.ts +6 -46
  199. package/src/protocols/protocol-v2/unlockPolicy.ts +105 -1
  200. package/src/protocols/protocol-v2/unlockRetry.ts +109 -0
  201. package/src/protocols/protocol-v2/walletSession.ts +30 -180
  202. package/src/topLevelInject.ts +8 -7
  203. package/src/types/api/checkAllFirmwareRelease.ts +4 -2
  204. package/src/types/api/deviceUnlock.ts +1 -12
  205. package/src/types/api/deviceUpdateBootloader.ts +6 -0
  206. package/src/types/api/export.ts +18 -1
  207. package/src/types/api/firmwareUpdate.ts +76 -3
  208. package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
  209. package/src/types/api/firmwareUpdatePlan.ts +38 -0
  210. package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
  211. package/src/types/api/index.ts +14 -13
  212. package/src/types/api/protocolV2.ts +0 -13
  213. package/src/types/device.ts +0 -3
  214. package/src/types/params.ts +1 -7
  215. package/src/types/settings.ts +13 -42
  216. package/src/utils/deviceFeaturesCompat.ts +6 -0
  217. package/src/utils/deviceFeaturesUtils.ts +0 -8
  218. package/src/utils/homescreen.ts +6 -32
  219. package/src/utils/index.ts +1 -6
  220. package/src/utils/pro2Wallpaper.ts +8 -35
  221. package/__tests__/deviceUploadNft.test.ts +0 -293
  222. package/__tests__/pro2Nft.test.ts +0 -108
  223. package/__tests__/protocol-binding.test.ts +0 -89
  224. package/__tests__/protocol-v2-resources.test.ts +0 -284
  225. package/__tests__/protocol-v2-ui-lifecycle.test.ts +0 -91
  226. package/__tests__/uiProgressThrottle.test.ts +0 -74
  227. package/__tests__/uiPromiseRegistry.test.ts +0 -86
  228. package/dist/api/DetectDeviceConnectProtocol.d.ts +0 -7
  229. package/dist/api/DetectDeviceConnectProtocol.d.ts.map +0 -1
  230. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +0 -31
  231. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +0 -1
  232. package/dist/core/uiPromiseRegistry.d.ts +0 -4
  233. package/dist/core/uiPromiseRegistry.d.ts.map +0 -1
  234. package/dist/protocols/protocol-v2/resources.d.ts +0 -30
  235. package/dist/protocols/protocol-v2/resources.d.ts.map +0 -1
  236. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -22
  237. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +0 -1
  238. package/dist/types/api/detectDeviceConnectProtocol.d.ts +0 -4
  239. package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +0 -1
  240. package/dist/utils/pro2Nft.d.ts +0 -31
  241. package/dist/utils/pro2Nft.d.ts.map +0 -1
  242. package/dist/utils/uiProgressThrottle.d.ts +0 -3
  243. package/dist/utils/uiProgressThrottle.d.ts.map +0 -1
  244. package/src/api/DetectDeviceConnectProtocol.ts +0 -18
  245. package/src/api/protocol-v2/DeviceUploadNft.ts +0 -189
  246. package/src/core/uiPromiseRegistry.ts +0 -41
  247. package/src/protocols/protocol-v2/resources.ts +0 -359
  248. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +0 -118
  249. package/src/types/api/detectDeviceConnectProtocol.ts +0 -7
  250. package/src/utils/pro2Nft.ts +0 -142
  251. package/src/utils/uiProgressThrottle.ts +0 -63
@@ -1,4 +1,3 @@
1
- import { HardwareErrorCode } from '@onekeyfe/hd-shared';
2
1
  import { TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
3
2
 
4
3
  import { initConnector, initCore } from '../src/core';
@@ -96,25 +95,7 @@ describe('public device lifecycle events', () => {
96
95
  expect(messages.filter(message => message.type === DEVICE.DISCONNECT)).toHaveLength(1);
97
96
  });
98
97
 
99
- test('uses a verified cached protocol as a strict expected protocol', async () => {
100
- jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
101
- const device = Device.fromDescriptor({
102
- id: 'ble-id',
103
- path: 'ble-id',
104
- commType: 'ble',
105
- protocolType: 'V1',
106
- } as never);
107
- const acquire = jest.fn().mockResolvedValue({ uuid: 'ble-id', protocolType: 'V1' });
108
- device.deviceConnector = { acquire } as never;
109
-
110
- await device.acquire();
111
-
112
- expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, 'V1', undefined);
113
- expect(device.getProtocol()).toBe('V1');
114
- expect(device.originalDescriptor.protocolType).toBe('V1');
115
- });
116
-
117
- test('bypasses a cached protocol only for explicit active detection', async () => {
98
+ test('uses a cached protocol as a fallback-capable acquire hint', async () => {
118
99
  jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
119
100
  const device = Device.fromDescriptor({
120
101
  id: 'ble-id',
@@ -125,96 +106,13 @@ describe('public device lifecycle events', () => {
125
106
  const acquire = jest.fn().mockResolvedValue({ uuid: 'ble-id', protocolType: 'V2' });
126
107
  device.deviceConnector = { acquire } as never;
127
108
 
128
- await device.acquire(undefined, { forceProtocolDetection: true });
109
+ await device.acquire();
129
110
 
130
- expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, undefined, undefined);
111
+ expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, undefined, 'V1');
131
112
  expect(device.getProtocol()).toBe('V2');
132
113
  expect(device.originalDescriptor.protocolType).toBe('V2');
133
114
  });
134
115
 
135
- test('does not reuse a stale protocol when active detection returns no protocol', async () => {
136
- jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
137
- const device = Device.fromDescriptor({
138
- id: 'ble-id',
139
- path: 'ble-id',
140
- commType: 'ble',
141
- protocolType: 'V1',
142
- } as never);
143
- const acquire = jest.fn().mockResolvedValue({ uuid: 'ble-id' });
144
- const release = jest.fn().mockResolvedValue(undefined);
145
- device.deviceConnector = { acquire, release } as never;
146
- await expect(
147
- device.acquire(undefined, {
148
- forceProtocolDetection: true,
149
- throwOnRunPromiseError: true,
150
- })
151
- ).rejects.toMatchObject({ errorCode: HardwareErrorCode.RuntimeError });
152
- expect(device.originalDescriptor.protocolType).toBe('V1');
153
- expect(device.hasDeviceAcquire()).toBe(false);
154
- expect(release).toHaveBeenCalledWith('ble-id', false);
155
- });
156
-
157
- test('actively reacquires an already connected device without initializing it', async () => {
158
- jest.spyOn(DataManager, 'getSettings').mockReturnValue('webusb' as never);
159
- const device = Device.fromDescriptor({
160
- id: 'usb-device',
161
- path: 'usb-device',
162
- session: 'old-session',
163
- protocolType: 'V1',
164
- } as never);
165
- device.mainId = 'old-session';
166
- device.commands = { disposed: false } as never;
167
- const release = jest.spyOn(device, 'release').mockImplementation(() => {
168
- device.mainId = null;
169
- device.originalDescriptor.session = null;
170
- device.commands.disposed = true;
171
- return Promise.resolve();
172
- });
173
- const acquire = jest.spyOn(device, 'acquire').mockImplementation(() => {
174
- device.mainId = 'new-session';
175
- device.originalDescriptor.session = 'new-session';
176
- device.originalDescriptor.protocolType = 'V2';
177
- device.commands.disposed = false;
178
- return Promise.resolve();
179
- });
180
- const initialize = jest.spyOn(device, 'initialize').mockResolvedValue(undefined);
181
-
182
- await device.run(() => Promise.resolve(undefined), {
183
- forceProtocolDetection: true,
184
- skipInitialize: true,
185
- });
186
-
187
- expect(release).toHaveBeenCalled();
188
- expect(acquire).toHaveBeenCalledWith(undefined, {
189
- forceProtocolDetection: true,
190
- });
191
- expect(initialize).not.toHaveBeenCalled();
192
- expect(device.getProtocol()).toBe('V2');
193
- });
194
-
195
- test('keeps the freshly probed React Native BLE session until the call completes', async () => {
196
- jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
197
- const device = Device.fromDescriptor({
198
- id: 'ble-device',
199
- path: 'ble-device',
200
- commType: 'ble',
201
- protocolType: 'V1',
202
- } as never);
203
- device.mainId = 'ble-device';
204
- device.commands = { disposed: false } as never;
205
- (device as unknown as { deviceAcquired: boolean }).deviceAcquired = true;
206
- const release = jest.spyOn(device, 'release').mockResolvedValue(undefined);
207
- const run = jest.fn().mockResolvedValue(undefined);
208
-
209
- await device.run(run, {
210
- forceProtocolDetection: true,
211
- skipInitialize: true,
212
- });
213
-
214
- expect(run).toHaveBeenCalledTimes(1);
215
- expect(release).toHaveBeenCalledTimes(1);
216
- });
217
-
218
116
  test('keeps an explicit connectProtocol as a strict expected protocol', async () => {
219
117
  jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
220
118
  const device = Device.fromDescriptor({
@@ -0,0 +1,175 @@
1
+ import { EDeviceType, EFirmwareType, ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
+
3
+ import CheckAllFirmwareRelease from '../../src/api/CheckAllFirmwareRelease';
4
+ import { buildFirmwareUpdatePlan } from '../../src/api/firmware/FirmwareUpdatePlan';
5
+ import {
6
+ getBleFirmwareReleaseInfo,
7
+ getBootloaderReleaseInfo,
8
+ getFirmwareReleaseInfo,
9
+ } from '../../src/api/firmware/releaseHelper';
10
+
11
+ jest.mock('../../src/data/config', () => ({
12
+ getSDKVersion: jest.fn(() => '1.0.0'),
13
+ DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
14
+ }));
15
+
16
+ jest.mock('../../src/api/firmware/FirmwareUpdatePlan', () => ({
17
+ buildFirmwareUpdatePlan: jest.fn(),
18
+ validateFirmwareUpdatePlanForceTargets: jest.fn(value => value ?? []),
19
+ }));
20
+
21
+ jest.mock('../../src/api/firmware/releaseHelper', () => ({
22
+ getBleFirmwareReleaseInfo: jest.fn(),
23
+ getBootloaderReleaseInfo: jest.fn(),
24
+ getFirmwareReleaseInfo: jest.fn(),
25
+ }));
26
+
27
+ const mockBuildFirmwareUpdatePlan = buildFirmwareUpdatePlan as jest.MockedFunction<
28
+ typeof buildFirmwareUpdatePlan
29
+ >;
30
+ const mockGetBleFirmwareReleaseInfo = getBleFirmwareReleaseInfo as jest.MockedFunction<
31
+ typeof getBleFirmwareReleaseInfo
32
+ >;
33
+ const mockGetBootloaderReleaseInfo = getBootloaderReleaseInfo as jest.MockedFunction<
34
+ typeof getBootloaderReleaseInfo
35
+ >;
36
+ const mockGetFirmwareReleaseInfo = getFirmwareReleaseInfo as jest.MockedFunction<
37
+ typeof getFirmwareReleaseInfo
38
+ >;
39
+
40
+ const noUpdate = {
41
+ status: 'valid' as const,
42
+ release: undefined,
43
+ };
44
+
45
+ const createMethod = (serialNo = 'device-id') => {
46
+ const method = new CheckAllFirmwareRelease({
47
+ id: 1,
48
+ payload: {
49
+ method: 'checkAllFirmwareRelease',
50
+ platform: 'native',
51
+ },
52
+ });
53
+ method.init();
54
+ method.device = {
55
+ isProtocolV2: jest.fn(() => false),
56
+ features: {
57
+ deviceType: EDeviceType.Classic1s,
58
+ serialNo,
59
+ firmwareType: EFirmwareType.Universal,
60
+ firmwareVersion: '1.0.0',
61
+ bootloaderVersion: '1.0.0',
62
+ },
63
+ } as typeof method.device;
64
+ return method;
65
+ };
66
+
67
+ const createMethodWithForceTargets = () => {
68
+ const method = createMethod();
69
+ method.payload = {
70
+ ...method.payload,
71
+ forceUpdateTargets: ['firmware', 'resource'],
72
+ };
73
+ return method;
74
+ };
75
+
76
+ describe('CheckAllFirmwareRelease', () => {
77
+ beforeEach(() => {
78
+ jest.clearAllMocks();
79
+ mockGetFirmwareReleaseInfo.mockReturnValue(noUpdate);
80
+ mockGetBootloaderReleaseInfo.mockReturnValue(noUpdate);
81
+ mockGetBleFirmwareReleaseInfo.mockReturnValue(noUpdate);
82
+ });
83
+
84
+ test('keeps release information available when an optional Plan cannot be built', async () => {
85
+ const firmware = {
86
+ status: 'outdated' as const,
87
+ release: {
88
+ url: 'https://firmware.onekey.so/classic/firmware.bin',
89
+ version: [3, 0, 0],
90
+ },
91
+ };
92
+ mockGetFirmwareReleaseInfo.mockReturnValue(firmware);
93
+ mockBuildFirmwareUpdatePlan.mockImplementation(() => {
94
+ throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Plan cannot be built', {
95
+ firmwareUpdateCode: 'FirmwarePlanInvalid',
96
+ });
97
+ });
98
+
99
+ await expect(createMethod('').run()).resolves.toEqual(
100
+ expect.objectContaining({
101
+ firmware,
102
+ bootloader: noUpdate,
103
+ ble: noUpdate,
104
+ firmwareUpdatePlan: undefined,
105
+ })
106
+ );
107
+ });
108
+
109
+ test('returns an optional Plan when the builder succeeds', async () => {
110
+ const plan = {
111
+ schemaVersion: 2 as const,
112
+ planDigest: 'a'.repeat(64),
113
+ executor: 'v3' as const,
114
+ deviceIdentity: 'device-id',
115
+ deviceModel: EDeviceType.Classic1s,
116
+ firmwareType: EFirmwareType.Universal,
117
+ platform: 'native' as const,
118
+ artifacts: [],
119
+ targetsToUpdate: [],
120
+ };
121
+ mockBuildFirmwareUpdatePlan.mockReturnValue(plan);
122
+
123
+ await expect(createMethod().run()).resolves.toEqual(
124
+ expect.objectContaining({
125
+ firmwareUpdatePlan: plan,
126
+ })
127
+ );
128
+ });
129
+
130
+ test('passes host-selected update targets to the Plan builder', async () => {
131
+ mockBuildFirmwareUpdatePlan.mockReturnValue({
132
+ schemaVersion: 2,
133
+ planDigest: 'a'.repeat(64),
134
+ executor: 'v2',
135
+ deviceIdentity: 'device-id',
136
+ deviceModel: EDeviceType.Classic1s,
137
+ firmwareType: EFirmwareType.Universal,
138
+ platform: 'native',
139
+ artifacts: [],
140
+ targetsToUpdate: [],
141
+ });
142
+
143
+ await createMethodWithForceTargets().run();
144
+
145
+ expect(mockBuildFirmwareUpdatePlan).toHaveBeenCalledWith(
146
+ expect.objectContaining({
147
+ forceUpdateTargets: ['firmware', 'resource'],
148
+ })
149
+ );
150
+ });
151
+
152
+ test('does not hide a Plan failure for an explicitly forced target', async () => {
153
+ const planError = ERRORS.TypedError(
154
+ HardwareErrorCode.RuntimeError,
155
+ 'Forced firmware target is unavailable',
156
+ {
157
+ firmwareUpdateCode: 'FirmwarePlanInvalid',
158
+ }
159
+ );
160
+ mockBuildFirmwareUpdatePlan.mockImplementation(() => {
161
+ throw planError;
162
+ });
163
+
164
+ await expect(createMethodWithForceTargets().run()).rejects.toBe(planError);
165
+ });
166
+
167
+ test('does not hide unexpected Plan builder failures', async () => {
168
+ const unexpectedError = new Error('unexpected builder failure');
169
+ mockBuildFirmwareUpdatePlan.mockImplementation(() => {
170
+ throw unexpectedError;
171
+ });
172
+
173
+ await expect(createMethod().run()).rejects.toBe(unexpectedError);
174
+ });
175
+ });
@@ -0,0 +1,119 @@
1
+ import {
2
+ MAX_FIRMWARE_ARTIFACT_READ_BYTES,
3
+ openFirmwareByteSource,
4
+ writeFirmwareByteSource,
5
+ } from '../../src/api/firmware/FirmwareArtifactSource';
6
+
7
+ import type { FirmwareArtifactReader } from '../../src/types/api/firmwareUpdate';
8
+
9
+ const artifact = {
10
+ artifactRef: `fw:${'a'.repeat(64)}`,
11
+ size: 6,
12
+ sha256: 'b'.repeat(64),
13
+ };
14
+
15
+ const createReader = () => {
16
+ const open = jest.fn(() => Promise.resolve({ readerId: 'reader-1', size: artifact.size }));
17
+ const read = jest.fn(({ offset, length }: { readerId: string; offset: number; length: number }) =>
18
+ Promise.resolve({
19
+ data: Uint8Array.from([1, 2, 3, 4, 5, 6]).slice(offset, offset + length).buffer,
20
+ bytesRead: length,
21
+ eof: offset + length === artifact.size,
22
+ })
23
+ );
24
+ const close = jest.fn(() => Promise.resolve());
25
+ const reader: FirmwareArtifactReader = { open, read, close };
26
+ return { reader, open, read, close };
27
+ };
28
+
29
+ describe('FirmwareArtifactSource', () => {
30
+ it('reads an opaque artifact through bounded sequential reads', async () => {
31
+ const { reader, close } = createReader();
32
+ const source = await openFirmwareByteSource({ artifact, reader });
33
+ if (!source) {
34
+ throw new Error('Expected a firmware byte source');
35
+ }
36
+
37
+ const writes: Array<{ offset: number; data: number[] }> = [];
38
+ await writeFirmwareByteSource({
39
+ source,
40
+ chunkSize: 4,
41
+ write: ({ data, sourceOffset, length }) => {
42
+ writes.push({
43
+ offset: sourceOffset,
44
+ data: Array.from(new Uint8Array(data)),
45
+ });
46
+ return Promise.resolve(length);
47
+ },
48
+ });
49
+ await source.close();
50
+
51
+ expect(writes).toEqual([
52
+ { offset: 0, data: [1, 2, 3, 4] },
53
+ { offset: 4, data: [5, 6] },
54
+ ]);
55
+ expect(close).toHaveBeenCalledWith({ readerId: 'reader-1' });
56
+ });
57
+
58
+ it('rejects a reader whose opened size differs from the receipt', async () => {
59
+ const { reader, open, close } = createReader();
60
+ open.mockResolvedValue({
61
+ readerId: 'reader-1',
62
+ size: artifact.size + 1,
63
+ });
64
+
65
+ await expect(openFirmwareByteSource({ artifact, reader })).rejects.toMatchObject({
66
+ params: {
67
+ firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch',
68
+ },
69
+ });
70
+ expect(close).toHaveBeenCalledWith({ readerId: 'reader-1' });
71
+ });
72
+
73
+ it('rejects paths and over-limit reads before invoking the host', async () => {
74
+ const { reader, read } = createReader();
75
+ await expect(
76
+ openFirmwareByteSource({
77
+ artifact: { ...artifact, artifactRef: '/tmp/firmware.bin' },
78
+ reader,
79
+ })
80
+ ).rejects.toMatchObject({
81
+ params: {
82
+ firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch',
83
+ },
84
+ });
85
+
86
+ const source = await openFirmwareByteSource({ artifact, reader });
87
+ if (!source) {
88
+ throw new Error('Expected a firmware byte source');
89
+ }
90
+ await expect(
91
+ writeFirmwareByteSource({
92
+ source,
93
+ chunkSize: MAX_FIRMWARE_ARTIFACT_READ_BYTES + 1,
94
+ write: ({ length }) => Promise.resolve(length),
95
+ })
96
+ ).rejects.toMatchObject({
97
+ params: {
98
+ firmwareUpdateCode: 'FirmwareArtifactReadTooLarge',
99
+ },
100
+ });
101
+ expect(read).not.toHaveBeenCalled();
102
+ await source.close();
103
+ });
104
+
105
+ it('closes stale readers when open returns invalid metadata', async () => {
106
+ const { reader, open, close } = createReader();
107
+ open.mockResolvedValue({
108
+ readerId: '',
109
+ size: artifact.size,
110
+ });
111
+
112
+ await expect(openFirmwareByteSource({ artifact, reader })).rejects.toMatchObject({
113
+ params: {
114
+ firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch',
115
+ },
116
+ });
117
+ expect(close).not.toHaveBeenCalled();
118
+ });
119
+ });
@@ -0,0 +1,70 @@
1
+ import {
2
+ getFirmwareUpdateHostBindingGeneration,
3
+ registerFirmwareUpdateHostBinding,
4
+ resolveFirmwareUpdateHostBinding,
5
+ unregisterFirmwareUpdateHostBinding,
6
+ } from '../../src/api/firmware/FirmwareHostBinding';
7
+
8
+ const createBinding = () => ({
9
+ artifactReader: {
10
+ open: jest.fn(() => Promise.resolve({ readerId: 'reader-1', size: 4 })),
11
+ read: jest.fn(() =>
12
+ Promise.resolve({
13
+ data: new ArrayBuffer(4),
14
+ bytesRead: 4,
15
+ eof: true,
16
+ })
17
+ ),
18
+ close: jest.fn(() => Promise.resolve()),
19
+ },
20
+ });
21
+
22
+ describe('firmware host binding generation', () => {
23
+ afterEach(() => {
24
+ unregisterFirmwareUpdateHostBinding();
25
+ });
26
+
27
+ test('invalidates callbacks from a replaced generation', async () => {
28
+ const staleBinding = createBinding();
29
+ const staleGeneration = registerFirmwareUpdateHostBinding(staleBinding);
30
+ const stale = resolveFirmwareUpdateHostBinding(staleGeneration);
31
+ const activeGeneration = registerFirmwareUpdateHostBinding(createBinding());
32
+
33
+ expect(activeGeneration).toBeGreaterThan(staleGeneration);
34
+ expect(getFirmwareUpdateHostBindingGeneration()).toBe(activeGeneration);
35
+ await expect(
36
+ stale.artifactReader.read({
37
+ readerId: 'reader-1',
38
+ offset: 0,
39
+ length: 4,
40
+ })
41
+ ).rejects.toMatchObject({
42
+ params: {
43
+ firmwareUpdateCode: 'FirmwareArtifactReaderInvalid',
44
+ },
45
+ });
46
+ expect(unregisterFirmwareUpdateHostBinding(staleGeneration)).toBe(false);
47
+ expect(getFirmwareUpdateHostBindingGeneration()).toBe(activeGeneration);
48
+ });
49
+
50
+ test('closes an artifact opened during a generation race', async () => {
51
+ const binding = createBinding();
52
+ binding.artifactReader.open.mockImplementationOnce(() => {
53
+ registerFirmwareUpdateHostBinding(createBinding());
54
+ return Promise.resolve({ readerId: 'stale-reader', size: 4 });
55
+ });
56
+ const generation = registerFirmwareUpdateHostBinding(binding);
57
+ const guarded = resolveFirmwareUpdateHostBinding(generation);
58
+
59
+ await expect(
60
+ guarded.artifactReader.open({ artifactRef: `fw:${'a'.repeat(64)}` })
61
+ ).rejects.toMatchObject({
62
+ params: {
63
+ firmwareUpdateCode: 'FirmwareArtifactReaderInvalid',
64
+ },
65
+ });
66
+ expect(binding.artifactReader.close).toHaveBeenCalledWith({
67
+ readerId: 'stale-reader',
68
+ });
69
+ });
70
+ });
@@ -0,0 +1,27 @@
1
+ import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
+
3
+ import { normalizeFirmwarePreparationError } from '../../src/api/firmware/FirmwarePreparationError';
4
+
5
+ describe('normalizeFirmwarePreparationError', () => {
6
+ test('preserves structured firmware invariant errors', () => {
7
+ const error = ERRORS.TypedError(
8
+ HardwareErrorCode.RuntimeError,
9
+ 'Firmware must be prepared by the external firmware host',
10
+ {
11
+ firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
12
+ artifactName: 'firmware',
13
+ }
14
+ );
15
+
16
+ expect(normalizeFirmwarePreparationError(error)).toBe(error);
17
+ });
18
+
19
+ test('wraps ordinary preparation failures as firmware download errors', () => {
20
+ const error = normalizeFirmwarePreparationError(new Error('request failed'));
21
+
22
+ expect(error).toMatchObject({
23
+ errorCode: HardwareErrorCode.FirmwareUpdateDownloadFailed,
24
+ message: 'request failed',
25
+ });
26
+ });
27
+ });