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

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.
@@ -1,6 +1,7 @@
1
1
  import * as hdShared from '@onekeyfe/hd-shared';
2
2
 
3
3
  import FirmwareUpdateV3 from '../../src/api/FirmwareUpdateV3';
4
+ import { DataManager } from '../../src/data-manager';
4
5
  import { DevicePool } from '../../src/device/DevicePool';
5
6
 
6
7
  import type { Device } from '../../src/device/Device';
@@ -112,10 +113,125 @@ describe('FirmwareUpdateV3 reconnect', () => {
112
113
  })
113
114
  ).rejects.toBe(reconnectError);
114
115
 
116
+ expect(commands.typedCall).toHaveBeenCalledWith('GetFeatures', 'Features', {});
115
117
  expect(waitForDeviceReconnect).toHaveBeenCalledWith(3 * 60 * 1000);
116
118
  } finally {
117
119
  jest.clearAllTimers();
118
120
  jest.useRealTimers();
119
121
  }
120
122
  });
123
+
124
+ it('lets Browser WebUSB clean up a timed out install probe before reconnecting', async () => {
125
+ jest.spyOn(hdShared, 'wait').mockResolvedValue(undefined);
126
+ jest.spyOn(DataManager, 'getSettings').mockReturnValue('webusb' as never);
127
+ jest.spyOn(DataManager, 'isBrowserWebUsb').mockReturnValue(true);
128
+ const method = new FirmwareUpdateV3({
129
+ id: 1,
130
+ payload: {
131
+ method: 'firmwareUpdateV3',
132
+ connectId: 'webusb-device',
133
+ },
134
+ });
135
+ const reconnectError = new Error('stop after WebUSB reconnect assertion');
136
+ const waitForDeviceReconnect = jest
137
+ .spyOn(method, 'waitForDeviceReconnect')
138
+ .mockRejectedValue(reconnectError);
139
+ method.isBleReconnect = jest.fn(() => false);
140
+ method.params = {
141
+ platform: 'web',
142
+ } as any;
143
+ const commands = {
144
+ typedCall: jest.fn().mockRejectedValue(new Error('Protocol V1 read timeout after 3000ms')),
145
+ };
146
+ method.device = {
147
+ features: {},
148
+ getCommands: () => commands,
149
+ } as unknown as Device;
150
+ (method as any).createUpdatesFolderIfNotExists = jest.fn().mockResolvedValue(undefined);
151
+ (method as any).startEmmcFirmwareUpdate = jest.fn().mockResolvedValue(undefined);
152
+ method.postTipMessage = jest.fn();
153
+ method.postProcessingMessage = jest.fn();
154
+ method.postProgressMessage = jest.fn();
155
+
156
+ await expect(
157
+ (method as any).executeUpdate({
158
+ resourceBinary: null,
159
+ resourceEntries: [],
160
+ fwSources: [],
161
+ bootloaderSource: null,
162
+ })
163
+ ).rejects.toBe(reconnectError);
164
+
165
+ expect(commands.typedCall).toHaveBeenCalledWith(
166
+ 'GetFeatures',
167
+ 'Features',
168
+ {},
169
+ {
170
+ timeoutMs: 3000,
171
+ }
172
+ );
173
+ expect(waitForDeviceReconnect).toHaveBeenCalledWith(60 * 1000);
174
+ });
175
+
176
+ it('does not treat cached firmware versions as Browser WebUSB install completion', async () => {
177
+ jest.spyOn(hdShared, 'wait').mockResolvedValue(undefined);
178
+ jest.spyOn(DataManager, 'getSettings').mockReturnValue('webusb' as never);
179
+ jest.spyOn(DataManager, 'isBrowserWebUsb').mockReturnValue(true);
180
+ const method = new FirmwareUpdateV3({
181
+ id: 1,
182
+ payload: {
183
+ method: 'firmwareUpdateV3',
184
+ connectId: 'webusb-device',
185
+ },
186
+ });
187
+ method.params = {
188
+ platform: 'web',
189
+ } as any;
190
+ const commands = {
191
+ typedCall: jest
192
+ .fn()
193
+ .mockResolvedValueOnce({
194
+ type: 'Features',
195
+ message: {
196
+ major_version: 0,
197
+ minor_version: 0,
198
+ patch_version: 0,
199
+ },
200
+ })
201
+ .mockResolvedValueOnce({
202
+ type: 'Features',
203
+ message: {
204
+ major_version: 4,
205
+ minor_version: 21,
206
+ patch_version: 0,
207
+ onekey_ble_version: '2.3.7',
208
+ },
209
+ }),
210
+ };
211
+ method.device = {
212
+ features: {
213
+ firmwareVersion: '4.21.0',
214
+ bleVersion: '2.3.7',
215
+ },
216
+ getCommands: () => commands,
217
+ } as unknown as Device;
218
+ (method as any).createUpdatesFolderIfNotExists = jest.fn().mockResolvedValue(undefined);
219
+ (method as any).startEmmcFirmwareUpdate = jest.fn().mockResolvedValue(undefined);
220
+ method.postTipMessage = jest.fn();
221
+ method.postProcessingMessage = jest.fn();
222
+ method.postProgressMessage = jest.fn();
223
+
224
+ const result = await (method as any).executeUpdate({
225
+ resourceBinary: null,
226
+ resourceEntries: [],
227
+ fwSources: [],
228
+ bootloaderSource: null,
229
+ });
230
+
231
+ expect(commands.typedCall).toHaveBeenCalledTimes(2);
232
+ expect(result).toMatchObject({
233
+ firmwareVersion: '4.21.0',
234
+ bleVersion: '2.3.7',
235
+ });
236
+ });
121
237
  });
