@onekeyfe/hd-core 1.1.20 → 1.1.21-alpha.1

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.
@@ -15,6 +15,8 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
15
15
  private prepareBootloaderBinary;
16
16
  private prepareFirmwareAndBleBinary;
17
17
  private executeUpdate;
18
+ private extractUpdateModeProgress;
19
+ private normalizeErrorMessage;
18
20
  waitForDeviceReconnect(timeout: number): Promise<void>;
19
21
  }
20
22
  //# sourceMappingURL=FirmwareUpdateV3.d.ts.map
@@ -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;AAG/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,qBAAqB,CAAC;AAKnE,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,IAAI;IAmCE,GAAG;;;;;IA8CT,OAAO,CAAC,wBAAwB;YAiBlB,qBAAqB;YAoBrB,uBAAuB;YAiBvB,2BAA2B;YAiD3B,aAAa;IA2KrB,sBAAsB,CAAC,OAAO,EAAE,MAAM;CAoD7C"}
1
+ {"version":3,"file":"FirmwareUpdateV3.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV3.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAG/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,qBAAqB,CAAC;AAKnE,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,IAAI;IAmCE,GAAG;;;;;IA8CT,OAAO,CAAC,wBAAwB;YAiBlB,qBAAqB;YAoBrB,uBAAuB;YAiBvB,2BAA2B;YAiD3B,aAAa;IA6K3B,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,qBAAqB;IAuBvB,sBAAsB,CAAC,OAAO,EAAE,MAAM;CAoD7C"}
@@ -7,6 +7,7 @@ import type { Deferred } from '@onekeyfe/hd-shared';
7
7
  import type { TypedResponseMessage } from '../../device/DeviceCommands';
8
8
  export declare class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
9
9
  checkPromise: Deferred<any> | null;
10
+ protected hasPromptedWebUsbBootloaderReauth: boolean;
10
11
  init(): void;
11
12
  run(): Promise<any>;
12
13
  isBleReconnect(): boolean;
@@ -15,6 +16,7 @@ export declare class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params>
15
16
  postProgressMessage: (progress: number, progressType: IFirmwareUpdateProgressType) => void;
16
17
  private _promptDeviceInBootloaderForWebDevice;
17
18
  checkDeviceToBootloader(connectId: string | undefined): void;
19
+ protected ensureWebUsbBootloaderReauthPrompt(): Promise<void>;
18
20
  private _checkDeviceInBootloaderMode;
19
21
  enterBootloaderMode(): Promise<true | undefined>;
