@onekeyfe/hd-core 1.2.0-alpha.67 → 1.2.0-alpha.68

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 (254) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +313 -0
  2. package/__tests__/DeviceCommands.test.ts +59 -13
  3. package/__tests__/DeviceEventRegistration.test.ts +6 -0
  4. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +198 -3
  5. package/__tests__/core-initialization.test.ts +23 -0
  6. package/__tests__/device-connector-protocol.test.ts +81 -0
  7. package/__tests__/device-lifecycle-events.test.ts +105 -3
  8. package/__tests__/device-pool-state.test.ts +22 -0
  9. package/__tests__/device-settings.test.ts +39 -18
  10. package/__tests__/device-state-contract.test.ts +1 -0
  11. package/__tests__/device-state-mapper.test.ts +13 -1
  12. package/__tests__/device-utils.test.ts +48 -1
  13. package/__tests__/deviceSettings.test.ts +11 -1
  14. package/__tests__/deviceUploadNft.test.ts +316 -0
  15. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +5 -0
  16. package/__tests__/get-device-state.test.ts +132 -12
  17. package/__tests__/homescreen.test.ts +41 -1
  18. package/__tests__/kaspa-use-tweak-pro2.test.ts +2 -2
  19. package/__tests__/kaspaSignTransaction.test.ts +3 -26
  20. package/__tests__/logBlockEvent.test.ts +1 -1
  21. package/__tests__/method-protocol-support.test.ts +19 -0
  22. package/__tests__/open-wallet-session.test.ts +568 -37
  23. package/__tests__/pro2Nft.test.ts +108 -0
  24. package/__tests__/protocol-binding.test.ts +89 -0
  25. package/__tests__/protocol-v2-resources.test.ts +340 -0
  26. package/__tests__/protocol-v2-ui-lifecycle.test.ts +91 -0
  27. package/__tests__/protocol-v2-unlock-policy.test.ts +300 -37
  28. package/__tests__/protocol-v2.test.ts +1449 -867
  29. package/__tests__/protocolV2FileWrite.test.ts +152 -0
  30. package/__tests__/protocolV2UiInteraction.test.ts +63 -0
  31. package/__tests__/public-pro2-api-boundary.test.ts +1 -0
  32. package/__tests__/search-devices.test.ts +12 -3
  33. package/__tests__/tron-sign-message-init.test.ts +2 -2
  34. package/__tests__/uiProgressThrottle.test.ts +74 -0
  35. package/__tests__/uiPromiseRegistry.test.ts +115 -0
  36. package/dist/api/BaseMethod.d.ts +3 -1
  37. package/dist/api/BaseMethod.d.ts.map +1 -1
  38. package/dist/api/CheckAllFirmwareRelease.d.ts +2 -1
  39. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  40. package/dist/api/DetectDeviceConnectProtocol.d.ts +7 -0
  41. package/dist/api/DetectDeviceConnectProtocol.d.ts.map +1 -0
  42. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  43. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  44. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  45. package/dist/api/FirmwareUpdateV4.d.ts +11 -4
  46. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  47. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  48. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  49. package/dist/api/SearchDevices.d.ts.map +1 -1
  50. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  51. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  52. package/dist/api/device/DeviceUnlock.d.ts +2 -2
  53. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  54. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +4 -3
  55. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  56. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  57. package/dist/api/helpers/protocolV2FileWrite.d.ts +9 -0
  58. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  59. package/dist/api/index.d.ts +2 -0
  60. package/dist/api/index.d.ts.map +1 -1
  61. package/dist/api/kaspa/KaspaGetAddress.d.ts +1 -1
  62. package/dist/api/kaspa/KaspaSignTransaction.d.ts +1 -1
  63. package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
  64. package/dist/api/polkadot/PolkadotGetAddress.d.ts +1 -1
  65. package/dist/api/polkadot/networks.d.ts +1 -1
  66. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +31 -0
  67. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
  68. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  69. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  70. package/dist/api/solana/SolSignMessage.d.ts +1 -1
  71. package/dist/api/solana/SolSignOffchainMessage.d.ts +1 -1
  72. package/dist/api/solana/SolSignTransaction.d.ts +2 -2
  73. package/dist/api/sui/SuiGetAddress.d.ts +1 -1
  74. package/dist/api/sui/SuiGetPublicKey.d.ts +1 -1
  75. package/dist/api/sui/SuiSignMessage.d.ts +1 -1
  76. package/dist/api/sui/SuiSignTransaction.d.ts +1 -1
  77. package/dist/api/ton/TonGetAddress.d.ts +1 -1
  78. package/dist/api/ton/TonSignMessage.d.ts +1 -1
  79. package/dist/api/ton/TonSignProof.d.ts +1 -1
  80. package/dist/api/tron/TronSignMessage.d.ts +2 -2
  81. package/dist/api/tron/TronSignTransaction.d.ts +1 -1
  82. package/dist/core/deviceEventRegistration.d.ts +2 -0
  83. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  84. package/dist/core/index.d.ts.map +1 -1
  85. package/dist/core/uiPromiseRegistry.d.ts +6 -0
  86. package/dist/core/uiPromiseRegistry.d.ts.map +1 -0
  87. package/dist/data-manager/DataManager.d.ts +9 -3
  88. package/dist/data-manager/DataManager.d.ts.map +1 -1
  89. package/dist/data-manager/TransportManager.d.ts.map +1 -1
  90. package/dist/device/Device.d.ts +29 -5
  91. package/dist/device/Device.d.ts.map +1 -1
  92. package/dist/device/DeviceCommands.d.ts +4 -4
  93. package/dist/device/DeviceCommands.d.ts.map +1 -1
  94. package/dist/device/DeviceConnector.d.ts +2 -1
  95. package/dist/device/DeviceConnector.d.ts.map +1 -1
  96. package/dist/device/DevicePool.d.ts.map +1 -1
  97. package/dist/deviceProfile/protocolV2DeviceIdentity.d.ts.map +1 -1
  98. package/dist/events/device.d.ts +4 -0
  99. package/dist/events/device.d.ts.map +1 -1
  100. package/dist/events/logBlockEvent.d.ts.map +1 -1
  101. package/dist/events/ui-promise.d.ts +4 -2
  102. package/dist/events/ui-promise.d.ts.map +1 -1
  103. package/dist/events/ui-request.d.ts +31 -2
  104. package/dist/events/ui-request.d.ts.map +1 -1
  105. package/dist/events/ui-response.d.ts +10 -2
  106. package/dist/events/ui-response.d.ts.map +1 -1
  107. package/dist/index.d.ts +243 -69
  108. package/dist/index.js +2563 -1217
  109. package/dist/inject.d.ts +6 -1
  110. package/dist/inject.d.ts.map +1 -1
  111. package/dist/lowLevelInject.d.ts.map +1 -1
  112. package/dist/protocols/protocol-v2/features.d.ts +0 -4
  113. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  114. package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
  115. package/dist/protocols/protocol-v2/resources.d.ts +30 -0
  116. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -0
  117. package/dist/protocols/protocol-v2/uiInteraction.d.ts +7 -4
  118. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  119. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +1 -3
  120. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  121. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
  122. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
  123. package/dist/protocols/protocol-v2/walletSession.d.ts +6 -1
  124. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  125. package/dist/topLevelInject.d.ts.map +1 -1
  126. package/dist/types/api/checkAllFirmwareRelease.d.ts +3 -1
  127. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  128. package/dist/types/api/detectDeviceConnectProtocol.d.ts +4 -0
  129. package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +1 -0
  130. package/dist/types/api/deviceUnlock.d.ts +5 -1
  131. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  132. package/dist/types/api/export.d.ts +1 -0
  133. package/dist/types/api/export.d.ts.map +1 -1
  134. package/dist/types/api/firmwareUpdate.d.ts +4 -2
  135. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  136. package/dist/types/api/index.d.ts +6 -1
  137. package/dist/types/api/index.d.ts.map +1 -1
  138. package/dist/types/api/protocolV2.d.ts +3 -0
  139. package/dist/types/api/protocolV2.d.ts.map +1 -1
  140. package/dist/types/device.d.ts +2 -2
  141. package/dist/types/device.d.ts.map +1 -1
  142. package/dist/types/params.d.ts +1 -0
  143. package/dist/types/params.d.ts.map +1 -1
  144. package/dist/types/settings.d.ts +38 -8
  145. package/dist/types/settings.d.ts.map +1 -1
  146. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
  147. package/dist/utils/deviceFeaturesUtils.d.ts +4 -0
  148. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  149. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  150. package/dist/utils/deviceSettings.d.ts.map +1 -1
  151. package/dist/utils/homescreen.d.ts +4 -0
  152. package/dist/utils/homescreen.d.ts.map +1 -1
  153. package/dist/utils/index.d.ts +1 -1
  154. package/dist/utils/index.d.ts.map +1 -1
  155. package/dist/utils/patch.d.ts +1 -1
  156. package/dist/utils/patch.d.ts.map +1 -1
  157. package/dist/utils/pro2Nft.d.ts +31 -0
  158. package/dist/utils/pro2Nft.d.ts.map +1 -0
  159. package/dist/utils/pro2Wallpaper.d.ts +10 -0
  160. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  161. package/dist/utils/uiProgressThrottle.d.ts +3 -0
  162. package/dist/utils/uiProgressThrottle.d.ts.map +1 -0
  163. package/package.json +4 -4
  164. package/src/api/BaseMethod.ts +8 -10
  165. package/src/api/CheckAllFirmwareRelease.ts +61 -11
  166. package/src/api/DetectDeviceConnectProtocol.ts +18 -0
  167. package/src/api/FirmwareUpdate.ts +6 -2
  168. package/src/api/FirmwareUpdateV2.ts +5 -2
  169. package/src/api/FirmwareUpdateV3.ts +6 -2
  170. package/src/api/FirmwareUpdateV4.ts +463 -258
  171. package/src/api/GetPassphraseState.ts +7 -1
  172. package/src/api/OpenWalletSession.ts +71 -17
  173. package/src/api/SearchDevices.ts +3 -1
  174. package/src/api/allnetwork/AllNetworkGetAddress.ts +21 -21
  175. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +36 -11
  176. package/src/api/device/DeviceSettings.ts +5 -4
  177. package/src/api/device/DeviceUnlock.ts +8 -3
  178. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +27 -12
  179. package/src/api/firmware/uploadFirmware.ts +17 -4
  180. package/src/api/helpers/protocolV2FileWrite.ts +202 -63
  181. package/src/api/index.ts +2 -0
  182. package/src/api/kaspa/KaspaGetAddress.ts +1 -1
  183. package/src/api/kaspa/KaspaSignTransaction.ts +2 -13
  184. package/src/api/polkadot/networks.ts +3 -3
  185. package/src/api/protocol-v2/DeviceUploadNft.ts +197 -0
  186. package/src/api/protocol-v2/ProtocolInfoRequest.ts +3 -1
  187. package/src/api/protocol-v2/helpers.ts +1 -1
  188. package/src/api/solana/SolSignMessage.ts +1 -1
  189. package/src/api/solana/SolSignOffchainMessage.ts +1 -1
  190. package/src/api/solana/SolSignTransaction.ts +2 -2
  191. package/src/api/sui/SuiGetAddress.ts +1 -1
  192. package/src/api/sui/SuiGetPublicKey.ts +1 -1
  193. package/src/api/sui/SuiSignMessage.ts +1 -1
  194. package/src/api/sui/SuiSignTransaction.ts +1 -1
  195. package/src/api/ton/TonGetAddress.ts +1 -1
  196. package/src/api/ton/TonSignMessage.ts +1 -1
  197. package/src/api/ton/TonSignProof.ts +1 -1
  198. package/src/api/tron/TronSignMessage.ts +2 -2
  199. package/src/api/tron/TronSignTransaction.ts +1 -1
  200. package/src/core/deviceEventRegistration.ts +4 -0
  201. package/src/core/index.ts +213 -111
  202. package/src/core/uiPromiseRegistry.ts +63 -0
  203. package/src/data/messages/messages-protocol-v2.json +25 -0
  204. package/src/data-manager/DataManager.ts +88 -11
  205. package/src/data-manager/TransportManager.ts +6 -0
  206. package/src/device/Device.ts +273 -43
  207. package/src/device/DeviceCommands.ts +31 -4
  208. package/src/device/DeviceConnector.ts +33 -13
  209. package/src/device/DevicePool.ts +21 -7
  210. package/src/deviceProfile/buildDeviceFeatures.ts +2 -2
  211. package/src/deviceProfile/protocolV2DeviceIdentity.ts +3 -0
  212. package/src/events/device.ts +4 -0
  213. package/src/events/logBlockEvent.ts +1 -0
  214. package/src/events/ui-promise.ts +4 -2
  215. package/src/events/ui-request.ts +36 -2
  216. package/src/events/ui-response.ts +12 -2
  217. package/src/inject.ts +58 -2
  218. package/src/lowLevelInject.ts +6 -3
  219. package/src/protocols/protocol-v2/features.ts +10 -7
  220. package/src/protocols/protocol-v2/firmware.ts +2 -0
  221. package/src/protocols/protocol-v2/resources.ts +390 -0
  222. package/src/protocols/protocol-v2/uiInteraction.ts +46 -6
  223. package/src/protocols/protocol-v2/unlockPolicy.ts +1 -105
  224. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +131 -0
  225. package/src/protocols/protocol-v2/walletSession.ts +214 -36
  226. package/src/topLevelInject.ts +6 -3
  227. package/src/types/api/checkAllFirmwareRelease.ts +3 -1
  228. package/src/types/api/detectDeviceConnectProtocol.ts +6 -0
  229. package/src/types/api/deviceUnlock.ts +12 -1
  230. package/src/types/api/export.ts +1 -0
  231. package/src/types/api/firmwareUpdate.ts +6 -3
  232. package/src/types/api/index.ts +13 -0
  233. package/src/types/api/protocolV2.ts +13 -0
  234. package/src/types/device.ts +15 -3
  235. package/src/types/params.ts +7 -1
  236. package/src/types/settings.ts +60 -9
  237. package/src/utils/deviceFeaturesCompat.ts +5 -0
  238. package/src/utils/deviceFeaturesUtils.ts +14 -3
  239. package/src/utils/deviceInfoUtils.ts +2 -0
  240. package/src/utils/deviceSettings.ts +3 -0
  241. package/src/utils/homescreen.ts +32 -6
  242. package/src/utils/index.ts +6 -1
  243. package/src/utils/pro2Nft.ts +142 -0
  244. package/src/utils/pro2Wallpaper.ts +35 -8
  245. package/src/utils/uiProgressThrottle.ts +63 -0
  246. package/dist/api/firmware/progressThrottle.d.ts +0 -3
  247. package/dist/api/firmware/progressThrottle.d.ts.map +0 -1
  248. package/dist/protocols/protocol-v2/lockedError.d.ts +0 -2
  249. package/dist/protocols/protocol-v2/lockedError.d.ts.map +0 -1
  250. package/dist/protocols/protocol-v2/unlockRetry.d.ts +0 -10
  251. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +0 -1
  252. package/src/api/firmware/progressThrottle.ts +0 -44
  253. package/src/protocols/protocol-v2/lockedError.ts +0 -10
  254. package/src/protocols/protocol-v2/unlockRetry.ts +0 -109