@@ -1 +1 @@
1
- {"version":3,"file":"FirmwareUpdateV3.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV3.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAc/E,OAAO,KAAK,EAEV,sBAAsB,EACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,qBAAqB,CAAC;AAMnE,eAAO,MAAM,gCAAgC,UAAU,CAAC;AAaxD,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,eAAe,CAA4B;IAEnD,IAAI;IA8HE,GAAG;;;;;YAQK,aAAa;IA6D3B,OAAO,CAAC,wBAAwB;YAiBlB,kBAAkB;YAelB,oBAAoB;IAKlC,OAAO,CAAC,wBAAwB;YAgBlB,oBAAoB;YA2DpB,uBAAuB;YAuBvB,4BAA4B;YA+E5B,aAAa;IAyN3B,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,qBAAqB;IAmB7B,OAAO,CAAC,sCAAsC;IAexC,sBAAsB,CAAC,OAAO,EAAE,MAAM;CA+E7C"}
1
+ {"version":3,"file":"FirmwareUpdateV3.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV3.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAc/E,OAAO,KAAK,EAEV,sBAAsB,EACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,qBAAqB,CAAC;AAMnE,eAAO,MAAM,gCAAgC,UAAU,CAAC;AAaxD,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,eAAe,CAA4B;IAEnD,IAAI;IA8HE,GAAG;;;;;YAQK,aAAa;IA6D3B,OAAO,CAAC,wBAAwB;YAiBlB,kBAAkB;YAelB,oBAAoB;IAKlC,OAAO,CAAC,wBAAwB;YAgBlB,oBAAoB;YA2DpB,uBAAuB;YAuBvB,4BAA4B;YA+E5B,aAAa;IAmO3B,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,qBAAqB;IAmB7B,OAAO,CAAC,sCAAsC;IAexC,sBAAsB,CAAC,OAAO,EAAE,MAAM;CA+E7C"}
package/dist/index.js CHANGED
@@ -51318,18 +51318,27 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
51318
51318
  try {
51319
51319
  const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
51320
51320
  const timeoutMs = 3000;
51321
- const featuresRes = yield Promise.race([
51322
- typedCall('GetFeatures', 'Features', {}),
51323
- new Promise((_, reject) => {
51324
- setTimeout(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodNotResponse, 'GetFeatures timeout', { method: 'GetFeatures', timeoutMs })), timeoutMs);
51325
- }),
51326
- ]);
51321
+ const isBrowserWebUsb = DataManager.isBrowserWebUsb(DataManager.getSettings('env'));
51322
+ const getFeaturesPromise = isBrowserWebUsb
51323
+ ? typedCall('GetFeatures', 'Features', {}, { timeoutMs })
51324
+ : typedCall('GetFeatures', 'Features', {});
51325
+ const featuresRes = isBrowserWebUsb
51326
+ ? yield getFeaturesPromise
51327
+ : yield Promise.race([
51328
+ getFeaturesPromise,
51329
+ new Promise((_, reject) => {
51330
+ setTimeout(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodNotResponse, 'GetFeatures timeout', { method: 'GetFeatures', timeoutMs })), timeoutMs);
51331
+ }),
51332
+ ]);
51327
51333
  getFeaturesTimeoutCount = 0;
51328
51334
  const features = buildProtocolV1FeaturesPayload(featuresRes.message, this.device.features);
51329
51335
  const bootloaderVersion = getDeviceBootloaderVersion(features).join('.');
51330
51336
  const bleVersion = getDeviceBLEFirmwareVersion(features).join('.');
51331
51337
  const firmwareVersion = getDeviceFirmwareVersion(features).join('.');
