@onekeyfe/hd-core 1.2.0-alpha.183 → 1.2.0-alpha.185

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 (49) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +20 -4
  2. package/__tests__/DeviceCommands.test.ts +13 -0
  3. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +0 -2
  4. package/__tests__/check-firmware-release-protocol-v2.test.ts +0 -2
  5. package/__tests__/device-lifecycle-events.test.ts +19 -0
  6. package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +102 -2
  7. package/__tests__/open-wallet-session.test.ts +127 -1
  8. package/__tests__/protocol-v2-resources.test.ts +0 -4
  9. package/__tests__/protocol-v2-unlock-policy.test.ts +35 -1
  10. package/__tests__/protocol-v2.test.ts +155 -2
  11. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  12. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  13. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  14. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +2 -2
  15. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  16. package/dist/api/firmware/getBinary.d.ts +2 -2
  17. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
  18. package/dist/core/index.d.ts +1 -0
  19. package/dist/core/index.d.ts.map +1 -1
  20. package/dist/device/Device.d.ts +1 -1
  21. package/dist/device/Device.d.ts.map +1 -1
  22. package/dist/events/ui-request.d.ts +3 -0
  23. package/dist/events/ui-request.d.ts.map +1 -1
  24. package/dist/index.d.ts +9 -4
  25. package/dist/index.js +644 -347
  26. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +2 -0
  27. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -1
  28. package/dist/protocols/protocol-v2/walletSession.d.ts +3 -0
  29. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  30. package/dist/types/settings.d.ts +2 -2
  31. package/dist/types/settings.d.ts.map +1 -1
  32. package/dist/utils/deviceFeaturesUtils.d.ts +3 -0
  33. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  34. package/dist/utils/patch.d.ts +1 -1
  35. package/dist/utils/patch.d.ts.map +1 -1
  36. package/package.json +4 -4
  37. package/src/api/FirmwareUpdateV4.ts +193 -21
  38. package/src/api/OpenWalletSession.ts +39 -9
  39. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +2 -1
  40. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +9 -3
  41. package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +7 -1
  42. package/src/core/index.ts +16 -2
  43. package/src/data/messages/messages-protocol-v2.json +111 -1
  44. package/src/device/Device.ts +3 -1
  45. package/src/events/ui-request.ts +3 -0
  46. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +8 -1
  47. package/src/protocols/protocol-v2/walletSession.ts +65 -22
  48. package/src/types/settings.ts +4 -2
  49. package/src/utils/deviceFeaturesUtils.ts +4 -0
package/dist/index.js CHANGED
@@ -27476,6 +27476,9 @@ var nested = {
27476
27476
  MessageType_DeviceCertificateSignature: 60423,
27477
27477
  MessageType_DeviceCertificateSign: 60424,
27478
27478
  MessageType_DeviceMiscUsbMscControl: 60440,
27479
+ MessageType_DeviceFindMyTokenState: 60450,
27480
+ MessageType_DeviceFindMyTokenUpdate: 60451,
27481
+ MessageType_DeviceFindMyTokenStateGet: 60452,
27479
27482
  MessageType_DeviceInfoGet: 60600,
27480
27483
  MessageType_DeviceInfo: 60601,
27481
27484
  MessageType_DeviceStatusGet: 60602,
@@ -32452,6 +32455,10 @@ var nested = {
32452
32455
  request_id: {
32453
32456
  type: "bytes",
32454
32457
  id: 5
32458
+ },
32459
+ source_fingerprint: {
32460
+ type: "uint32",
32461
+ id: 6
32455
32462
  }
32456
32463
  }
32457
32464
  },
@@ -32587,6 +32594,14 @@ var nested = {
32587
32594
  tx_type: {
32588
32595
  type: "uint32",
32589
32596
  id: 10
32597
+ },
32598
+ expected_address: {
32599
+ type: "bytes",
32600
+ id: 12
32601
+ },
32602
+ source_fingerprint: {
32603
+ type: "uint32",
32604
+ id: 13
32590
32605
  }
32591
32606
  }
32592
32607
  },
@@ -32667,6 +32682,14 @@ var nested = {
32667
32682
  rule: "repeated",
32668
32683
  type: "EthereumAccessListOneKey",
32669
32684
  id: 11
32685
+ },
32686
+ expected_address: {
32687
+ type: "bytes",
32688
+ id: 12
32689
+ },
32690
+ source_fingerprint: {
32691
+ type: "uint32",
32692
+ id: 13
32670
32693
  }
32671
32694
  }
32672
32695
  },
@@ -32843,6 +32866,10 @@ var nested = {
32843
32866
  chain_id: {
32844
32867
  type: "uint64",
32845
32868
  id: 3
32869
+ },
32870
+ source_fingerprint: {
32871
+ type: "uint32",
32872
+ id: 4
32846
32873
  }
32847
32874
  }
32848
32875
  },
@@ -36545,6 +36572,10 @@ var nested = {
36545
36572
  rule: "required",
36546
36573
  type: "bytes",
36547
36574
  id: 2
36575
+ },
36576
+ source_fingerprint: {
36577
+ type: "uint32",
36578
+ id: 3
36548
36579
  }
36549
36580
  }
36550
36581
  },
@@ -36589,6 +36620,10 @@ var nested = {
36589
36620
  application_domain: {
36590
36621
  type: "bytes",
36591
36622
  id: 5
36623
+ },
36624
+ source_fingerprint: {
36625
+ type: "uint32",
36626
+ id: 6
36592
36627
  }
36593
36628
  }
36594
36629
  },
@@ -36606,6 +36641,10 @@ var nested = {
36606
36641
  rule: "required",
36607
36642
  type: "bytes",
36608
36643
  id: 2
36644
+ },
36645
+ source_fingerprint: {
36646
+ type: "uint32",
36647
+ id: 3
36609
36648
  }
36610
36649
  }
36611
36650
  },
@@ -38841,6 +38880,28 @@ var nested = {
38841
38880
  }
38842
38881
  }
38843
38882
  },
