@onekeyfe/hd-core 1.2.0-alpha.111 → 1.2.0-alpha.112

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 (32) hide show
  1. package/__tests__/DeviceCommands.test.ts +2 -2
  2. package/__tests__/device-lifecycle-events.test.ts +1 -1
  3. package/__tests__/device-state-mapper.test.ts +4 -4
  4. package/__tests__/device-utils.test.ts +1 -1
  5. package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +36 -89
  6. package/__tests__/get-device-state.test.ts +8 -8
  7. package/__tests__/protocol-v2-resources.test.ts +20 -0
  8. package/__tests__/protocol-v2.test.ts +219 -240
  9. package/dist/api/FirmwareUpdateV4.d.ts +0 -3
  10. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  11. package/dist/api/protocol-v2/DeviceInfoGet.d.ts +1 -1
  12. package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
  13. package/dist/index.d.ts +5 -20
  14. package/dist/index.js +133 -214
  15. package/dist/protocols/protocol-v2/features.d.ts +4 -4
  16. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  17. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -1
  18. package/dist/types/settings.d.ts +4 -19
  19. package/dist/types/settings.d.ts.map +1 -1
  20. package/dist/utils/patch.d.ts +1 -1
  21. package/dist/utils/patch.d.ts.map +1 -1
  22. package/package.json +4 -4
  23. package/src/api/FirmwareUpdateV4.ts +85 -178
  24. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
  25. package/src/api/protocol-v2/DeviceInfoGet.ts +3 -3
  26. package/src/data/messages/messages-protocol-v2.json +31 -14
  27. package/src/device/DeviceStateMapper.ts +15 -15
  28. package/src/deviceProfile/buildDeviceFeatures.ts +3 -3
  29. package/src/protocols/protocol-v2/features.ts +6 -6
  30. package/src/protocols/protocol-v2/resources.ts +10 -49
  31. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +1 -0
  32. package/src/types/settings.ts +4 -19