@@ -0,0 +1,63 @@
1
+ import { UI_RESPONSE } from '../events/ui-response';
2
+
3
+ import type { UiPromise, UiPromiseResponse } from '../events/ui-promise';
4
+ import type { UiResponseEvent } from '../events/ui-response';
5
+
6
+ const normalizeUiPromiseError = (error: unknown) =>
7
+ error instanceof Error ? error : new Error(String(error));
8
+
9
+ export const consumeUiPromise = <T>(
10
+ promise: Promise<T>,
11
+ onFulfilled: (value: T) => void,
12
+ onRejected: (error: Error) => void
13
+ ) => {
14
+ promise.then(onFulfilled, error => {
15
+ onRejected(normalizeUiPromiseError(error));
16
+ });
17
+ };
18
+
19
+ export const rejectUiPromises = (
20
+ uiPromises: UiPromise<UiPromiseResponse['type']>[],
21
+ error: Error
22
+ ) => {
23
+ for (const uiPromise of uiPromises) {
24
+ uiPromise.reject(error);
25
+ }
26
+ };
27
+
28
+ const isSensitiveUiResponse = (
29
+ response: UiResponseEvent
30
+ ): response is Extract<
31
+ UiResponseEvent,
32
+ { type: typeof UI_RESPONSE.RECEIVE_PIN | typeof UI_RESPONSE.RECEIVE_PASSPHRASE }
33
+ > => response.type === UI_RESPONSE.RECEIVE_PIN || response.type === UI_RESPONSE.RECEIVE_PASSPHRASE;
34
+
35
+ export const findUiPromiseForResponse = (
36
+ uiPromises: UiPromise<UiPromiseResponse['type']>[],
37
+ response: UiResponseEvent
38
+ ) => {
39
+ const candidates = uiPromises.filter(promise => promise.id === response.type);
40
+ if (!isSensitiveUiResponse(response)) {
41
+ return candidates[0];
42
+ }
43
+
44
+ const hasInteractionId = typeof response.interactionId === 'string';
45
+ const hasDeviceId = typeof response.deviceId === 'string';
46
+ if (hasInteractionId !== hasDeviceId) {
47
+ return undefined;
48
+ }
49
+
50
+ if (hasInteractionId && hasDeviceId) {
51
+ return candidates.find(promise => {
52
+ const correlation = promise.responseCorrelation;
53
+ return (
54
+ correlation?.interactionId === response.interactionId &&
55
+ correlation?.deviceId === response.deviceId
56
+ );
57
+ });
58
+ }
59
+
60
+ // Legacy clients do not return correlation metadata. Preserve their single-request
61
+ // behavior, but never guess when multiple sensitive requests are pending.
62
+ return candidates.length === 1 ? candidates[0] : undefined;
63
+ };
@@ -470,6 +470,7 @@
470
470
  "MessageType_DeviceSessionAskPin": 61202,