38883
+ DeviceFindMyTokenUpdate: {
38884
+ fields: {
38885
+ token: {
38886
+ rule: "required",
38887
+ type: "bytes",
38888
+ id: 1
38889
+ }
38890
+ }
38891
+ },
38892
+ DeviceFindMyTokenStateGet: {
38893
+ fields: {
38894
+ }
38895
+ },
38896
+ DeviceFindMyTokenState: {
38897
+ fields: {
38898
+ burned: {
38899
+ rule: "required",
38900
+ type: "bool",
38901
+ id: 1
38902
+ }
38903
+ }
38904
+ },
38844
38905
  DeviceFactoryAck: {
38845
38906
  values: {
38846
38907
  FACTORY_ACK_SUCCESS: 0,
@@ -38971,6 +39032,13 @@ var nested = {
38971
39032
  FW_MGMT_UPDATER_TASK_STATUS_FAILED_ENTRY_OUT_OF_BOUNDS: 10
38972
39033
  }
38973
39034
  },
39035
+ DeviceFirmwareUpdatePhase: {
39036
+ values: {
39037
+ FW_MGMT_UPDATER_PHASE_PREPARE: 0,
39038
+ FW_MGMT_UPDATER_PHASE_INSTALL: 1,
39039
+ FW_MGMT_UPDATER_PHASE_VERIFY: 2
39040
+ }
39041
+ },
38974
39042
  DeviceFirmwareTarget: {
38975
39043
  fields: {
38976
39044
  target_id: {
@@ -38996,6 +39064,24 @@ var nested = {
38996
39064
  },
38997
39065
  DeviceFirmwareUpdateRequest: {
38998
39066
  fields: {
39067
+ reboot_after_update: {
39068
+ type: "bool",
39069
+ id: 1
39070
+ }
39071
+ }
39072
+ },
39073
+ DeviceFirmwareUpdatePhaseInfo: {
39074
+ fields: {
39075
+ phase: {
39076
+ rule: "required",
39077
+ type: "DeviceFirmwareUpdatePhase",
39078
+ id: 1
39079
+ },
39080
+ progress_percent: {
39081
+ rule: "required",
39082
+ type: "uint32",
39083
+ id: 2
39084
+ }
38999
39085
  }
39000
39086
  },
39001
39087
  DeviceFirmwareUpdateRecord: {
@@ -39009,6 +39095,14 @@ var nested = {
39009
39095
  type: "DeviceFirmwareUpdateTaskStatus",
39010
39096
  id: 10
39011
39097
  },
39098
+ progress_percent: {
39099
+ type: "uint32",
39100
+ id: 11
39101
+ },
39102
+ phase_info: {
39103
+ type: "DeviceFirmwareUpdatePhaseInfo",
39104
+ id: 12
39105
+ },
39012
39106
  payload_version: {
39013
39107
  type: "uint32",
39014
39108
  id: 20
@@ -39025,6 +39119,14 @@ var nested = {
39025
39119
  type: "bool",
39026
39120
  id: 10
39027
39121
  },
39122
+ progress_percent: {
39123
+ type: "bool",
39124
+ id: 11
39125
+ },
39126
+ phase_info: {
39127
+ type: "bool",
39128
+ id: 12
39129
+ },
39028
39130
  payload_version: {
39029
39131
  type: "bool",
39030
39132
  id: 20
@@ -39796,6 +39898,10 @@ var nested = {
39796
39898
  text_id: {
39797
39899
  type: "uint32",
39798
39900
  id: 3
39901
+ },
39902
+ text_arg: {
39903
+ type: "string",
39904
+ id: 4
39799
39905
  }
39800
39906
  }
39801
39907
  },
@@ -39863,6 +39969,10 @@ var nested = {
39863
39969
  title_id: {
39864
39970
  type: "uint32",
39865
39971
  id: 8
39972
+ },
39973
+ title_arg: {
39974
+ type: "string",
39975
+ id: 9
39866
39976
  }
39867
39977
  }
39868
39978
  },
@@ -41579,11 +41689,12 @@ const buildDeviceSessionGetRequest = ({ sessionId, expectedPassphraseState, deri
41579
41689
  hdTransport.DeviceSessionSeedDomain.SeedDomain_Standard,
41580
41690
  ...(deriveCardano ? [hdTransport.DeviceSessionSeedDomain.SeedDomain_Cardano] : []),
41581
41691
  ] }));
41582
- const askDevicePassphrase = (device, requestPayload) => __awaiter(void 0, void 0, void 0, function* () {
41692
+ const askDevicePassphrase = (device, requestPayload, onStatusRefreshed) => __awaiter(void 0, void 0, void 0, function* () {
41583
41693
  yield device.commands.typedCall('DeviceSessionAskPassphrase', 'Success', requestPayload);
41584
41694
  yield refreshProtocolV2DeviceStatus(device);
41695
+ onStatusRefreshed === null || onStatusRefreshed === void 0 ? void 0 : onStatusRefreshed();
41585
41696
  });
41586
- const selectDeviceSession = (device, expectedPassphraseState, deriveCardano) => __awaiter(void 0, void 0, void 0, function* () {
41697
+ const selectDeviceSession = (device, expectedPassphraseState, deriveCardano, onStatusRefreshed) => __awaiter(void 0, void 0, void 0, function* () {
41587
41698
  var _a, _b, _c, _d;
41588
41699
  const existsAttachPinUser = ((_a = device.features) === null || _a === void 0 ? void 0 : _a.attachToPinEnabled) === true;
41589
41700
  const metadata = Object.assign({ source: 'wallet-session-coordinator', reason: expectedPassphraseState ? 'session-recovery' : 'open-wallet' }, (expectedPassphraseState ? { expectedPassphraseState } : {}));
@@ -41616,18 +41727,19 @@ const selectDeviceSession = (device, expectedPassphraseState, deriveCardano) =>
41616
41727
  emitUiEvent: false,
41617
41728
  interaction: attachPinInteraction,
41618
41729
  });
41730
+ onStatusRefreshed === null || onStatusRefreshed === void 0 ? void 0 : onStatusRefreshed();
41619
41731
  return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
41620
41732
  }
41621
41733
  if (hasHostPassphrase) {
41622
41734
  yield askDevicePassphrase(device, {
41623
41735
  passphrase: hostPassphrase,
41624
41736
  on_device: false,
41625
- });
41737
+ }, onStatusRefreshed);
41626
41738
  return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
41627
41739
  }
41628
41740
  const passphraseOnDeviceInteraction = (_d = device.createProtocolV2UiPhaseMetadata) === null || _d === void 0 ? void 0 : _d.call(device, 'passphrase-on-device', 'start');
41629
41741
  device.emit(DEVICE.PASSPHRASE_ON_DEVICE, device, Object.assign(Object.assign({}, metadata), (passphraseOnDeviceInteraction ? { interaction: passphraseOnDeviceInteraction } : {})));
41630
- yield askDevicePassphrase(device, { on_device: true });
41742
+ yield askDevicePassphrase(device, { on_device: true }, onStatusRefreshed);
41631
41743
  return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
41632
41744
  });
41633
41745
  function getProtocolV2WalletSession(device, options) {
@@ -41661,9 +41773,15 @@ function getProtocolV2WalletSession(device, options) {
41661
41773
  : undefined;
41662
41774
  let response;
41663
41775
  let resumed = false;
41664
- let mainPinSelected = (options === null || options === void 0 ? void 0 : options.onlyMainPin) === true &&
41665
- ((_d = device.features) === null || _d === void 0 ? void 0 : _d.unlocked) === true &&
41666
- ((_e = device.features) === null || _e === void 0 ? void 0 : _e.unlockedAttachPin) === false;
41776
+ let walletStatusRefreshed = false;
41777
+ const markWalletStatusRefreshed = () => {
41778
+ walletStatusRefreshed = true;
41779
+ };
41780
+ let mainPinAuthenticated = (options === null || options === void 0 ? void 0 : options.mainPinSelected) === true ||
41781
+ ((options === null || options === void 0 ? void 0 : options.onlyMainPin) === true &&
41782
+ ((_d = device.features) === null || _d === void 0 ? void 0 : _d.unlocked) === true &&
41783
+ ((_e = device.features) === null || _e === void 0 ? void 0 : _e.unlockedAttachPin) === false);
41784
+ let standardWalletSelected = (options === null || options === void 0 ? void 0 : options.mainPinSelected) === true;
41667
41785
  const clearCurrentWalletSession = () => {
41668
41786
  var _a;
41669
41787
  if (options === null || options === void 0 ? void 0 : options.onlyMainPin) {
@@ -41676,6 +41794,7 @@ function getProtocolV2WalletSession(device, options) {
41676
41794
  const rejectMismatchedAttachPinWallet = () => __awaiter(this, void 0, void 0, function* () {
41677
41795
  var _k;
41678
41796
  const features = yield refreshProtocolV2DeviceStatus(device);
41797
+ markWalletStatusRefreshed();
41679
41798
  if (features.unlockedAttachPin !== true) {
41680
41799
  return;
41681
41800
  }
@@ -41697,28 +41816,35 @@ function getProtocolV2WalletSession(device, options) {
41697
41816
  yield rejectMismatchedAttachPinWallet();
41698
41817
  }
41699
41818
  const selectMainPin = (force = false) => __awaiter(this, void 0, void 0, function* () {
41700
- if (force || !mainPinSelected) {
41819
+ if (force || !mainPinAuthenticated) {
41701
41820
  yield device.unlockDevice(hdTransport.DeviceSessionPinType.Main, {
41702
41821
  source: 'wallet-session-coordinator',
41703
41822
  reason: expectedPassphraseState ? 'session-recovery' : 'open-wallet',
41704
41823
  deviceOnly: true,
41705
41824
  });
41706
- mainPinSelected = true;
41825
+ markWalletStatusRefreshed();
41826
+ mainPinAuthenticated = true;
41827
+ standardWalletSelected = true;
41707
41828
  }
41708
41829
  });
41709
41830
  const selectStandardWallet = () => __awaiter(this, void 0, void 0, function* () {
41710
41831
  var _m;
41711
- yield selectMainPin();
41712
41832
  if (((_m = device.features) === null || _m === void 0 ? void 0 : _m.passphraseProtection) === true) {
41833
+ yield selectMainPin();
41713
41834
  yield askDevicePassphrase(device, {
41714
41835
  passphrase: '',
41715
41836
  on_device: false,
41716
- });
41837
+ }, markWalletStatusRefreshed);
41838
+ standardWalletSelected = true;
41839
+ }
41840
+ else if (!standardWalletSelected) {
41841
+ yield selectMainPin(true);
41717
41842
  }
41718
41843
  });
41719
41844
  if (readCurrentAttachPinSession) {
41720
41845
  const status = yield requestProtocolV2DeviceStatus$1(device);
41721
41846
  device.updateProtocolV2Status(status);
41847
+ markWalletStatusRefreshed();
41722
41848
  if (status.unlocked !== true ||
41723
41849
  status.passphrase_enabled !== true ||
41724
41850
  status.unlocked_by_attach_to_pin !== true) {
@@ -41789,7 +41915,7 @@ function getProtocolV2WalletSession(device, options) {
41789
41915
  device.clearInternalState();
41790
41916
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WalletSessionInvalid);
41791
41917
  }
41792
- response = yield selectDeviceSession(device, expectedPassphraseState, options === null || options === void 0 ? void 0 : options.deriveCardano);
41918
+ response = yield selectDeviceSession(device, expectedPassphraseState, options === null || options === void 0 ? void 0 : options.deriveCardano, markWalletStatusRefreshed);
41793
41919
  }
41794
41920
  let { message } = response;
41795
41921
  try {
@@ -41818,7 +41944,7 @@ function getProtocolV2WalletSession(device, options) {
41818
41944
  }
41819
41945
  else {
41820
41946
  device.clearInternalState();
41821
- response = yield selectDeviceSession(device, expectedPassphraseState, options === null || options === void 0 ? void 0 : options.deriveCardano);
41947
+ response = yield selectDeviceSession(device, expectedPassphraseState, options === null || options === void 0 ? void 0 : options.deriveCardano, markWalletStatusRefreshed);
41822
41948
  }
41823
41949
  message = response.message;
41824
41950
  try {
@@ -41856,7 +41982,7 @@ function getProtocolV2WalletSession(device, options) {
41856
41982
  if (readCurrentAttachPinSession) {
41857
41983
  unlockedAttachPin = true;
41858
41984
  }
41859
- else if (mainPinSelected) {
41985
+ else if (mainPinAuthenticated) {
41860
41986
  unlockedAttachPin = false;
41861
41987
  }
41862
41988
  return {
@@ -41864,6 +41990,7 @@ function getProtocolV2WalletSession(device, options) {
41864
41990
  newSession: message.session_id,
41865
41991
  unlockedAttachPin,
41866
41992
  resumed,
41993
+ walletStatusRefreshed,
41867
41994
  };
41868
41995
  });
41869
41996
  }
@@ -41931,6 +42058,7 @@ const getPassphraseStateWithRefreshDeviceInfo = (device, options) => __awaiter(v
41931
42058
  onlyMainPin: options === null || options === void 0 ? void 0 : options.onlyMainPin,
41932
42059
  deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano,
41933
42060
  rejectAttachPinForMainWallet: options === null || options === void 0 ? void 0 : options.rejectAttachPinForMainWallet,
42061
+ mainPinSelected: options === null || options === void 0 ? void 0 : options.mainPinSelected,
41934
42062
  });
41935
42063
  }
41936
42064
  const { features } = device;
@@ -41976,6 +42104,7 @@ const getPassphraseState = (device, options) => __awaiter(void 0, void 0, void 0
41976
42104
  onlyMainPin: options === null || options === void 0 ? void 0 : options.onlyMainPin,
41977
42105
  deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano,
41978
42106
  rejectAttachPinForMainWallet: options === null || options === void 0 ? void 0 : options.rejectAttachPinForMainWallet,
42107
+ mainPinSelected: options === null || options === void 0 ? void 0 : options.mainPinSelected,
41979
42108
  });
41980
42109
  }
41981
42110
  const supportAttachPinCapability = existCapability(features, hdTransport.Enum_Capability.Capability_AttachToPin);
@@ -46460,7 +46589,7 @@ class Device extends events.exports {
46460
46589
  return Promise.resolve(features);
46461
46590
  });
46462
46591
  }
46463
- checkPassphraseStateSafety(passphraseState, useEmptyPassphrase, skipPassphraseCheck, deriveCardano) {
46592
+ checkPassphraseStateSafety(passphraseState, useEmptyPassphrase, skipPassphraseCheck, deriveCardano, mainPinSelected) {
46464
46593
  return __awaiter(this, void 0, void 0, function* () {
46465
46594
  if (this.isUnacquired())
46466
46595
  return false;
@@ -46470,6 +46599,7 @@ class Device extends events.exports {
46470
46599
  onlyMainPin: useEmptyPassphrase,
46471
46600
  deriveCardano,
46472
46601
  rejectAttachPinForMainWallet: useEmptyPassphrase === true,
46602
+ mainPinSelected,
46473
46603
  });
46474
46604
  const mainWalletUseAttachPin = unlockedAttachPin && useEmptyPassphrase;
46475
46605
  const useErrorAttachPin = unlockedAttachPin &&
@@ -47294,6 +47424,10 @@ const wasResumed = (session) => !!session &&
47294
47424
  typeof session === 'object' &&
47295
47425
  'resumed' in session &&
47296
47426
  session.resumed === true;
47427
+ const wasWalletStatusRefreshed = (session) => !!session &&
47428
+ typeof session === 'object' &&
47429
+ 'walletStatusRefreshed' in session &&
47430
+ session.walletStatusRefreshed === true;
47297
47431
  const requireHiddenWalletResponse = (session) => {
47298
47432
  if (!session.passphraseState) {
47299
47433
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInitializeFailed, 'Hidden wallet response is missing passphraseState');
@@ -47336,12 +47470,20 @@ class OpenWalletSession extends BaseMethod {
47336
47470
  this.unlockPolicy = 'unlock-before-run';
47337
47471
  this.skipForceUpdateCheck = true;
47338
47472
  this.params = normalizeParams(this.payload);
47473
+ this.protocolV2PreUnlockPinType =
47474
+ this.params.mode === OpenWalletSessionMode.SelectHidden
47475
+ ? hdTransport.DeviceSessionPinType.Any
47476
+ : hdTransport.DeviceSessionPinType.Main;
47339
47477
  this.payload.useEmptyPassphrase = this.params.mode === OpenWalletSessionMode.Standard;
47340
47478
  }
47341
47479
  run() {
47480
+ var _a, _b;
47342
47481
  return __awaiter(this, void 0, void 0, function* () {
47343
47482
  const isProtocolV2 = this.device.isProtocolV2();
47344
- let state = yield this.device.getDeviceState({ refreshSections: ['status'] });
47483
+ const reusePreflightStatus = isProtocolV2 && ((_a = this.protocolV2UnlockContext) === null || _a === void 0 ? void 0 : _a.preflightStatusRefreshed) === true;
47484
+ let state = reusePreflightStatus
47485
+ ? yield this.device.getDeviceState()
47486
+ : yield this.device.getDeviceState({ refreshSections: ['status'] });
47345
47487
  let currentDeviceId = state.identity.deviceId;
47346
47488
  const hasAuthoritativeProtocolV2WalletStatus = (candidate) => candidate.status.unlocked === true &&
47347
47489
  typeof candidate.status.passphraseProtection === 'boolean' &&
@@ -47363,9 +47505,18 @@ class OpenWalletSession extends BaseMethod {
47363
47505
  currentDeviceId = state.identity.deviceId;
47364
47506
  return state;
47365
47507
  });
47508
+ const resolveProtocolV2DeviceStateAfterSession = (session) => __awaiter(this, void 0, void 0, function* () {
47509
+ if (!wasWalletStatusRefreshed(session)) {
47510
+ return refreshProtocolV2DeviceState();
47511
+ }
47512
+ state = yield this.device.getDeviceState();
47513
+ currentDeviceId = state.identity.deviceId;
47514
+ return state;
47515
+ });
47366
47516
  const ensureProtocolV2WalletStatus = () => __awaiter(this, void 0, void 0, function* () {
47517
+ var _d;
47367
47518
  if (isProtocolV2 && !hasAuthoritativeProtocolV2WalletStatus(state)) {
47368
- yield this.device.unlockDevice(hdTransport.DeviceSessionPinType.Main, {
47519
+ yield this.device.unlockDevice((_d = this.protocolV2PreUnlockPinType) !== null && _d !== void 0 ? _d : hdTransport.DeviceSessionPinType.Main, {
47369
47520
  source: 'unlock-coordinator',
47370
47521
  reason: 'device-locked',
47371
47522
  deviceOnly: true,
@@ -47384,13 +47535,14 @@ class OpenWalletSession extends BaseMethod {
47384
47535
  deriveCardano: this.payload.deriveCardano,
47385
47536
  selectMainWalletBeforeRestore: !hasAuthoritativeProtocolV2WalletStatus(state) ||
47386
47537
  state.status.unlockedAttachPin === true,
47538
+ mainPinSelected: (_b = this.protocolV2UnlockContext) === null || _b === void 0 ? void 0 : _b.preflightMainPinSelected,
47387
47539
  })
47388
47540
  : yield getPassphraseStateWithRefreshDeviceInfo(this.device, {
47389
47541
  onlyMainPin: true,
47390
47542
  initSession: this.payload.initSession,
47391
47543
  });
47392
47544
  const refreshedState = isProtocolV2
47393
- ? requireAuthoritativeProtocolV2WalletStatus(yield refreshProtocolV2DeviceState())
47545
+ ? requireAuthoritativeProtocolV2WalletStatus(yield resolveProtocolV2DeviceStateAfterSession(session))
47394
47546
  : state;
47395
47547
  const deviceId = requireDeviceId();
47396
47548
  if (session.unlockedAttachPin ||
@@ -47398,7 +47550,7 @@ class OpenWalletSession extends BaseMethod {
47398
47550
  try {
47399
47551
  yield this.device.lockDevice();
47400
47552
  }
47401
- catch (_a) {
47553
+ catch (_c) {
47402
47554
  }
47403
47555
  this.device.clearInternalState();
47404
47556
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckUnlockTypeError);
@@ -47462,7 +47614,7 @@ class OpenWalletSession extends BaseMethod {
47462
47614
  : { forceWalletSelection: true })), { deriveCardano: this.payload.deriveCardano }))
47463
47615
  : yield getPassphraseStateWithRefreshDeviceInfo(this.device, { initSession: true });
47464
47616
  const refreshedState = isProtocolV2
47465
- ? requireAuthoritativeProtocolV2WalletStatus(yield refreshProtocolV2DeviceState())
47617
+ ? requireAuthoritativeProtocolV2WalletStatus(yield resolveProtocolV2DeviceStateAfterSession(session))
47466
47618
  : state;
47467
47619
  const deviceId = requireDeviceId();
47468
47620
  if (isProtocolV2 && refreshedState.status.passphraseProtection !== true) {
@@ -51708,14 +51860,289 @@ const INSTALLABLE_FIRMWARE_TARGET_IDS = new Set([
51708
51860
  ]);
51709
51861
  new Map(Object.entries(ProtocolV2FirmwareTargetType).flatMap(([key, value]) => INSTALLABLE_FIRMWARE_TARGET_IDS.has(value) ? [[key, value]] : []));
51710
51862
 
51711
- const Log$7 = getLogger(exports.LoggerNames.Method);
51863
+ const Log$7 = getLogger(exports.LoggerNames.Core);
51864
+ const MIN_FILE_CHUNK_SIZE = 64;
51865
+ const FILE_TRANSFER_RATE_WINDOW_MS = 1000;
51866
+ const FILE_TRANSFER_LOG_INTERVAL_MS = 10000;
51712
51867
  const SESSION_ERROR$1 = 'session not found';
51868
+ function formatFileTransferRate(bytesPerSecond) {
51869
+ return (Math.max(bytesPerSecond, 0) / 1024).toFixed(2);
51870
+ }
51871
+ function getAverageFileTransferRate(transferredBytes, elapsedMs) {
51872
+ if (elapsedMs <= 0)
51873
+ return 0;
51874
+ return Math.round((Math.max(transferredBytes, 0) / elapsedMs) * 1000);
51875
+ }
51876
+ function getFileTransferTransport() {
51877
+ const env = DataManager.getSettings('env');
51878
+ return env && DataManager.isBleConnect(env) ? 'BLE' : String(env !== null && env !== void 0 ? env : 'unknown');
51879
+ }
51880
+ function logFileTransferMetrics({ transport, status, path, transferredBytes, totalBytes, elapsedMs, rateBytesPerSecond, hostWriteElapsedMs, responseWaitElapsedMs, measuredAttempts, }) {
51881
+ const segmentedMetrics = measuredAttempts > 0
51882
+ ? ` hostWriteTotal=${(hostWriteElapsedMs / 1000).toFixed(2)}s responseWaitTotal=${(responseWaitElapsedMs / 1000).toFixed(2)}s measuredAttempts=${measuredAttempts}`
51883
+ : '';
51884
+ Log$7.log(`[FileWrite] metrics transport=${transport} status=${status} path=${path} bytes=${transferredBytes}/${totalBytes} elapsed=${(elapsedMs / 1000).toFixed(2)}s speed=${formatFileTransferRate(rateBytesPerSecond)} KiB/s${segmentedMetrics}`);
51885
+ }
51886
+ function isProtocolV2ResponseTimeout(error) {
51887
+ var _a, _b;
51888
+ if (!error || typeof error !== 'object')
51889
+ return false;
51890
+ const candidate = error;
51891
+ const code = (_a = candidate.errorCode) !== null && _a !== void 0 ? _a : candidate.code;
51892
+ return (code === hdShared.HardwareErrorCode.BleTimeoutError ||
51893
+ code === 'response-timeout' ||
51894
+ /(?:BLE|Lowlevel|Protocol V2) response timeout/i.test((_b = candidate.message) !== null && _b !== void 0 ? _b : ''));
51895
+ }
51896
+ function getProtocolV2FileChunkLimit() {
51897
+ const env = DataManager.getSettings('env');
51898
+ return env && DataManager.isBleConnect(env)
51899
+ ? hdTransport.PROTOCOL_V2_BLE_FILE_CHUNK_SIZE
51900
+ : hdTransport.PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE;
51901
+ }
51902
+ function dataToUint8Array(data) {
51903
+ return __awaiter(this, void 0, void 0, function* () {
51904
+ if (typeof data === 'string')
51905
+ return new TextEncoder().encode(data);
51906
+ if (data instanceof ArrayBuffer)
51907
+ return new Uint8Array(data);
51908
+ if (ArrayBuffer.isView(data)) {
51909
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
51910
+ }
51911
+ if (typeof Blob !== 'undefined' && data instanceof Blob) {
51912
+ return new Uint8Array(yield data.arrayBuffer());
51913
+ }
51914
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Unsupported FilesystemFileWrite data');
51915
+ });
51916
+ }
51917
+ function normalizeChunkSize(value, maxChunkSize) {
51918
+ const numeric = Number(value);
51919
+ if (!Number.isFinite(numeric) || numeric <= 0)
51920
+ return maxChunkSize;
51921
+ return Math.min(Math.max(Math.floor(numeric), MIN_FILE_CHUNK_SIZE), maxChunkSize);
51922
+ }
51923
+ function getDeviceTransferProgress(before, after, total) {
51924
+ if (!Number.isFinite(total) || total <= 0)
51925
+ return 100;
51926
+ if (before <= 0 && after < total)
51927
+ return 0;
51928
+ if (after >= total)
51929
+ return 100;
51930
+ return Math.min(Math.max(Math.ceil((after / total) * 100), 1), 99);
51931
+ }
51932
+ function getConfirmedProgress(processed, total, written, length) {
51933
+ if (Number.isFinite(processed) && Number.isFinite(total) && total > 0) {
51934
+ if (processed >= total)
51935
+ return 100;
51936
+ return Math.min(Math.max(Math.floor((processed / total) * 100), 0), 99);
51937
+ }
51938
+ if (length > 0)
51939
+ return written >= length ? 100 : Math.floor((written / length) * 100);
51940
+ return 100;
51941
+ }
51942
+ function writeProtocolV2File(options) {
51943
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
51944
+ return __awaiter(this, void 0, void 0, function* () {
51945
+ (_a = options.throwIfAborted) === null || _a === void 0 ? void 0 : _a.call(options);
51946
+ const data = yield dataToUint8Array(options.data);
51947
+ const dataLength = data.byteLength;
51948
+ const startOffset = Number.isFinite(options.offset) && Number(options.offset) > 0 ? Number(options.offset) : 0;
51949
+ const totalSize = Number.isFinite(options.totalSize) && Number(options.totalSize) > 0
51950
+ ? Number(options.totalSize)
51951
+ : startOffset + dataLength;
51952
+ if (totalSize < startOffset + dataLength) {
51953
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `FilesystemFileWrite totalSize ${totalSize} is smaller than offset + data length ${startOffset + dataLength}`);
51954
+ }
51955
+ const defaultChunkSizeLimit = getProtocolV2FileChunkLimit();
51956
+ const configuredChunkSizeLimit = Number(options.chunkSizeLimit);
51957
+ const chunkSizeLimit = Number.isFinite(configuredChunkSizeLimit) && configuredChunkSizeLimit > 0
51958
+ ? Math.floor(configuredChunkSizeLimit)
51959
+ : defaultChunkSizeLimit;
51960
+ const chunkSize = normalizeChunkSize((_b = options.chunkSize) !== null && _b !== void 0 ? _b : options.chunkLen, chunkSizeLimit);
51961
+ let written = 0;
51962
+ let chunks = 0;
51963
+ let lastMessage;
51964
+ const startTime = Date.now();
51965
+ let rateWindowStartedAt = startTime;
51966
+ let rateWindowStartedBytes = 0;
51967
+ let rateBytesPerSecond;
51968
+ let lastConfirmedAt = startTime;
51969
+ let logWindowStartedAt = startTime;
51970
+ let logWindowStartedBytes = 0;
51971
+ let hostWriteElapsedMs = 0;
51972
+ let responseWaitElapsedMs = 0;
51973
+ let measuredAttempts = 0;
51974
+ const transport = getFileTransferTransport();
51975
+ Log$7.log(`[FileWrite] started transport=${transport} path=${options.path} bytes=${dataLength} offset=${startOffset} chunk=${chunkSize}`);
51976
+ try {
51977
+ while (written < dataLength) {
51978
+ (_c = options.throwIfAborted) === null || _c === void 0 ? void 0 : _c.call(options);
51979
+ const chunk = data.slice(written, Math.min(written + chunkSize, dataLength));
51980
+ const offset = startOffset + written;
51981
+ const progress = (_f = (_d = options.uiPercentage) !== null && _d !== void 0 ? _d : (_e = options.getUiPercentage) === null || _e === void 0 ? void 0 : _e.call(options, {
51982
+ offset,
51983
+ chunkLength: chunk.byteLength,
51984
+ totalSize,
51985
+ })) !== null && _f !== void 0 ? _f : getDeviceTransferProgress(offset, offset + chunk.byteLength, totalSize);
51986
+ const request = {
51987
+ file: { path: options.path, offset, total_size: totalSize, data: chunk },
51988
+ overwrite: chunks === 0 ? (_g = options.overwrite) !== null && _g !== void 0 ? _g : false : false,
51989
+ append: (_h = options.append) !== null && _h !== void 0 ? _h : false,
51990
+ ui_percentage: progress,
51991
+ };
51992
+ const maxChunkRetries = Math.max(Math.floor((_j = options.maxChunkRetries) !== null && _j !== void 0 ? _j : 0), 0);
51993
+ let retryCount = 0;
51994
+ let response;
51995
+ let isWritePending = true;
51996
+ while (isWritePending) {
51997
+ let currentHostWriteElapsedMs;
51998
+ let responseWaitStartedAt;
51999
+ try {
52000
+ const callOptions = options.writeWithResponse === undefined
52001
+ ? {
52002
+ timeoutMs: options.timeoutMs,
52003
+ onWriteCompleted: ({ elapsedMs }) => {
52004
+ currentHostWriteElapsedMs = elapsedMs;
52005
+ responseWaitStartedAt = Date.now();
52006
+ },
52007
+ }
52008
+ : Object.assign(Object.assign({}, (options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs })), { writeWithResponse: options.writeWithResponse, onWriteCompleted: ({ elapsedMs }) => {
52009
+ currentHostWriteElapsedMs = elapsedMs;
52010
+ responseWaitStartedAt = Date.now();
52011
+ } });
52012
+ response = yield options.commands.typedCall('FilesystemFileWrite', 'FilesystemFile', request, callOptions);
52013
+ isWritePending = false;
52014
+ }
52015
+ catch (error) {
52016
+ if (retryCount >= maxChunkRetries || !isProtocolV2ResponseTimeout(error))
52017
+ throw error;
52018
+ retryCount += 1;
52019
+ (_k = options.throwIfAborted) === null || _k === void 0 ? void 0 : _k.call(options);
52020
+ }
52021
+ finally {
52022
+ if (currentHostWriteElapsedMs !== undefined && responseWaitStartedAt !== undefined) {
52023
+ hostWriteElapsedMs += currentHostWriteElapsedMs;
52024
+ responseWaitElapsedMs += Math.max(Date.now() - responseWaitStartedAt, 0);
52025
+ measuredAttempts += 1;
52026
+ }
52027
+ }
52028
+ }
52029
+ if (!response) {
52030
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'FilesystemFileWrite completed without a response');
52031
+ }
52032
+ const responseType = response.type;
52033
+ if (responseType && responseType !== 'FilesystemFile') {
52034
+ const responseError = (_l = response.message) === null || _l === void 0 ? void 0 : _l.error;
52035
+ if (typeof responseError === 'string' && responseError.includes(SESSION_ERROR$1)) {
52036
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, SESSION_ERROR$1);
52037
+ }
52038
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `FilesystemFileWrite received unexpected response ${responseType}`);
52039
+ }
52040
+ (_m = options.throwIfAborted) === null || _m === void 0 ? void 0 : _m.call(options);
52041
+ lastMessage = response.message;
52042
+ const rawProcessedByte = (_o = response.message) === null || _o === void 0 ? void 0 : _o.processed_byte;
52043
+ const processedByte = Number(rawProcessedByte);
52044
+ if (rawProcessedByte !== undefined &&
52045
+ (!Number.isFinite(processedByte) ||
52046
+ processedByte <= offset ||
52047
+ processedByte > offset + chunk.byteLength)) {
52048
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `FilesystemFileWrite invalid processed_byte ${processedByte}`);
52049
+ }
52050
+ written =
52051
+ rawProcessedByte === undefined ? written + chunk.byteLength : processedByte - startOffset;
52052
+ chunks += 1;
52053
+ const now = Date.now();
52054
+ lastConfirmedAt = now;
52055
+ const elapsedMs = now - startTime;
52056
+ const transferredBytes = Math.min(written, dataLength);
52057
+ const rateWindowElapsedMs = now - rateWindowStartedAt;
52058
+ if (rateWindowElapsedMs >= FILE_TRANSFER_RATE_WINDOW_MS) {
52059
+ const rateWindowBytes = Math.max(transferredBytes - rateWindowStartedBytes, 0);
52060
+ rateBytesPerSecond = Math.round((rateWindowBytes / rateWindowElapsedMs) * 1000);
52061
+ rateWindowStartedAt = now;
52062
+ rateWindowStartedBytes = transferredBytes;
52063
+ }
52064
+ else if (rateBytesPerSecond === undefined && elapsedMs > 0) {
52065
+ rateBytesPerSecond = Math.round((transferredBytes / elapsedMs) * 1000);
52066
+ }
52067
+ (_p = options.onProgress) === null || _p === void 0 ? void 0 : _p.call(options, {
52068
+ progress: getConfirmedProgress(startOffset + written, totalSize, written, dataLength),
52069
+ transferredBytes,
52070
+ totalBytes: dataLength,
52071
+ rateBytesPerSecond,
52072
+ elapsedMs,
52073
+ });
52074
+ const logWindowElapsedMs = now - logWindowStartedAt;
52075
+ if (logWindowElapsedMs >= FILE_TRANSFER_LOG_INTERVAL_MS && transferredBytes < dataLength) {
52076
+ const logWindowBytes = Math.max(transferredBytes - logWindowStartedBytes, 0);
52077
+ logFileTransferMetrics({
52078
+ transport,
52079
+ status: 'progress',
52080
+ path: options.path,
52081
+ transferredBytes,
52082
+ totalBytes: dataLength,
52083
+ elapsedMs,
52084
+ rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
52085
+ hostWriteElapsedMs,
52086
+ responseWaitElapsedMs,
52087
+ measuredAttempts,
52088
+ });
52089
+ logWindowStartedAt = now;
52090
+ logWindowStartedBytes = transferredBytes;
52091
+ }
52092
+ if (options.paceMs && options.paceMs > 0) {
52093
+ yield new Promise(resolve => {
52094
+ setTimeout(resolve, options.paceMs);
52095
+ });
52096
+ }
52097
+ }
52098
+ }
52099
+ catch (error) {
52100
+ const now = Date.now();
52101
+ const elapsedMs = Math.max(now - startTime, 0);
52102
+ const logWindowElapsedMs = Math.max(now - logWindowStartedAt, 0);
52103
+ const logWindowBytes = Math.max(written - logWindowStartedBytes, 0);
52104
+ logFileTransferMetrics({
52105
+ transport,
52106
+ status: 'failed',
52107
+ path: options.path,
52108
+ transferredBytes: written,
52109
+ totalBytes: dataLength,
52110
+ elapsedMs,
52111
+ rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
52112
+ hostWriteElapsedMs,
52113
+ responseWaitElapsedMs,
52114
+ measuredAttempts,
52115
+ });
52116
+ throw error;
52117
+ }
52118
+ const elapsedMs = Math.max(lastConfirmedAt - startTime, 0);
52119
+ const logWindowElapsedMs = Math.max(lastConfirmedAt - logWindowStartedAt, 0);
52120
+ const logWindowBytes = Math.max(written - logWindowStartedBytes, 0);
52121
+ logFileTransferMetrics({
52122
+ transport,
52123
+ status: 'completed',
52124
+ path: options.path,
52125
+ transferredBytes: written,
52126
+ totalBytes: dataLength,
52127
+ elapsedMs,
52128
+ rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
52129
+ hostWriteElapsedMs,
52130
+ responseWaitElapsedMs,
52131
+ measuredAttempts,
52132
+ });
52133
+ return Object.assign(Object.assign({}, lastMessage), { path: options.path, offset: startOffset, total_size: totalSize, processed_byte: startOffset + written, chunks });
52134
+ });
52135
+ }
52136
+
52137
+ const Log$6 = getLogger(exports.LoggerNames.Method);
52138
+ const SESSION_ERROR = 'session not found';
51713
52139
  const PROTOCOL_V2_BOOTLOADER_RECONNECT_TIMEOUT = 90 * 1000;
51714
52140
  const PROTOCOL_V2_FINAL_RECONNECT_TIMEOUT = 3 * 60 * 1000;
51715
52141
  const PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT = 5 * 1000;
51716
52142
  const PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT = 15 * 1000;
51717
52143
  const PROTOCOL_V2_INSTALL_TIMEOUT = 5 * 60 * 1000;
51718
52144
  const PROTOCOL_V2_INSTALL_STATUS_INITIAL_DELAY = 1000;
52145
+ const PROTOCOL_V2_INSTALL_FINISHED_AFTER_RECONNECT_POLLS = 4;
51719
52146
  const PROTOCOL_V2_TARGET_STATUS_PENDING = 0;
51720
52147
  const PROTOCOL_V2_TARGET_STATUS_IN_PROGRESS = 1;
51721
52148
  const PROTOCOL_V2_TARGET_STATUS_FINISHED = 2;
@@ -51871,11 +52298,12 @@ const isProtocolV2FirmwareStatusEndpointUnavailable = (error) => {
51871
52298
  };
51872
52299
  const isProtocolV2TerminalInstallStatusError = (error) => {
51873
52300
  var _a;
51874
- return error instanceof hdShared.HardwareError &&
51875
- (error.errorCode === hdShared.HardwareErrorCode.ActionCancelled ||
51876
- error.errorCode === hdShared.HardwareErrorCode.FirmwareError ||
51877
- error.errorCode === hdShared.HardwareErrorCode.FirmwareVerificationFailed ||
51878
- ((_a = error.params) === null || _a === void 0 ? void 0 : _a.firmwareUpdateCode) === PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE);
52301
+ return hdShared.isBleStaleBondHardwareError(error) ||
52302
+ (error instanceof hdShared.HardwareError &&
52303
+ (error.errorCode === hdShared.HardwareErrorCode.ActionCancelled ||
52304
+ error.errorCode === hdShared.HardwareErrorCode.FirmwareError ||
52305
+ error.errorCode === hdShared.HardwareErrorCode.FirmwareVerificationFailed ||
52306
+ ((_a = error.params) === null || _a === void 0 ? void 0 : _a.firmwareUpdateCode) === PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE));
51879
52307
  };
51880
52308
  const isProtocolV2TargetStatusFinished = (status) => normalizeProtocolV2TargetStatus(status) === PROTOCOL_V2_TARGET_STATUS_FINISHED;
51881
52309
  const isProtocolV2TargetStatusInProgress = (status) => normalizeProtocolV2TargetStatus(status) === PROTOCOL_V2_TARGET_STATUS_PENDING ||
@@ -51899,6 +52327,14 @@ const normalizeProtocolV2TargetStatus = (status) => {
51899
52327
  }
51900
52328
  return undefined;
51901
52329
  };
52330
+ const PROTOCOL_V2_INSTALL_PHASE_BY_DECODED_VALUE = new Map([
52331
+ [0, 'prepare'],
52332
+ [1, 'install'],
52333
+ [2, 'verify'],
52334
+ ['FW_MGMT_UPDATER_PHASE_PREPARE', 'prepare'],
52335
+ ['FW_MGMT_UPDATER_PHASE_INSTALL', 'install'],
52336
+ ['FW_MGMT_UPDATER_PHASE_VERIFY', 'verify'],
52337
+ ]);
51902
52338
  const normalizeProtocolV2Hex = (value) => value === null || value === void 0 ? void 0 : value.replace(/^0x/i, '').toLowerCase();
51903
52339
  const versionArrayToNumber = (version) => {
51904
52340
  if (!version)
@@ -51954,6 +52390,10 @@ const toProtocolV2FiniteNumber = (value) => {
51954
52390
  }
51955
52391
  return undefined;
51956
52392
  };
52393
+ const normalizeProtocolV2ProgressPercent = (value) => {
52394
+ const progress = toProtocolV2FiniteNumber(value);
52395
+ return progress === undefined ? undefined : Math.min(100, Math.max(0, progress));
52396
+ };
51957
52397
  const isProtocolV2FirmwareFingerprintValid = (binary, fingerprint) => {
51958
52398
  const expectedFingerprint = normalizeProtocolV2Hex(fingerprint);
51959
52399
  if (!expectedFingerprint)
@@ -52154,7 +52594,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52154
52594
  }
52155
52595
  run() {
52156
52596
  return __awaiter(this, void 0, void 0, function* () {
52157
- Log$7.debug('FirmwareUpdateV4 strategy: Protocol V2');
52597
+ Log$6.debug('FirmwareUpdateV4 strategy: Protocol V2');
52158
52598
  return this.runProtocolV2();
52159
52599
  });
52160
52600
  }
@@ -52586,7 +53026,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52586
53026
  if (!observedVersion) {
52587
53027
  const hasCompleteTargetEvidence = targetId !== undefined && this.protocolV2CompletedTargetIds.has(targetId);
52588
53028
  if (hasCompleteTargetEvidence) {
52589
- Log$7.warn(`Protocol V2 target ${target} has no observable final version; install completion is authoritative`);
53029
+ Log$6.warn(`Protocol V2 target ${target} has no observable final version; install completion is authoritative`);
52590
53030
  }
52591
53031
  else {
52592
53032
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareVerificationFailed, `Protocol V2 target ${target} has no observable final version after status fallback`);
@@ -52949,7 +53389,10 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52949
53389
  return true;
52950
53390
  }
52951
53391
  catch (error) {
52952
- Log$7.log(`[FirmwareUpdateV4] RESC bundle ${bundle.name} header check failed: `, error);
53392
+ if (hdShared.isBleStaleBondHardwareError(error)) {
53393
+ throw error;
53394
+ }
53395
+ Log$6.log(`[FirmwareUpdateV4] RESC bundle ${bundle.name} header check failed: `, error);
52953
53396
  return false;
52954
53397
  }
52955
53398
  });
@@ -52989,7 +53432,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52989
53432
  if (error instanceof hdShared.HardwareError) {
52990
53433
  throw error;
52991
53434
  }
52992
- Log$7.log('Protocol V2 auto go to bootloader mode failed: ', error);
53435
+ Log$6.log('Protocol V2 auto go to bootloader mode failed: ', error);
52993
53436
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateAutoEnterBootFailure);
52994
53437
  }
52995
53438
  });
@@ -52997,12 +53440,12 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52997
53440
  enterProtocolV2BootloaderMode() {
52998
53441
  return __awaiter(this, void 0, void 0, function* () {
52999
53442
  if (this.isProtocolV2RomloaderMode()) {
53000
- Log$7.debug('Protocol V2 device is in romloader mode; start firmware update directly');
53443
+ Log$6.debug('Protocol V2 device is in romloader mode; start firmware update directly');
53001
53444
  this.protocolV2ExecutionInLoader = true;
53002
53445
  return false;
53003
53446
  }
53004
53447
  if (this.isProtocolV2BootloaderMode()) {
53005
- Log$7.debug('Protocol V2 device is already in bootloader mode, skip reboot');
53448
+ Log$6.debug('Protocol V2 device is already in bootloader mode, skip reboot');
53006
53449
  this.protocolV2ExecutionInLoader = true;
53007
53450
  this.postTipMessage(exports.FirmwareUpdateTipMessage.GoToBootloaderSuccess);
53008
53451
  return false;
@@ -53033,12 +53476,12 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53033
53476
  lastError = new Error('Protocol V2 device is reachable but is not in bootloader mode');
53034
53477
  }
53035
53478
  catch (error) {
53036
- if (this.isProtocolV2ReconnectIdentityError(error)) {
53479
+ if (hdShared.isBleStaleBondHardwareError(error) || this.isProtocolV2ReconnectIdentityError(error)) {
53037
53480
  throw error;
53038
53481
  }
53039
53482
  shouldReconnect = true;
53040
53483
  lastError = error;
53041
- Log$7.log('Protocol V2 bootloader mode not ready, polling reconnect: ', error);
53484
+ Log$6.log('Protocol V2 bootloader mode not ready, polling reconnect: ', error);
53042
53485
  }
53043
53486
  yield hdShared.wait(retryInterval);
53044
53487
  }
@@ -53134,7 +53577,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53134
53577
  const resourcesToSync = [];
53135
53578
  for (const resource of resourceSources) {
53136
53579
  if (yield this.isProtocolV2ResourceBundleUpToDate(resource)) {
53137
- Log$7.log(`[FirmwareUpdateV4] skip RESC bundle ${resource.name}; already up to date`);
53580
+ Log$6.log(`[FirmwareUpdateV4] skip RESC bundle ${resource.name}; already up to date`);
53138
53581
  }
53139
53582
  else {
53140
53583
  resourcesToSync.push(resource);
@@ -53236,6 +53679,9 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53236
53679
  return processedSize + source.size;
53237
53680
  }
53238
53681
  catch (error) {
53682
+ if (hdShared.isBleStaleBondHardwareError(error)) {
53683
+ throw error;
53684
+ }
53239
53685
  lastError = error;
53240
53686
  if (attempt < PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT) {
53241
53687
  yield this.recoverProtocolV2FileTransfer();
@@ -53271,7 +53717,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53271
53717
  }
53272
53718
  assertProtocolV2TargetStatus(statusTargets, expectedTargetIds, expectedPaths, liveTargetIds) {
53273
53719
  const resolvedExpectedPaths = expectedPaths !== null && expectedPaths !== void 0 ? expectedPaths : new Map();
53274
- Log$7.log(`[FirmwareUpdateV4] DeviceFirmwareUpdateStatus records=${JSON.stringify(statusTargets)}`);
53720
+ Log$6.log(`[FirmwareUpdateV4] DeviceFirmwareUpdateStatus records=${JSON.stringify(statusTargets)}`);
53275
53721
  const failedTarget = statusTargets.find(target => {
53276
53722
  var _a;
53277
53723
  const targetId = (_a = normalizeProtocolV2TargetId(target.target_id)) !== null && _a !== void 0 ? _a : -1;
@@ -53286,7 +53732,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53286
53732
  payloadVersion: failedTarget.payload_version,
53287
53733
  path: failedTarget.path,
53288
53734
  });
53289
- Log$7.error(`[FirmwareUpdateV4] firmware install failed target=${failedTargetDetails}`);
53735
+ Log$6.error(`[FirmwareUpdateV4] firmware install failed target=${failedTargetDetails}`);
53290
53736
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, 'Protocol V2 firmware install failed', {
53291
53737
  firmwareUpdateCode: PROTOCOL_V2_INSTALL_FAILED_CODE,
53292
53738
  });
@@ -53300,7 +53746,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53300
53746
  !liveTargetIds.has(targetId));
53301
53747
  });
53302
53748
  if (staleFailedTargets.length > 0) {
53303
- Log$7.log(`[FirmwareUpdateV4] ignoring stale failed firmware status until those targets start: ${JSON.stringify(staleFailedTargets.map(target => ({
53749
+ Log$6.log(`[FirmwareUpdateV4] ignoring stale failed firmware status until those targets start: ${JSON.stringify(staleFailedTargets.map(target => ({
53304
53750
  targetId: target.target_id,
53305
53751
  status: target.status,
53306
53752
  path: target.path,
@@ -53311,14 +53757,15 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53311
53757
  const seenTargetIds = new Set();
53312
53758
  for (const target of matchingTargets) {
53313
53759
  const targetId = normalizeProtocolV2TargetId(target.target_id);
53314
- const pathConflictsWithCurrentInstall = Boolean(target.path) &&
53760
+ const pathConflictsWithCurrentInstall = targetId !== undefined &&
53761
+ Boolean(target.path) &&
53315
53762
  Boolean(resolvedExpectedPaths.get(targetId)) &&
53316
53763
  target.path !== resolvedExpectedPaths.get(targetId) &&
53317
53764
  (!liveTargetIds || liveTargetIds.has(targetId));
53318
53765
  if (targetId === undefined ||
53319
53766
  seenTargetIds.has(targetId) ||
53320
53767
  pathConflictsWithCurrentInstall) {
53321
- Log$7.error(`[FirmwareUpdateV4] install status conflicts with target=${target.target_id}`);
53768
+ Log$6.error(`[FirmwareUpdateV4] install status conflicts with target=${target.target_id}`);
53322
53769
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, 'Protocol V2 firmware install status conflict', {
53323
53770
  firmwareUpdateCode: PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE,
53324
53771
  });
@@ -53359,10 +53806,41 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53359
53806
  return true;
53360
53807
  }
53361
53808
  if (expectedTargetIds.size > 0 && matchingTargets.length > 0) {
53362
- const hasInProgressTarget = matchingTargets.some(target => isProtocolV2TargetStatusInProgress(target.status));
53809
+ let detailedProgress = completedTargetIds.size * 100;
53810
+ let installProgressMetadata;
53811
+ let hasInProgressTarget = false;
53812
+ matchingTargets.forEach(target => {
53813
+ var _a, _b;
53814
+ const targetId = normalizeProtocolV2TargetId(target.target_id);
53815
+ if (targetId === undefined ||
53816
+ completedTargetIds.has(targetId) ||
53817
+ !isProtocolV2TargetStatusInProgress(target.status) ||
53818
+ (liveTargetIds && !liveTargetIds.has(targetId))) {
53819
+ return;
53820
+ }
53821
+ hasInProgressTarget = true;
53822
+ detailedProgress += (_a = normalizeProtocolV2ProgressPercent(target.progress_percent)) !== null && _a !== void 0 ? _a : 0;
53823
+ const installPhase = target.phase_info
53824
+ ? PROTOCOL_V2_INSTALL_PHASE_BY_DECODED_VALUE.get(target.phase_info.phase)
53825
+ : undefined;
53826
+ const installPhaseProgress = normalizeProtocolV2ProgressPercent((_b = target.phase_info) === null || _b === void 0 ? void 0 : _b.progress_percent);
53827
+ if (installPhase && installPhaseProgress !== undefined && !installProgressMetadata) {
53828
+ installProgressMetadata = {
53829
+ installTargetId: targetId,
53830
+ installPhase,
53831
+ installPhaseProgress,
53832
+ };
53833
+ }
53834
+ });
53363
53835
  const completedProgress = Math.floor((completedTargetIds.size / expectedTargetIds.size) * 100);
53364
- const progress = Math.min(99, Math.max(completedProgress, hasInProgressTarget ? 1 : 0));
53365
- this.postProgressMessage(progress, 'installingFirmware');
53836
+ const reportedProgress = Math.floor(detailedProgress / expectedTargetIds.size);
53837
+ const progress = Math.min(99, Math.max(completedProgress, reportedProgress, hasInProgressTarget ? 1 : 0));
53838
+ if (installProgressMetadata) {
53839
+ this.postProgressMessage(progress, 'installingFirmware', installProgressMetadata);
53840
+ }
53841
+ else {
53842
+ this.postProgressMessage(progress, 'installingFirmware');
53843
+ }
53366
53844
  }
53367
53845
  return false;
53368
53846
  }
@@ -53418,9 +53896,14 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53418
53896
  const startTime = Date.now();
53419
53897
  let lastError;
53420
53898
  let shouldReconnect = this.protocolV2InstallNeedsReconnect;
53899
+ let installTransportReleaseObserved = shouldReconnect;
53421
53900
  this.protocolV2InstallNeedsReconnect = false;
53422
53901
  let deviceInfo;
53423
53902
  let bleInstallLinkReady = false;
53903
+ let installReconnectObserved = false;
53904
+ let finishedStatusSnapshotKey;
53905
+ let finishedStatusSnapshotPolls = 0;
53906
+ let fastFinishedInstallProgressReported = false;
53424
53907
  let installEvidenceObserved = this.protocolV2InstallTerminalSuccessObserved;
53425
53908
  let currentInstallStatusObserved = false;
53426
53909
  const liveTargetIds = new Set();
@@ -53434,6 +53917,9 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53434
53917
  deviceInfo = isBleInstallReconnect
53435
53918
  ? undefined
53436
53919
  : yield this.verifyProtocolV2ReconnectIdentity();
53920
+ if (installTransportReleaseObserved) {
53921
+ installReconnectObserved = true;
53922
+ }
53437
53923
  shouldReconnect = false;
53438
53924
  }
53439
53925
  let currentDeviceInfo = deviceInfo;
@@ -53441,6 +53927,8 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53441
53927
  const statusResponse = yield this.device.getCommands().typedCall('DeviceFirmwareUpdateStatusGet', 'DeviceFirmwareUpdateStatus', {
53442
53928
  fields: {
53443
53929
  status: true,
53930
+ progress_percent: true,
53931
+ phase_info: true,
53444
53932
  payload_version: true,
53445
53933
  path: true,
53446
53934
  },
@@ -53465,10 +53953,67 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53465
53953
  const targetId = normalizeProtocolV2TargetId(target.target_id);
53466
53954
  return targetId !== undefined && expectedTargetIds.has(targetId);
53467
53955
  });
53468
- const hasCurrentInstallEvidence = currentInstallStatusObserved || this.protocolV2InstallTerminalSuccessObserved;
53956
+ const matchingFinishedTargetIds = new Set();
53957
+ const matchingFinishedStatus = matchingStatusTargets
53958
+ .map(target => {
53959
+ const targetId = normalizeProtocolV2TargetId(target.target_id);
53960
+ const expectedPath = targetId === undefined ? undefined : expectedPaths.get(targetId);
53961
+ const expectedVersion = targetId === undefined
53962
+ ? undefined
53963
+ : this.getExpectedProtocolV2TargetVersion(targetId);
53964
+ const payloadVersion = toProtocolV2FiniteNumber(target.payload_version);
53965
+ if (targetId === undefined ||
53966
+ matchingFinishedTargetIds.has(targetId) ||
53967
+ !isProtocolV2TargetStatusFinished(target.status) ||
53968
+ target.path !== expectedPath ||
53969
+ (expectedVersion !== undefined && payloadVersion !== expectedVersion)) {
53970
+ return undefined;
53971
+ }
53972
+ matchingFinishedTargetIds.add(targetId);
53973
+ return [targetId, target.path, payloadVersion !== null && payloadVersion !== void 0 ? payloadVersion : null];
53974
+ })
53975
+ .filter((target) => !!target)
53976
+ .sort(([leftTargetId], [rightTargetId]) => leftTargetId - rightTargetId);
53977
+ const hasCompleteMatchingFinishedStatus = matchingFinishedStatus.length === expectedTargetIds.size &&
53978
+ matchingFinishedTargetIds.size === expectedTargetIds.size &&
53979
+ expectedTargetIds.size > 0;
53980
+ if (requireCurrentInstallStatus &&
53981
+ installReconnectObserved &&
53982
+ hasCompleteMatchingFinishedStatus) {
53983
+ const nextSnapshotKey = JSON.stringify(matchingFinishedStatus);
53984
+ if (nextSnapshotKey === finishedStatusSnapshotKey) {
53985
+ finishedStatusSnapshotPolls += 1;
53986
+ }
53987
+ else {
53988
+ finishedStatusSnapshotKey = nextSnapshotKey;
53989
+ finishedStatusSnapshotPolls = 1;
53990
+ }
53991
+ }
53992
+ else {
53993
+ finishedStatusSnapshotKey = undefined;
53994
+ finishedStatusSnapshotPolls = 0;
53995
+ }
53996
+ if (requireCurrentInstallStatus &&
53997
+ installReconnectObserved &&
53998
+ hasCompleteMatchingFinishedStatus &&
53999
+ !currentInstallStatusObserved &&
54000
+ !this.protocolV2InstallTerminalSuccessObserved &&
54001
+ !fastFinishedInstallProgressReported) {
54002
+ this.postProgressMessage(1, 'installingFirmware');
54003
+ fastFinishedInstallProgressReported = true;
54004
+ }
54005
+ const finishedAfterReconnectObserved = finishedStatusSnapshotPolls >= PROTOCOL_V2_INSTALL_FINISHED_AFTER_RECONNECT_POLLS;
54006
+ const hasCurrentInstallEvidence = currentInstallStatusObserved ||
54007
+ this.protocolV2InstallTerminalSuccessObserved ||
54008
+ finishedAfterReconnectObserved;
54009
+ if (hasCurrentInstallEvidence) {
54010
+ installEvidenceObserved = true;
54011
+ }
53469
54012
  const shouldVerifyTargetCompletion = !requireCurrentInstallStatus || hasCurrentInstallEvidence;
53470
54013
  if (shouldVerifyTargetCompletion &&
53471
- this.assertProtocolV2TargetStatus(statusTargets, expectedTargetIds, expectedPaths, requireCurrentInstallStatus && !this.protocolV2InstallTerminalSuccessObserved
54014
+ this.assertProtocolV2TargetStatus(statusTargets, expectedTargetIds, expectedPaths, requireCurrentInstallStatus &&
54015
+ !this.protocolV2InstallTerminalSuccessObserved &&
54016
+ !finishedAfterReconnectObserved
53472
54017
  ? liveTargetIds
53473
54018
  : undefined)) {
53474
54019
  return;
@@ -53493,7 +54038,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53493
54038
  if (isNormalMode &&
53494
54039
  (installEvidenceObserved ||
53495
54040
  this.hasProtocolV2InstallVersionChanged(expectedTargetIds))) {
53496
- Log$7.log('[FirmwareUpdateV4] empty firmware status after confirmed App reboot; update complete');
54041
+ Log$6.log('[FirmwareUpdateV4] empty firmware status after confirmed App reboot; update complete');
53497
54042
  this.recordProtocolV2AuthoritativeInstallCompletion(expectedTargetIds);
53498
54043
  this.postProgressMessage(100, 'installingFirmware');
53499
54044
  return;
@@ -53532,7 +54077,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53532
54077
  if (isNormalMode &&
53533
54078
  (installEvidenceObserved ||
53534
54079
  this.hasProtocolV2InstallVersionChanged(expectedTargetIds))) {
53535
- Log$7.log('[FirmwareUpdateV4] firmware status endpoint unavailable after confirmed App reboot');
54080
+ Log$6.log('[FirmwareUpdateV4] firmware status endpoint unavailable after confirmed App reboot');
53536
54081
  this.recordProtocolV2AuthoritativeInstallCompletion(expectedTargetIds);
53537
54082
  this.postProgressMessage(100, 'installingFirmware');
53538
54083
  return;
@@ -53545,11 +54090,16 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53545
54090
  }
53546
54091
  }
53547
54092
  else {
54093
+ if (isProtocolV2DeviceDisconnectedError(error) || isProtocolV2ResponseTimeout(error)) {
54094
+ installTransportReleaseObserved = true;
54095
+ finishedStatusSnapshotKey = undefined;
54096
+ finishedStatusSnapshotPolls = 0;
54097
+ }
53548
54098
  shouldReconnect = true;
53549
54099
  deviceInfo = undefined;
53550
54100
  bleInstallLinkReady = false;
53551
54101
  lastError = error;
53552
- Log$7.log('[FirmwareUpdateV4] DeviceFirmwareUpdateStatusGet unavailable during install: ', error);
54102
+ Log$6.log('[FirmwareUpdateV4] DeviceFirmwareUpdateStatusGet unavailable during install: ', error);
53553
54103
  }
53554
54104
  }
53555
54105
  }
@@ -53568,11 +54118,11 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53568
54118
  shouldReconnect = true;
53569
54119
  deviceInfo = undefined;
53570
54120
  bleInstallLinkReady = false;
53571
- Log$7.log('Protocol V2 firmware install device readiness probe failed: ', error);
54121
+ Log$6.log('Protocol V2 firmware install device readiness probe failed: ', error);
53572
54122
  }
53573
54123
  yield hdShared.wait(1000);
53574
54124
  }
53575
- Log$7.error(`[FirmwareUpdateV4] install timed out after ${PROTOCOL_V2_INSTALL_TIMEOUT / 1000}s: ${this.normalizeErrorMessage(lastError)}`);
54125
+ Log$6.error(`[FirmwareUpdateV4] install timed out after ${PROTOCOL_V2_INSTALL_TIMEOUT / 1000}s: ${this.normalizeErrorMessage(lastError)}`);
53576
54126
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, 'Protocol V2 firmware install timed out', {
53577
54127
  firmwareUpdateCode: PROTOCOL_V2_INSTALL_TIMEOUT_CODE,
53578
54128
  });
@@ -53584,12 +54134,15 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53584
54134
  const deviceInfo = yield this.verifyProtocolV2ReconnectIdentity();
53585
54135
  try {
53586
54136
  if (yield this.probeProtocolV2NormalMode(deviceInfo)) {
53587
- Log$7.log('[FirmwareUpdateV4] device already returned to App mode; skip Normal reboot');
54137
+ Log$6.log('[FirmwareUpdateV4] device already returned to App mode; skip Normal reboot');
53588
54138
  return;
53589
54139
  }
53590
54140
  }
53591
54141
  catch (error) {
53592
- Log$7.log('[FirmwareUpdateV4] unable to confirm App mode before Normal reboot: ', error);
54142
+ if (hdShared.isBleStaleBondHardwareError(error)) {
54143
+ throw error;
54144
+ }
54145
+ Log$6.log('[FirmwareUpdateV4] unable to confirm App mode before Normal reboot: ', error);
53593
54146
  }
53594
54147
  yield this.protocolV2Reboot(hdTransport.DeviceRebootType.Normal);
53595
54148
  this.protocolV2ExecutionInLoader = false;
@@ -53617,7 +54170,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53617
54170
  const firmwareVersion = getDeviceFirmwareVersion(features).join('.');
53618
54171
  this.protocolV2LatestFinalFeatures = features;
53619
54172
  if (firmwareVersion === '0.0.0') {
53620
- Log$7.warn('Protocol V2 firmware update finished but app firmware version is still 0.0.0. This is allowed for Pro2 debug BLE-only update flows.');
54173
+ Log$6.warn('Protocol V2 firmware update finished but app firmware version is still 0.0.0. This is allowed for Pro2 debug BLE-only update flows.');
53621
54174
  }
53622
54175
  return {
53623
54176
  bootloaderVersion,
@@ -53663,12 +54216,12 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53663
54216
  lastError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound, 'Protocol V2 device is still in bootloader mode');
53664
54217
  }
53665
54218
  catch (error) {
53666
- if (this.isProtocolV2ReconnectIdentityError(error)) {
54219
+ if (hdShared.isBleStaleBondHardwareError(error) || this.isProtocolV2ReconnectIdentityError(error)) {
53667
54220
  throw error;
53668
54221
  }
53669
54222
  shouldReconnect = true;
53670
54223
  lastError = error;
53671
- Log$7.log('Protocol V2 normal mode not ready, polling Ping: ', error);
54224
+ Log$6.log('Protocol V2 normal mode not ready, polling Ping: ', error);
53672
54225
  }
53673
54226
  yield hdShared.wait(1000);
53674
54227
  }
@@ -53732,7 +54285,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53732
54285
  if (!reconnectDevice) {
53733
54286
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound);
53734
54287
  }
53735
- Log$7.debug('Protocol V2 firmware reconnect using matched device:', reconnectDevice.getConnectId());
54288
+ Log$6.debug('Protocol V2 firmware reconnect using matched device:', reconnectDevice.getConnectId());
53736
54289
  this.device.updateFromCache(reconnectDevice);
53737
54290
  yield this.ensureProtocolV2DeviceAcquired();
53738
54291
  this.device.commands.disposed = false;
@@ -53773,8 +54326,8 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53773
54326
  });
53774
54327
  if (writeRes.type !== 'FilesystemFile') {
53775
54328
  if (writeRes.type === 'CallMethodError') {
53776
- if (((_a = writeRes.message.error) !== null && _a !== void 0 ? _a : '').indexOf(SESSION_ERROR$1) > -1) {
53777
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, SESSION_ERROR$1);
54329
+ if (((_a = writeRes.message.error) !== null && _a !== void 0 ? _a : '').indexOf(SESSION_ERROR) > -1) {
54330
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, SESSION_ERROR);
53778
54331
  }
53779
54332
  }
53780
54333
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.EmmcFileWriteFirmwareError, 'transfer data error');
@@ -53826,17 +54379,17 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53826
54379
  return;
53827
54380
  this.protocolV2InstallTerminalSuccessObserved = true;
53828
54381
  this.device.clearCancelableAction();
53829
- Log$7.log('[FirmwareUpdateV4] firmware install completed by device response');
54382
+ Log$6.log('[FirmwareUpdateV4] firmware install completed by device response');
53830
54383
  },
53831
54384
  });
