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

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 (315) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +0 -313
  2. package/__tests__/DeviceCommands.test.ts +13 -59
  3. package/__tests__/DeviceEventRegistration.test.ts +0 -6
  4. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +3 -198
  5. package/__tests__/connectSettings.test.ts +47 -5
  6. package/__tests__/device-initialize-timeout.test.ts +56 -0
  7. package/__tests__/device-lifecycle-events.test.ts +3 -105
  8. package/__tests__/device-pool-state.test.ts +0 -22
  9. package/__tests__/device-settings.test.ts +18 -39
  10. package/__tests__/device-state-contract.test.ts +0 -1
  11. package/__tests__/device-state-mapper.test.ts +1 -13
  12. package/__tests__/device-utils.test.ts +1 -48
  13. package/__tests__/deviceSettings.test.ts +1 -11
  14. package/__tests__/firmware-update/check-all-firmware-release.test.ts +175 -0
  15. package/__tests__/firmware-update/device-update-bootloader.test.ts +87 -0
  16. package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
  17. package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
  18. package/__tests__/firmware-update/firmware-preparation-error.test.ts +27 -0
  19. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +200 -0
  20. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
  21. package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +394 -0
  22. package/__tests__/firmware-update/firmware-update-plan.test.ts +593 -0
  23. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +231 -0
  24. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +59 -31
  25. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +58 -0
  26. package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
  27. package/__tests__/get-device-state.test.ts +12 -132
  28. package/__tests__/homescreen.test.ts +1 -41
  29. package/__tests__/kaspa-use-tweak-pro2.test.ts +2 -2
  30. package/__tests__/kaspaSignTransaction.test.ts +26 -3
  31. package/__tests__/logBlockEvent.test.ts +1 -1
  32. package/__tests__/method-protocol-support.test.ts +0 -19
  33. package/__tests__/open-wallet-session.test.ts +37 -568
  34. package/__tests__/protocol-v2-unlock-policy.test.ts +37 -300
  35. package/__tests__/protocol-v2.test.ts +1153 -1458
  36. package/__tests__/protocolV2FileWrite.test.ts +0 -152
  37. package/__tests__/protocolV2UiInteraction.test.ts +0 -63
  38. package/__tests__/public-pro2-api-boundary.test.ts +0 -1
  39. package/__tests__/search-devices.test.ts +3 -12
  40. package/__tests__/tron-sign-message-init.test.ts +2 -2
  41. package/dist/api/BaseMethod.d.ts +1 -3
  42. package/dist/api/BaseMethod.d.ts.map +1 -1
  43. package/dist/api/CheckAllFirmwareRelease.d.ts +1 -2
  44. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  45. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  46. package/dist/api/FirmwareUpdateV2.d.ts +10 -0
  47. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  48. package/dist/api/FirmwareUpdateV3.d.ts +7 -3
  49. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  50. package/dist/api/FirmwareUpdateV4.d.ts +27 -13
  51. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  52. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  53. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  54. package/dist/api/SearchDevices.d.ts.map +1 -1
  55. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  56. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  57. package/dist/api/device/DeviceUnlock.d.ts +2 -2
  58. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  59. package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
  60. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  61. package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
  62. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
  63. package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
  64. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
  65. package/dist/api/firmware/FirmwarePreparationError.d.ts +3 -0
  66. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +1 -0
  67. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +11 -4
  68. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  69. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
  70. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
  71. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +25 -0
  72. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
  73. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +32 -0
  74. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
  75. package/dist/api/firmware/getBinary.d.ts +7 -0
  76. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  77. package/dist/api/firmware/progressThrottle.d.ts +3 -0
  78. package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
  79. package/dist/api/firmware/updateBootloader.d.ts +2 -0
  80. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  81. package/dist/api/firmware/uploadFirmware.d.ts +9 -1
  82. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  83. package/dist/api/helpers/protocolV2FileWrite.d.ts +0 -9
  84. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  85. package/dist/api/index.d.ts +0 -2
  86. package/dist/api/index.d.ts.map +1 -1
  87. package/dist/api/kaspa/KaspaGetAddress.d.ts +1 -1
  88. package/dist/api/kaspa/KaspaSignTransaction.d.ts +1 -1
  89. package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
  90. package/dist/api/polkadot/PolkadotGetAddress.d.ts +1 -1
  91. package/dist/api/polkadot/networks.d.ts +1 -1
  92. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  93. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  94. package/dist/api/solana/SolSignMessage.d.ts +1 -1
  95. package/dist/api/solana/SolSignOffchainMessage.d.ts +1 -1
  96. package/dist/api/solana/SolSignTransaction.d.ts +2 -2
  97. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  98. package/dist/api/sui/SuiGetAddress.d.ts +1 -1
  99. package/dist/api/sui/SuiGetPublicKey.d.ts +1 -1
  100. package/dist/api/sui/SuiSignMessage.d.ts +1 -1
  101. package/dist/api/sui/SuiSignTransaction.d.ts +1 -1
  102. package/dist/api/ton/TonGetAddress.d.ts +1 -1
  103. package/dist/api/ton/TonSignMessage.d.ts +1 -1
  104. package/dist/api/ton/TonSignProof.d.ts +1 -1
  105. package/dist/api/tron/TronSignMessage.d.ts +2 -2
  106. package/dist/api/tron/TronSignTransaction.d.ts +1 -1
  107. package/dist/core/deviceEventRegistration.d.ts +0 -2
  108. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  109. package/dist/core/index.d.ts.map +1 -1
  110. package/dist/data-manager/DataManager.d.ts +4 -9
  111. package/dist/data-manager/DataManager.d.ts.map +1 -1
  112. package/dist/data-manager/TransportManager.d.ts.map +1 -1
  113. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  114. package/dist/device/Device.d.ts +6 -29
  115. package/dist/device/Device.d.ts.map +1 -1
  116. package/dist/device/DeviceCommands.d.ts +4 -4
  117. package/dist/device/DeviceCommands.d.ts.map +1 -1
  118. package/dist/device/DeviceConnector.d.ts +1 -2
  119. package/dist/device/DeviceConnector.d.ts.map +1 -1
  120. package/dist/device/DevicePool.d.ts.map +1 -1
  121. package/dist/deviceProfile/protocolV2DeviceIdentity.d.ts.map +1 -1
  122. package/dist/events/device.d.ts +0 -4
  123. package/dist/events/device.d.ts.map +1 -1
  124. package/dist/events/logBlockEvent.d.ts.map +1 -1
  125. package/dist/events/ui-promise.d.ts +2 -4
  126. package/dist/events/ui-promise.d.ts.map +1 -1
  127. package/dist/events/ui-request.d.ts +2 -31
  128. package/dist/events/ui-request.d.ts.map +1 -1
  129. package/dist/events/ui-response.d.ts +2 -10
  130. package/dist/events/ui-response.d.ts.map +1 -1
  131. package/dist/index.d.ts +247 -243
  132. package/dist/index.d.ts.map +1 -1
  133. package/dist/index.js +3773 -3054
  134. package/dist/inject.d.ts +1 -6
  135. package/dist/inject.d.ts.map +1 -1
  136. package/dist/lowLevelInject.d.ts.map +1 -1
  137. package/dist/protocols/protocol-v2/features.d.ts +4 -0
  138. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  139. package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
  140. package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
  141. package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
  142. package/dist/protocols/protocol-v2/uiInteraction.d.ts +4 -7
  143. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  144. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +3 -1
  145. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  146. package/dist/protocols/protocol-v2/unlockRetry.d.ts +10 -0
  147. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
  148. package/dist/protocols/protocol-v2/walletSession.d.ts +1 -6
  149. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  150. package/dist/topLevelInject.d.ts.map +1 -1
  151. package/dist/types/api/checkAllFirmwareRelease.d.ts +5 -3
  152. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  153. package/dist/types/api/deviceUnlock.d.ts +1 -5
  154. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  155. package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
  156. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  157. package/dist/types/api/export.d.ts +4 -2
  158. package/dist/types/api/export.d.ts.map +1 -1
  159. package/dist/types/api/firmwareUpdate.d.ts +70 -4
  160. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  161. package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
  162. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
  163. package/dist/types/api/firmwareUpdatePlan.d.ts +28 -0
  164. package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
  165. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
  166. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
  167. package/dist/types/api/index.d.ts +10 -7
  168. package/dist/types/api/index.d.ts.map +1 -1
  169. package/dist/types/api/protocolV2.d.ts +0 -3
  170. package/dist/types/api/protocolV2.d.ts.map +1 -1
  171. package/dist/types/device.d.ts +2 -2
  172. package/dist/types/device.d.ts.map +1 -1
  173. package/dist/types/params.d.ts +0 -1
  174. package/dist/types/params.d.ts.map +1 -1
  175. package/dist/types/settings.d.ts +21 -38
  176. package/dist/types/settings.d.ts.map +1 -1
  177. package/dist/utils/deviceFeaturesCompat.d.ts +1 -0
  178. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
  179. package/dist/utils/deviceFeaturesUtils.d.ts +0 -4
  180. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  181. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  182. package/dist/utils/deviceSettings.d.ts.map +1 -1
  183. package/dist/utils/homescreen.d.ts +0 -4
  184. package/dist/utils/homescreen.d.ts.map +1 -1
  185. package/dist/utils/index.d.ts +1 -1
  186. package/dist/utils/index.d.ts.map +1 -1
  187. package/dist/utils/patch.d.ts +1 -1
  188. package/dist/utils/patch.d.ts.map +1 -1
  189. package/dist/utils/pro2Wallpaper.d.ts +0 -10
  190. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  191. package/package.json +4 -4
  192. package/src/api/BaseMethod.ts +10 -8
  193. package/src/api/CheckAllFirmwareRelease.ts +60 -59
  194. package/src/api/FirmwareUpdate.ts +15 -7
  195. package/src/api/FirmwareUpdateV2.ts +298 -126
  196. package/src/api/FirmwareUpdateV3.ts +265 -63
  197. package/src/api/FirmwareUpdateV4.ts +1017 -602
  198. package/src/api/GetPassphraseState.ts +1 -7
  199. package/src/api/OpenWalletSession.ts +17 -71
  200. package/src/api/SearchDevices.ts +1 -3
  201. package/src/api/allnetwork/AllNetworkGetAddress.ts +21 -21
  202. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +11 -36
  203. package/src/api/device/DeviceSettings.ts +4 -5
  204. package/src/api/device/DeviceUnlock.ts +3 -8
  205. package/src/api/device/DeviceUpdateBootloader.ts +125 -6
  206. package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
  207. package/src/api/firmware/FirmwareHostBinding.ts +100 -0
  208. package/src/api/firmware/FirmwarePreparationError.ts +12 -0
  209. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +83 -27
  210. package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
  211. package/src/api/firmware/FirmwareUpdatePlan.ts +772 -0
  212. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +449 -0
  213. package/src/api/firmware/progressThrottle.ts +44 -0
  214. package/src/api/firmware/updateBootloader.ts +19 -4
  215. package/src/api/firmware/uploadFirmware.ts +144 -39
  216. package/src/api/helpers/protocolV2FileWrite.ts +63 -202
  217. package/src/api/index.ts +0 -2
  218. package/src/api/kaspa/KaspaGetAddress.ts +1 -1
  219. package/src/api/kaspa/KaspaSignTransaction.ts +13 -2
  220. package/src/api/polkadot/networks.ts +3 -3
  221. package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -3
  222. package/src/api/protocol-v2/helpers.ts +1 -1
  223. package/src/api/solana/SolSignMessage.ts +1 -1
  224. package/src/api/solana/SolSignOffchainMessage.ts +1 -1
  225. package/src/api/solana/SolSignTransaction.ts +2 -2
  226. package/src/api/sui/SuiGetAddress.ts +1 -1
  227. package/src/api/sui/SuiGetPublicKey.ts +1 -1
  228. package/src/api/sui/SuiSignMessage.ts +1 -1
  229. package/src/api/sui/SuiSignTransaction.ts +1 -1
  230. package/src/api/ton/TonGetAddress.ts +1 -1
  231. package/src/api/ton/TonSignMessage.ts +1 -1
  232. package/src/api/ton/TonSignProof.ts +1 -1
  233. package/src/api/tron/TronSignMessage.ts +2 -2
  234. package/src/api/tron/TronSignTransaction.ts +1 -1
  235. package/src/core/deviceEventRegistration.ts +0 -4
  236. package/src/core/index.ts +111 -213
  237. package/src/data/messages/messages-protocol-v2.json +0 -25
  238. package/src/data-manager/DataManager.ts +41 -113
  239. package/src/data-manager/TransportManager.ts +0 -6
  240. package/src/data-manager/connectSettings.ts +11 -0
  241. package/src/device/Device.ts +49 -274
  242. package/src/device/DeviceCommands.ts +4 -31
  243. package/src/device/DeviceConnector.ts +13 -33
  244. package/src/device/DevicePool.ts +7 -21
  245. package/src/deviceProfile/buildDeviceFeatures.ts +2 -2
  246. package/src/deviceProfile/protocolV2DeviceIdentity.ts +0 -3
  247. package/src/events/device.ts +0 -4
  248. package/src/events/logBlockEvent.ts +0 -1
  249. package/src/events/ui-promise.ts +2 -4
  250. package/src/events/ui-request.ts +2 -36
  251. package/src/events/ui-response.ts +2 -12
  252. package/src/index.ts +5 -0
  253. package/src/inject.ts +24 -60
  254. package/src/lowLevelInject.ts +8 -7
  255. package/src/protocols/protocol-v2/features.ts +7 -10
  256. package/src/protocols/protocol-v2/firmware.ts +0 -2
  257. package/src/protocols/protocol-v2/lockedError.ts +10 -0
  258. package/src/protocols/protocol-v2/uiInteraction.ts +6 -46
  259. package/src/protocols/protocol-v2/unlockPolicy.ts +105 -1
  260. package/src/protocols/protocol-v2/unlockRetry.ts +109 -0
  261. package/src/protocols/protocol-v2/walletSession.ts +36 -214
  262. package/src/topLevelInject.ts +8 -7
  263. package/src/types/api/checkAllFirmwareRelease.ts +5 -3
  264. package/src/types/api/deviceUnlock.ts +1 -12
  265. package/src/types/api/deviceUpdateBootloader.ts +6 -0
  266. package/src/types/api/export.ts +18 -1
  267. package/src/types/api/firmwareUpdate.ts +78 -6
  268. package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
  269. package/src/types/api/firmwareUpdatePlan.ts +38 -0
  270. package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
  271. package/src/types/api/index.ts +14 -13
  272. package/src/types/api/protocolV2.ts +0 -13
  273. package/src/types/device.ts +3 -15
  274. package/src/types/params.ts +1 -7
  275. package/src/types/settings.ts +22 -60
  276. package/src/utils/deviceFeaturesCompat.ts +6 -5
  277. package/src/utils/deviceFeaturesUtils.ts +3 -14
  278. package/src/utils/deviceInfoUtils.ts +0 -2
  279. package/src/utils/deviceSettings.ts +0 -3
  280. package/src/utils/homescreen.ts +6 -32
  281. package/src/utils/index.ts +1 -6
  282. package/src/utils/pro2Wallpaper.ts +8 -35
  283. package/__tests__/core-initialization.test.ts +0 -23
  284. package/__tests__/device-connector-protocol.test.ts +0 -81
  285. package/__tests__/deviceUploadNft.test.ts +0 -316
  286. package/__tests__/pro2Nft.test.ts +0 -108
  287. package/__tests__/protocol-binding.test.ts +0 -89
  288. package/__tests__/protocol-v2-resources.test.ts +0 -340
  289. package/__tests__/protocol-v2-ui-lifecycle.test.ts +0 -91
  290. package/__tests__/uiProgressThrottle.test.ts +0 -74
  291. package/__tests__/uiPromiseRegistry.test.ts +0 -115
  292. package/dist/api/DetectDeviceConnectProtocol.d.ts +0 -7
  293. package/dist/api/DetectDeviceConnectProtocol.d.ts.map +0 -1
  294. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +0 -31
  295. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +0 -1
  296. package/dist/core/uiPromiseRegistry.d.ts +0 -6
  297. package/dist/core/uiPromiseRegistry.d.ts.map +0 -1
  298. package/dist/protocols/protocol-v2/resources.d.ts +0 -30
  299. package/dist/protocols/protocol-v2/resources.d.ts.map +0 -1
  300. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -22
  301. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +0 -1
  302. package/dist/types/api/detectDeviceConnectProtocol.d.ts +0 -4
  303. package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +0 -1
  304. package/dist/utils/pro2Nft.d.ts +0 -31
  305. package/dist/utils/pro2Nft.d.ts.map +0 -1
  306. package/dist/utils/uiProgressThrottle.d.ts +0 -3
  307. package/dist/utils/uiProgressThrottle.d.ts.map +0 -1
  308. package/src/api/DetectDeviceConnectProtocol.ts +0 -18
  309. package/src/api/protocol-v2/DeviceUploadNft.ts +0 -197
  310. package/src/core/uiPromiseRegistry.ts +0 -63
  311. package/src/protocols/protocol-v2/resources.ts +0 -390
  312. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +0 -131
  313. package/src/types/api/detectDeviceConnectProtocol.ts +0 -6
  314. package/src/utils/pro2Nft.ts +0 -142
  315. package/src/utils/uiProgressThrottle.ts +0 -63
