@onekeyfe/hd-core 1.2.0-alpha.41 → 1.2.0-alpha.42

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 (200) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +78 -0
  2. package/__tests__/DeviceEventRegistration.test.ts +6 -0
  3. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +14 -1
  4. package/__tests__/connectSettings.test.ts +5 -47
  5. package/__tests__/deviceUploadNft.test.ts +187 -0
  6. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +31 -59
  7. package/__tests__/get-device-state.test.ts +132 -12
  8. package/__tests__/homescreen.test.ts +41 -1
  9. package/__tests__/logBlockEvent.test.ts +1 -1
  10. package/__tests__/open-wallet-session.test.ts +259 -18
  11. package/__tests__/pro2Nft.test.ts +108 -0
  12. package/__tests__/protocol-v2-resources.test.ts +204 -0
  13. package/__tests__/protocol-v2-ui-lifecycle.test.ts +56 -0
  14. package/__tests__/protocol-v2-unlock-policy.test.ts +86 -35
  15. package/__tests__/protocol-v2.test.ts +526 -955
  16. package/__tests__/public-pro2-api-boundary.test.ts +1 -0
  17. package/__tests__/uiProgressThrottle.test.ts +74 -0
  18. package/dist/api/BaseMethod.d.ts +3 -1
  19. package/dist/api/BaseMethod.d.ts.map +1 -1
  20. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  21. package/dist/api/FirmwareUpdateV2.d.ts +0 -11
  22. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  23. package/dist/api/FirmwareUpdateV3.d.ts +3 -7
  24. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  25. package/dist/api/FirmwareUpdateV4.d.ts +6 -25
  26. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  27. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  28. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  29. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  30. package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
  31. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  32. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -8
  33. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  34. package/dist/api/firmware/getBinary.d.ts +0 -7
  35. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  36. package/dist/api/firmware/updateBootloader.d.ts +0 -2
  37. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  38. package/dist/api/firmware/uploadFirmware.d.ts +1 -9
  39. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  40. package/dist/api/helpers/protocolV2FileWrite.d.ts +2 -0
  41. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  42. package/dist/api/index.d.ts +1 -0
  43. package/dist/api/index.d.ts.map +1 -1
  44. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +30 -0
  45. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
  46. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  47. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  48. package/dist/core/deviceEventRegistration.d.ts +2 -0
  49. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  50. package/dist/core/index.d.ts.map +1 -1
  51. package/dist/data-manager/DataManager.d.ts +3 -2
  52. package/dist/data-manager/DataManager.d.ts.map +1 -1
  53. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  54. package/dist/device/Device.d.ts +22 -4
  55. package/dist/device/Device.d.ts.map +1 -1
  56. package/dist/events/device.d.ts +4 -0
  57. package/dist/events/device.d.ts.map +1 -1
  58. package/dist/events/logBlockEvent.d.ts.map +1 -1
  59. package/dist/events/ui-request.d.ts +27 -2
  60. package/dist/events/ui-request.d.ts.map +1 -1
  61. package/dist/index.d.ts +110 -182
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +1919 -3336
  64. package/dist/inject.d.ts.map +1 -1
  65. package/dist/lowLevelInject.d.ts.map +1 -1
  66. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  67. package/dist/protocols/protocol-v2/resources.d.ts +30 -0
  68. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -0
  69. package/dist/protocols/protocol-v2/uiInteraction.d.ts +3 -3
  70. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  71. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +1 -3
  72. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  73. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
  74. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
  75. package/dist/protocols/protocol-v2/walletSession.d.ts +4 -1
  76. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  77. package/dist/topLevelInject.d.ts.map +1 -1
  78. package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -4
  79. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  80. package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
  81. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  82. package/dist/types/api/export.d.ts +1 -4
  83. package/dist/types/api/export.d.ts.map +1 -1
  84. package/dist/types/api/firmwareUpdate.d.ts +0 -69
  85. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  86. package/dist/types/api/index.d.ts +3 -10
  87. package/dist/types/api/index.d.ts.map +1 -1
  88. package/dist/types/api/protocolV2.d.ts +3 -0
  89. package/dist/types/api/protocolV2.d.ts.map +1 -1
  90. package/dist/types/settings.d.ts +12 -13
  91. package/dist/types/settings.d.ts.map +1 -1
  92. package/dist/utils/deviceFeaturesUtils.d.ts +2 -0
  93. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  94. package/dist/utils/homescreen.d.ts +4 -0
  95. package/dist/utils/homescreen.d.ts.map +1 -1
  96. package/dist/utils/index.d.ts +1 -1
  97. package/dist/utils/index.d.ts.map +1 -1
  98. package/dist/utils/patch.d.ts +1 -1
  99. package/dist/utils/patch.d.ts.map +1 -1
  100. package/dist/utils/pro2Nft.d.ts +29 -0
  101. package/dist/utils/pro2Nft.d.ts.map +1 -0
  102. package/dist/utils/pro2Wallpaper.d.ts +10 -0
  103. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  104. package/dist/utils/uiProgressThrottle.d.ts +3 -0
  105. package/dist/utils/uiProgressThrottle.d.ts.map +1 -0
  106. package/package.json +4 -4
  107. package/src/api/BaseMethod.ts +8 -10
  108. package/src/api/CheckAllFirmwareRelease.ts +40 -53
  109. package/src/api/FirmwareUpdateV2.ts +120 -298
  110. package/src/api/FirmwareUpdateV3.ts +57 -263
  111. package/src/api/FirmwareUpdateV4.ts +307 -912
  112. package/src/api/GetPassphraseState.ts +7 -1
  113. package/src/api/OpenWalletSession.ts +54 -17
  114. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +32 -11
  115. package/src/api/device/DeviceUnlock.ts +1 -1
  116. package/src/api/device/DeviceUpdateBootloader.ts +6 -122
  117. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +0 -57
  118. package/src/api/firmware/updateBootloader.ts +4 -19
  119. package/src/api/firmware/uploadFirmware.ts +22 -140
  120. package/src/api/helpers/protocolV2FileWrite.ts +11 -4
  121. package/src/api/index.ts +1 -0
  122. package/src/api/protocol-v2/DeviceUploadNft.ts +166 -0
  123. package/src/api/protocol-v2/ProtocolInfoRequest.ts +3 -1
  124. package/src/core/deviceEventRegistration.ts +4 -0
  125. package/src/core/index.ts +118 -75
  126. package/src/data/messages/messages-protocol-v2.json +53 -0
  127. package/src/data-manager/DataManager.ts +63 -38
  128. package/src/data-manager/connectSettings.ts +0 -11
  129. package/src/device/Device.ts +193 -21
  130. package/src/events/device.ts +4 -0
  131. package/src/events/logBlockEvent.ts +1 -0
  132. package/src/events/ui-request.ts +32 -2
  133. package/src/index.ts +0 -5
  134. package/src/inject.ts +3 -22
  135. package/src/lowLevelInject.ts +1 -5
  136. package/src/protocols/protocol-v2/features.ts +9 -2
  137. package/src/protocols/protocol-v2/resources.ts +233 -0
  138. package/src/protocols/protocol-v2/uiInteraction.ts +31 -5
  139. package/src/protocols/protocol-v2/unlockPolicy.ts +1 -105
  140. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +117 -0
  141. package/src/protocols/protocol-v2/walletSession.ts +93 -18
  142. package/src/topLevelInject.ts +1 -5
  143. package/src/types/api/checkAllFirmwareRelease.ts +1 -4
  144. package/src/types/api/deviceUpdateBootloader.ts +0 -6
  145. package/src/types/api/export.ts +0 -18
  146. package/src/types/api/firmwareUpdate.ts +0 -76
  147. package/src/types/api/index.ts +2 -14
  148. package/src/types/api/protocolV2.ts +13 -0
  149. package/src/types/settings.ts +26 -13
  150. package/src/utils/deviceFeaturesUtils.ts +4 -0
  151. package/src/utils/homescreen.ts +32 -6
  152. package/src/utils/index.ts +6 -1
  153. package/src/utils/pro2Nft.ts +91 -0
  154. package/src/utils/pro2Wallpaper.ts +35 -8
  155. package/src/utils/uiProgressThrottle.ts +63 -0
  156. package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -175
  157. package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
  158. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
  159. package/__tests__/firmware-update/firmware-preparation-error.test.ts +0 -27
  160. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
  161. package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
  162. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -213
  163. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +0 -58
  164. package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
  165. package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
  166. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
  167. package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
  168. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
  169. package/dist/api/firmware/FirmwarePreparationError.d.ts +0 -3
  170. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +0 -1
  171. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
  172. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
  173. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -25
  174. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
  175. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -30
  176. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
  177. package/dist/api/firmware/progressThrottle.d.ts +0 -3
  178. package/dist/api/firmware/progressThrottle.d.ts.map +0 -1
  179. package/dist/protocols/protocol-v2/lockedError.d.ts +0 -2
  180. package/dist/protocols/protocol-v2/lockedError.d.ts.map +0 -1
  181. package/dist/protocols/protocol-v2/unlockRetry.d.ts +0 -10
  182. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +0 -1
  183. package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
  184. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
  185. package/dist/types/api/firmwareUpdatePlan.d.ts +0 -28
  186. package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
  187. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
  188. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
  189. package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
  190. package/src/api/firmware/FirmwareHostBinding.ts +0 -100
  191. package/src/api/firmware/FirmwarePreparationError.ts +0 -12
  192. package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
  193. package/src/api/firmware/FirmwareUpdatePlan.ts +0 -745
  194. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -392
  195. package/src/api/firmware/progressThrottle.ts +0 -44
  196. package/src/protocols/protocol-v2/lockedError.ts +0 -10
  197. package/src/protocols/protocol-v2/unlockRetry.ts +0 -109
  198. package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
  199. package/src/types/api/firmwareUpdatePlan.ts +0 -38
  200. package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