471
471
  "MessageType_DeviceSessionAskPassphrase": 61203,
472
472
  "MessageType_PortfolioUpdate": 61400,
473
+ "MessageType_NftUpdate": 61500,
473
474
  "MessageType_OnboardingStatusGet": 61600,
474
475
  "MessageType_OnboardingStatus": 61601
475
476
  },
@@ -12200,11 +12201,26 @@
12200
12201
  "DeviceSessionError_Busy": 5
12201
12202
  }
12202
12203
  },
12204
+ "DeviceSessionSeedDomain": {
12205
+ "values": {
12206
+ "SeedDomain_Standard": 1,
12207
+ "SeedDomain_Cardano": 2
12208
+ }
12209
+ },
12203
12210
  "DeviceSessionGet": {
12204
12211
  "fields": {
12205
12212
  "session_id": {
12206
12213
  "type": "bytes",
12207
12214
  "id": 1
12215
+ },
12216
+ "btc_test_address": {
12217
+ "type": "string",
12218
+ "id": 2
12219
+ },
12220
+ "seed_domains": {
12221
+ "rule": "repeated",
12222
+ "type": "DeviceSessionSeedDomain",
12223
+ "id": 3
12208
12224
  }
12209
12225
  }
12210
12226
  },
@@ -12538,6 +12554,15 @@
12538
12554
  }