53832
- Log$7.log('[FirmwareUpdateV4] firmware install request written; continue with status polling');
54385
+ Log$6.log('[FirmwareUpdateV4] firmware install request written; continue with status polling');
53833
54386
  }
53834
54387
  catch (error) {
53835
54388
  this.throwIfAborted();
53836
54389
  if (!isProtocolV2DeviceDisconnectedError(error)) {
53837
54390
  throw error;
53838
54391
  }
53839
- Log$7.log('[FirmwareUpdateV4] transport released while writing install request; continue status polling');
54392
+ Log$6.log('[FirmwareUpdateV4] transport released while writing install request; continue status polling');
53840
54393
  this.protocolV2InstallNeedsReconnect = true;
53841
54394
  }
53842
54395
  });
@@ -53847,12 +54400,14 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53847
54400
  try {
53848
54401
  const res = yield typedCall('DeviceReboot', 'Success', {
53849
54402
  reboot_type: rebootType,
53850
- });
54403
+ }, { timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT });
53851
54404
  this.device.markProtocolV2Reboot(rebootType);
53852
54405
  return res.message;
53853
54406
  }
53854
54407
  catch (error) {
53855
- if (isProtocolV2DeviceDisconnectedError(error) || isProtocolV2ReconnectProbeError(error)) {
54408
+ if (isProtocolV2DeviceDisconnectedError(error) ||
54409
+ isProtocolV2ReconnectProbeError(error) ||
54410
+ isProtocolV2ResponseTimeout(error)) {
53856
54411
  this.device.markProtocolV2Reboot(rebootType);
53857
54412
  return { message: 'Device rebooted successfully' };
53858
54413
  }
@@ -53868,7 +54423,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53868
54423
  }
53869
54424
  }