package/src/core/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import semver from 'semver';
2
2
  import EventEmitter from 'events';
3
- import { TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
3
+ import { DeviceSessionPinType, TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
4
4
  import {
5
5
  ERRORS,
6
6
  ERROR_CODES_REQUIRE_RELEASE,
@@ -55,11 +55,12 @@ import DeviceConnector from '../device/DeviceConnector';
55
55
  import RequestQueue from './RequestQueue';
56
56
  import { registerHardwareUiEventListeners } from './deviceEventRegistration';
57
57
  import { getSynchronize } from '../utils/getSynchronize';
58
- import { runMethodWithUnlockRetry } from '../protocols/protocol-v2/unlockRetry';
58
+ import { runMethodWithUnlockPolicy } from '../protocols/protocol-v2/unlockPolicyRunner';
59
59
  import {
60
60
  ProtocolV2UiInteractionCoordinator,
61
61
  isProtocolV2UiEnabled,
62
62
  } from '../protocols/protocol-v2/uiInteraction';
63
+ import { createUiProgressMessageFilter } from '../utils/uiProgressThrottle';
63
64
 
64
65
  import type { ConnectSettings, Features, KnownDevice } from '../types';
65
66
  import type { CoreMessage, IFrameCallMessage, UiPromise, UiPromiseResponse } from '../events';
@@ -154,7 +155,12 @@ export const callAPI = async (context: CoreContext, message: CoreMessage) => {
154
155
  try {
155
156
  method = findMethod(message as IFrameCallMessage);
156
157
  method.connector = _connector;
157
- method.postMessage = postMessage;
158
+ const shouldPostMessage = createUiProgressMessageFilter();
159
+ method.postMessage = event => {
160
+ if (shouldPostMessage(event)) {
161
+ postMessage(event);
162
+ }
163
+ };
158
164
  method.setContext?.(context);
159
165
 
160
166
  method.requestContext = createRequestContext(method.responseID, method.name, {
@@ -406,6 +412,8 @@ const onCallDevice = async (
406
412
 
407
413
  registerHardwareUiEventListeners(device, {
408
414
  pin: onDevicePinHandler,
415
+ pinOnDevice: onEnterPinOnDeviceHandler,
416
+ pinOnDeviceComplete: onPinOnDeviceCompleteHandler,
409
417
  button: onDeviceButtonHandler,
410
418
  passphrase: message.payload.useEmptyPassphrase
411
419
  ? onEmptyPassphraseHandler
@@ -421,6 +429,7 @@ const onCallDevice = async (
421
429
  );
422
430
 
423
431
  const protocolV2UiCoordinator = new ProtocolV2UiInteractionCoordinator(device, postMessage);
432
+ device.beginProtocolV2UiInteraction();
424
433
  device.on(
425
434
  DEVICE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE,
426
435
  onSelectDeviceForSwitchFirmwareWebDeviceHandler
@@ -547,89 +556,92 @@ const onCallDevice = async (
547
556
  );
548
557
  }
549
558
 
550
- if (method.deviceId && method.checkDeviceId) {
551
- const isSameDeviceID = await checkLiveDeviceId(device, method.deviceId);
552
- if (!isSameDeviceID) {
553
- return Promise.reject(ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError));
554
- }
555
- }
559
+ try {
560
+ let deviceIdCheckedDuringUnlockPreflight = false;
561
+ const response = await runMethodWithUnlockPolicy<object>(method, device, {
562
+ uiCoordinator: protocolV2UiCoordinator,
563
+ afterStatusBeforeUnlock: () => {
564
+ if (method.deviceId && method.checkDeviceId) {
565
+ if (!device.checkDeviceId(method.deviceId)) {
566
+ throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
567
+ }
568
+ deviceIdCheckedDuringUnlockPreflight = true;
569
+ }
570
+ },
571
+ prepare: async () => {
572
+ if (method.deviceId && method.checkDeviceId && !deviceIdCheckedDuringUnlockPreflight) {
573
+ const isSameDeviceID = await checkLiveDeviceId(device, method.deviceId);
574
+ if (!isSameDeviceID) {
575
+ throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
576
+ }
577
+ }
556
578
 
557
- /**
558
- * check firmware release info
559
- */
560
- method.checkFirmwareRelease();
579
+ /**
580
+ * check firmware release info
581
+ */
582
+ method.checkFirmwareRelease();
561
583
 
562
- /**
563
- * check additional supported feature
564
- */
565
- method.checkDeviceSupportFeature();
584
+ /**
585
+ * check additional supported feature
586
+ */
587
+ method.checkDeviceSupportFeature();
566
588
 
567
- // reconfigure messages
568
- if (_deviceList && device.features && !device.isProtocolV2()) {
569
- await TransportManager.reconfigure(device.features);
570
- }
571
-
572
- // Check to see if it is safe to use Passphrase
573
- checkPassphraseEnableState(method, device.features);
589
+ // reconfigure messages
590
+ if (_deviceList && device.features && !device.isProtocolV2()) {
591
+ await TransportManager.reconfigure(device.features);
592
+ }
574
593
 
575
- if (shouldCheckPassphraseState(method, device)) {
576
- // check version
577
- const support = device.supportNewPassphrase();
578
- if (!support.support) {
579
- return Promise.reject(
580
- ERRORS.TypedError(
581
- HardwareErrorCode.DeviceNotSupportPassphrase,
582
- `Device not support passphrase, please update to ${support.require}`,
583
- {
584
- require: support.require,
594
+ // Check to see if it is safe to use Passphrase
595
+ checkPassphraseEnableState(method, device.features);
596
+
597
+ if (shouldCheckPassphraseState(method, device)) {
598
+ // check version
599
+ const support = device.supportNewPassphrase();
600
+ if (!support.support) {
601
+ throw ERRORS.TypedError(
602
+ HardwareErrorCode.DeviceNotSupportPassphrase,
603
+ `Device not support passphrase, please update to ${support.require}`,
604
+ {
605
+ require: support.require,
606
+ }
607
+ );
585
608
  }
586
- )
587
- );
588
- }
589
609
 
590
- // Check Device passphrase State
591
- const passphraseStateSafety = await device.checkPassphraseStateSafety(
592
- method.payload?.passphraseState,
593
- method.payload?.useEmptyPassphrase,
594
- method.payload?.skipPassphraseCheck
595
- );
596
-
597
- // Double check, handles the special case of Touch/Pro
598
- checkPassphraseEnableState(method, device.features);
610
+ // Check Device passphrase State after the Protocol V2 pre-unlock gate.
611
+ const passphraseStateSafety = await device.checkPassphraseStateSafety(
612
+ method.payload?.passphraseState,
613
+ method.payload?.useEmptyPassphrase,
614
+ method.payload?.skipPassphraseCheck,
615
+ hasDeriveCardano(method)
616
+ );
599
617
 
600
- if (!passphraseStateSafety) {
601
- DevicePool.clearDeviceCache(method.payload.connectId);
602
- return Promise.reject(
603
- ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError)
604
- );
605
- }
618
+ // Double check, handles the special case of Touch/Pro
619
+ checkPassphraseEnableState(method, device.features);
606
620
 
607
- // close pin popup window
608
- postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW));
609
- }
621
+ if (!passphraseStateSafety) {
622
+ DevicePool.clearDeviceCache(method.payload.connectId);
623
+ throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError);
624
+ }
610
625
 
611
- // Automatic check safety_check level for Kovan, Ropsten, Rinkeby, Goerli test networks.
612
- try {
613
- await method.checkSafetyLevelOnTestNet();
614
- } catch (e) {
615
- const error =
616
- e instanceof HardwareError
617
- ? e
618
- : ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'open safety check failed.');
619
- // messageResponse = createResponseMessage(method.responseID, false, { error });
620
- // requestQueue.resolveRequest(method.responseID, messageResponse);
621
- // return;
622
- throw error;
623
- }
626
+ // Protocol V2 emits the PIN phase completion from DeviceSessionAskPin.
627
+ // Keep the legacy compatibility close for Protocol V1 only.
628
+ if (!device.isProtocolV2()) {
629
+ postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW));
630
+ }
631
+ }
624
632
 
625
- method.device?.commands?.checkDisposed();
633
+ // Automatic check safety_check level for Kovan, Ropsten, Rinkeby, Goerli test networks.
634
+ try {
635
+ await method.checkSafetyLevelOnTestNet();
636
+ } catch (e) {
637
+ throw e instanceof HardwareError
638
+ ? e
639
+ : ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'open safety check failed.');
640
+ }
626
641
 
627
- try {
628
- const response: object = await runMethodWithUnlockRetry(
629
- method,
630
- device,
631
- protocolV2UiCoordinator
632
- );
642
+ method.device?.commands?.checkDisposed();
643
+ },
644
+ });
633
645
  messageResponse = createResponseMessage(method.responseID, true, response);
634
646
  requestQueue.resolveRequest(method.responseID, messageResponse);
635
647
  completeMethodRequestContext(method);
@@ -1279,6 +1291,7 @@ const onDevicePassphraseHandler = async (
1279
1291
  source: requestPayload.source,
1280
1292
  reason: requestPayload.reason,
1281
1293
  expectedPassphraseState: requestPayload.expectedPassphraseState,
1294
+ ...(requestPayload.interaction ? { interaction: requestPayload.interaction } : {}),
1282
1295
  })
1283
1296
  );
1284
1297
  // wait for passphrase
@@ -1308,6 +1321,7 @@ const onEnterPassphraseOnDeviceHandler = (
1308
1321
  passphraseState: device.passphraseState,
1309
1322
  source: requestPayload?.source,
1310
1323
  reason: requestPayload?.reason,
1324
+ ...(requestPayload?.interaction ? { interaction: requestPayload.interaction } : {}),
1311
1325
  })
1312
1326
  );