20
22
  startEmmcFirmwareUpdate({ path }: {
@@ -1 +1 @@
1
- {"version":3,"file":"FirmwareUpdateBaseMethod.d.ts","sourceRoot":"","sources":["../../../src/api/firmware/FirmwareUpdateBaseMethod.ts"],"names":[],"mappings":";AAaA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,OAAO,KAAK,EACV,2BAA2B,EAC3B,yBAAyB,EAC1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAexE,qBAAa,wBAAwB,CAAC,MAAM,CAAE,SAAQ,UAAU,CAAC,MAAM,CAAC;IACtE,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,IAAI,IAAI,IAAI;IAEZ,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAInB,cAAc,IAAI,OAAO;IASzB,cAAc,YAAa,yBAAyB,UASlD;IAMF,qBAAqB,SAAU,UAAU,GAAG,KAAK,GAAG,YAAY,GAAG,UAAU,UAM3E;IAMF,mBAAmB,aAAc,MAAM,gBAAgB,2BAA2B,UAQhF;YAEY,qCAAqC;IAkBnD,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;YAmFvC,4BAA4B;IAuBpC,mBAAmB;IA8CnB,uBAAuB,CAAC,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;IA6BlD,8BAA8B,CAAC,IAAI,EAAE,MAAM;IAW3C,uBAAuB,CAAC,EAC5B,OAAO,EACP,QAAQ,EACR,aAAa,EACb,SAAS,GACV,EAAE,KAAK,CAAC,cAAc,GAAG;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;IA4CK,sBAAsB,CAC1B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,WAAW,GAAG,MAAM,EAC3B,SAAS,EAAE,OAAO,EAClB,QAAQ,EAAE,MAAM,GAAG,IAAI;IAwEnB,MAAM,CAAC,UAAU,EAAE,UAAU;CAsBpC"}
1
+ {"version":3,"file":"FirmwareUpdateBaseMethod.d.ts","sourceRoot":"","sources":["../../../src/api/firmware/FirmwareUpdateBaseMethod.ts"],"names":[],"mappings":";AAaA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,OAAO,KAAK,EACV,2BAA2B,EAC3B,yBAAyB,EAC1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAexE,qBAAa,wBAAwB,CAAC,MAAM,CAAE,SAAQ,UAAU,CAAC,MAAM,CAAC;IACtE,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,SAAS,CAAC,iCAAiC,UAAS;IAEpD,IAAI,IAAI,IAAI;IAEZ,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAInB,cAAc,IAAI,OAAO;IASzB,cAAc,YAAa,yBAAyB,UASlD;IAMF,qBAAqB,SAAU,UAAU,GAAG,KAAK,GAAG,YAAY,GAAG,UAAU,UAM3E;IAMF,mBAAmB,aAAc,MAAM,gBAAgB,2BAA2B,UAQhF;YAEY,qCAAqC;IAkBnD,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;cAuFrC,kCAAkC;YAmBpC,4BAA4B;IAuBpC,mBAAmB;IA8CnB,uBAAuB,CAAC,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;IA6BlD,8BAA8B,CAAC,IAAI,EAAE,MAAM;IAW3C,uBAAuB,CAAC,EAC5B,OAAO,EACP,QAAQ,EACR,aAAa,EACb,SAAS,GACV,EAAE,KAAK,CAAC,cAAc,GAAG;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;IA4CK,sBAAsB,CAC1B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,WAAW,GAAG,MAAM,EAC3B,SAAS,EAAE,OAAO,EAClB,QAAQ,EAAE,MAAM,GAAG,IAAI;IAwEnB,MAAM,CAAC,UAAU,EAAE,UAAU;CAsBpC"}
@@ -1,6 +1,6 @@
1
1
  import { EFirmwareType } from '@onekeyfe/hd-shared';
2
2
  import type { AssetsMap, ConnectSettings, DeviceTypeMap, Features, IDeviceBLEFirmwareStatus, IDeviceFirmwareStatus, ITransportStatus, IVersionArray } from '../types';
3
- export declare const FIRMWARE_FIELDS: readonly ["firmware", "firmware-v2", "firmware-v7", "firmware-btc-v7"];
3
+ export declare const FIRMWARE_FIELDS: readonly ["firmware", "firmware-v2", "firmware-v8", "firmware-btc-v8"];
4
4
  export type IFirmwareField = (typeof FIRMWARE_FIELDS)[number];
5
5
  export type MessageVersion = 'latest' | 'v1';
6
6
  export default class DataManager {
package/dist/index.d.ts CHANGED
@@ -224,8 +224,8 @@ type DeviceTypeMap = {
224
224
  [k in IKnownDevice]: {
225
225
  firmware: IFirmwareReleaseInfo[];
226
226
  'firmware-v2'?: IFirmwareReleaseInfo[];
227
- 'firmware-v7'?: IFirmwareReleaseInfo[];
228
- 'firmware-btc-v7'?: IFirmwareReleaseInfo[];
227
+ 'firmware-v8'?: IFirmwareReleaseInfo[];
228
+ 'firmware-btc-v8'?: IFirmwareReleaseInfo[];
229
229
  ble: IBLEFirmwareReleaseInfo[];
230
230
  };
231
231
  };
@@ -3241,7 +3241,7 @@ declare const getDeviceBLEFirmwareVersion: (features: Features) => IVersionArray
3241
3241
  declare const getDeviceBootloaderVersion: (features: Features | undefined) => IVersionArray;
3242
3242
  declare const getDeviceBoardloaderVersion: (features: Features) => IVersionArray;
3243
3243
 
3244
- declare const FIRMWARE_FIELDS: readonly ["firmware", "firmware-v2", "firmware-v7", "firmware-btc-v7"];
3244
+ declare const FIRMWARE_FIELDS: readonly ["firmware", "firmware-v2", "firmware-v8", "firmware-btc-v8"];
3245
3245
  type IFirmwareField = (typeof FIRMWARE_FIELDS)[number];
3246
3246
  type MessageVersion = 'latest' | 'v1';
3247
3247
  declare class DataManager {
package/dist/index.js CHANGED
@@ -25050,14 +25050,14 @@ const Log$e = getLogger(exports.LoggerNames.Core);
25050
25050
  const FIRMWARE_FIELDS = [
25051
25051
  'firmware',
25052
25052
  'firmware-v2',
25053
- 'firmware-v7',
25054
- 'firmware-btc-v7',
25053
+ 'firmware-v8',
25054
+ 'firmware-btc-v8',
25055
25055
  ];
25056
25056
  const FIRMWARE_FIELD_TYPE_MAP = {
25057
25057
  firmware: hdShared.EFirmwareType.Universal,
25058
25058
  'firmware-v2': hdShared.EFirmwareType.Universal,
25059
- 'firmware-v7': hdShared.EFirmwareType.Universal,
25060
- 'firmware-btc-v7': hdShared.EFirmwareType.BitcoinOnly,
25059
+ 'firmware-v8': hdShared.EFirmwareType.Universal,
25060
+ 'firmware-btc-v8': hdShared.EFirmwareType.BitcoinOnly,
25061
25061
  };
25062
25062
  function getFirmwareTypeFromField(firmwareField) {
25063
25063
  const firmwareType = FIRMWARE_FIELD_TYPE_MAP[firmwareField];
@@ -25561,9 +25561,9 @@ const supportModifyHomescreen = (features) => {
25561
25561
  };
25562
25562
  const getLatestFirmwareField = (firmwareType) => {
25563
25563
  if (firmwareType === 'bitcoinonly') {
25564
- return `firmware-btc-v7`;
25564
+ return `firmware-btc-v8`;
25565
25565
  }
25566
- return `firmware-v7`;
25566
+ return `firmware-v8`;
25567
25567
  };
25568
25568
  const getFirmwareUpdateField = ({ features, updateType, targetVersion, firmwareType, }) => {
25569
25569
  const deviceType = getDeviceType(features);
@@ -25600,23 +25600,23 @@ const getFirmwareUpdateFieldArray = (features, updateType) => {
25600
25600
  deviceType === 'classic1s' ||
25601
25601
  deviceType === 'mini' ||
25602
25602
  deviceType === 'classicpure') {
25603
- return ['firmware-v7'];
25603
+ return ['firmware-v8'];
25604
25604
  }
25605
25605
  if (deviceType === 'touch') {
25606
25606
  const currentVersion = getDeviceFirmwareVersion(features).join('.');
25607
25607
  if (semver__default["default"].gt(currentVersion, '4.0.0')) {
25608
- return ['firmware-v7', 'firmware'];
25608
+ return ['firmware-v8', 'firmware'];
25609
25609
  }
25610
25610
  if (semver__default["default"].gte(currentVersion, '4.0.0')) {
25611
25611
  return ['firmware-v2', 'firmware'];
25612
25612
  }
25613
25613
  if (!currentVersion || semver__default["default"].lt(currentVersion, '3.0.0')) {
25614
- return ['firmware-v7', 'firmware-v2', 'firmware'];
25614
+ return ['firmware-v8', 'firmware-v2', 'firmware'];
25615
25615
  }
25616
25616
  return ['firmware'];
25617
25617
  }
25618
25618
  if (deviceType === 'pro') {
25619
- return ['firmware-v7'];
25619
+ return ['firmware-v8'];
25620
25620
  }
25621
25621
  return ['firmware'];
25622
25622
  };
@@ -29369,6 +29369,7 @@ class FirmwareUpdateBaseMethod extends BaseMethod {
29369
29369
  constructor() {
29370
29370
  super(...arguments);
29371
29371
  this.checkPromise = null;
29372
+ this.hasPromptedWebUsbBootloaderReauth = false;
29372
29373
  this.postTipMessage = (message) => {
29373
29374
  this.postMessage(createUiMessage(UI_REQUEST.FIRMWARE_TIP, {
29374
29375
  device: this.device.toMessageObject(),
@@ -29447,7 +29448,7 @@ class FirmwareUpdateBaseMethod extends BaseMethod {
29447
29448
  }
29448
29449
  }
29449
29450
  catch (e) {
29450
- Log$7.log('FirmwareUpdateBaseMethod [checkDeviceToBootloader] promptDeviceInBootloaderForWebDevice failed: ', e);
29451
+ Log$7.log('FirmwareUpdateBaseMethod [checkDeviceToBootloader] _promptDeviceInBootloaderForWebDevice failed: ', e);
29451
29452
  (_c = this.checkPromise) === null || _c === void 0 ? void 0 : _c.reject(e);
29452
29453
  }
29453
29454
  return;
@@ -29476,6 +29477,23 @@ class FirmwareUpdateBaseMethod extends BaseMethod {
29476
29477
  }
29477
29478
  }, 30000);
29478
29479
  }
29480
+ ensureWebUsbBootloaderReauthPrompt() {
29481
+ return __awaiter(this, void 0, void 0, function* () {
29482
+ if (this.hasPromptedWebUsbBootloaderReauth ||
29483
+ !DataManager.isBrowserWebUsb(DataManager.getSettings('env')) ||
29484
+ this.device.listenerCount(DEVICE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE) === 0) {
29485
+ return;
29486
+ }
29487
+ this.hasPromptedWebUsbBootloaderReauth = true;
29488
+ this.postTipMessage(exports.FirmwareUpdateTipMessage.SelectDeviceInBootloaderForWebDevice);
29489
+ try {
29490
+ yield this._promptDeviceInBootloaderForWebDevice();
29491
+ }
29492
+ catch (error) {
29493
+ Log$7.log('WebUSB 设备重新授权失败: ', error);
29494
+ }
29495
+ });
29496
+ }
29479
29497
  _checkDeviceInBootloaderMode(connectId, intervalTimer, timeoutTimer) {
29480
29498
  var _a, _b, _c, _d, _e;
29481
29499
  return __awaiter(this, void 0, void 0, function* () {
@@ -30402,7 +30420,6 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
30402
30420
  });
30403
30421
  }
30404
30422
  executeUpdate({ resourceBinary, fwBinaryMap, bootloaderBinary, }) {
30405
- var _a;
30406
30423
  return __awaiter(this, void 0, void 0, function* () {
30407
30424
  let totalSize = 0;
30408
30425
  let processedSize = 0;
@@ -30503,19 +30520,20 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
30503
30520
  const bootloaderVersion = getDeviceBootloaderVersion(features).join('.');
30504
30521
  const bleVersion = getDeviceBLEFirmwareVersion(features).join('.');
30505
30522
  const firmwareVersion = getDeviceFirmwareVersion(features).join('.');
30506
- this.postTipMessage(exports.FirmwareUpdateTipMessage.FirmwareUpdateCompleted);
30507
- DevicePool.resetState();
30508
- return {
30509
- bootloaderVersion,
30510
- bleVersion,
30511
- firmwareVersion,
30512
- };
30523
+ if (firmwareVersion !== '0.0.0') {
30524
+ this.postTipMessage(exports.FirmwareUpdateTipMessage.FirmwareUpdateCompleted);
30525
+ DevicePool.resetState();
30526
+ return {
30527
+ bootloaderVersion,
30528
+ bleVersion,
30529
+ firmwareVersion,
30530
+ };
30531
+ }
30532
+ yield hdShared.wait(1000);
30513
30533
  }
30514
30534
  catch (error) {
30515
- if (error.message && error.message.includes('Update mode')) {
30516
- const updateParts = error.message.split('Update mode ');
30517
- const progressValue = (_a = updateParts[1]) !== null && _a !== void 0 ? _a : '0';
30518
- const progress = parseInt(progressValue, 10) || 0;
30535
+ const progress = this.extractUpdateModeProgress(error);
30536
+ if (progress !== null) {
30519
30537
  this.postProgressMessage(progress, 'installingFirmware');
30520
30538
  yield hdShared.wait(1000);
30521
30539
  }
@@ -30524,12 +30542,43 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
30524
30542
  const reconnectTimeout = this.isBleReconnect() && (this.params.bleBinary || this.params.bleVersion)
30525
30543
  ? 3 * 60 * 1000
30526
30544
  : 60 * 1000;
30545
+ yield this.ensureWebUsbBootloaderReauthPrompt();
30527
30546
  yield this.waitForDeviceReconnect(reconnectTimeout);
30528
30547
  }
30529
30548
  }
30530
30549
  }
30531
30550
  });
30532
30551
  }
30552
+ extractUpdateModeProgress(error) {
30553
+ const message = this.normalizeErrorMessage(error);
30554
+ if (!message) {
30555
+ return null;
30556
+ }
30557
+ const match = message.match(/Update mode\s*(\d+)/i);
30558
+ if (!match) {
30559
+ return null;
30560
+ }
30561
+ const progress = parseInt(match[1], 10);
30562
+ return Number.isNaN(progress) ? null : progress;
30563
+ }
30564
+ normalizeErrorMessage(error) {
30565
+ if (!error) {
30566
+ return '';
30567
+ }
30568
+ if (typeof error === 'string') {
30569
+ return error;
30570
+ }
30571
+ if (typeof error === 'object') {
30572
+ const { message } = error;
30573
+ if (typeof message === 'string') {
30574
+ return message;
30575
+ }
30576
+ if (message !== undefined && message !== null) {
30577
+ return String(message);
30578
+ }
30579
+ }
30580
+ return '';
30581
+ }
30533
30582
  waitForDeviceReconnect(timeout) {
30534
30583
  var _a, _b, _c, _d;
30535
30584
  return __awaiter(this, void 0, void 0, function* () {
@@ -60,8 +60,8 @@ export type DeviceTypeMap = {
60
60
  [k in IKnownDevice]: {
61
61
  firmware: IFirmwareReleaseInfo[];
62
62
  'firmware-v2'?: IFirmwareReleaseInfo[];
63
- 'firmware-v7'?: IFirmwareReleaseInfo[];
64
- 'firmware-btc-v7'?: IFirmwareReleaseInfo[];
63
+ 'firmware-v8'?: IFirmwareReleaseInfo[];
64
+ 'firmware-btc-v8'?: IFirmwareReleaseInfo[];
65
65
  ble: IBLEFirmwareReleaseInfo[];
66
66
  };
67
67
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.1.20",
3
+ "version": "1.1.21-alpha.1",
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.1.20",
29
- "@onekeyfe/hd-transport": "1.1.20",
28
+ "@onekeyfe/hd-shared": "1.1.21-alpha.1",
29
+ "@onekeyfe/hd-transport": "1.1.21-alpha.1",
30
30
  "axios": "1.12.2",
31
31
  "bignumber.js": "^9.0.2",
32
32
  "bytebuffer": "^5.0.1",
@@ -44,5 +44,5 @@
44
44
  "@types/w3c-web-usb": "^1.0.10",
45
45
  "@types/web-bluetooth": "^0.0.21"
46
46
  },
47
- "gitHead": "3f1367f1ad5253e2207442e74fa47361df7ff442"
47
+ "gitHead": "933dbbcf45753b685ba7f76500158de42b68215b"
48
48
  }
@@ -247,7 +247,7 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
247
247
  }
248
248
 
249
249
  this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
250
- // 处理资源文件
250
+ // Process resource zip contents
251
251
  if (resourceBinary) {
252
252
  const file = await JSZip.loadAsync(resourceBinary);
253
253
  const files = Object.entries(file.files);
@@ -358,19 +358,21 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
358
358
  const bootloaderVersion = getDeviceBootloaderVersion(features).join('.');
359
359
  const bleVersion = getDeviceBLEFirmwareVersion(features).join('.');
360
360
  const firmwareVersion = getDeviceFirmwareVersion(features).join('.');
361
- this.postTipMessage(FirmwareUpdateTipMessage.FirmwareUpdateCompleted);
362
- DevicePool.resetState();
363
- return {
364
- bootloaderVersion,
365
- bleVersion,
366
- firmwareVersion,
367
- };
361
+ // Treat update as complete once firmware version becomes non-zero
362
+ if (firmwareVersion !== '0.0.0') {
363
+ this.postTipMessage(FirmwareUpdateTipMessage.FirmwareUpdateCompleted);
364
+ DevicePool.resetState();
365
+ return {
366
+ bootloaderVersion,
367
+ bleVersion,
368
+ firmwareVersion,
369
+ };
370
+ }
371
+ // Still in update mode; continue polling (e.g., iOS may return firmwareVersion 0.0.0 during switches)
372
+ await wait(1000);
368
373
  } catch (error) {
369
- // Hardware install firmware progress message
370
- if (error.message && error.message.includes('Update mode')) {
371
- const updateParts = error.message.split('Update mode ');
372
- const progressValue = updateParts[1] ?? '0';
373
- const progress = parseInt(progressValue, 10) || 0;
374
+ const progress = this.extractUpdateModeProgress(error);
375
+ if (progress !== null) {
374
376
  this.postProgressMessage(progress, 'installingFirmware');
375
377
  await wait(1000);
376
378
  } else {
@@ -385,12 +387,48 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
385
387
  ? 3 * 60 * 1000 // 3 minutes for BLE reconnect
386
388
  : 60 * 1000; // 1 minute for normal reconnect
387
389
 
390
+ await this.ensureWebUsbBootloaderReauthPrompt();
388
391
  await this.waitForDeviceReconnect(reconnectTimeout);
389
392
  }
390
393
  }
391
394
  }
392
395
  }
393
396
 
397
+ /**
398
+ * Parse “Update mode XX” progress value from device errors to avoid hardcoded message.includes.
399
+ */
400
+ private extractUpdateModeProgress(error: unknown): number | null {
401
+ const message = this.normalizeErrorMessage(error);
402
+ if (!message) {
403
+ return null;
404
+ }
405
+ const match = message.match(/Update mode\s*(\d+)/i);
406
+ if (!match) {
407
+ return null;
408
+ }
409
+ const progress = parseInt(match[1], 10);
410
+ return Number.isNaN(progress) ? null : progress;
411
+ }
412
+
413
+ private normalizeErrorMessage(error: unknown): string {
414
+ if (!error) {
415
+ return '';
416
+ }
417
+ if (typeof error === 'string') {
418
+ return error;
419
+ }
420
+ if (typeof error === 'object') {
421
+ const { message } = error as { message?: unknown };
422
+ if (typeof message === 'string') {
423
+ return message;
424
+ }
425
+ if (message !== undefined && message !== null) {
426
+ return String(message);
427
+ }
428
+ }
429
+ return '';
430
+ }
431
+
394
432
  /**
395
433
  * @description Reconnect device - While update with bootloader, it will reconnect device
396
434
  * @param {number} timeout - The timeout for the reconnection
@@ -40,6 +40,8 @@ const isDeviceDisconnectedError = (error: unknown) => {
40
40
  export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
41
41
  checkPromise: Deferred<any> | null = null;
42
42
 
43
+ protected hasPromptedWebUsbBootloaderReauth = false;
44
+
43
45
  init(): void {}
44
46
 
45
47
  run(): Promise<any> {
@@ -153,7 +155,7 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
153
155
  }
154
156
  } catch (e) {
155
157
  Log.log(
156
- 'FirmwareUpdateBaseMethod [checkDeviceToBootloader] promptDeviceInBootloaderForWebDevice failed: ',
158
+ 'FirmwareUpdateBaseMethod [checkDeviceToBootloader] _promptDeviceInBootloaderForWebDevice failed: ',
157
159
  e
158
160
  );
159
161
  this.checkPromise?.reject(e);
@@ -193,6 +195,29 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
193
195
  }, 30000);
194
196
  }
195
197
 
198
+ /**
199
+ * 仅在 firmware 被抹掉、需要重新授权的 bootloader 场景下才提示 WebUSB
200
+ * (比如 BTC-only 与通用固件互转后算作新设备)。
201
+ */
202
+ protected async ensureWebUsbBootloaderReauthPrompt() {
203
+ if (
204
+ this.hasPromptedWebUsbBootloaderReauth ||
205
+ !DataManager.isBrowserWebUsb(DataManager.getSettings('env')) ||
206
+ this.device.listenerCount(DEVICE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE) === 0
207
+ ) {
208
+ return;
209
+ }
210
+
211
+ this.hasPromptedWebUsbBootloaderReauth = true;
212
+ this.postTipMessage(FirmwareUpdateTipMessage.SelectDeviceInBootloaderForWebDevice);
213
+
214
+ try {
215
+ await this._promptDeviceInBootloaderForWebDevice();
216
+ } catch (error) {
217
+ Log.log('WebUSB 设备重新授权失败: ', error);
218
+ }
219
+ }
220
+
196
221
  private async _checkDeviceInBootloaderMode(
197
222
  connectId: string | undefined,
198
223
  intervalTimer?: ReturnType<typeof setInterval>,
@@ -34,8 +34,8 @@ const Log = getLogger(LoggerNames.Core);
34
34
  export const FIRMWARE_FIELDS = [
35
35
  'firmware',
36
36
  'firmware-v2',
37
- 'firmware-v7',
38
- 'firmware-btc-v7',
37
+ 'firmware-v8',
38
+ 'firmware-btc-v8',
39
39
  ] as const;
40
40
 
41
41
  export type IFirmwareField = (typeof FIRMWARE_FIELDS)[number];
@@ -45,8 +45,8 @@ export type MessageVersion = 'latest' | 'v1';
45
45
  const FIRMWARE_FIELD_TYPE_MAP: Readonly<Record<IFirmwareField, EFirmwareType>> = {
46
46
  firmware: EFirmwareType.Universal,
47
47
  'firmware-v2': EFirmwareType.Universal,
48
- 'firmware-v7': EFirmwareType.Universal,
49
- 'firmware-btc-v7': EFirmwareType.BitcoinOnly,
48
+ 'firmware-v8': EFirmwareType.Universal,
49
+ 'firmware-btc-v8': EFirmwareType.BitcoinOnly,
50
50
  } as const;
51
51
 
52
52
  function getFirmwareTypeFromField(firmwareField: IFirmwareField): EFirmwareType {
@@ -98,9 +98,9 @@ type IKnownDevice = Exclude<IDeviceType, 'unknown'>;
98
98
  * // {
99
99
  * // firmware: IFirmwareReleaseInfo[];
100
100
  * // 'firmware-v2'?: IFirmwareReleaseInfo[];
101
- * // 'firmware-v7'?: IFirmwareReleaseInfo[];
101
+ * // 'firmware-v8'?: IFirmwareReleaseInfo[];
102
102
  * // 'firmware-v8'?: IFirmwareReleaseInfo[]; // New
103
- * // 'firmware-btc-v7'?: IFirmwareReleaseInfo[];
103
+ * // 'firmware-btc-v8'?: IFirmwareReleaseInfo[];
104
104
  * // 'firmware-btc-v8'?: IFirmwareReleaseInfo[]; // New
105
105
  * // ble: IBLEFirmwareReleaseInfo[];
106
106
  * // }
@@ -112,9 +112,9 @@ export type DeviceTypeMap = {
112
112
  /** Firmware v2 (Touch/Pro specific) */
113
113
  'firmware-v2'?: IFirmwareReleaseInfo[];
114
114
  /** Universal firmware v7 */
115
- 'firmware-v7'?: IFirmwareReleaseInfo[];
115
+ 'firmware-v8'?: IFirmwareReleaseInfo[];
116
116
  /** Bitcoin-only firmware v7 */
117
- 'firmware-btc-v7'?: IFirmwareReleaseInfo[];
117
+ 'firmware-btc-v8'?: IFirmwareReleaseInfo[];
118
118
  // Future firmware versions should be added here as optional fields:
119
119
  // 'firmware-v8'?: IFirmwareReleaseInfo[];
120
120
  // 'firmware-btc-v8'?: IFirmwareReleaseInfo[];
@@ -235,9 +235,9 @@ export const supportModifyHomescreen = (features?: Features): SupportFeatureType
235
235
 
236
236
  export const getLatestFirmwareField = (firmwareType?: EFirmwareType): IFirmwareField => {
237
237
  if (firmwareType === 'bitcoinonly') {
238
- return `firmware-btc-v7`;
238
+ return `firmware-btc-v8`;
239
239
  }
240
- return `firmware-v7`;
240
+ return `firmware-v8`;
241
241
  };
242
242
 
243
243
  /**
@@ -300,25 +300,25 @@ export const getFirmwareUpdateFieldArray = (
300
300
  deviceType === 'mini' ||
301
301
  deviceType === 'classicpure'
302
302
  ) {
303
- return ['firmware-v7'];
303
+ return ['firmware-v8'];
304
304
  }
305
305
 
306
306
  if (deviceType === 'touch') {
307
307
  const currentVersion = getDeviceFirmwareVersion(features).join('.');
308
308
  if (semver.gt(currentVersion, '4.0.0')) {
309
- return ['firmware-v7', 'firmware'];
309
+ return ['firmware-v8', 'firmware'];
310
310
  }
311
311
  if (semver.gte(currentVersion, '4.0.0')) {
312
312
  return ['firmware-v2', 'firmware'];
313
313
  }
314
314
  if (!currentVersion || semver.lt(currentVersion, '3.0.0')) {
315
- return ['firmware-v7', 'firmware-v2', 'firmware'];
315
+ return ['firmware-v8', 'firmware-v2', 'firmware'];
316
316
  }
317
317
  return ['firmware'];
318
318
  }
319
319
 
320
320
  if (deviceType === 'pro') {
321
- return ['firmware-v7'];
321
+ return ['firmware-v8'];
322
322
  }
323
323
 
324
324
  return ['firmware'];