53870
54425
 
53871
- const Log$6 = getLogger(exports.LoggerNames.Method);
54426
+ const Log$5 = getLogger(exports.LoggerNames.Method);
53872
54427
  class PromptWebDeviceAccess extends BaseMethod {
53873
54428
  init() {
53874
54429
  this.useDevice = false;
@@ -53923,7 +54478,7 @@ class PromptWebDeviceAccess extends BaseMethod {
53923
54478
  return { device: null };
53924
54479
  }
53925
54480
  catch (error) {
53926
- Log$6.debug(error);
54481
+ Log$5.debug(error);
53927
54482
  return Promise.reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Please select the device to connect'));
53928
54483
  }
53929
54484
  });
@@ -54028,280 +54583,6 @@ function decodeJpegBase64ToRgba({ jpegBase64, parameterName, expectedWidth, expe
54028
54583
  return decoded;
54029
54584
  }
54030
54585
 
54031
- const Log$5 = getLogger(exports.LoggerNames.Core);
54032
- const MIN_FILE_CHUNK_SIZE = 64;
54033
- const FILE_TRANSFER_RATE_WINDOW_MS = 1000;
54034
- const FILE_TRANSFER_LOG_INTERVAL_MS = 10000;
54035
- const SESSION_ERROR = 'session not found';
54036
- function formatFileTransferRate(bytesPerSecond) {
54037
- return (Math.max(bytesPerSecond, 0) / 1024).toFixed(2);
54038
- }
54039
- function getAverageFileTransferRate(transferredBytes, elapsedMs) {
54040
- if (elapsedMs <= 0)
54041
- return 0;
54042
- return Math.round((Math.max(transferredBytes, 0) / elapsedMs) * 1000);
54043
- }
54044
- function getFileTransferTransport() {
54045
- const env = DataManager.getSettings('env');
54046
- return env && DataManager.isBleConnect(env) ? 'BLE' : String(env !== null && env !== void 0 ? env : 'unknown');
54047
- }
54048
- function logFileTransferMetrics({ transport, status, path, transferredBytes, totalBytes, elapsedMs, rateBytesPerSecond, hostWriteElapsedMs, responseWaitElapsedMs, measuredAttempts, }) {
54049
- const segmentedMetrics = measuredAttempts > 0
54050
- ? ` hostWriteTotal=${(hostWriteElapsedMs / 1000).toFixed(2)}s responseWaitTotal=${(responseWaitElapsedMs / 1000).toFixed(2)}s measuredAttempts=${measuredAttempts}`
54051
- : '';
54052
- Log$5.log(`[FileWrite] metrics transport=${transport} status=${status} path=${path} bytes=${transferredBytes}/${totalBytes} elapsed=${(elapsedMs / 1000).toFixed(2)}s speed=${formatFileTransferRate(rateBytesPerSecond)} KiB/s${segmentedMetrics}`);
54053
- }
54054
- function isProtocolV2ResponseTimeout(error) {
54055
- var _a, _b;
54056
- if (!error || typeof error !== 'object')
54057
- return false;
54058
- const candidate = error;
54059
- const code = (_a = candidate.errorCode) !== null && _a !== void 0 ? _a : candidate.code;
54060
- return (code === hdShared.HardwareErrorCode.BleTimeoutError ||
54061
- code === 'response-timeout' ||
54062
- /(?:BLE|Lowlevel|Protocol V2) response timeout/i.test((_b = candidate.message) !== null && _b !== void 0 ? _b : ''));
54063
- }
54064
- function getProtocolV2FileChunkLimit() {
54065
- const env = DataManager.getSettings('env');
54066
- return env && DataManager.isBleConnect(env)
54067
- ? hdTransport.PROTOCOL_V2_BLE_FILE_CHUNK_SIZE
54068
- : hdTransport.PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE;
54069
- }
54070
- function dataToUint8Array(data) {
54071
- return __awaiter(this, void 0, void 0, function* () {
54072
- if (typeof data === 'string')
54073
- return new TextEncoder().encode(data);
54074
- if (data instanceof ArrayBuffer)
54075
- return new Uint8Array(data);
54076
- if (ArrayBuffer.isView(data)) {
54077
- return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
54078
- }
54079
- if (typeof Blob !== 'undefined' && data instanceof Blob) {
54080
- return new Uint8Array(yield data.arrayBuffer());
54081
- }
54082
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Unsupported FilesystemFileWrite data');
54083
- });
54084
- }
54085
- function normalizeChunkSize(value, maxChunkSize) {
54086
- const numeric = Number(value);
54087
- if (!Number.isFinite(numeric) || numeric <= 0)
54088
- return maxChunkSize;
54089
- return Math.min(Math.max(Math.floor(numeric), MIN_FILE_CHUNK_SIZE), maxChunkSize);
54090
- }
54091
- function getDeviceTransferProgress(before, after, total) {
54092
- if (!Number.isFinite(total) || total <= 0)
54093
- return 100;
54094
- if (before <= 0 && after < total)
54095
- return 0;
54096
- if (after >= total)
54097
- return 100;
54098
- return Math.min(Math.max(Math.ceil((after / total) * 100), 1), 99);
54099
- }
54100
- function getConfirmedProgress(processed, total, written, length) {
54101
- if (Number.isFinite(processed) && Number.isFinite(total) && total > 0) {
54102
- if (processed >= total)
54103
- return 100;
54104
- return Math.min(Math.max(Math.floor((processed / total) * 100), 0), 99);
54105
- }
54106
- if (length > 0)
54107
- return written >= length ? 100 : Math.floor((written / length) * 100);
54108
- return 100;
54109
- }
54110
- function writeProtocolV2File(options) {
54111
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
54112
- return __awaiter(this, void 0, void 0, function* () {
54113
- (_a = options.throwIfAborted) === null || _a === void 0 ? void 0 : _a.call(options);
54114
- const data = yield dataToUint8Array(options.data);
54115
- const dataLength = data.byteLength;
54116
- const startOffset = Number.isFinite(options.offset) && Number(options.offset) > 0 ? Number(options.offset) : 0;
54117
- const totalSize = Number.isFinite(options.totalSize) && Number(options.totalSize) > 0
54118
- ? Number(options.totalSize)
54119
- : startOffset + dataLength;
54120
- if (totalSize < startOffset + dataLength) {
54121
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `FilesystemFileWrite totalSize ${totalSize} is smaller than offset + data length ${startOffset + dataLength}`);
54122
- }
54123
- const defaultChunkSizeLimit = getProtocolV2FileChunkLimit();
54124
- const configuredChunkSizeLimit = Number(options.chunkSizeLimit);
54125
- const chunkSizeLimit = Number.isFinite(configuredChunkSizeLimit) && configuredChunkSizeLimit > 0
54126
- ? Math.floor(configuredChunkSizeLimit)
54127
- : defaultChunkSizeLimit;
54128
- const chunkSize = normalizeChunkSize((_b = options.chunkSize) !== null && _b !== void 0 ? _b : options.chunkLen, chunkSizeLimit);
54129
- let written = 0;
54130
- let chunks = 0;
54131
- let lastMessage;
54132
- const startTime = Date.now();
54133
- let rateWindowStartedAt = startTime;
54134
- let rateWindowStartedBytes = 0;
54135
- let rateBytesPerSecond;
54136
- let lastConfirmedAt = startTime;
54137
- let logWindowStartedAt = startTime;
54138
- let logWindowStartedBytes = 0;
54139
- let hostWriteElapsedMs = 0;
54140
- let responseWaitElapsedMs = 0;
54141
- let measuredAttempts = 0;
54142
- const transport = getFileTransferTransport();
54143
- Log$5.log(`[FileWrite] started transport=${transport} path=${options.path} bytes=${dataLength} offset=${startOffset} chunk=${chunkSize}`);
54144
- try {
54145
- while (written < dataLength) {
54146
- (_c = options.throwIfAborted) === null || _c === void 0 ? void 0 : _c.call(options);
54147
- const chunk = data.slice(written, Math.min(written + chunkSize, dataLength));
54148
- const offset = startOffset + written;
54149
- const progress = (_f = (_d = options.uiPercentage) !== null && _d !== void 0 ? _d : (_e = options.getUiPercentage) === null || _e === void 0 ? void 0 : _e.call(options, {
54150
- offset,
54151
- chunkLength: chunk.byteLength,
54152
- totalSize,
54153
- })) !== null && _f !== void 0 ? _f : getDeviceTransferProgress(offset, offset + chunk.byteLength, totalSize);
54154
- const request = {
54155
- file: { path: options.path, offset, total_size: totalSize, data: chunk },
54156
- overwrite: chunks === 0 ? (_g = options.overwrite) !== null && _g !== void 0 ? _g : false : false,
54157
- append: (_h = options.append) !== null && _h !== void 0 ? _h : false,
54158
- ui_percentage: progress,
54159
- };
54160
- const maxChunkRetries = Math.max(Math.floor((_j = options.maxChunkRetries) !== null && _j !== void 0 ? _j : 0), 0);
54161
- let retryCount = 0;
54162
- let response;
54163
- let isWritePending = true;
54164
- while (isWritePending) {
54165
- let currentHostWriteElapsedMs;
54166
- let responseWaitStartedAt;
54167
- try {
54168
- const callOptions = options.writeWithResponse === undefined
54169
- ? {
54170
- timeoutMs: options.timeoutMs,
54171
- onWriteCompleted: ({ elapsedMs }) => {
54172
- currentHostWriteElapsedMs = elapsedMs;
54173
- responseWaitStartedAt = Date.now();
54174
- },
54175
- }
54176
- : Object.assign(Object.assign({}, (options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs })), { writeWithResponse: options.writeWithResponse, onWriteCompleted: ({ elapsedMs }) => {
54177
- currentHostWriteElapsedMs = elapsedMs;
54178
- responseWaitStartedAt = Date.now();
54179
- } });
54180
- response = yield options.commands.typedCall('FilesystemFileWrite', 'FilesystemFile', request, callOptions);
54181
- isWritePending = false;
54182
- }
54183
- catch (error) {
54184
- if (retryCount >= maxChunkRetries || !isProtocolV2ResponseTimeout(error))
54185
- throw error;
54186
- retryCount += 1;
54187
- (_k = options.throwIfAborted) === null || _k === void 0 ? void 0 : _k.call(options);
54188
- }
54189
- finally {
54190
- if (currentHostWriteElapsedMs !== undefined && responseWaitStartedAt !== undefined) {
54191
- hostWriteElapsedMs += currentHostWriteElapsedMs;
54192
- responseWaitElapsedMs += Math.max(Date.now() - responseWaitStartedAt, 0);
54193
- measuredAttempts += 1;
54194
- }
54195
- }
54196
- }
54197
- if (!response) {
54198
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'FilesystemFileWrite completed without a response');
54199
- }
54200
- const responseType = response.type;
54201
- if (responseType && responseType !== 'FilesystemFile') {
54202
- const responseError = (_l = response.message) === null || _l === void 0 ? void 0 : _l.error;
54203
- if (typeof responseError === 'string' && responseError.includes(SESSION_ERROR)) {
54204
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, SESSION_ERROR);
54205
- }
54206
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `FilesystemFileWrite received unexpected response ${responseType}`);
54207
- }
54208
- (_m = options.throwIfAborted) === null || _m === void 0 ? void 0 : _m.call(options);
54209
- lastMessage = response.message;
54210
- const rawProcessedByte = (_o = response.message) === null || _o === void 0 ? void 0 : _o.processed_byte;
54211
- const processedByte = Number(rawProcessedByte);
54212
- if (rawProcessedByte !== undefined &&
54213
- (!Number.isFinite(processedByte) ||
54214
- processedByte <= offset ||
54215
- processedByte > offset + chunk.byteLength)) {
54216
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `FilesystemFileWrite invalid processed_byte ${processedByte}`);
54217
- }
54218
- written =
54219
- rawProcessedByte === undefined ? written + chunk.byteLength : processedByte - startOffset;
54220
- chunks += 1;
54221
- const now = Date.now();
54222
- lastConfirmedAt = now;
54223
- const elapsedMs = now - startTime;
54224
- const transferredBytes = Math.min(written, dataLength);
54225
- const rateWindowElapsedMs = now - rateWindowStartedAt;
54226
- if (rateWindowElapsedMs >= FILE_TRANSFER_RATE_WINDOW_MS) {
54227
- const rateWindowBytes = Math.max(transferredBytes - rateWindowStartedBytes, 0);
54228
- rateBytesPerSecond = Math.round((rateWindowBytes / rateWindowElapsedMs) * 1000);
54229
- rateWindowStartedAt = now;
54230
- rateWindowStartedBytes = transferredBytes;
54231
- }
54232
- else if (rateBytesPerSecond === undefined && elapsedMs > 0) {
54233
- rateBytesPerSecond = Math.round((transferredBytes / elapsedMs) * 1000);
54234
- }
54235
- (_p = options.onProgress) === null || _p === void 0 ? void 0 : _p.call(options, {
54236
- progress: getConfirmedProgress(startOffset + written, totalSize, written, dataLength),
54237
- transferredBytes,
54238
- totalBytes: dataLength,
54239
- rateBytesPerSecond,
54240
- elapsedMs,
54241
- });
54242
- const logWindowElapsedMs = now - logWindowStartedAt;
54243
- if (logWindowElapsedMs >= FILE_TRANSFER_LOG_INTERVAL_MS && transferredBytes < dataLength) {
54244
- const logWindowBytes = Math.max(transferredBytes - logWindowStartedBytes, 0);
54245
- logFileTransferMetrics({
54246
- transport,
54247
- status: 'progress',
54248
- path: options.path,
54249
- transferredBytes,
54250
- totalBytes: dataLength,
54251
- elapsedMs,
54252
- rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
54253
- hostWriteElapsedMs,
54254
- responseWaitElapsedMs,
54255
- measuredAttempts,
54256
- });
54257
- logWindowStartedAt = now;
54258
- logWindowStartedBytes = transferredBytes;
54259
- }
54260
- if (options.paceMs && options.paceMs > 0) {
54261
- yield new Promise(resolve => {
54262
- setTimeout(resolve, options.paceMs);
54263
- });
54264
- }
54265
- }
54266
- }
54267
- catch (error) {
54268
- const now = Date.now();
54269
- const elapsedMs = Math.max(now - startTime, 0);
54270
- const logWindowElapsedMs = Math.max(now - logWindowStartedAt, 0);
54271
- const logWindowBytes = Math.max(written - logWindowStartedBytes, 0);
54272
- logFileTransferMetrics({
54273
- transport,
54274
- status: 'failed',
54275
- path: options.path,
54276
- transferredBytes: written,
54277
- totalBytes: dataLength,
54278
- elapsedMs,
54279
- rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
54280
- hostWriteElapsedMs,
54281
- responseWaitElapsedMs,
54282
- measuredAttempts,
54283
- });
54284
- throw error;
54285
- }
54286
- const elapsedMs = Math.max(lastConfirmedAt - startTime, 0);
54287
- const logWindowElapsedMs = Math.max(lastConfirmedAt - logWindowStartedAt, 0);
54288
- const logWindowBytes = Math.max(written - logWindowStartedBytes, 0);
54289
- logFileTransferMetrics({
54290
- transport,
54291
- status: 'completed',
54292
- path: options.path,
54293
- transferredBytes: written,
54294
- totalBytes: dataLength,
54295
- elapsedMs,
54296
- rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
54297
- hostWriteElapsedMs,
54298
- responseWaitElapsedMs,
54299
- measuredAttempts,
54300
- });
54301
- return Object.assign(Object.assign({}, lastMessage), { path: options.path, offset: startOffset, total_size: totalSize, processed_byte: startOffset + written, chunks });
54302
- });
54303
- }
54304
-
54305
54586
  const WALLPAPER_DIRECTORY = 'vol1:/wallpapers';