@@ -193,7 +193,7 @@ describe('DeviceCommands failure mapping', () => {
193
193
  Device_type: 7,
194
194
  hardware_version: '1.0.0',
195
195
  },
196
- fw: {
196
+ main_mcu: {
197
197
  application: {
198
198
  version: '5.0.0',
199
199
  build_id: '20260811',
@@ -218,7 +218,7 @@ describe('DeviceCommands failure mapping', () => {
218
218
  Device_type: 7,
219
219
  hardware_version: '1.0.0',
220
220
  },
221
- fw: {
221
+ main_mcu: {
222
222
  application: {
223
223
  version: '5.0.0',
224
224
  build_id: '20260811',
@@ -353,7 +353,7 @@ describe('public device lifecycle events', () => {
353
353
  message: {
354
354
  protocol_version: 2,
355
355
  hw: { Device_type: protocolV2DeviceType, serial_no: 'SERIAL-001' },
356
- fw: { application: { version: '5.0.0' } },
356
+ main_mcu: { application: { version: '5.0.0' } },
357
357
  },
358
358
  };
359
359
  }
@@ -115,7 +115,7 @@ describe('DeviceStateMapper', () => {
115
115
  {
116
116
  protocol_version: 2,
117
117
  hw: { Device_type: DeviceType.PRO2, serial_no: 'SERIAL-1' },
118
- fw: {
118
+ main_mcu: {
119
119
  application: { version: '5.0.0', build_id: 'p1-build', hash: [0x01, 0x02] },
120
120
  application_data: { version: '5.0.1', build_id: 'p2-build', hash: [0x03, 0x04] },
121
121
  bootloader: { version: '2.0.0' },
@@ -188,7 +188,7 @@ describe('DeviceStateMapper', () => {
188
188
  {
189
189
  protocol_version: 2,
190
190
  hw: { serial_no: 'SERIAL-NORMAL' },
191
- fw: {
191
+ main_mcu: {
192
192
  application: { version: '5.0.0' },
193
193
  bootloader: { version: '2.0.0' },
194
194
  },
@@ -214,7 +214,7 @@ describe('DeviceStateMapper', () => {
214
214
  'bootloader',
215
215
  {
216
216
  hw: { serial_no: 'SERIAL-BOOT' },
217
- fw: { bootloader: { version: '2.0.0' } },
217
+ main_mcu: { bootloader: { version: '2.0.0' } },
218
218
  se1: {},
219
219
  },
220
220
  ],
@@ -222,7 +222,7 @@ describe('DeviceStateMapper', () => {
222
222
  'romloader',
223
223
  {
224
224
  hw: { serial_no: 'SERIAL-ROM' },
225
- fw: {
225
+ main_mcu: {
226
226
  romloader: { version: '1.0.0' },
227
227
  bootloader: { version: '2.0.0' },
228
228
  },
@@ -89,7 +89,7 @@ describe('device feature selectors', () => {
89
89
  const features = buildProtocolV2FeaturesPayload({
90
90
  deviceInfo: {
91
91
  hw: { Device_type: DeviceType.PRO2, serial_no: 'P2-001' },
92
- fw: {
92
+ main_mcu: {
93
93
  application: { version: '5.0.0' },
94
94
  bootloader: { version: '2.0.0' },
95
95
  romloader: { version: '1.0.0' },
@@ -1,7 +1,6 @@
1
- import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
1
+ import { HardwareErrorCode } from '@onekeyfe/hd-shared';
2
2
 
3
3
  import FirmwareUpdateV4 from '../../src/api/FirmwareUpdateV4';
4
- import { DataManager } from '../../src/data-manager';
5
4
 
6
5
  import type { Device } from '../../src/device/Device';
7
6
 
@@ -11,19 +10,11 @@ jest.mock('../../src/data/config', () => ({
11
10
  }));
12
11
 
13
12
  describe('FirmwareUpdateV4 install polling', () => {
14
- let getSettingsSpy: jest.SpyInstance;
15
-
16
- beforeEach(() => {
17
- getSettingsSpy = jest
18
- .spyOn(DataManager, 'getSettings')
19
- .mockReturnValue('react-native' as never);
20
- });
21
-
22
13
  afterEach(() => {
23
14
  jest.restoreAllMocks();
24
15
  });
25
16
 
26
- test('polls status instead of replaying install after React Native BLE releases', async () => {
17
+ test('uses Stage, an empty write-only Request, then status polling', async () => {
27
18
  const method = new FirmwareUpdateV4({
28
19
  id: 1,
29
20
  payload: {
@@ -34,8 +25,9 @@ describe('FirmwareUpdateV4 install polling', () => {
34
25
  const targets = [{ target_id: 4, path: 'vol0:/application_p1.bin' }];
35
26
  const typedCall = jest
36
27
  .fn()
37
- .mockRejectedValueOnce(new Error('React Native BLE transport released'))
28
+ .mockResolvedValueOnce({ type: 'Success', message: {} })
38
29
  .mockResolvedValueOnce({
30
+ type: 'DeviceFirmwareUpdateStatus',
39
31
  message: {
40
32
  records: [
41
33
  {
@@ -46,15 +38,16 @@ describe('FirmwareUpdateV4 install polling', () => {
46
38
  ],
47
39
  },
48
40
  });
41
+ const call = jest.fn().mockResolvedValue({ type: 'WriteCompleted', message: {} });
49
42
 
50
43
  method.device = {
51
- getCommands: () => ({ typedCall }),
44
+ getCommands: () => ({ typedCall, call }),
52
45
  } as unknown as Device;
53
46
  method.postTipMessage = jest.fn();
54
47
  method.postProgressMessage = jest.fn();
55
48
 
56
49
  const firmwareUpdate = method as unknown as {
57
- protocolV2StartFirmwareUpdate: (params: { targets: typeof targets }) => Promise<unknown>;
50
+ protocolV2StartFirmwareUpdate: (params: { targets: typeof targets }) => Promise<void>;
58
51
  waitForProtocolV2FirmwareUpdateComplete: (value: typeof targets) => Promise<void>;
59
52
  reconnectProtocolV2Device: () => Promise<void>;
60
53
  verifyProtocolV2ReconnectIdentity: () => Promise<Record<string, never>>;
@@ -62,19 +55,20 @@ describe('FirmwareUpdateV4 install polling', () => {
62
55
  firmwareUpdate.reconnectProtocolV2Device = jest.fn().mockResolvedValue(undefined);
63
56
  firmwareUpdate.verifyProtocolV2ReconnectIdentity = jest.fn().mockResolvedValue({});
64
57
 
65
- await expect(
66
- firmwareUpdate.protocolV2StartFirmwareUpdate({ targets })
67
- ).resolves.toBeUndefined();
68
- await expect(
69
- firmwareUpdate.waitForProtocolV2FirmwareUpdateComplete(targets)
70
- ).resolves.toBeUndefined();
58
+ await firmwareUpdate.protocolV2StartFirmwareUpdate({ targets });
59
+ await firmwareUpdate.waitForProtocolV2FirmwareUpdateComplete(targets);
71
60
 
72
- expect(typedCall).toHaveBeenCalledTimes(2);
73
- expect(typedCall.mock.calls[0]?.[0]).toBe('DeviceFirmwareUpdateRequest');
61
+ expect(typedCall.mock.calls[0]).toEqual(['DeviceFirmwareUpdateStage', 'Success', { targets }]);
62
+ expect(call).toHaveBeenCalledWith(
63
+ 'DeviceFirmwareUpdateRequest',
64
+ {},
65
+ { returnAfterWrite: true }
66
+ );
74
67
  expect(typedCall.mock.calls[1]?.[0]).toBe('DeviceFirmwareUpdateStatusGet');
68
+ expect(call.mock.invocationCallOrder[0]).toBeLessThan(typedCall.mock.invocationCallOrder[1]);
75
69
  });
76
70
 
77
- test('does not treat an explicit workflow cancellation as an install reboot', async () => {
71
+ test('does not send Request when Stage is rejected', async () => {
78
72
  const method = new FirmwareUpdateV4({
79
73
  id: 1,
80
74
  payload: {
@@ -83,34 +77,25 @@ describe('FirmwareUpdateV4 install polling', () => {
83
77
  },
84
78
  });
85
79
  const targets = [{ target_id: 4, path: 'vol0:/application_p1.bin' }];
86
- const typedCall = jest.fn().mockRejectedValue(new Error('React Native BLE transport released'));
87
- const abortController = new AbortController();
88
- abortController.abort();
80
+ const typedCall = jest.fn().mockRejectedValue(new Error('stage rejected'));
81
+ const call = jest.fn();
89
82
 
90
- method.abortSignal = abortController.signal;
91
83
  method.device = {
92
- getCommands: () => ({ typedCall }),
84
+ getCommands: () => ({ typedCall, call }),
93
85
  } as unknown as Device;
94
86
 
95
87
  await expect(
96
88
  (
97
89
  method as unknown as {
98
- protocolV2StartFirmwareUpdate: (params: { targets: typeof targets }) => Promise<unknown>;
90
+ protocolV2StartFirmwareUpdate: (params: { targets: typeof targets }) => Promise<void>;
99
91
  }
100
92
  ).protocolV2StartFirmwareUpdate({ targets })
101
- ).rejects.toMatchObject({
102
- errorCode: HardwareErrorCode.CallQueueActionCancelled,
103
- });
93
+ ).rejects.toThrow('stage rejected');
104
94
 
105
- expect(typedCall).toHaveBeenCalledTimes(1);
95
+ expect(call).not.toHaveBeenCalled();
106
96
  });
107
97
 
108
- test.each([
109
- HardwareErrorCode.BleConnectedError,
110
- HardwareErrorCode.BleCharacteristicNotifyError,
111
- HardwareErrorCode.BleForceCleanRunPromise,
112
- HardwareErrorCode.BleDeviceDisconnected,
113
- ])('continues install polling after BLE interruption error %s', async errorCode => {
98
+ test('does not hide an explicit workflow cancellation during status polling', async () => {
114
99
  const method = new FirmwareUpdateV4({
115
100
  id: 1,
116
101
  payload: {
@@ -118,61 +103,23 @@ describe('FirmwareUpdateV4 install polling', () => {
118
103
  connectId: 'pro2-ble',
119
104
  },
120
105
  });
121
- const targets = [{ target_id: 4, path: 'vol0:/application_p1.bin' }];
122
- const typedCall = jest.fn().mockRejectedValue(ERRORS.TypedError(errorCode));
106
+ const abortController = new AbortController();
107
+ abortController.abort();
123
108
 
124
- method.device = {
125
- getCommands: () => ({ typedCall }),
126
- } as unknown as Device;
127
- method.postTipMessage = jest.fn();
128
- method.postProgressMessage = jest.fn();
109
+ method.abortSignal = abortController.signal;
129
110
 
130
111
  await expect(
131
112
  (
132
113
  method as unknown as {
133
- protocolV2StartFirmwareUpdate: (params: { targets: typeof targets }) => Promise<unknown>;
114
+ waitForProtocolV2FirmwareUpdateComplete: (
115
+ targets: Array<{ target_id: number; path: string }>
116
+ ) => Promise<void>;
134
117
  }
135
- ).protocolV2StartFirmwareUpdate({ targets })
136
- ).resolves.toBeUndefined();
137
-
138
- expect(typedCall).toHaveBeenCalledTimes(1);
118
+ ).waitForProtocolV2FirmwareUpdateComplete([
119
+ { target_id: 4, path: 'vol0:/application_p1.bin' },
120
+ ])
121
+ ).rejects.toMatchObject({
122
+ errorCode: HardwareErrorCode.CallQueueActionCancelled,
123
+ });
139
124
  });
140
-
141
- test.each([
142
- ['webusb', 'React Native BLE transport released'],
143
- ['react-native', 'Unrelated transport failure'],
144
- ])(
145
- 'requires both a BLE environment and an explicit transport release signal: %s / %s',
146
- async (env, message) => {
147
- getSettingsSpy.mockReturnValue(env);
148
- const method = new FirmwareUpdateV4({
149
- id: 1,
150
- payload: {
151
- method: 'firmwareUpdateV4',
152
- connectId: 'pro2-device',
153
- },
154
- });
155
- const targets = [{ target_id: 4, path: 'vol0:/application_p1.bin' }];
156
- const typedCall = jest.fn().mockRejectedValue(new Error(message));
157
-
158
- method.device = {
159
- getCommands: () => ({ typedCall }),
160
- } as unknown as Device;
161
- method.postTipMessage = jest.fn();
162
- method.postProgressMessage = jest.fn();
163
-
164
- await expect(
165
- (
166
- method as unknown as {
167
- protocolV2StartFirmwareUpdate: (params: {
168
- targets: typeof targets;
169
- }) => Promise<unknown>;
170
- }
171
- ).protocolV2StartFirmwareUpdate({ targets })
172
- ).rejects.toThrow(message);
173
-
174
- expect(method.postTipMessage).not.toHaveBeenCalled();
175
- expect(method.postProgressMessage).not.toHaveBeenCalled();
176
- }
177
- );
178
125
  });
@@ -123,7 +123,7 @@ describe('getDeviceState', () => {
123
123
  message: {
124
124
  protocol_version: 2,
125
125
  hw: { serial_no: 'SERIAL-1' },
126
- fw: { application: { version: '5.0.0' } },
126
+ main_mcu: { application: { version: '5.0.0' } },
127
127
  },
128
128
  };
129
129
  }
@@ -150,7 +150,7 @@ describe('getDeviceState', () => {
150
150
  message: {
151
151
  protocol_version: 2,
152
152
  hw: { serial_no: 'SERIAL-1' },
153
- fw: { application: { version: '5.0.0', hash: 'HASH-1' } },
153
+ main_mcu: { application: { version: '5.0.0', hash: 'HASH-1' } },
154
154
  },
155
155
  };
156
156
  }
@@ -182,7 +182,7 @@ describe('getDeviceState', () => {
182
182
  message: {
183
183
  protocol_version: 2,
184
184
  hw: { serial_no: 'SERIAL-1' },
185
- fw: { application: { version: '5.0.0' } },
185
+ main_mcu: { application: { version: '5.0.0' } },
186
186
  se1: { application: { version: '1.0.0' } },
187
187
  },
188
188
  });
@@ -230,7 +230,7 @@ describe('getDeviceState', () => {
230
230
  raw: {
231
231
  protocolV2DeviceInfo: {
232
232
  hw: { Device_type: protocolV2DeviceType, serial_no: 'SERIAL-1' },
233
- fw:
233
+ main_mcu:
234
234
  mode === 'romloader'
235
235
  ? { romloader: { version: '1.0.0' } }
236
236
  : { bootloader: { version: '1.0.0' } },
@@ -285,7 +285,7 @@ describe('getDeviceState', () => {
285
285
  return {
286
286
  message: {
287
287
  hw: { serial_no: 'SERIAL-1' },
288
- fw: { application: { version: '5.0.0' } },
288
+ main_mcu: { application: { version: '5.0.0' } },
289
289
  },
290
290
  };
291
291
  }
@@ -354,7 +354,7 @@ describe('getDeviceState', () => {
354
354
  return {
355
355
  message: {
356
356
  hw: { serial_no: 'SERIAL-1' },
357
- fw: { application: { version: '5.0.0' } },
357
+ main_mcu: { application: { version: '5.0.0' } },
358
358
  },
359
359
  };
360
360
  }
@@ -397,7 +397,7 @@ describe('getDeviceState', () => {
397
397
  return {
398
398
  message: {
399
399
  hw: { serial_no: 'SERIAL-1' },
400
- fw: { application: { version: '5.0.0' } },
400
+ main_mcu: { application: { version: '5.0.0' } },
401
401
  },
402
402
  };
403
403
  }
@@ -582,7 +582,7 @@ describe('getDeviceState', () => {
582
582
  message: {
583
583
  protocol_version: 1,
584
584
  hw: { serial_no: 'SERIAL-1' },
585
- fw: { bootloader: { version: '1.0.0' } },
585
+ main_mcu: { bootloader: { version: '1.0.0' } },
586
586
  se1: {},
587
587
  },
588
588
  };
@@ -126,6 +126,26 @@ describe('Pro2 resource configuration', () => {
126
126
  expect(parseProtocolV2ResourceManifest(resourceManifest).files).toHaveLength(9);
127
127
  });
128
128
 
129
+ test('uses only the resource file list from a manifest', () => {
130
+ expect(
131
+ parseProtocolV2ResourceManifest({
132
+ files: resourceManifest.files,
133
+ })
134
+ ).toEqual({ files: resourceManifest.files });
135
+ });
136
+
137
+ test('ignores release metadata and accepts a partial resource file set', () => {
138
+ expect(
139
+ parseProtocolV2ResourceManifest({
140
+ schema: 1,
141
+ variant: 'dev_resource',
142
+ restore_mode: 'bootloader_update',
143
+ trees: [],
144
+ files: [resourceManifest.files[0]],
145
+ })
146
+ ).toEqual({ files: [resourceManifest.files[0]] });
147
+ });
148
+
129
149
  test('rejects missing source and malformed manifest paths', () => {
130
150
  expect(() => parseProtocolV2Resources({})).toThrow('source is required');
131
151
  expect(() =>