1313
1327
  };
@@ -1321,10 +1335,39 @@ const onEnterAttachPinOnDeviceHandler = (
1321
1335
  type: 'ButtonRequest_AttachPin',
1322
1336
  source: requestPayload?.source,
1323
1337
  reason: requestPayload?.reason,
1338
+ ...(requestPayload?.interaction ? { interaction: requestPayload.interaction } : {}),
1324
1339
  })
1325
1340
  );
1326
1341
  };
1327
1342
 
1343
+ const onEnterPinOnDeviceHandler = (
1344
+ ...[device, pinType, metadata]: [...DeviceEvents['pin_on_device']]
1345
+ ) => {
1346
+ postMessage(
1347
+ createUiMessage(UI_REQUEST.REQUEST_PIN, {
1348
+ device: device.toMessageObject() as KnownDevice,
1349
+ type:
1350
+ pinType === DeviceSessionPinType.AttachToPin
1351
+ ? 'ButtonRequest_AttachPin'
1352
+ : 'ButtonRequest_PinEntry',
1353
+ source: metadata?.source,
1354
+ reason: metadata?.reason,
1355
+ deviceOnly: metadata?.deviceOnly ?? true,
1356
+ completion: metadata?.completion,
1357
+ method: metadata?.method,
1358
+ page: metadata?.page,
1359
+ operation: metadata?.operation,
1360
+ ...(metadata?.interaction ? { interaction: metadata.interaction } : {}),
1361
+ })
1362
+ );
1363
+ };
1364
+
1365
+ const onPinOnDeviceCompleteHandler = (
1366
+ ...[_, metadata]: [...DeviceEvents['pin_on_device_complete']]
1367
+ ) => {
1368
+ postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW, metadata));
1369
+ };
1370
+
1328
1371
  const onSelectDeviceInBootloaderForWebDeviceHandler = async (
1329
1372
  ...[device, callback]: [...DeviceEvents['select_device_in_bootloader_for_web_device']]
1330
1373
  ) => {
@@ -450,6 +450,8 @@
450
450
  "MessageType_DeviceInfo": 60601,
451
451
  "MessageType_DeviceStatusGet": 60602,
452
452
  "MessageType_DeviceStatus": 60603,
453
+ "MessageType_ResourceInventoryGet": 60604,
454
+ "MessageType_ResourceInventory": 60605,
453
455
  "MessageType_FilesystemPermissionFix": 60800,
454
456
  "MessageType_FilesystemPathInfo": 60801,
455
457
  "MessageType_FilesystemPathInfoQuery": 60802,
@@ -470,6 +472,7 @@
470
472
  "MessageType_DeviceSessionAskPin": 61202,
471
473
  "MessageType_DeviceSessionAskPassphrase": 61203,
472
474
  "MessageType_PortfolioUpdate": 61400,
475
+ "MessageType_NftUpdate": 61500,
473
476
  "MessageType_OnboardingStatusGet": 61600,
474
477
  "MessageType_OnboardingStatus": 61601
475
478
  },