54306
54587
  const SAFE_FILE_NAME = /^[A-Za-z0-9_-]+(?:\.bin)?$/;
54307
54588
  const DEVICE_SETTINGS_SET_MESSAGE_TYPE = 60412;
@@ -54861,6 +55142,8 @@ class ProtocolV2UiInteractionCoordinator {
54861
55142
  const Log$3 = getLogger(exports.LoggerNames.Core);
54862
55143
  const createProtocolV2UnlockContext = () => ({
54863
55144
  preflightCompleted: false,
55145
+ preflightStatusRefreshed: false,
55146
+ preflightMainPinSelected: false,
54864
55147
  });
54865
55148
  const resolvePreUnlockPinType = (method) => {
54866
55149
  var _a, _b;
@@ -54893,10 +55176,11 @@ function runMethodWithUnlockPolicy(method, device, options = {}) {
54893
55176
  }
54894
55177
  yield (afterStatusBeforeUnlock === null || afterStatusBeforeUnlock === void 0 ? void 0 : afterStatusBeforeUnlock());
54895
55178
  if (!status.unlocked) {
55179
+ const preUnlockPinType = resolvePreUnlockPinType(method);
54896
55180
  const unlockInteraction = shouldCoordinateUi
54897
55181
  ? uiCoordinator.enterUnlockInteraction(method.name)
54898
55182
  : undefined;
54899
- const unlockedStatus = yield device.unlockDevice(resolvePreUnlockPinType(method), shouldCoordinateUi
55183
+ const unlockedStatus = yield device.unlockDevice(preUnlockPinType, shouldCoordinateUi
54900
55184
  ? { emitUiEvent: false, interaction: unlockInteraction }
54901
55185
  : {
54902
55186
  source: 'unlock-coordinator',
@@ -54907,8 +55191,10 @@ function runMethodWithUnlockPolicy(method, device, options = {}) {
54907
55191
  if ((unlockedStatus === null || unlockedStatus === void 0 ? void 0 : unlockedStatus.unlocked) !== true) {
54908
55192
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 device remained locked after the unlock flow.');
54909
55193
  }
55194
+ context.preflightMainPinSelected = preUnlockPinType === hdTransport.DeviceSessionPinType.Main;
54910
55195
  Log$3.debug('Protocol V2 pre-unlock completed', { method: method.name });
54911
55196
  }
55197
+ context.preflightStatusRefreshed = true;
54912
55198
  context.preflightCompleted = true;
54913
55199
  }
54914
55200
  yield (prepare === null || prepare === void 0 ? void 0 : prepare());
@@ -55197,6 +55483,7 @@ class AllNetworkGetAddressBase extends BaseMethod {
55197
55483
  const response = yield runMethodWithUnlockPolicy(method, this.device, {
55198
55484
  context: this.protocolV2UnlockContext,
55199
55485
  prepare: () => __awaiter(this, void 0, void 0, function* () {
55486
+ var _d;
55200
55487
  if (this.temporarySafetyCheckPrompted) {
55201
55488
  method.temporarySafetyCheckPrompted = true;
55202
55489
  }
@@ -55210,7 +55497,7 @@ class AllNetworkGetAddressBase extends BaseMethod {
55210
55497
  const deriveCardano = method.name.startsWith('cardano');
55211
55498
  const shouldResumeWalletSession = useEmptyPassphrase || !!this.payload.passphraseState;
55212
55499
  if (this.device.isProtocolV2() && shouldResumeWalletSession) {
55213
- const passphraseStateSafety = yield this.device.checkPassphraseStateSafety(this.payload.passphraseState, useEmptyPassphrase, this.payload.skipPassphraseCheck, deriveCardano);
55500
+ const passphraseStateSafety = yield this.device.checkPassphraseStateSafety(this.payload.passphraseState, useEmptyPassphrase, this.payload.skipPassphraseCheck, deriveCardano, (_d = this.protocolV2UnlockContext) === null || _d === void 0 ? void 0 : _d.preflightMainPinSelected);
55214
55501
  if (!passphraseStateSafety) {
55215
55502
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckPassphraseStateError);
55216
55503
  }
@@ -65307,7 +65594,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65307
65594
  }
65308
65595
  },
65309
65596
  prepare: () => __awaiter(void 0, void 0, void 0, function* () {
65310
- var _o, _p, _q, _r, _s;
65597
+ var _o, _p, _q, _r, _s, _t;
65311
65598
  if (method.deviceId && method.checkDeviceId && !deviceIdCheckedDuringUnlockPreflight) {
65312
65599
  const isSameDeviceID = yield checkLiveDeviceId(device, method.deviceId);
65313
65600
  if (!isSameDeviceID) {
@@ -65327,7 +65614,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65327
65614
  require: support.require,
65328
65615
  });
65329
65616
  }
65330
- const passphraseStateSafety = yield device.checkPassphraseStateSafety((_o = method.payload) === null || _o === void 0 ? void 0 : _o.passphraseState, (_p = method.payload) === null || _p === void 0 ? void 0 : _p.useEmptyPassphrase, (_q = method.payload) === null || _q === void 0 ? void 0 : _q.skipPassphraseCheck, hasDeriveCardano(method));
65617
+ const passphraseStateSafety = yield device.checkPassphraseStateSafety((_o = method.payload) === null || _o === void 0 ? void 0 : _o.passphraseState, (_p = method.payload) === null || _p === void 0 ? void 0 : _p.useEmptyPassphrase, (_q = method.payload) === null || _q === void 0 ? void 0 : _q.skipPassphraseCheck, hasDeriveCardano(method), (_r = method.protocolV2UnlockContext) === null || _r === void 0 ? void 0 : _r.preflightMainPinSelected);
65331
65618
  checkPassphraseEnableState(method, device.features);
65332
65619
  if (!passphraseStateSafety) {
65333
65620
  DevicePool.clearDeviceCache(method.payload.connectId);
@@ -65345,7 +65632,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65345
65632
  ? e
65346
65633
  : hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'open safety check failed.');
65347
65634
  }
65348
- (_s = (_r = method.device) === null || _r === void 0 ? void 0 : _r.commands) === null || _s === void 0 ? void 0 : _s.checkDisposed();
65635
+ (_t = (_s = method.device) === null || _s === void 0 ? void 0 : _s.commands) === null || _t === void 0 ? void 0 : _t.checkDisposed();
65349
65636
  }),
65350
65637
  });
65351
65638
  messageResponse = createResponseMessage(method.responseID, true, response);
@@ -65561,6 +65848,11 @@ function isMissingDetectedProtocolV2Error(method, error) {
65561
65848
  typeof typedError.message === 'string' &&
65562
65849
  typedError.message.includes('Device protocol has not been detected'));
65563
65850
  }
65851
+ function isProtocolV2PeerRemovedPairingError(method, error) {
65852
+ return (method.payload.connectProtocol === 'V2' &&
65853
+ (error === null || error === void 0 ? void 0 : error.errorCode) ===
65854
+ hdShared.HardwareErrorCode.BlePeerRemovedPairingInformation);
65855
+ }
65564
65856
  const BLE_ACQUIRE_DEADLINE_MS = 60 * 1000;
65565
65857
  function raceBleAcquire(acquirePromise, abortSignal) {
65566
65858
  return new Promise((resolve, reject) => {
@@ -65672,7 +65964,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
65672
65964
  Log.debug(`EnsureConnected function start, MAX_RETRY_COUNT=${MAX_RETRY_COUNT}, POLL_INTERVAL_TIME=${POLL_INTERVAL_TIME} `);
65673
65965
  const poll = (time = POLL_INTERVAL_TIME) => __awaiter(void 0, void 0, void 0, function* () {
65674
65966
  return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
65675
- var _t;
65967
+ var _u;
65676
65968
  const abort = () => {
65677
65969
  if (abortSignal && abortSignal.aborted) {
65678
65970
  if (timer) {
@@ -65782,7 +66074,8 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
65782
66074
  hdShared.HardwareErrorCode.BridgeNeedsPermission,
65783
66075
  hdShared.HardwareErrorCode.DeviceInterruptedFromUser,
65784
66076
  hdShared.HardwareErrorCode.CallQueueActionCancelled,
65785
- ].includes(error.errorCode)) {
66077
+ ].includes(error.errorCode) ||
66078
+ isProtocolV2PeerRemovedPairingError(method, error)) {
65786
66079
  reject(error);
65787
66080
  return;
65788
66081
  }
@@ -65792,7 +66085,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
65792
66085
  clearTimeout(timer);
65793
66086
  }
65794
66087
  Log.debug('EnsureConnected get to max try count, will return: ', tryCount);
65795
- if (DataManager.isBrowserWebUsb(env) && !((_t = method.payload) === null || _t === void 0 ? void 0 : _t.skipWebDevicePrompt)) {
66088
+ if (DataManager.isBrowserWebUsb(env) && !((_u = method.payload) === null || _u === void 0 ? void 0 : _u.skipWebDevicePrompt)) {
65796
66089
  postMessage(createUiMessage(UI_REQUEST.WEB_DEVICE_PROMPT_ACCESS_PERMISSION));
65797
66090
  reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WebDeviceNotFoundOrNeedsPermission));
65798
66091
  }
@@ -65905,8 +66198,12 @@ const checkPassphraseEnableState = (method, features) => {
65905
66198
  }
65906
66199
  };
65907
66200
  const shouldCheckPassphraseState = (method, device) => {
66201
+ var _a;
65908
66202
  if (!method.useDevicePassphraseState)
65909
66203
  return false;
66204
+ if (device.isProtocolV2() && ((_a = method.payload) === null || _a === void 0 ? void 0 : _a.useEmptyPassphrase) === true) {
66205
+ return true;
66206
+ }
65910
66207
  return device.hasUsePassphrase();
65911
66208
  };
65912
66209
  const cleanup = () => {