@onekeyfe/hd-core 1.2.0-alpha.19 → 1.2.0-alpha.20

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 (256) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +75 -0
  2. package/__tests__/DeviceCommands.test.ts +143 -7
  3. package/__tests__/RequestQueue.test.ts +106 -0
  4. package/__tests__/UploadPortfolio.test.ts +46 -0
  5. package/__tests__/core-dispose.test.ts +34 -0
  6. package/__tests__/core-error-output.test.ts +39 -0
  7. package/__tests__/device-lifecycle-events.test.ts +117 -0
  8. package/__tests__/device-pool-state.test.ts +20 -1
  9. package/__tests__/device-settings.test.ts +184 -6
  10. package/__tests__/device-state-events.test.ts +1 -2
  11. package/__tests__/device-state-mapper.test.ts +33 -26
  12. package/__tests__/device-state-store.test.ts +1 -34
  13. package/__tests__/device-utils.test.ts +106 -0
  14. package/__tests__/device-wallet-session-store.test.ts +65 -29
  15. package/__tests__/deviceSettings.test.ts +21 -12
  16. package/__tests__/evmLedgerLegacySafety.test.ts +2 -2
  17. package/__tests__/evmSignTypedData.test.ts +80 -0
  18. package/__tests__/filesystemValidation.test.ts +53 -0
  19. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +402 -0
  20. package/__tests__/get-device-state.test.ts +77 -41
  21. package/__tests__/logBlockEvent.test.ts +24 -11
  22. package/__tests__/networkUtils.test.ts +386 -0
  23. package/__tests__/open-wallet-session-error-response.test.ts +43 -0
  24. package/__tests__/open-wallet-session.test.ts +559 -0
  25. package/__tests__/protocol-v2.test.ts +756 -452
  26. package/__tests__/public-device-state-api.test.ts +113 -13
  27. package/__tests__/public-pro2-api-boundary.test.ts +91 -0
  28. package/__tests__/search-devices.test.ts +43 -0
  29. package/dist/api/BaseMethod.d.ts +3 -0
  30. package/dist/api/BaseMethod.d.ts.map +1 -1
  31. package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
  32. package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
  33. package/dist/api/ClearSessionCache.d.ts.map +1 -1
  34. package/dist/api/DirList.d.ts.map +1 -1
  35. package/dist/api/FileRead.d.ts.map +1 -1
  36. package/dist/api/FirmwareUpdateV2.d.ts +2 -2
  37. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  38. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  39. package/dist/api/FirmwareUpdateV4.d.ts +3 -2
  40. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  41. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  42. package/dist/api/OpenWalletSession.d.ts +14 -0
  43. package/dist/api/OpenWalletSession.d.ts.map +1 -0
  44. package/dist/api/PathInfo.d.ts.map +1 -1
  45. package/dist/api/PromptWebDeviceAccess.d.ts.map +1 -1
  46. package/dist/api/SearchDevices.d.ts +3 -0
  47. package/dist/api/SearchDevices.d.ts.map +1 -1
  48. package/dist/api/UploadPortfolio.d.ts.map +1 -1
  49. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  50. package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
  51. package/dist/api/device/DeviceFullyUploadResource.d.ts +1 -2
  52. package/dist/api/device/DeviceFullyUploadResource.d.ts.map +1 -1
  53. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  54. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  55. package/dist/api/device/DeviceWipe.d.ts.map +1 -1
  56. package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
  57. package/dist/api/firmware/getBinary.d.ts +7 -3
  58. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  59. package/dist/api/helpers/filesystemValidation.d.ts +3 -0
  60. package/dist/api/helpers/filesystemValidation.d.ts.map +1 -1
  61. package/dist/api/helpers/paramsValidator.d.ts +1 -0
  62. package/dist/api/helpers/paramsValidator.d.ts.map +1 -1
  63. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  64. package/dist/api/index.d.ts +7 -11
  65. package/dist/api/index.d.ts.map +1 -1
  66. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
  67. package/dist/api/protocol-v2/DeviceSettingsPageShow.d.ts.map +1 -1
  68. package/dist/api/protocol-v2/DeviceSettingsSet.d.ts.map +1 -1
  69. package/dist/api/utils.d.ts.map +1 -1
  70. package/dist/core/RequestQueue.d.ts +17 -1
  71. package/dist/core/RequestQueue.d.ts.map +1 -1
  72. package/dist/core/index.d.ts +3 -1
  73. package/dist/core/index.d.ts.map +1 -1
  74. package/dist/device/Device.d.ts +6 -5
  75. package/dist/device/Device.d.ts.map +1 -1
  76. package/dist/device/DeviceCommands.d.ts +5 -5
  77. package/dist/device/DeviceCommands.d.ts.map +1 -1
  78. package/dist/device/DevicePool.d.ts +1 -0
  79. package/dist/device/DevicePool.d.ts.map +1 -1
  80. package/dist/device/DeviceStateMapper.d.ts +2 -2
  81. package/dist/device/DeviceStateMapper.d.ts.map +1 -1
  82. package/dist/device/DeviceStateProjector.d.ts +1 -2
  83. package/dist/device/DeviceStateProjector.d.ts.map +1 -1
  84. package/dist/device/DeviceStateStore.d.ts +1 -3
  85. package/dist/device/DeviceStateStore.d.ts.map +1 -1
  86. package/dist/device/DeviceWalletSessionStore.d.ts +6 -1
  87. package/dist/device/DeviceWalletSessionStore.d.ts.map +1 -1
  88. package/dist/device/cloneDeviceState.d.ts +2 -0
  89. package/dist/device/cloneDeviceState.d.ts.map +1 -0
  90. package/dist/deviceProfile/buildDeviceFeatures.d.ts +3 -1
  91. package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
  92. package/dist/events/logBlockEvent.d.ts.map +1 -1
  93. package/dist/index.d.ts +608 -75
  94. package/dist/index.js +2287 -1706
  95. package/dist/inject.d.ts.map +1 -1
  96. package/dist/protocols/protocol-v2/deviceSession.d.ts +7 -0
  97. package/dist/protocols/protocol-v2/deviceSession.d.ts.map +1 -0
  98. package/dist/protocols/protocol-v2/features.d.ts +11 -4
  99. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  100. package/dist/protocols/protocol-v2/index.d.ts +2 -2
  101. package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
  102. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts +16 -0
  103. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -0
  104. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  105. package/dist/protocols/protocol-v2/walletSession.d.ts +8 -3
  106. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  107. package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -2
  108. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  109. package/dist/types/api/deviceSettings.d.ts +1 -0
  110. package/dist/types/api/deviceSettings.d.ts.map +1 -1
  111. package/dist/types/api/deviceUnlock.d.ts +1 -1
  112. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  113. package/dist/types/api/getFeatures.d.ts.map +1 -1
  114. package/dist/types/api/getOnekeyFeatures.d.ts.map +1 -1
  115. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  116. package/dist/types/api/index.d.ts +13 -15
  117. package/dist/types/api/index.d.ts.map +1 -1
  118. package/dist/types/api/openWalletSession.d.ts +41 -0
  119. package/dist/types/api/openWalletSession.d.ts.map +1 -0
  120. package/dist/types/api/protocolV2.d.ts +6 -11
  121. package/dist/types/api/protocolV2.d.ts.map +1 -1
  122. package/dist/types/device.d.ts +2 -9
  123. package/dist/types/device.d.ts.map +1 -1
  124. package/dist/utils/assets.d.ts +2 -1
  125. package/dist/utils/assets.d.ts.map +1 -1
  126. package/dist/utils/deviceFeaturesCompat.d.ts +13 -0
  127. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -0
  128. package/dist/utils/deviceFeaturesUtils.d.ts +11 -1
  129. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  130. package/dist/utils/deviceInfoUtils.d.ts +9 -8
  131. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  132. package/dist/utils/deviceSettings.d.ts +2 -0
  133. package/dist/utils/deviceSettings.d.ts.map +1 -1
  134. package/dist/utils/deviceVersionUtils.d.ts +6 -5
  135. package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
  136. package/dist/utils/index.d.ts +2 -2
  137. package/dist/utils/index.d.ts.map +1 -1
  138. package/dist/utils/networkUtils.d.ts +9 -1
  139. package/dist/utils/networkUtils.d.ts.map +1 -1
  140. package/dist/utils/patch.d.ts +1 -1
  141. package/dist/utils/patch.d.ts.map +1 -1
  142. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  143. package/package.json +4 -4
  144. package/src/api/BaseMethod.ts +17 -10
  145. package/src/api/CheckBootloaderRelease.ts +1 -2
  146. package/src/api/CheckFirmwareRelease.ts +1 -2
  147. package/src/api/ClearSessionCache.ts +0 -4
  148. package/src/api/DirList.ts +5 -3
  149. package/src/api/DirMake.ts +3 -3
  150. package/src/api/DirRemove.ts +3 -3
  151. package/src/api/FileDelete.ts +3 -3
  152. package/src/api/FileRead.ts +9 -6
  153. package/src/api/FileWrite.ts +3 -3
  154. package/src/api/FirmwareUpdate.ts +4 -4
  155. package/src/api/FirmwareUpdateV2.ts +133 -45
  156. package/src/api/FirmwareUpdateV3.ts +3 -5
  157. package/src/api/FirmwareUpdateV4.ts +192 -154
  158. package/src/api/GetPassphraseState.ts +10 -16
  159. package/src/api/OpenWalletSession.ts +221 -0
  160. package/src/api/PathInfo.ts +5 -3
  161. package/src/api/PromptWebDeviceAccess.ts +2 -3
  162. package/src/api/SearchDevices.ts +6 -2
  163. package/src/api/UploadPortfolio.ts +12 -3
  164. package/src/api/alephium/AlephiumSignTransaction.ts +2 -2
  165. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +4 -8
  166. package/src/api/benfen/BenfenGetAddress.ts +1 -1
  167. package/src/api/btc/BTCGetPublicKey.ts +1 -1
  168. package/src/api/device/DeviceChangePin.ts +1 -0
  169. package/src/api/device/DeviceFullyUploadResource.ts +4 -5
  170. package/src/api/device/DeviceSettings.ts +93 -0
  171. package/src/api/device/DeviceUpdateBootloader.ts +1 -2
  172. package/src/api/device/DeviceWipe.ts +1 -0
  173. package/src/api/evm/EVMSignTypedData.ts +3 -5
  174. package/src/api/evm/legacyV1/getAddress.ts +2 -2
  175. package/src/api/evm/legacyV1/getPublicKey.ts +2 -2
  176. package/src/api/evm/legacyV1/signMessage.ts +2 -2
  177. package/src/api/evm/legacyV1/signTypedData.ts +2 -2
  178. package/src/api/evm/legacyV1/signTypedHash.ts +2 -2
  179. package/src/api/evm/legacyV1/verifyMessage.ts +2 -2
  180. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +3 -3
  181. package/src/api/firmware/getBinary.ts +8 -3
  182. package/src/api/helpers/batchGetPublickeys.ts +2 -2
  183. package/src/api/helpers/filesystemValidation.ts +61 -0
  184. package/src/api/helpers/paramsValidator.ts +1 -1
  185. package/src/api/helpers/protocolV2FileWrite.ts +3 -2
  186. package/src/api/index.ts +9 -12
  187. package/src/api/nervos/NervosSignTransaction.ts +2 -2
  188. package/src/api/nexa/NexaSignTransaction.ts +1 -1
  189. package/src/api/protocol-v2/DeviceFactoryInfoGet.ts +1 -1
  190. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
  191. package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +4 -4
  192. package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +6 -5
  193. package/src/api/protocol-v2/DeviceInfoGet.ts +4 -4
  194. package/src/api/protocol-v2/DeviceReboot.ts +1 -1
  195. package/src/api/protocol-v2/DeviceSettingsPageShow.ts +11 -8
  196. package/src/api/protocol-v2/DeviceSettingsSet.ts +4 -11
  197. package/src/api/protocol-v2/FilesystemFormat.ts +1 -1
  198. package/src/api/protocol-v2/FilesystemPermissionFix.ts +1 -1
  199. package/src/api/protocol-v2/Ping.ts +1 -1
  200. package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -1
  201. package/src/api/utils.ts +1 -3
  202. package/src/core/RequestQueue.ts +107 -6
  203. package/src/core/index.ts +91 -46
  204. package/src/data/messages/messages-protocol-v2.json +25 -79
  205. package/src/data-manager/DataManager.ts +6 -6
  206. package/src/device/Device.ts +186 -102
  207. package/src/device/DeviceCommands.ts +51 -21
  208. package/src/device/DeviceFeaturesState.ts +4 -4
  209. package/src/device/DevicePool.ts +17 -3
  210. package/src/device/DeviceStateMapper.ts +13 -29
  211. package/src/device/DeviceStateProjector.ts +11 -8
  212. package/src/device/DeviceStateStore.ts +11 -52
  213. package/src/device/DeviceWalletSessionStore.ts +31 -4
  214. package/src/device/cloneDeviceState.ts +39 -0
  215. package/src/device/deviceIdentity.ts +2 -2
  216. package/src/deviceProfile/buildDeviceFeatures.ts +29 -88
  217. package/src/events/logBlockEvent.ts +8 -1
  218. package/src/inject.ts +14 -24
  219. package/src/protocols/protocol-v2/deviceSession.ts +24 -0
  220. package/src/protocols/protocol-v2/features.ts +37 -49
  221. package/src/protocols/protocol-v2/firmware.ts +1 -1
  222. package/src/protocols/protocol-v2/index.ts +2 -3
  223. package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +61 -0
  224. package/src/protocols/protocol-v2/uiInteraction.ts +4 -3
  225. package/src/protocols/protocol-v2/walletSession.ts +57 -146
  226. package/src/types/api/checkAllFirmwareRelease.ts +1 -2
  227. package/src/types/api/deviceSettings.ts +1 -0
  228. package/src/types/api/deviceUnlock.ts +1 -1
  229. package/src/types/api/firmwareUpdate.ts +5 -5
  230. package/src/types/api/getDeviceState.ts +1 -1
  231. package/src/types/api/getFeatures.ts +3 -0
  232. package/src/types/api/getOnekeyFeatures.ts +3 -0
  233. package/src/types/api/getPassphraseState.ts +6 -0
  234. package/src/types/api/index.ts +16 -23
  235. package/src/types/api/openWalletSession.ts +64 -0
  236. package/src/types/api/protocolV2.ts +36 -18
  237. package/src/types/device.ts +20 -14
  238. package/src/types/params.ts +1 -1
  239. package/src/types/settings.ts +8 -8
  240. package/src/utils/assets.ts +4 -1
  241. package/src/utils/deviceFeaturesCompat.ts +173 -0
  242. package/src/utils/deviceFeaturesUtils.ts +9 -8
  243. package/src/utils/deviceInfoUtils.ts +26 -64
  244. package/src/utils/deviceSettings.ts +18 -11
  245. package/src/utils/deviceVersionUtils.ts +25 -44
  246. package/src/utils/findDefectiveBatchDevice.ts +3 -3
  247. package/src/utils/index.ts +2 -5
  248. package/src/utils/networkUtils.ts +270 -14
  249. package/src/utils/pro2Wallpaper.ts +11 -13
  250. package/src/utils/tracing.ts +2 -2
  251. package/dist/api/internal.d.ts +0 -4
  252. package/dist/api/internal.d.ts.map +0 -1
  253. package/dist/api/protocol-v2/DeviceSessionOpen.d.ts +0 -28
  254. package/dist/api/protocol-v2/DeviceSessionOpen.d.ts.map +0 -1
  255. package/src/api/internal.ts +0 -9
  256. package/src/api/protocol-v2/DeviceSessionOpen.ts +0 -100