51332
- if (firmwareVersion !== '0.0.0') {
51338
+ const completionFirmwareVersion = isBrowserWebUsb
51339
+ ? getDeviceFirmwareVersion(featuresRes.message).join('.')
51340
+ : firmwareVersion;
51341
+ if (completionFirmwareVersion !== '0.0.0') {
51333
51342
  this.postTipMessage(exports.FirmwareUpdateTipMessage.FirmwareUpdateCompleted);
51334
51343
  DevicePool.resetState();
51335
51344
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.0-alpha.111",
3
+ "version": "1.2.0-alpha.113",
4
4
  "description": "Core processes and APIs for communicating with OneKey hardware devices.",
5
5
  "author": "OneKey",
6
6
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -25,8 +25,8 @@
25
25
  "url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@onekeyfe/hd-shared": "1.2.0-alpha.111",
29
- "@onekeyfe/hd-transport": "1.2.0-alpha.111",
28
+ "@onekeyfe/hd-shared": "1.2.0-alpha.113",
29
+ "@onekeyfe/hd-transport": "1.2.0-alpha.113",
30
30
  "axios": "1.15.2",
31
31
  "bignumber.js": "^9.0.2",
32
32
  "buffer": "^6.0.3",
@@ -46,5 +46,5 @@
46
46
  "@types/w3c-web-usb": "^1.0.10",
47
47
  "@types/web-bluetooth": "^0.0.21"
48
48
  },
49
- "gitHead": "7619f316471ad423fb83f68e82e1aec89f34ac0a"
49
+ "gitHead": "859d0105877f964acb536cd6f337d2d3999d22d5"
50
50
  }
@@ -609,29 +609,40 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
609
609
  try {
610
610
  const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
611
611
  const timeoutMs = 3000;
612
- const featuresRes = await Promise.race<TypedResponseMessage<'Features'>>([
613
- typedCall('GetFeatures', 'Features', {}),
614
- new Promise<never>((_, reject) => {
615
- setTimeout(
616
- () =>
617
- reject(
618
- ERRORS.TypedError(
619
- HardwareErrorCode.CallMethodNotResponse,
620
- 'GetFeatures timeout',
621
- { method: 'GetFeatures', timeoutMs }
622
- )
623
- ),
624
- timeoutMs
625
- );
626
- }),
627
- ]);
612
+ const isBrowserWebUsb = DataManager.isBrowserWebUsb(DataManager.getSettings('env'));
613
+ const getFeaturesPromise = isBrowserWebUsb
614
+ ? typedCall('GetFeatures', 'Features', {}, { timeoutMs })
615
+ : typedCall('GetFeatures', 'Features', {});
616
+ // WebUSB owns timeout cleanup so a reboot cannot leave a pending transfer blocking reconnect.
617
+ const featuresRes = isBrowserWebUsb
618
+ ? await getFeaturesPromise
619
+ : await Promise.race<TypedResponseMessage<'Features'>>([
620
+ getFeaturesPromise,
621
+ new Promise<never>((_, reject) => {
622
+ setTimeout(
623
+ () =>
624
+ reject(
625
+ ERRORS.TypedError(
626
+ HardwareErrorCode.CallMethodNotResponse,
627
+ 'GetFeatures timeout',
628
+ { method: 'GetFeatures', timeoutMs }
629
+ )
630
+ ),
631
+ timeoutMs
632
+ );
633
+ }),
634
+ ]);
628
635
  getFeaturesTimeoutCount = 0;
629
636
  const features = buildProtocolV1FeaturesPayload(featuresRes.message, this.device.features);
630
637
  const bootloaderVersion = getDeviceBootloaderVersion(features).join('.');
631
638
  const bleVersion = getDeviceBLEFirmwareVersion(features).join('.');
632
639
  const firmwareVersion = getDeviceFirmwareVersion(features).join('.');
633
- // Treat update as complete once firmware version becomes non-zero
634
- if (firmwareVersion !== '0.0.0') {
640
+ // Browser WebUSB may read updater Features before the final reboot. Do not let cached
641
+ // pre-update versions promote a current 0.0.0 response to install completion.
642
+ const completionFirmwareVersion = isBrowserWebUsb
643
+ ? getDeviceFirmwareVersion(featuresRes.message).join('.')
644
+ : firmwareVersion;
645
+ if (completionFirmwareVersion !== '0.0.0') {
635
646
  this.postTipMessage(FirmwareUpdateTipMessage.FirmwareUpdateCompleted);
636
647
  DevicePool.resetState();
637
648
  return {
@@ -640,7 +651,6 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
640
651
  firmwareVersion,
641
652
  };
642
653
  }
643
- // Still in update mode; continue polling (e.g., iOS may return firmwareVersion 0.0.0 during switches)
644
654
  await wait(1000);
645
655
  } catch (error) {
646
656
  Log.log('getFeatures error', error);