@@ -8,8 +8,6 @@ export const PRO2_WALLPAPER_HEIGHT = 1024;
8
8
 
9
9
  export type Pro2WallpaperColorFormat = 'RGB565' | 'RGB565A8';
10
10
 
11
- export type Pro2ImageAlphaMode = 'preserve' | 'black-background';
12
-
13
11
  const COLOR_FORMAT_RGB565 = 0x12;
14
12
  const COLOR_FORMAT_RGB565A8 = 0x14;
15
13
 
@@ -38,11 +36,10 @@ function align(value: number, boundary: number): number {
38
36
  return Math.ceil(value / boundary) * boundary;
39
37
  }
40
38
 
41
- export function encodePro2Image(options: {
39
+ export function encodePro2Wallpaper(options: {
42
40
  width: number;
43
41
  height: number;
44
42
  rgba: Uint8Array | ArrayBuffer;
45
- alphaMode?: Pro2ImageAlphaMode;
46
43
  }): { data: Uint8Array; colorFormat: Pro2WallpaperColorFormat } {
47
44
  const { width, height } = options;
48
45
  if (!Number.isInteger(width) || width <= 0 || width > 0xffff) {
@@ -60,14 +57,11 @@ export function encodePro2Image(options: {
60
57
  );
61
58
  }
62
59
 
63
- const alphaMode = options.alphaMode ?? 'preserve';
64
60
  let hasTransparency = false;
65
- if (alphaMode === 'preserve') {
66
- for (let index = 3; index < rgba.length; index += 4) {
67
- if (rgba[index] !== 0xff) {
68
- hasTransparency = true;
69
- break;
70
- }
61
+ for (let index = 3; index < rgba.length; index += 4) {
62
+ if (rgba[index] !== 0xff) {
63
+ hasTransparency = true;
64
+ break;
71
65
  }
72
66
  }
73
67
 
@@ -91,22 +85,9 @@ export function encodePro2Image(options: {
91
85
  for (let x = 0; x < width; x += 1) {
92
86
  const sourceOffset = (y * width + x) * 4;
93
87
  const thresholdIndex = ((y & 7) << 3) + (x & 7);
94
- const alpha = rgba[sourceOffset + 3];
95
- const redChannel =
96
- alphaMode === 'black-background'
97
- ? Math.round((rgba[sourceOffset] * alpha) / 0xff)
98
- : rgba[sourceOffset];
99
- const greenChannel =
100
- alphaMode === 'black-background'
101
- ? Math.round((rgba[sourceOffset + 1] * alpha) / 0xff)
102
- : rgba[sourceOffset + 1];
103
- const blueChannel =
104
- alphaMode === 'black-background'
105
- ? Math.round((rgba[sourceOffset + 2] * alpha) / 0xff)
106
- : rgba[sourceOffset + 2];
107
- const red = Math.min(redChannel + RED_THRESHOLD[thresholdIndex], 0xff) & 0xf8;
108
- const green = Math.min(greenChannel + GREEN_THRESHOLD[thresholdIndex], 0xff) & 0xfc;
109
- const blue = Math.min(blueChannel + BLUE_THRESHOLD[thresholdIndex], 0xff) & 0xf8;
88
+ const red = Math.min(rgba[sourceOffset] + RED_THRESHOLD[thresholdIndex], 0xff) & 0xf8;
89
+ const green = Math.min(rgba[sourceOffset + 1] + GREEN_THRESHOLD[thresholdIndex], 0xff) & 0xfc;
90
+ const blue = Math.min(rgba[sourceOffset + 2] + BLUE_THRESHOLD[thresholdIndex], 0xff) & 0xf8;
110
91
  const rgb565 = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
111
92
  const rgbOffset = 12 + y * stride + x * 2;
112
93
  data[rgbOffset] = rgb565 & 0xff;
@@ -120,11 +101,3 @@ export function encodePro2Image(options: {
120
101
 
121
102
  return { data, colorFormat };
122
103
  }
123
-
124
- export function encodePro2Wallpaper(options: {
125
- width: number;
126
- height: number;
127
- rgba: Uint8Array | ArrayBuffer;
128
- }): { data: Uint8Array; colorFormat: Pro2WallpaperColorFormat } {
129
- return encodePro2Image(options);
130
- }
@@ -1,23 +0,0 @@
1
- import { DataManager } from '../src/data-manager';
2
- import { init } from '../src/core';
3
-
4
- import type { ConnectSettings } from '../src/types';
5
-
6
- jest.mock('../src/data/config', () => ({
7
- getSDKVersion: jest.fn(() => '1.0.0-test'),
8
- DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0-test/',
9
- }));
10
-
11
- describe('Core initialization', () => {
12
- afterEach(() => {
13
- jest.restoreAllMocks();
14
- });
15
-
16
- it('does not create a partially initialized core when settings loading fails', async () => {
17
- jest.spyOn(DataManager, 'load').mockRejectedValue(new Error('settings load failed'));
18
-
19
- await expect(init({} as ConnectSettings, class TestTransport {})).rejects.toThrow(
20
- 'settings load failed'
21
- );
22
- });
23
- });
@@ -1,81 +0,0 @@
1
- import { HardwareErrorCode } from '@onekeyfe/hd-shared';
2
-
3
- import DeviceConnector from '../src/device/DeviceConnector';
4
-
5
- jest.mock('../src/data-manager/TransportManager', () => ({
6
- __esModule: true,
7
- default: {
8
- load: jest.fn(),
9
- getTransport: jest.fn(),
10
- },
11
- }));
12
-
13
- jest.mock('../src/data-manager', () => ({
14
- DataManager: {
15
- getSettings: jest.fn(() => 'desktop-web-ble'),
16
- isBleConnect: jest.fn(() => true),
17
- },
18
- }));
19
-
20
- jest.mock('../src/device/DevicePool', () => ({
21
- DevicePool: {
22
- setConnector: jest.fn(),
23
- },
24
- }));
25
-
26
- const transportManagerMock: {
27
- default: {
28
- getTransport: jest.Mock;
29
- };
30
- } = jest.requireMock('../src/data-manager/TransportManager');
31
-
32
- describe('DeviceConnector protocol validation', () => {
33
- beforeEach(() => {
34
- jest.clearAllMocks();
35
- });
36
-
37
- it('reports an explicit transport error when connector initialization ran too early', async () => {
38
- transportManagerMock.default.getTransport.mockReturnValue(undefined);
39
- const connector = new DeviceConnector();
40
-
41
- await expect(connector.enumerate()).rejects.toMatchObject({
42
- errorCode: HardwareErrorCode.TransportNotConfigured,
43
- });
44
- });
45
-
46
- it('uses the actively probed protocol returned by acquire when the cache was cleared', async () => {
47
- const acquire = jest.fn().mockResolvedValue({
48
- id: 'pro2-id',
49
- path: 'pro2-id',
50
- protocolType: 'V2',
51
- });
52
- transportManagerMock.default.getTransport.mockReturnValue({
53
- acquire,
54
- getProtocolType: jest.fn(() => undefined),
55
- });
56
- const connector = new DeviceConnector();
57
-
58
- await expect(connector.acquire('pro2-id', undefined, undefined, 'V2')).resolves.toEqual(
59
- expect.objectContaining({ protocolType: 'V2' })
60
- );
61
- expect(acquire).toHaveBeenCalledWith(
62
- expect.objectContaining({ uuid: 'pro2-id', expectedProtocol: 'V2' })
63
- );
64
- });
65
-
66
- it('still rejects a real mismatch reported by the active protocol probe', async () => {
67
- transportManagerMock.default.getTransport.mockReturnValue({
68
- acquire: jest.fn().mockResolvedValue({
69
- id: 'classic-id',
70
- path: 'classic-id',
71
- protocolType: 'V1',
72
- }),
73
- getProtocolType: jest.fn(() => 'V1'),
74
- });
75
- const connector = new DeviceConnector();
76
-
77
- await expect(connector.acquire('classic-id', undefined, undefined, 'V2')).rejects.toThrow(
78
- 'Device protocol mismatch: expected V2, detected V1'
79
- );
80
- });
81
- });
@@ -1,316 +0,0 @@
1
- import { HardwareErrorCode } from '@onekeyfe/hd-shared';
2
-
3
- import DeviceUploadNft from '../src/api/protocol-v2/DeviceUploadNft';
4
-
5
- jest.mock('../src/data/config', () => ({
6
- getSDKVersion: jest.fn(() => '1.0.0'),
7
- DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
8
- }));
9
-
10
- const createRgba = (width: number, height: number) => {
11
- const data = new Uint8Array(width * height * 4);
12
- for (let index = 3; index < data.length; index += 4) data[index] = 0xff;
13
- return data;
14
- };
15
-
16
- const createMethod = ({
17
- typedCall,
18
- supportedMessages = [60802, 60805, 60808, 61500],
19
- useFullBundle = false,
20
- }: {
21
- typedCall: jest.Mock;
22
- supportedMessages?: number[];
23
- useFullBundle?: boolean;
24
- }) => {
25
- const method = new DeviceUploadNft({
26
- id: 1,
27
- payload: {
28
- method: 'deviceUploadNft',
29
- image: { width: 540, height: 540, rgba: createRgba(540, 540) },
30
- thumbnail: { width: 263, height: 263, rgba: createRgba(263, 263) },
31
- title: 'CryptoPunk #3100',
32
- subtitle: 'CryptoPunks',
33
- timestampMs: 1_760_000_000_000,
34
- chunkSize: 2048,
35
- paceMs: 0,
36
- },
37
- });
38
- (method as any).device = {
39
- commands: { typedCall },
40
- ensureProtocolV2RuntimeContext: jest.fn(() =>
41
- Promise.resolve({
42
- version: 2,
43
- build_fingerprint: 'application__1.0.0__test__DEV__DEBUG',
44
- supported_messages: supportedMessages,
45
- })
46
- ),
47
- getCurrentFirmwareType: jest.fn(),
48
- };
49
- method.postMessage = jest.fn();
50
-
51
- if (useFullBundle) {
52
- method.init();
53
- } else {
54
- (method as any).params = { chunkSize: 2048, paceMs: 0, timeoutMs: 15_000 };
55
- (method as any).bundle = {
56
- basename: 'nft-deadbeef-1760000000000',
57
- image: new Uint8Array([1]),
58
- thumbnail: new Uint8Array([2]),
59
- metadata: new TextEncoder().encode('{"title":"NFT","subtitle":""}'),
60
- };
61
- }
62
-
63
- return method;
64
- };
65
-
66
- const fileWriteSuccess = (params: { file: { offset: number; data: Uint8Array } }) => ({
67
- message: {
68
- processed_byte: params.file.offset + params.file.data.byteLength,
69
- },
70
- });
71
-
72
- const nftFileList = (count: number, basenameAt?: number) =>
73
- Array.from({ length: count }, (_, index) => {
74
- const basename =
75
- index === basenameAt
76
- ? 'nft-deadbeef-1760000000000'
77
- : `nft-${index.toString(16).padStart(8, '0')}-${1760000000001 + index}`;
78
- return [`${basename}.bin`, `${basename}_m.bin`, `${basename}.json`];
79
- })
80
- .flat()
81
- .join('\n');
82
-
83
- describe('DeviceUploadNft', () => {
84
- test('defaults to maximum-size chunks without artificial pacing', () => {
85
- const method = new DeviceUploadNft({
86
- id: 1,
87
- payload: {
88
- method: 'deviceUploadNft',
89
- image: { width: 540, height: 540, rgba: createRgba(540, 540) },
90
- thumbnail: { width: 263, height: 263, rgba: createRgba(263, 263) },
91
- title: 'CryptoPunk #3100',
92
- subtitle: 'CryptoPunks',
93
- timestampMs: 1_760_000_000_000,
94
- },
95
- });
96
-
97
- method.init();
98
-
99
- expect((method as any).params).toMatchObject({
100
- chunkSize: 2048,
101
- paceMs: 0,
102
- });
103
- });
104
-
105
- test('uploads the triplet in order without creating the firmware-owned directory', async () => {
106
- const typedCall = jest.fn((request: string, _response: string, params: any) => {
107
- if (request === 'FilesystemPathInfoQuery') {
108
- return { message: { exist: true, directory: true } };
109
- }
110
- if (request === 'FilesystemDirList') {
111
- return { message: { path: 'vol1:/nft', child_files: '' } };
112
- }
113
- if (request === 'FilesystemFileWrite') return fileWriteSuccess(params);
114
- if (request === 'NftUpdate') return { message: { message: 'NFT updated' } };
115
- throw new Error(`Unexpected request: ${request}`);
116
- });
117
- const method = createMethod({ typedCall, useFullBundle: true });
118
-
119
- const result = await method.run();
120
-
121
- const requests = typedCall.mock.calls.map(call => call[0]);
122
- expect(requests[0]).toBe('FilesystemPathInfoQuery');
123
- expect(typedCall).toHaveBeenNthCalledWith(
124
- 1,
125
- 'FilesystemPathInfoQuery',
126
- 'FilesystemPathInfo',
127
- { path: 'vol1:/nft' },
128
- { timeoutMs: 15_000 }
129
- );
130
- expect(typedCall).toHaveBeenNthCalledWith(
131
- 2,
132
- 'FilesystemDirList',
133
- 'FilesystemDir',
134
- { path: 'vol1:/nft', depth: 1 },
135
- { timeoutMs: 15_000 }
136
- );
137
- expect(requests).not.toContain('FilesystemDirMake');
138
- expect(requests.at(-1)).toBe('NftUpdate');
139
- const fileWrites = typedCall.mock.calls.filter(call => call[0] === 'FilesystemFileWrite');
140
- const paths = fileWrites.map(call => call[2].file.path as string);
141
- const imagePath = paths[0];
142
- const thumbnailStart = paths.findIndex(path => path.endsWith('_m.bin'));
143
- const metadataStart = paths.findIndex(path => path.endsWith('.json'));
144
- expect(imagePath).toMatch(/^vol1:\/nft\/nft-[a-f0-9]{8}-1760000000000\.bin$/);
145
- expect(thumbnailStart).toBeGreaterThan(0);
146
- expect(metadataStart).toBeGreaterThan(thumbnailStart);
147
- expect(new Set(paths.slice(0, thumbnailStart))).toEqual(new Set([imagePath]));
148
- expect(new Set(paths.slice(thumbnailStart, metadataStart))).toEqual(
149
- new Set([result.thumbnailPath])
150
- );
151
- expect(typedCall).toHaveBeenLastCalledWith(
152
- 'NftUpdate',
153
- 'Success',
154
- { file_name_no_ext: result.basename },
155
- { timeoutMs: 15_000 }
156
- );
157
- expect(result).toMatchObject({
158
- nftUpdated: true,
159
- message: 'NFT updated',
160
- totalSize: 583_212 + 138_876 + 53,
161
- });
162
- expect(method.postMessage).toHaveBeenLastCalledWith({
163
- event: 'UI_EVENT',
164
- type: 'ui-device_progress',
165
- payload: expect.objectContaining({
166
- progress: 100,
167
- transferredBytes: result.totalSize,
168
- totalBytes: result.totalSize,
169
- }),
170
- });
171
- });
172
-
173
- test('treats a missing NFT directory as empty before the first upload', async () => {
174
- const typedCall = jest.fn((request: string, _response: string, params: any) => {
175
- if (request === 'FilesystemPathInfoQuery') {
176
- return { message: { exist: false, directory: false } };
177
- }
178
- if (request === 'FilesystemFileWrite') return fileWriteSuccess(params);
179
- if (request === 'NftUpdate') return { message: { message: 'NFT updated' } };
180
- throw new Error(`Unexpected request: ${request}`);
181
- });
182
- const method = createMethod({ typedCall });
183
-
184
- await expect(method.run()).resolves.toMatchObject({ nftUpdated: true });
185
- expect(typedCall.mock.calls.map(call => call[0])).not.toContain('FilesystemDirList');
186
- expect(typedCall.mock.calls.some(call => call[0] === 'FilesystemFileWrite')).toBe(true);
187
- });
188
-
189
- test('does not retry a timed-out NftUpdate', async () => {
190
- const timeout = Object.assign(new Error('Protocol V2 response timeout'), {
191
- code: 'response-timeout',
192
- });
193
- const typedCall = jest.fn((request: string, _response: string, params: any) => {
194
- if (request === 'FilesystemPathInfoQuery') {
195
- return { message: { exist: true, directory: true } };
196
- }
197
- if (request === 'FilesystemDirList') {
198
- return { message: { path: 'vol1:/nft', child_files: '' } };
199
- }
200
- if (request === 'FilesystemFileWrite') return fileWriteSuccess(params);
201
- if (request === 'NftUpdate') throw timeout;
202
- throw new Error(`Unexpected request: ${request}`);
203
- });
204
- const method = createMethod({ typedCall });
205
-
206
- await expect(method.run()).rejects.toBe(timeout);
207
-
208
- const updateRequests = typedCall.mock.calls.filter(call => call[0] === 'NftUpdate');
209
- expect(updateRequests).toHaveLength(1);
210
- });
211
-
212
- test('does not retry a non-timeout NftUpdate failure', async () => {
213
- const typedCall = jest.fn((request: string, _response: string, params: any) => {
214
- if (request === 'FilesystemPathInfoQuery') {
215
- return { message: { exist: true, directory: true } };
216
- }
217
- if (request === 'FilesystemDirList') {
218
- return { message: { path: 'vol1:/nft', child_files: '' } };
219
- }
220
- if (request === 'FilesystemFileWrite') return fileWriteSuccess(params);
221
- if (request === 'NftUpdate') throw new Error('Invalid NFT metadata');
222
- throw new Error(`Unexpected request: ${request}`);
223
- });
224
- const method = createMethod({ typedCall });
225
-
226
- await expect(method.run()).rejects.toThrow('Invalid NFT metadata');
227
- expect(typedCall.mock.calls.filter(call => call[0] === 'NftUpdate')).toHaveLength(1);
228
- });
229
-
230
- test('does not publish when a file write fails', async () => {
231
- const typedCall = jest.fn((request: string) => {
232
- if (request === 'FilesystemPathInfoQuery') {
233
- return { message: { exist: true, directory: true } };
234
- }
235
- if (request === 'FilesystemDirList') {
236
- return { message: { path: 'vol1:/nft', child_files: '' } };
237
- }
238
- if (request === 'FilesystemFileWrite') throw new Error('Filesystem full');
239
- throw new Error(`Unexpected request: ${request}`);
240
- });
241
- const method = createMethod({ typedCall });
242
-
243
- await expect(method.run()).rejects.toThrow('Filesystem full');
244
- expect(typedCall.mock.calls.some(call => call[0] === 'NftUpdate')).toBe(false);
245
- });
246
-
247
- test('rejects unsupported firmware before writing files', async () => {
248
- const typedCall = jest.fn();
249
- const method = createMethod({ typedCall, supportedMessages: [60805] });
250
-
251
- await expect(method.run()).rejects.toBeDefined();
252
- expect(typedCall).not.toHaveBeenCalled();
253
- });
254
-
255
- test('rejects a new NFT before writing when ten complete NFT bundles exist', async () => {
256
- const typedCall = jest.fn((request: string) => {
257
- if (request === 'FilesystemPathInfoQuery') {
258
- return { message: { exist: true, directory: true } };
259
- }
260
- if (request === 'FilesystemDirList') {
261
- return { message: { path: 'vol1:/nft', child_files: nftFileList(10) } };
262
- }
263
- throw new Error(`Unexpected request: ${request}`);
264
- });
265
- const method = createMethod({ typedCall });
266
-
267
- await expect(method.run()).rejects.toMatchObject({
268
- errorCode: HardwareErrorCode.NftStorageLimitReached,
269
- params: { count: 10, limit: 10 },
270
- });
271
- expect(typedCall.mock.calls.map(call => call[0])).toEqual([
272
- 'FilesystemPathInfoQuery',
273
- 'FilesystemDirList',
274
- ]);
275
- });
276
-
277
- test('allows an idempotent retry for a basename already counted at the limit', async () => {
278
- const typedCall = jest.fn((request: string, _response: string, params: any) => {
279
- if (request === 'FilesystemPathInfoQuery') {
280
- return { message: { exist: true, directory: true } };
281
- }
282
- if (request === 'FilesystemDirList') {
283
- return { message: { path: 'vol1:/nft', child_files: nftFileList(10, 0) } };
284
- }
285
- if (request === 'FilesystemFileWrite') return fileWriteSuccess(params);
286
- if (request === 'NftUpdate') return { message: {} };
287
- throw new Error(`Unexpected request: ${request}`);
288
- });
289
- const method = createMethod({ typedCall });
290
-
291
- await expect(method.run()).resolves.toMatchObject({ nftUpdated: true });
292
- expect(typedCall.mock.calls.some(call => call[0] === 'FilesystemFileWrite')).toBe(true);
293
- });
294
-
295
- test('does not count unrelated or incomplete files as stored NFTs', async () => {
296
- const typedCall = jest.fn((request: string, _response: string, params: any) => {
297
- if (request === 'FilesystemPathInfoQuery') {
298
- return { message: { exist: true, directory: true } };
299
- }
300
- if (request === 'FilesystemDirList') {
301
- return {
302
- message: {
303
- path: 'vol1:/nft',
304
- child_files: `${nftFileList(9)}\nnft-ffffffff-1760000009999.json\nnotes.txt`,
305
- },
306
- };
307
- }
308
- if (request === 'FilesystemFileWrite') return fileWriteSuccess(params);
309
- if (request === 'NftUpdate') return { message: {} };
310
- throw new Error(`Unexpected request: ${request}`);
311
- });
312
- const method = createMethod({ typedCall });
313
-
314
- await expect(method.run()).resolves.toMatchObject({ nftUpdated: true });
315
- });
316
- });
@@ -1,108 +0,0 @@
1
- import { blake2s } from '@noble/hashes/blake2s';
2
- import { bytesToHex } from '@noble/hashes/utils';
3
-
4
- import {
5
- PRO2_NFT_IMAGE_HEIGHT,
6
- PRO2_NFT_IMAGE_WIDTH,
7
- PRO2_NFT_THUMBNAIL_HEIGHT,
8
- PRO2_NFT_THUMBNAIL_WIDTH,
9
- buildPro2NftBundle,
10
- } from '../src/utils/pro2Nft';
11
-
12
- const rgba = (width: number, height: number, alpha = 0xff) => {
13
- const data = new Uint8Array(width * height * 4);
14
- for (let index = 3; index < data.length; index += 4) data[index] = alpha;
15
- return data;
16
- };
17
-
18
- describe('buildPro2NftBundle', () => {
19
- test('builds the exact Pro2 RGB565 triplet and basename', () => {
20
- const bundle = buildPro2NftBundle({
21
- image: {
22
- width: PRO2_NFT_IMAGE_WIDTH,
23
- height: PRO2_NFT_IMAGE_HEIGHT,
24
- rgba: rgba(PRO2_NFT_IMAGE_WIDTH, PRO2_NFT_IMAGE_HEIGHT),
25
- },
26
- thumbnail: {
27
- width: PRO2_NFT_THUMBNAIL_WIDTH,
28
- height: PRO2_NFT_THUMBNAIL_HEIGHT,
29
- rgba: rgba(PRO2_NFT_THUMBNAIL_WIDTH, PRO2_NFT_THUMBNAIL_HEIGHT),
30
- },
31
- title: 'CryptoPunk #3100',
32
- subtitle: 'CryptoPunks',
33
- timestampMs: 1_760_000_000_000,
34
- });
35
-
36
- expect(bundle.image.byteLength).toBe(583_212);
37
- expect(bundle.thumbnail.byteLength).toBe(138_876);
38
- expect(Array.from(bundle.image.slice(0, 12))).toEqual([
39
- 0x19, 0x12, 0, 0, 28, 2, 28, 2, 56, 4, 0, 0,
40
- ]);
41
- expect(Array.from(bundle.thumbnail.slice(0, 12))).toEqual([
42
- 0x19, 0x12, 0, 0, 7, 1, 7, 1, 16, 2, 0, 0,
43
- ]);
44
- expect(new TextDecoder().decode(bundle.metadata)).toBe(
45
- '{"title":"CryptoPunk #3100","subtitle":"CryptoPunks"}'
46
- );
47
- expect(bytesToHex(blake2s(bundle.image))).toBe(
48
- 'af4b5f8fe216cfd0ef4a9162a42b5c66a73466f2491066f66f756c4e28cc869e'
49
- );
50
- expect(bytesToHex(blake2s(bundle.thumbnail))).toBe(
51
- '44591afae1163cc14651d77644501c6a110f96506889b825cab0351ff4de857d'
52
- );
53
- expect(bytesToHex(blake2s(bundle.metadata))).toBe(
54
- 'e30d4dc2cddd441c9f1438c783e05a623ccf76f2f6219d4281769dda1b3635b5'
55
- );
56
- expect(bundle.basename).toBe('nft-af4b5f8f-1760000000000');
57
- });
58
-
59
- test('composites transparent pixels onto black without an alpha plane', () => {
60
- const image = rgba(PRO2_NFT_IMAGE_WIDTH, PRO2_NFT_IMAGE_HEIGHT);
61
- image.set([255, 255, 255, 0], 0);
62
- const bundle = buildPro2NftBundle({
63
- image: { width: PRO2_NFT_IMAGE_WIDTH, height: PRO2_NFT_IMAGE_HEIGHT, rgba: image },
64
- thumbnail: {
65
- width: PRO2_NFT_THUMBNAIL_WIDTH,
66
- height: PRO2_NFT_THUMBNAIL_HEIGHT,
67
- rgba: rgba(PRO2_NFT_THUMBNAIL_WIDTH, PRO2_NFT_THUMBNAIL_HEIGHT, 0),
68
- },
69
- title: 'NFT',
70
- subtitle: '',
71
- timestampMs: 1,
72
- });
73
-
74
- expect(bundle.image[1]).toBe(0x12);
75
- expect(Array.from(bundle.image.slice(12, 14))).toEqual([0, 0]);
76
- expect(bundle.thumbnail.byteLength).toBe(138_876);
77
- });
78
-
79
- test('rejects invalid dimensions and metadata byte lengths', () => {
80
- const validThumbnail = {
81
- width: PRO2_NFT_THUMBNAIL_WIDTH,
82
- height: PRO2_NFT_THUMBNAIL_HEIGHT,
83
- rgba: rgba(PRO2_NFT_THUMBNAIL_WIDTH, PRO2_NFT_THUMBNAIL_HEIGHT),
84
- };
85
- expect(() =>
86
- buildPro2NftBundle({
87
- image: { width: 1, height: 1, rgba: new Uint8Array(4) },
88
- thumbnail: validThumbnail,
89
- title: 'NFT',
90
- subtitle: '',
91
- timestampMs: 1,
92
- })
93
- ).toThrow('540x540');
94
- expect(() =>
95
- buildPro2NftBundle({
96
- image: {
97
- width: PRO2_NFT_IMAGE_WIDTH,
98
- height: PRO2_NFT_IMAGE_HEIGHT,
99
- rgba: rgba(PRO2_NFT_IMAGE_WIDTH, PRO2_NFT_IMAGE_HEIGHT),
100
- },
101
- thumbnail: validThumbnail,
102
- title: 'a'.repeat(64),
103
- subtitle: '',
104
- timestampMs: 1,
105
- })
106
- ).toThrow('1 to 63');
107
- });
108
- });