@@ -1,10 +1,15 @@
1
1
  import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
2
- import { Enum_Capability } from '@onekeyfe/hd-transport';
3
2
 
4
3
  import {
5
- isProtocolV2BootloaderDeviceInfo,
6
- isProtocolV2RomloaderDeviceInfo,
7
- } from '../protocols/protocol-v2/features';
4
+ resolveDeviceBleFirmwareVersion,
5
+ resolveDeviceBleName,
6
+ resolveDeviceBoardVersion,
7
+ resolveDeviceBootloaderVersion,
8
+ resolveDeviceFirmwareType,
9
+ resolveDeviceFirmwareVersion,
10
+ resolveDeviceSerialNo,
11
+ resolveDeviceType,
12
+ } from '../utils/deviceFeaturesCompat';
8
13
 
9
14
  import type {
10
15
  DeviceFirmwareImageInfo,
@@ -12,6 +17,7 @@ import type {
12
17
  ProtocolV2DeviceInfo,
13
18
  } from '@onekeyfe/hd-transport';
14
19
  import type { PROTO } from '../constants';
20
+ import type { ProtocolV2RuntimeMode } from '../protocols/protocol-v2/features';
15
21
  import type { DeviceFeaturesMode, Features } from '../types';
16
22
 
17
23
  type ProtocolV1FeaturesCompat = PROTO.Features &
@@ -47,9 +53,6 @@ const firstValue = <T>(...values: Array<T | null | undefined>) =>
47
53
  const firstMeaningfulVersion = (...versions: Array<string | null | undefined>) =>
48
54
  versions.find(version => Boolean(version && version !== '0.0.0')) ?? null;
49
55
 
50
- const versionFromParts = (major?: number | null, minor?: number | null, patch?: number | null) =>
51
- [major, minor, patch].map(part => Number(part) || 0).join('.');
52
-
53
56
  const getProtocolV1Mode = (features: ProtocolV1FeaturesCompat): Features['mode'] => {
54
57
  if (features.bootloader_mode === true) return 'bootloader';
55
58
  if (features.initialized === false) return 'notInitialized';
@@ -57,57 +60,6 @@ const getProtocolV1Mode = (features: ProtocolV1FeaturesCompat): Features['mode']
57
60
  return 'normal';
58
61
  };
59
62
 
60
- const getProtocolV1DeviceType = (features: ProtocolV1FeaturesCompat): Features['deviceType'] => {
61
- const onekeyDeviceType = features.onekey_device_type as string | null | undefined;
62
- switch (onekeyDeviceType) {
63
- case 'CLASSIC':
64
- return EDeviceType.Classic;
65
- case 'CLASSIC1S':
66
- return EDeviceType.Classic1s;
67
- case 'MINI':
68
- return EDeviceType.Mini;
69
- case 'TOUCH':
70
- return EDeviceType.Touch;
71
- case 'PRO':
72
- return EDeviceType.Pro;
73
- case 'PRO2':
74
- case 'pro2':
75
- return EDeviceType.Pro2;
76
- case 'PURE':
77
- return EDeviceType.ClassicPure;
78
- default:
79
- break;
80
- }
81
-
82
- const serialNo = features.onekey_serial_no || features.onekey_serial || features.serial_no || '';
83
- const prefix = serialNo.slice(0, 2).toLowerCase();
84
- if (prefix === 'bi' || prefix === 'cl') return EDeviceType.Classic;
85
- if (prefix === 'cp') return EDeviceType.ClassicPure;
86
- if (prefix === 'mi') return EDeviceType.Mini;
87
- if (prefix === 'tc') return EDeviceType.Touch;
88
- if (prefix === 'pr') return EDeviceType.Pro;
89
- if (prefix === 'p2') return EDeviceType.Pro2;
90
- if (!serialNo && features.bootloader_mode === true && features.model === '1') {
91
- return EDeviceType.Classic;
92
- }
93
- return EDeviceType.Unknown;
94
- };
95
-
96
- const getProtocolV1FirmwareType = (
97
- features: ProtocolV1FeaturesCompat
98
- ): Features['firmwareType'] => {
99
- if (features.fw_vendor === 'OneKey Bitcoin-only') return EFirmwareType.BitcoinOnly;
100
- const capabilities = features.capabilities as unknown as Array<number | string> | undefined;
101
- if (
102
- capabilities?.length &&
103
- !capabilities.includes(Enum_Capability.Capability_Bitcoin_like) &&
104
- !capabilities.includes('Capability_Bitcoin_like')
105
- ) {
106
- return EFirmwareType.BitcoinOnly;
107
- }
108
- return EFirmwareType.Universal;
109
- };
110
-
111
63
  const getProtocolV1Label = (features: ProtocolV1FeaturesCompat) =>
112
64
  typeof features.label === 'string' && features.label.length > 0 ? features.label : null;
113
65
 
@@ -117,32 +69,24 @@ export const buildProtocolV1FeaturesPayload = (
117
69
  ): Features => {
118
70
  const features = protocolV1Features as ProtocolV1FeaturesCompat;
119
71
  const firmwareVersion = firstMeaningfulVersion(
120
- features.onekey_firmware_version,
121
- features.onekey_version,
122
- versionFromParts(features.major_version, features.minor_version, features.patch_version),
72
+ resolveDeviceFirmwareVersion(features),
123
73
  previous?.firmwareVersion
124
74
  );
125
75
  const bootloaderVersion = firstMeaningfulVersion(
126
- features.onekey_boot_version,
127
- features.bootloader_version,
128
- features.bootloader_mode
129
- ? versionFromParts(features.major_version, features.minor_version, features.patch_version)
130
- : null,
76
+ resolveDeviceBootloaderVersion(features),
131
77
  previous?.bootloaderVersion
132
78
  );
133
79
  const boardVersion = firstMeaningfulVersion(
134
- features.onekey_board_version,
135
- features.boardloader_version,
80
+ resolveDeviceBoardVersion(features),
136
81
  previous?.boardVersion
137
82
  );
138
83
  const bleVersion = firstMeaningfulVersion(
139
- features.onekey_ble_version,
140
- features.ble_ver,
84
+ resolveDeviceBleFirmwareVersion(features),
141
85
  previous?.bleVersion
142
86
  );
143
- const serialNo = features.onekey_serial_no || features.onekey_serial || features.serial_no || '';
144
- const bleName = features.onekey_ble_name || features.ble_name || null;
145
- const deviceType = getProtocolV1DeviceType(features);
87
+ const serialNo = resolveDeviceSerialNo(features);
88
+ const bleName = resolveDeviceBleName(features);
89
+ const deviceType = resolveDeviceType(features);
146
90
  const sessionId = features.session_id ?? previous?.sessionId ?? null;
147
91
 
148
92
  return {
@@ -150,7 +94,7 @@ export const buildProtocolV1FeaturesPayload = (
150
94
  protocol: 'V1',
151
95
  protocolVersion: features.protocol_version ?? previous?.protocolVersion ?? 1,
152
96
  deviceType,
153
- firmwareType: getProtocolV1FirmwareType(features),
97
+ firmwareType: resolveDeviceFirmwareType(features),
154
98
  model: features.model ?? null,
155
99
  vendor: features.vendor ?? null,
156
100
  deviceId: features.device_id ?? null,
@@ -252,20 +196,22 @@ export const buildProtocolV1FeaturesPayload = (
252
196
  };
253
197
 
254
198
  /**
255
- * Protocol V2 的结构化 `Features` 构建器。
199
+ * Structured Protocol V2 `Features` builder.
256
200
  *
257
- * 这是 Device 内部唯一缓存状态。字段只来自 DeviceInfoGet 或前一次 features
258
- * 缓存的同名字段级合并;不存在协议等价语义的字段保持 null/空值,不再通过
259
- * 统一 DeviceState transport path 做身份兜底。
201
+ * This is the only cached Device state. Fields come from DeviceInfoGet or same-name
202
+ * values in the previous cache. Fields without protocol-equivalent meaning remain
203
+ * null or empty and never fall back to DeviceState or a transport path.
260
204
  */
261
205
  export const buildProtocolV2FeaturesPayload = ({
262
206
  deviceInfo,
263
207
  deviceStatus,
264
208
  previous,
209
+ runtimeMode,
265
210
  }: {
266
211
  deviceInfo?: ProtocolV2DeviceInfo;
267
212
  deviceStatus?: DeviceStatus;
268
213
  previous?: Features;
214
+ runtimeMode?: ProtocolV2RuntimeMode;
269
215
  }): Features => {
270
216
  const info = deviceInfo;
271
217
  const fwApplication = info?.fw?.application;
@@ -293,8 +239,8 @@ export const buildProtocolV2FeaturesPayload = ({
293
239
  const label = cached?.label ?? null;
294
240
  const bleName = firstValue(info?.coprocessor?.bt_adv_name, cached?.bleName);
295
241
  const initialized = firstValue(status?.init_states, cached?.initialized) ?? null;
296
- // Pro2 在锁定状态下返回的 passphrase_enabled 不是最终钱包状态。
297
- // 只有完成 PIN 解锁后的 DeviceStatus 才能作为 passphrase 开关真值来源。
242
+ // passphrase_enabled from a locked Pro2 is not authoritative. Only DeviceStatus
243
+ // after PIN unlock can determine the final passphrase setting.
298
244
  let passphraseProtection = cached?.passphraseProtection ?? null;
299
245
  if (status?.unlocked === true) {
300
246
  passphraseProtection = status.passphrase_enabled ?? null;
@@ -306,21 +252,16 @@ export const buildProtocolV2FeaturesPayload = ({
306
252
  const attachToPinEnabled = status?.attach_to_pin_enabled ?? cached?.attachToPinEnabled ?? null;
307
253
  const unlockedAttachPin =
308
254
  status?.unlocked_by_attach_to_pin ?? cached?.unlockedAttachPin ?? undefined;
309
- const romloaderMode = isProtocolV2RomloaderDeviceInfo(info, status);
310
- const bootloaderMode = isProtocolV2BootloaderDeviceInfo(info, status);
255
+ const bootloaderMode = runtimeMode === 'bootloader';
311
256
  let mode: DeviceFeaturesMode = 'unknown';
312
- if (romloaderMode) {
313
- mode = 'romloader';
314
- } else if (bootloaderMode) {
315
- mode = 'bootloader';
257
+ if (runtimeMode) {
258
+ mode = runtimeMode;
316
259
  } else if (initialized === false) {
317
260
  mode = 'notInitialized';
318
261
  } else if (initialized === true) {
319
262
  mode = 'normal';
320
263
  } else if (cached?.mode === 'notInitialized' || cached?.mode === 'backupMode') {
321
264
  mode = cached.mode;
322
- } else if (info) {
323
- mode = 'normal';
324
265
  } else if (cached?.mode) {
325
266
  mode = cached.mode;
326
267
  }
@@ -5,7 +5,14 @@ export const LogBlockEvent: Set<string> = new Set([
5
5
  UI_RESPONSE.RECEIVE_PASSPHRASE,
6
6
  ]);
7
7
 
8
- const LogBlockMethod: Set<string> = new Set(['evmSignTypedData', 'deviceSessionOpen']);
8
+ const LogBlockMethod: Set<string> = new Set([
9
+ 'evmSignTypedData',
10
+ 'openWalletSession',
11
+ 'deviceUploadWallpaper',
12
+ 'uploadPortfolio',
13
+ 'fileWrite',
14
+ 'fileRead',
15
+ ]);
9
16
 
10
17
  export function getLogBlockLabel(message: unknown): string | undefined {
11
18
  if (!message || typeof message !== 'object') return undefined;
package/src/inject.ts CHANGED
@@ -158,15 +158,19 @@ export const createCoreApi = (
158
158
  deviceRebootToBoardloader: connectId => call({ connectId, method: 'deviceRebootToBoardloader' }),
159
159
  deviceRebootToBootloader: connectId => call({ connectId, method: 'deviceRebootToBootloader' }),
160
160
 
161
- // File system & device control API (Protocol V2 only)
162
- protocolInfoRequest: (connectId, params) =>
163
- call({ ...params, connectId, method: 'protocolInfoRequest' }),
164
- ping: (connectId, params) => call({ ...params, connectId, method: 'ping' }),
161
+ // Pro2 business API
165
162
  deviceReboot: (connectId, params) => call({ ...params, connectId, method: 'deviceReboot' }),
166
163
  deviceGetOnboardingStatus: (connectId, params) =>
167
164
  call({ ...params, connectId, method: 'deviceGetOnboardingStatus' }),
168
- deviceSessionOpen: (connectId, params) =>
169
- call({ ...params, connectId, method: 'deviceSessionOpen' }),
165
+ deviceUploadWallpaper: (connectId, params) =>
166
+ call({ ...params, connectId, method: 'deviceUploadWallpaper' }),
167
+ deviceInfoGet: (connectId, params) => call({ ...params, connectId, method: 'deviceInfoGet' }),
168
+ deviceStatusGet: (connectId, params) => call({ ...params, connectId, method: 'deviceStatusGet' }),
169
+ deviceSettingsGet: (connectId, params) =>
170
+ call({ ...params, connectId, method: 'deviceSettingsGet' }),
171
+ protocolInfoRequest: (connectId, params) =>
172
+ call({ ...params, connectId, method: 'protocolInfoRequest' }),
173
+ ping: (connectId, params) => call({ ...params, connectId, method: 'ping' }),
170
174
  deviceFirmwareUpdate: (connectId, params) =>
171
175
  call({ ...params, connectId, method: 'deviceFirmwareUpdate' }),
172
176
  deviceGetFirmwareUpdateStatus: (connectId, params) =>
@@ -179,10 +183,10 @@ export const createCoreApi = (
179
183
  call({ ...params, connectId, method: 'deviceSettingsSet' }),
180
184
  deviceSettingsPageShow: (connectId, params) =>
181
185
  call({ ...params, connectId, method: 'deviceSettingsPageShow' }),
182
- deviceUploadWallpaper: (connectId, params) =>
183
- call({ ...params, connectId, method: 'deviceUploadWallpaper' }),
184
186
  filesystemPermissionFix: (connectId, params) =>
185
187
  call({ ...params, connectId, method: 'filesystemPermissionFix' }),
188
+ filesystemFormat: connectId => call({ connectId, method: 'filesystemFormat' }),
189
+ uploadPortfolio: (connectId, params) => call({ ...params, connectId, method: 'uploadPortfolio' }),
186
190
  fileRead: (connectId, params) => call({ ...params, connectId, method: 'fileRead' }),
187
191
  fileWrite: (connectId, params) => call({ ...params, connectId, method: 'fileWrite' }),
188
192
  fileDelete: (connectId, params) => call({ ...params, connectId, method: 'fileDelete' }),
@@ -190,22 +194,6 @@ export const createCoreApi = (
190
194
  dirMake: (connectId, params) => call({ ...params, connectId, method: 'dirMake' }),
191
195
  dirRemove: (connectId, params) => call({ ...params, connectId, method: 'dirRemove' }),
192
196
  pathInfo: (connectId, params) => call({ ...params, connectId, method: 'pathInfo' }),
193
- filesystemFileRead: (connectId, params) =>
194
- call({ ...params, connectId, method: 'filesystemFileRead' }),
195
- filesystemFileWrite: (connectId, params) =>
196
- call({ ...params, connectId, method: 'filesystemFileWrite' }),
197
- uploadPortfolio: (connectId, params) => call({ ...params, connectId, method: 'uploadPortfolio' }),
198
- filesystemFileDelete: (connectId, params) =>
199
- call({ ...params, connectId, method: 'filesystemFileDelete' }),
200
- filesystemDirList: (connectId, params) =>
201
- call({ ...params, connectId, method: 'filesystemDirList' }),
202
- filesystemDirMake: (connectId, params) =>
203
- call({ ...params, connectId, method: 'filesystemDirMake' }),
204
- filesystemDirRemove: (connectId, params) =>
205
- call({ ...params, connectId, method: 'filesystemDirRemove' }),
206
- filesystemPathInfoQuery: (connectId, params) =>
207
- call({ ...params, connectId, method: 'filesystemPathInfoQuery' }),
208
- filesystemFormat: connectId => call({ connectId, method: 'filesystemFormat' }),
209
197
  deviceRecovery: (connectId, params) => call({ ...params, connectId, method: 'deviceRecovery' }),
210
198
  deviceReset: (connectId, params) => call({ ...params, connectId, method: 'deviceReset' }),
211
199
  deviceSettings: (connectId, params) => call({ ...params, connectId, method: 'deviceSettings' }),
@@ -221,6 +209,8 @@ export const createCoreApi = (
221
209
  call({ ...params, connectId, method: 'deviceUpdateBootloader' }),
222
210
  getPassphraseState: (connectId, params) =>
223
211
  call({ ...params, connectId, method: 'getPassphraseState' }),
212
+ openWalletSession: (connectId, params) =>
213
+ call({ ...params, connectId, method: 'openWalletSession' }),
224
214
  deviceCancel: (connectId, params) => call({ ...params, connectId, method: 'deviceCancel' }),
225
215
  deviceLock: (connectId, params) => call({ ...params, connectId, method: 'deviceLock' }),
226
216
  deviceUnlock: (connectId, params) =>
@@ -0,0 +1,24 @@
1
+ import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
+
3
+ import type { DeviceSession } from '@onekeyfe/hd-transport';
4
+
5
+ export type CompleteDeviceSession = DeviceSession & {
6
+ session_id: string;
7
+ btc_test_address: string;
8
+ };
9
+
10
+ export function assertCompleteDeviceSession(
11
+ message: DeviceSession
12
+ ): asserts message is CompleteDeviceSession {
13
+ if (
14
+ typeof message.session_id !== 'string' ||
15
+ !message.session_id ||
16
+ typeof message.btc_test_address !== 'string' ||
17
+ !message.btc_test_address
18
+ ) {
19
+ throw ERRORS.TypedError(
20
+ HardwareErrorCode.RuntimeError,
21
+ 'DeviceSessionGet returned an incomplete DeviceSession response.'
22
+ );
23
+ }
24
+ }
@@ -8,8 +8,7 @@ import type {
8
8
  } from '@onekeyfe/hd-transport';
9
9
  import type { DeviceCommands } from '../../device/DeviceCommands';
10
10
 
11
- // 单源类型:直接使用 hd-transport 生成的 ProtocolV2DeviceInfo / DeviceSEInfo /
12
- // DeviceFirmwareImageInfo(与 firmware-pro2 proto 一致),不再维护手写副本。
11
+ // Use hd-transport generated Protocol V2 types as the single source of truth.
13
12
  export type { ProtocolV2DeviceInfo };
14
13
  export type { DeviceFirmwareImageInfo as ProtocolV2FirmwareImageInfo } from '@onekeyfe/hd-transport';
15
14
  export type { DeviceSEInfo as ProtocolV2SEInfo } from '@onekeyfe/hd-transport';
@@ -17,8 +16,8 @@ export type { DeviceSEInfo as ProtocolV2SEInfo } from '@onekeyfe/hd-transport';
17
16
  export type ProtocolV2SeStateLabel = 'BOOT' | 'APP_FACTORY' | 'APP';
18
17
 
19
18
  /**
20
- * 传输层沿用历史 decode 语义:单值 proto enum 输出为名称字符串。
21
- * 这里按 SDK decode 后的字符串语义处理,同时接受数字枚举,便于低层调用复用。
19
+ * The transport historically decodes scalar proto enums as name strings.
20
+ * Accept both that SDK representation and numeric enums for low-level callers.
22
21
  */
23
22
  const normalizeEnumValue = <T extends Record<string | number, string | number>>(
24
23
  enumObject: T,
@@ -31,8 +30,8 @@ const normalizeEnumValue = <T extends Record<string | number, string | number>>(
31
30
  };
32
31
 
33
32
  /**
34
- * DeviceSEInfo.state 可读标签。SDK 内唯一的 SE 状态映射实现,
35
- * DeviceState Mapper 与老协议 Features 兼容投影都从这里取。
33
+ * Map DeviceSEInfo.state to a readable label. This is the SDK's canonical mapping
34
+ * used by DeviceState and the legacy Features projection.
36
35
  */
37
36
  export const getProtocolV2SeState = (se?: DeviceSEInfo): ProtocolV2SeStateLabel | null => {
38
37
  const label = normalizeEnumValue(DeviceSEState, se?.state);
@@ -49,57 +48,41 @@ export const getProtocolV2SeState = (se?: DeviceSEInfo): ProtocolV2SeStateLabel
49
48
  };
50
49
 
51
50
  /**
52
- * DeviceSEInfo.type 可读标签(如 'THD89')。DeviceState / Features
53
- * 的 SE 类型归一化从这里取。
51
+ * Map DeviceSEInfo.type to a readable label such as `THD89`.
54
52
  */
55
53
  export const getProtocolV2SeType = (se?: DeviceSEInfo): string | null =>
56
54
  normalizeEnumValue(DeviceSeType, se?.type);
57
55
 
56
+ export type ProtocolV2RuntimeMode = 'normal' | 'bootloader';
57
+
58
58
  /**
59
- * 兼容尚未提供显式 runtime mode Protocol V2 固件。
59
+ * TODO: Once firmware-pro2 exposes ProtocolInfo.build_fingerprint, parse the running
60
+ * binary name and remove the temporary DeviceStatusGet-failure heuristic. romloader
61
+ * is a separate recovery flow and is excluded until its contract is defined.
60
62
  *
61
- * 当前 romloader 只上报 hw、fw.romloader fw.bootloader。普通版本读取也会
62
- * 返回 SE 信息,因此 SE 不能作为 bootloader 判据;在没有显式 runtime mode
63
- * 兼容固件上,只能把缺少 application/application_data 的非-romloader 形态视为
64
- * bootloader。
63
+ * The temporary contract has two states: DeviceStatusGet success means normal and
64
+ * failure means bootloader. Do not infer mode from application/SE/romloader fields.
65
65
  */
66
- export const isProtocolV2RomloaderDeviceInfo = (
67
- deviceInfo?: ProtocolV2DeviceInfo | null,
68
- deviceStatus?: DeviceStatus | null
69
- ) =>
70
- !!deviceInfo &&
71
- deviceStatus == null &&
72
- deviceInfo.fw?.romloader != null &&
73
- deviceInfo.fw?.application == null &&
74
- deviceInfo.fw?.application_data == null &&
75
- deviceInfo.coprocessor == null &&
76
- deviceInfo.se1 == null &&
77
- deviceInfo.se2 == null &&
78
- deviceInfo.se3 == null &&
79
- deviceInfo.se4 == null;
80
-
81
- export const isProtocolV2BootloaderDeviceInfo = (
82
- deviceInfo?: ProtocolV2DeviceInfo | null,
83
- deviceStatus?: DeviceStatus | null
84
- ) =>
85
- !!deviceInfo &&
86
- deviceStatus == null &&
87
- !isProtocolV2RomloaderDeviceInfo(deviceInfo, deviceStatus) &&
88
- deviceInfo.fw?.application == null &&
89
- deviceInfo.fw?.application_data == null;
90
-
91
- export const isProtocolV2LoaderDeviceInfo = (
92
- deviceInfo?: ProtocolV2DeviceInfo | null,
93
- deviceStatus?: DeviceStatus | null
94
- ) =>
95
- isProtocolV2RomloaderDeviceInfo(deviceInfo, deviceStatus) ||
96
- isProtocolV2BootloaderDeviceInfo(deviceInfo, deviceStatus);
66
+ export const getProtocolV2RuntimeMode = ({
67
+ deviceInfo: _deviceInfo,
68
+ deviceStatusAvailable,
69
+ }: {
70
+ deviceInfo?: ProtocolV2DeviceInfo | null;
71
+ deviceStatusAvailable: boolean;
72
+ }): ProtocolV2RuntimeMode => {
73
+ if (deviceStatusAvailable) return 'normal';
74
+ return 'bootloader';
75
+ };
97
76
 
98
77
  export const PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST = {
99
78
  targets: {
100
79
  hw: true,
101
80
  fw: true,
102
81
  coprocessor: true,
82
+ se1: true,
83
+ se2: true,
84
+ se3: true,
85
+ se4: true,
103
86
  },
104
87
  types: {
105
88
  version: true,
@@ -108,8 +91,8 @@ export const PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST = {
108
91
  };
109
92
 
110
93
  /**
111
- * 固件升级完成后的版本探测请求。
112
- * 仅读取硬件与各固件组件信息,不隐式请求 DeviceStatus
94
+ * Version probe used after firmware update completion.
95
+ * It reads hardware and firmware component data without requesting DeviceStatus.
113
96
  */
114
97
  export const PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST = {
115
98
  targets: {
@@ -160,16 +143,21 @@ export async function requestProtocolV2DeviceInfo({
160
143
  const { message } = await commands.typedCall('DeviceInfoGet', 'DeviceInfo', request, {
161
144
  timeoutMs,
162
145
  });
163
- // 'DeviceInfo' 在生成类型里是 V1 DeviceInfo | ProtocolV2DeviceInfo 的合并;
164
- // DeviceInfoGet 是 V2-only 消息,这里收窄到 V2 形态。
146
+ // Generated DeviceInfo is a V1/V2 union; DeviceInfoGet narrows it to the V2 shape.
165
147
  return message as ProtocolV2DeviceInfo;
166
148
  }
167
149
 
168
150
  export async function requestProtocolV2DeviceStatus({
169
151
  commands,
152
+ timeoutMs,
170
153
  }: {
171
154
  commands: DeviceCommands;
155
+ timeoutMs?: number;
172
156
  }): Promise<DeviceStatus> {
173
- const { message } = await commands.typedCall('DeviceStatusGet', 'DeviceStatus', {});
157
+ const response =
158
+ timeoutMs === undefined
159
+ ? await commands.typedCall('DeviceStatusGet', 'DeviceStatus', {})
160
+ : await commands.typedCall('DeviceStatusGet', 'DeviceStatus', {}, { timeoutMs });
161
+ const { message } = response;
174
162
  return message;
175
163
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * 当前 firmware-pro2 子模块的 DeviceFirmwareTargetType。
2
+ * DeviceFirmwareTargetType from the current firmware-pro2 submodule.
3
3
  */
4
4
  export const ProtocolV2FirmwareTargetType = {
5
5
  FW_MGMT_TARGET_INVALID: 0,
@@ -3,9 +3,7 @@ export {
3
3
  PROTOCOL_V2_DEVICE_INFO_TIMEOUT_MS,
4
4
  PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST,
5
5
  PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST,
6
- isProtocolV2BootloaderDeviceInfo,
7
- isProtocolV2LoaderDeviceInfo,
8
- isProtocolV2RomloaderDeviceInfo,
6
+ getProtocolV2RuntimeMode,
9
7
  getProtocolV2SeState,
10
8
  getProtocolV2SeType,
11
9
  } from './features';
@@ -14,6 +12,7 @@ export type {
14
12
  ProtocolV2FirmwareImageInfo,
15
13
  ProtocolV2SEInfo,
16
14
  ProtocolV2SeStateLabel,
15
+ ProtocolV2RuntimeMode,
17
16
  } from './features';
18
17
  export * from './firmware';
19
18
  export * from './walletSession';
@@ -0,0 +1,61 @@
1
+ import type { DeviceSettings, DeviceSettingsPage } from '@onekeyfe/hd-transport';
2
+ import type { UnlockPolicy } from '../../api/BaseMethod';
3
+ import type { ProtocolV2InteractionDescriptor } from './uiInteraction';
4
+
5
+ const LOCK_FREE_DEVICE_SETTINGS = new Set<keyof DeviceSettings>([
6
+ 'label',
7
+ 'language',
8
+ 'brightness',
9
+ 'haptic_feedback',
10
+ ]);
11
+
12
+ export const getProtocolV2SettingsUnlockPolicy = (settings: DeviceSettings): UnlockPolicy =>
13
+ Object.keys(settings).every(key => LOCK_FREE_DEVICE_SETTINGS.has(key as keyof DeviceSettings))
14
+ ? 'none'
15
+ : 'retry-on-locked';
16
+
17
+ export type ProtocolV2SettingsOperation =
18
+ | {
19
+ kind: 'direct';
20
+ settings: DeviceSettings;
21
+ }
22
+ | {
23
+ kind: 'page';
24
+ page: DeviceSettingsPage;
25
+ };
26
+
27
+ export const getProtocolV2SettingsBehavior = (
28
+ operation: ProtocolV2SettingsOperation
29
+ ): {
30
+ unlockPolicy: UnlockPolicy;
31
+ uiInteraction?: ProtocolV2InteractionDescriptor;
32
+ } => {
33
+ if (operation.kind === 'page') {
34
+ return {
35
+ unlockPolicy: 'retry-on-locked',
36
+ uiInteraction: {
37
+ request: 'button',
38
+ source: 'method-lifecycle',
39
+ reason: 'settings-page',
40
+ completion: 'operation-completed',
41
+ deviceOnly: true,
42
+ page: operation.page,
43
+ },
44
+ };
45
+ }
46
+
47
+ return {
48
+ unlockPolicy: getProtocolV2SettingsUnlockPolicy(operation.settings),
49
+ uiInteraction:
50
+ typeof operation.settings.label === 'string'
51
+ ? {
52
+ request: 'button',
53
+ source: 'method-lifecycle',
54
+ reason: 'device-management',
55
+ completion: 'operation-completed',
56
+ deviceOnly: true,
57
+ operation: 'change-label',
58
+ }
59
+ : undefined,
60
+ };
61
+ };
@@ -88,8 +88,9 @@ const hasCipherConfirmation = (value: unknown): boolean => {
88
88
  };
89
89
 
90
90
  /**
91
- * Protocol V2 不再依赖固件 ButtonRequest,因此在统一层根据业务方法生成兼容 UI Event。
92
- * 显式声明始终优先;地址和公钥只在设备实际展示时提示,签名统一提示一次。
91
+ * Protocol V2 no longer relies on firmware ButtonRequest, so the SDK synthesizes
92
+ * compatible UI events. Explicit descriptors win; address/public-key prompts appear
93
+ * only when displayed, while signing emits one prompt.
93
94
  */
94
95
  export const resolveProtocolV2UiInteraction = (
95
96
  method: ProtocolV2InteractionMethod
@@ -106,7 +107,7 @@ export const resolveProtocolV2UiInteraction = (
106
107
  const payloadDisplay = getDisplayState(method.payload);
107
108
  const display = paramsDisplay.seen ? paramsDisplay : payloadDisplay;
108
109
 
109
- // 地址接口通常默认在设备展示;公钥接口存在默认静默读取,优先依赖归一化参数。
110
+ // Address methods usually display by default; public-key methods may be silent.
110
111
  const shouldDisplay = display.seen ? display.enabled : isAddress;
111
112
  if (!shouldDisplay) return undefined;
112
113