12539
12555
  }
12540
12556
  },
12557
+ "NftUpdate": {
12558
+ "fields": {
12559
+ "file_name_no_ext": {
12560
+ "rule": "required",
12561
+ "type": "string",
12562
+ "id": 1
12563
+ }
12564
+ }
12565
+ },
12541
12566
  "OnboardingStep": {
12542
12567
  "values": {
12543
12568
  "ONBOARDING_STEP_UNKNOWN": 0,
@@ -1,6 +1,6 @@
1
1
  import axios from 'axios';
2
2
  import semver from 'semver';
3
- import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
3
+ import { EDeviceType, EFirmwareType, ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
4
4
 
5
5
  import MessagesJSON from '../data/messages/messages.json';
6
6
  import MessagesLegacyV1JSON from '../data/messages/messages_legacy_v1.json';
@@ -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,
@@ -25,6 +26,7 @@ import type {
25
26
  Features,
26
27
  IDeviceBLEFirmwareStatus,
27
28
  IDeviceFirmwareStatus,
29
+ IProtocolV2Resources,
28
30
  ITransportStatus,
29
31
  IVersionArray,
30
32
  RemoteConfigResponse,
@@ -67,7 +69,7 @@ function getFirmwareTypeFromField(firmwareField: IFirmwareField): EFirmwareType
67
69
 
68
70
  export default class DataManager {
69
71
  static deviceMap: DeviceTypeMap & {
70
- [k: string]: DeviceTypeMap[keyof DeviceTypeMap] | undefined;
72
+ [k: string]: NonNullable<DeviceTypeMap[keyof DeviceTypeMap]> | undefined;
71
73
  } = {
72
74
  [EDeviceType.Classic]: {
73
75
  firmware: [],
@@ -93,6 +95,10 @@ export default class DataManager {
93
95
  firmware: [],
94
96
  ble: [],
95
97
  },
98
+ [EDeviceType.Neo]: {
99
+ firmware: [],
100
+ ble: [],
101
+ },
96
102
  [EDeviceType.ClassicPure]: {
97
103
  firmware: [],
98
104
  ble: [],
@@ -111,6 +117,8 @@ export default class DataManager {
111
117
 
112
118
  static lastCheckTimestamp = 0;
113
119
 
120
+ static protocolV2ResourcesConfigError: Error | undefined;
121
+
114
122
  static getFirmwareStatus = (
115
123
  features: Features,
116
124
  firmwareType: EFirmwareType
@@ -355,7 +363,7 @@ export default class DataManager {
355
363
 
356
364
  private static enrichFirmwareReleaseInfo(
357
365
  deviceData: DeviceTypeMap[keyof DeviceTypeMap] | undefined
358
- ): DeviceTypeMap[keyof DeviceTypeMap] {
366
+ ): NonNullable<DeviceTypeMap[keyof DeviceTypeMap]> {
359
367
  // Safety check: return default structure if input is undefined/null
360
368
  if (!deviceData || typeof deviceData !== 'object') {
361
369
  return {
@@ -397,20 +405,21 @@ export default class DataManager {
397
405
  return enrichedData;
398
406
  }
399
407
 
400
- static async load(settings: ConnectSettings) {
408
+ static async load(settings: ConnectSettings): Promise<boolean> {
401
409
  this.settings = settings;
410
+ this.protocolV2ResourcesConfigError = undefined;
402
411
  const manifestMode =
403
412
  settings.firmwareManifestMode ?? (settings.fetchConfig ? 'sdk-managed' : undefined);
404
413
  if (settings.preloadedConfig) {
405
414
  this.applyRemoteConfig(settings.preloadedConfig);
406
415
  Log.log('[DataConfig] Preloaded firmware config loaded');
407
- return;
416
+ return true;
408
417
  }
409
418
  if (manifestMode === 'external-only') {
410
419
  throw new Error('External firmware config snapshot is required');
411
420
  }
412
421
  if (manifestMode !== 'sdk-managed') {
413
- return;
422
+ return false;
414
423
  }
415
424
 
416
425
  const url = settings.preRelease
@@ -419,10 +428,14 @@ export default class DataManager {
419
428
 
420
429
  const urlWithCache = `${url}?noCache=${getTimeStamp()}`;
421
430
  let data: RemoteConfigResponse | null = null;
431
+ let fetchMethod: 'configFetcher' | 'axios' | 'none' = 'none';
422
432
  if (settings.configFetcher) {
423
433
  Log.debug('[DataConfig] Trying client configFetcher...');
424
434
  try {
425
435
  data = await settings.configFetcher(urlWithCache);
436
+ if (data) {
437
+ fetchMethod = 'configFetcher';
438
+ }
426
439
  } catch (e) {
427
440
  Log.warn('[DataConfig] Client configFetcher failed:', e);
428
441
  }
@@ -435,6 +448,7 @@ export default class DataManager {
435
448
  timeout: 7000,
436
449
  });
437
450
  data = response.data;
451
+ fetchMethod = 'axios';
438
452
  Log.log('[DataConfig] SDK-managed config request succeeded');
439
453
  } catch (e) {
440
454
  Log.warn('[DataConfig] SDK-managed config request failed:', e);
@@ -443,12 +457,34 @@ export default class DataManager {
443
457
 
444
458
  if (data) {
445
459
  this.applyRemoteConfig(data);
446
- } else {
447
- Log.warn('[DataConfig] SDK-managed config request failed, using built-in default config');
460
+ Log.log(`[DataConfig] Config loaded successfully via [${fetchMethod}]`);
461
+ return true;
448
462
  }
463
+ Log.warn('[DataConfig] All fetch methods failed, using built-in default config');
464
+ return false;
449
465
  }
450
466
 
451
467
  private static applyRemoteConfig(data: RemoteConfigResponse) {
468
+ let pro2Resources: IProtocolV2Resources | undefined;
469
+ let neoResources: IProtocolV2Resources | undefined;
470
+ try {
471
+ pro2Resources = parseProtocolV2Resources(
472
+ (data.pro2 as { resources?: unknown } | undefined)?.resources
473
+ );
474
+ neoResources = parseProtocolV2Resources(
475
+ (data.neo as { resources?: unknown } | undefined)?.resources
476
+ );
477
+ } catch (error) {
478
+ // Firmware resource metadata is not required for base communication. If the
479
+ // remote config is temporarily incomplete, disable this resource update only.
480
+ this.protocolV2ResourcesConfigError =
481
+ error instanceof Error ? error : new Error(String(error));
482
+ Log.warn('[DataConfig] Ignoring invalid Protocol V2 resources config:', error);
483
+ }
484
+ const enrichedPro2Config = this.enrichFirmwareReleaseInfo(data.pro2);
485
+ const enrichedNeoConfig = this.enrichFirmwareReleaseInfo(data.neo);
486
+ const { resources: _unvalidatedResources, ...pro2Config } = enrichedPro2Config;
487
+ const { resources: _unvalidatedNeoResources, ...neoConfig } = enrichedNeoConfig;
452
488
  this.deviceMap = {
453
489
  [EDeviceType.Classic]: this.enrichFirmwareReleaseInfo(data.classic),
454
490
  [EDeviceType.Classic1s]: this.enrichFirmwareReleaseInfo(data.classic1s),
@@ -456,7 +492,14 @@ export default class DataManager {
456
492
  [EDeviceType.Mini]: this.enrichFirmwareReleaseInfo(data.mini),
457
493
  [EDeviceType.Touch]: this.enrichFirmwareReleaseInfo(data.touch),
458
494
  [EDeviceType.Pro]: this.enrichFirmwareReleaseInfo(data.pro),
459
- [EDeviceType.Pro2]: this.enrichFirmwareReleaseInfo(data.pro2),
495
+ [EDeviceType.Pro2]: {
496
+ ...pro2Config,
497
+ ...(pro2Resources ? { resources: pro2Resources } : undefined),
498
+ },
499
+ [EDeviceType.Neo]: {
500
+ ...neoConfig,
501
+ ...(neoResources ? { resources: neoResources } : undefined),
502
+ },
460
503
  };
461
504
  this.assets = {
462
505
  bridge: data.bridge,
@@ -478,12 +521,46 @@ export default class DataManager {
478
521
 
479
522
  static async checkAndReloadData() {
480
523
  if (getTimeStamp() - this.lastCheckTimestamp > 1000 * 60 * 60 * 3) {
481
- await this.load(this.settings).then(() => {
524
+ const loaded = await this.load(this.settings);
525
+ if (loaded) {
482
526
  this.lastCheckTimestamp = getTimeStamp();
483
- });
527
+ }
484
528
  }
485
529
  }
486
530
 
531
+ /** Force a fresh remote config before an update is allowed to mutate the device. */
532
+ static async forceReloadData({
533
+ requireResources = false,
534
+ }: { requireResources?: boolean } = {}): Promise<void> {
535
+ if (!this.settings) {
536
+ throw new Error('Remote config settings are not initialized');
537
+ }
538
+ const loaded = await this.load(this.settings);
539
+ if (!loaded) {
540
+ throw ERRORS.TypedError(
541
+ HardwareErrorCode.NetworkError,
542
+ 'Unable to refresh the latest remote config'
543
+ );
544
+ }
545
+ if (requireResources && this.protocolV2ResourcesConfigError) {
546
+ throw ERRORS.TypedError(
547
+ HardwareErrorCode.FirmwareUpdateDownloadFailed,
548
+ `Invalid Pro2 resources config: ${this.protocolV2ResourcesConfigError.message}`
549
+ );
550
+ }
551
+ this.lastCheckTimestamp = getTimeStamp();
552
+ }
553
+
554
+ static getProtocolV2Resources(deviceType: EDeviceType.Pro2 | EDeviceType.Neo = EDeviceType.Pro2) {
555
+ return this.deviceMap[deviceType]?.resources?.stable;
556
+ }
557
+
558
+ static getProtocolV2BootResources(
559
+ deviceType: EDeviceType.Pro2 | EDeviceType.Neo = EDeviceType.Pro2
560
+ ) {
561
+ return this.deviceMap[deviceType]?.resources?.boot;
562
+ }
563
+
487
564
  static getProtobufMessages(schema: ProtobufMessageSchema = 'v1CurrentSchema'): JSON {
488
565
  return this.messages[schema];
489
566
  }
@@ -121,6 +121,12 @@ export default class TransportManager {
121
121
  }
122
122
 
123
123
  static setTransport(TransportConstructor: any, plugin?: LowlevelTransportSharedPlugin) {
124
+ if (typeof TransportConstructor !== 'function') {
125
+ throw ERRORS.TypedError(
126
+ HardwareErrorCode.TransportNotConfigured,
127
+ 'Transport constructor is not available'
128
+ );
129
+ }
124
130
  const env = DataManager.getSettings('env');
125
131
  if (env === 'react-native') {
126
132
  /** Actually initializes the ReactNativeTransport */