@@ -11993,6 +11996,16 @@
11993
11996
  "APP": 85
11994
11997
  }
11995
11998
  },
11999
+ "ResourceBundleType": {
12000
+ "values": {
12001
+ "IMAGES": 0,
12002
+ "ANIMATION": 1,
12003
+ "WALLPAPER": 2,
12004
+ "TRANSLATIONS": 3,
12005
+ "ROOBERT": 4,
12006
+ "NOTO": 5
12007
+ }
12008
+ },
11996
12009
  "DeviceFirmwareImageInfo": {
11997
12010
  "fields": {
11998
12011
  "version": {
@@ -12190,6 +12203,37 @@
12190
12203
  }
12191
12204
  }
12192
12205
  },
12206
+ "ResourceInventoryGet": {
12207
+ "fields": {}
12208
+ },
12209
+ "ResourceInventoryItem": {
12210
+ "fields": {
12211
+ "type": {
12212
+ "rule": "required",
12213
+ "type": "ResourceBundleType",
12214
+ "id": 1
12215
+ },
12216
+ "size": {
12217
+ "rule": "required",
12218
+ "type": "uint32",
12219
+ "id": 2
12220
+ },
12221
+ "header_hash": {
12222
+ "rule": "required",
12223
+ "type": "bytes",
12224
+ "id": 3
12225
+ }
12226
+ }
12227
+ },
12228
+ "ResourceInventory": {
12229
+ "fields": {
12230
+ "items": {
12231
+ "rule": "repeated",
12232
+ "type": "ResourceInventoryItem",
12233
+ "id": 1
12234
+ }
12235
+ }
12236
+ },
12193
12237
  "DeviceSessionErrorCode": {
12194
12238
  "values": {
12195
12239
  "DeviceSessionError_None": 0,
@@ -12538,6 +12582,15 @@
12538
12582
  }
12539
12583
  }
12540
12584
  },
12585
+ "NftUpdate": {
12586
+ "fields": {
12587
+ "file_name_no_ext": {
12588
+ "rule": "required",
12589
+ "type": "string",
12590
+ "id": 1
12591
+ }
12592
+ }
12593
+ },
12541
12594
  "OnboardingStep": {
12542
12595
  "values": {
12543
12596
  "ONBOARDING_STEP_UNKNOWN": 0,
@@ -17,6 +17,7 @@ import {
17
17
  } from '../utils';
18
18
  import { DeviceModelToTypes } from '../types';
19
19
  import { findLatestRelease, getReleaseChangelog, getReleaseStatus } from '../utils/release';
20
+ import { parseProtocolV2Resources } from '../protocols/protocol-v2/resources';
20
21
 
21
22
  import type {
22
23
  AssetsMap,
@@ -397,20 +398,10 @@ export default class DataManager {
397
398
  return enrichedData;
398
399
  }
399
400
 
400
- static async load(settings: ConnectSettings) {
401
+ static async load(settings: ConnectSettings): Promise<boolean> {
401
402
  this.settings = settings;
402
- const manifestMode =
403
- settings.firmwareManifestMode ?? (settings.fetchConfig ? 'sdk-managed' : undefined);
404
- if (settings.preloadedConfig) {
405
- this.applyRemoteConfig(settings.preloadedConfig);
406
- Log.log('[DataConfig] Preloaded firmware config loaded');
407
- return;
408
- }
409
- if (manifestMode === 'external-only') {
410
- throw new Error('External firmware config snapshot is required');
411
- }
412
- if (manifestMode !== 'sdk-managed') {
413
- return;
403
+ if (!settings.fetchConfig) {
404
+ return false;
414
405
  }
415
406
 
416
407
  const url = settings.preRelease
@@ -419,48 +410,65 @@ export default class DataManager {
419
410
 
420
411
  const urlWithCache = `${url}?noCache=${getTimeStamp()}`;
421
412
  let data: RemoteConfigResponse | null = null;
413
+ let fetchMethod: 'configFetcher' | 'axios' | 'none' = 'none';
414
+
415
+ // 1. Try custom configFetcher first (client-side IP direct connection support)
422
416
  if (settings.configFetcher) {
423
- Log.debug('[DataConfig] Trying client configFetcher...');
417
+ Log.debug('[DataConfig] Trying configFetcher (client-side fetcher)...');
424
418
  try {
425
419
  data = await settings.configFetcher(urlWithCache);
420
+ if (data) {
421
+ fetchMethod = 'configFetcher';
422
+ Log.log('[DataConfig] ConfigFetcher success');
423
+ } else {
424
+ Log.debug('[DataConfig] ConfigFetcher returned null, will fallback to axios');
425
+ }
426
426
  } catch (e) {
427
- Log.warn('[DataConfig] Client configFetcher failed:', e);
427
+ Log.warn('[DataConfig] ConfigFetcher error, will fallback to axios:', e);
428
428
  }
429
429
  }
430
+
431
+ // 2. Fallback to default axios request
430
432
  if (!data) {
431
- Log.debug('[DataConfig] Trying SDK-managed config request...');
433
+ Log.debug('[DataConfig] Trying axios (SDK default fetcher)...');
432
434
  try {
433
435
  const response = await axios.get<RemoteConfigResponse>(urlWithCache, {
434
436
  // because of iframe timeout is 10000
435
437
  timeout: 7000,
436
438
  });
437
439
  data = response.data;
438
- Log.log('[DataConfig] SDK-managed config request succeeded');
440
+ fetchMethod = 'axios';
441
+ Log.log('[DataConfig] Axios fetch success');
439
442
  } catch (e) {
440
- Log.warn('[DataConfig] SDK-managed config request failed:', e);
443
+ Log.warn('[DataConfig] Axios fetch error:', e);
441
444
  }
442
445
  }
443
446
 
447
+ // 3. Apply config if available
444
448
  if (data) {
445
- this.applyRemoteConfig(data);
446
- } else {
447
- Log.warn('[DataConfig] SDK-managed config request failed, using built-in default config');
449
+ const pro2Resources = parseProtocolV2Resources(
450
+ (data.pro2 as { resources?: unknown } | undefined)?.resources
451
+ );
452
+ Log.log(`[DataConfig] Config loaded successfully via [${fetchMethod}]`);
453
+ this.deviceMap = {
454
+ [EDeviceType.Classic]: this.enrichFirmwareReleaseInfo(data.classic),
455
+ [EDeviceType.Classic1s]: this.enrichFirmwareReleaseInfo(data.classic1s),
456
+ [EDeviceType.ClassicPure]: this.enrichFirmwareReleaseInfo(data.classicpure),
457
+ [EDeviceType.Mini]: this.enrichFirmwareReleaseInfo(data.mini),
458
+ [EDeviceType.Touch]: this.enrichFirmwareReleaseInfo(data.touch),
459
+ [EDeviceType.Pro]: this.enrichFirmwareReleaseInfo(data.pro),
460
+ [EDeviceType.Pro2]: {
461
+ ...this.enrichFirmwareReleaseInfo(data.pro2),
462
+ ...(pro2Resources ? { resources: pro2Resources } : undefined),
463
+ },
464
+ };
465
+ this.assets = {
466
+ bridge: data.bridge,
467
+ };
468
+ return true;
448
469
  }
449
- }
450
-
451
- private static applyRemoteConfig(data: RemoteConfigResponse) {
452
- this.deviceMap = {
453
- [EDeviceType.Classic]: this.enrichFirmwareReleaseInfo(data.classic),
454
- [EDeviceType.Classic1s]: this.enrichFirmwareReleaseInfo(data.classic1s),
455
- [EDeviceType.ClassicPure]: this.enrichFirmwareReleaseInfo(data.classicpure),
456
- [EDeviceType.Mini]: this.enrichFirmwareReleaseInfo(data.mini),
457
- [EDeviceType.Touch]: this.enrichFirmwareReleaseInfo(data.touch),
458
- [EDeviceType.Pro]: this.enrichFirmwareReleaseInfo(data.pro),
459
- [EDeviceType.Pro2]: this.enrichFirmwareReleaseInfo(data.pro2),
460
- };
461
- this.assets = {
462
- bridge: data.bridge,
463
- };
470
+ Log.warn('[DataConfig] All fetch methods failed, using built-in default config');
471
+ return false;
464
472
  }
465
473
 
466
474
  static updateEnv(newEnv: ConnectSettings['env']) {
@@ -478,10 +486,27 @@ export default class DataManager {
478
486
 
479
487
  static async checkAndReloadData() {
480
488
  if (getTimeStamp() - this.lastCheckTimestamp > 1000 * 60 * 60 * 3) {
481
- await this.load(this.settings).then(() => {
489
+ const loaded = await this.load(this.settings);
490
+ if (loaded) {
482
491
  this.lastCheckTimestamp = getTimeStamp();
483
- });
492
+ }
493
+ }
494
+ }
495
+
496
+ /** Force a fresh remote config before an update is allowed to mutate the device. */
497
+ static async forceReloadData(): Promise<void> {
498
+ if (!this.settings) {
499
+ throw new Error('Remote config settings are not initialized');
500
+ }
501
+ const loaded = await this.load(this.settings);
502
+ if (!loaded) {
503
+ throw new Error('Unable to refresh the latest remote config');
484
504
  }
505
+ this.lastCheckTimestamp = getTimeStamp();
506
+ }
507
+
508
+ static getProtocolV2Resources() {
509
+ return this.deviceMap[EDeviceType.Pro2]?.resources?.stable;
485
510
  }
486
511
 
487
512
  static getProtobufMessages(schema: ProtobufMessageSchema = 'v1CurrentSchema'): JSON {
@@ -115,21 +115,10 @@ export const parseConnectSettings = (input: Partial<ConnectSettings> = {}) => {
115
115
  settings.fetchConfig = input.fetchConfig;
116
116
  }
117
117
 
118
- if (
119
- input.firmwareManifestMode === 'sdk-managed' ||
120
- input.firmwareManifestMode === 'external-only'
121
- ) {
122
- settings.firmwareManifestMode = input.firmwareManifestMode;
123
- }
124
-
125
118
  if (input.configFetcher) {
126
119
  settings.configFetcher = input.configFetcher;
127
120
  }
128
121
 
129
- if (input.preloadedConfig) {
130
- settings.preloadedConfig = input.preloadedConfig;
131
- }
132
-
133
122
  return settings;
134
123
  };
135
124