@onekeyfe/hd-core 1.2.0-alpha.99 → 1.2.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +20 -4
  2. package/__tests__/DeviceCommands.test.ts +203 -27
  3. package/__tests__/base64Data.test.ts +69 -0
  4. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +48 -2
  5. package/__tests__/check-firmware-release-protocol-v2.test.ts +82 -13
  6. package/__tests__/device-connector-protocol.test.ts +21 -0
  7. package/__tests__/device-lifecycle-events.test.ts +427 -7
  8. package/__tests__/device-pool-state.test.ts +25 -0
  9. package/__tests__/device-settings.test.ts +237 -9
  10. package/__tests__/device-state-events.test.ts +2 -2
  11. package/__tests__/device-state-mapper.test.ts +61 -5
  12. package/__tests__/device-utils.test.ts +15 -1
  13. package/__tests__/device-wallet-session-store.test.ts +147 -21
  14. package/__tests__/deviceSettings.test.ts +7 -3
  15. package/__tests__/deviceUploadNft.test.ts +36 -4
  16. package/__tests__/firmware-update/device-update-bootloader.test.ts +13 -3
  17. package/__tests__/firmware-update/firmware-artifact-source.test.ts +61 -9
  18. package/__tests__/firmware-update/firmware-prepared-host-digest.test.ts +19 -9
  19. package/__tests__/firmware-update/firmware-prepared-resource-archive.test.ts +21 -0
  20. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +63 -0
  21. package/__tests__/firmware-update/firmware-update-plan.test.ts +59 -55
  22. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +19 -5
  23. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +116 -0
  24. package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +979 -0
  25. package/__tests__/firmware-update/firmware-update-v4-parameters.test.ts +85 -0
  26. package/__tests__/get-device-state.test.ts +60 -21
  27. package/__tests__/logBlockEvent.test.ts +13 -1
  28. package/__tests__/open-wallet-session.test.ts +127 -1
  29. package/__tests__/protocol-v2-firmware-targets.test.ts +23 -0
  30. package/__tests__/protocol-v2-resources.test.ts +185 -88
  31. package/__tests__/protocol-v2-unlock-policy.test.ts +235 -2
  32. package/__tests__/protocol-v2.test.ts +2199 -486
  33. package/__tests__/refresh-device-state.test.ts +3 -1
  34. package/__tests__/resourceBase64Boundary.test.ts +48 -0
  35. package/__tests__/search-devices.test.ts +79 -32
  36. package/__tests__/ton-sign-message.test.ts +84 -0
  37. package/dist/api/BaseMethod.d.ts +2 -1
  38. package/dist/api/BaseMethod.d.ts.map +1 -1
  39. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  40. package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
  41. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  42. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  43. package/dist/api/FirmwareUpdateV4.d.ts +20 -6
  44. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  45. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  46. package/dist/api/SearchDevices.d.ts.map +1 -1
  47. package/dist/api/UploadPortfolio.d.ts +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/DeviceRebootToBoardloader.d.ts.map +1 -1
  52. package/dist/api/device/DeviceRebootToBootloader.d.ts.map +1 -1
  53. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  54. package/dist/api/device/DeviceVerify.d.ts +1 -0
  55. package/dist/api/device/DeviceVerify.d.ts.map +1 -1
  56. package/dist/api/device/DeviceWipe.d.ts.map +1 -1
  57. package/dist/api/firmware/FirmwareArtifactSource.d.ts +5 -1
  58. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -1
  59. package/dist/api/firmware/FirmwarePreparedResourceArchive.d.ts.map +1 -1
  60. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +2 -2
  61. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  62. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -15
  63. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
  64. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
  65. package/dist/api/firmware/getBinary.d.ts +3 -2
  66. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  67. package/dist/api/firmware/protocolV2Release.d.ts.map +1 -1
  68. package/dist/api/helpers/base64Data.d.ts +16 -0
  69. package/dist/api/helpers/base64Data.d.ts.map +1 -0
  70. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +3 -1
  71. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
  72. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
  73. package/dist/api/protocol-v2/DeviceInfoGet.d.ts +1 -1
  74. package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
  75. package/dist/api/protocol-v2/DeviceReboot.d.ts +1 -1
  76. package/dist/api/protocol-v2/DeviceReboot.d.ts.map +1 -1
  77. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +2 -3
  78. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
  79. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +2 -3
  80. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
  81. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  82. package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
  83. package/dist/core/index.d.ts +6 -1
  84. package/dist/core/index.d.ts.map +1 -1
  85. package/dist/data-manager/DataManager.d.ts +4 -3
  86. package/dist/data-manager/DataManager.d.ts.map +1 -1
  87. package/dist/data-manager/TransportManager.d.ts.map +1 -1
  88. package/dist/device/Device.d.ts +16 -3
  89. package/dist/device/Device.d.ts.map +1 -1
  90. package/dist/device/DeviceCommands.d.ts +4 -4
  91. package/dist/device/DeviceCommands.d.ts.map +1 -1
  92. package/dist/device/DeviceConnector.d.ts +1 -1
  93. package/dist/device/DeviceConnector.d.ts.map +1 -1
  94. package/dist/device/DevicePool.d.ts.map +1 -1
  95. package/dist/device/DeviceStateMapper.d.ts.map +1 -1
  96. package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
  97. package/dist/events/logBlockEvent.d.ts.map +1 -1
  98. package/dist/events/ui-request.d.ts +3 -0
  99. package/dist/events/ui-request.d.ts.map +1 -1
  100. package/dist/index.d.ts +54 -84
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +2150 -1469
  103. package/dist/protocols/protocol-v2/features.d.ts +13 -5
  104. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  105. package/dist/protocols/protocol-v2/index.d.ts +2 -2
  106. package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
  107. package/dist/protocols/protocol-v2/resources.d.ts +12 -7
  108. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  109. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +3 -1
  110. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -1
  111. package/dist/protocols/protocol-v2/walletSession.d.ts +3 -0
  112. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  113. package/dist/types/api/firmwareUpdatePlan.d.ts +2 -2
  114. package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -1
  115. package/dist/types/api/protocolV2.d.ts +1 -1
  116. package/dist/types/api/protocolV2.d.ts.map +1 -1
  117. package/dist/types/device.d.ts.map +1 -1
  118. package/dist/types/settings.d.ts +3 -31
  119. package/dist/types/settings.d.ts.map +1 -1
  120. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
  121. package/dist/utils/deviceFeaturesUtils.d.ts +3 -0
  122. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  123. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  124. package/dist/utils/deviceSettings.d.ts +1 -0
  125. package/dist/utils/deviceSettings.d.ts.map +1 -1
  126. package/dist/utils/index.d.ts +1 -1
  127. package/dist/utils/index.d.ts.map +1 -1
  128. package/dist/utils/patch.d.ts +1 -1
  129. package/dist/utils/patch.d.ts.map +1 -1
  130. package/dist/utils/pro2Nft.d.ts +7 -0
  131. package/dist/utils/pro2Nft.d.ts.map +1 -1
  132. package/package.json +6 -4
  133. package/src/api/BaseMethod.ts +8 -1
  134. package/src/api/CheckAllFirmwareRelease.ts +2 -4
  135. package/src/api/CheckBLEFirmwareRelease.ts +2 -2
  136. package/src/api/CheckBootloaderRelease.ts +3 -2
  137. package/src/api/CheckFirmwareRelease.ts +2 -2
  138. package/src/api/FirmwareUpdateV2.ts +12 -9
  139. package/src/api/FirmwareUpdateV3.ts +29 -19
  140. package/src/api/FirmwareUpdateV4.ts +934 -739
  141. package/src/api/OpenWalletSession.ts +39 -9
  142. package/src/api/PromptWebDeviceAccess.ts +2 -2
  143. package/src/api/SearchDevices.ts +6 -3
  144. package/src/api/UploadPortfolio.ts +9 -2
  145. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +2 -1
  146. package/src/api/device/DeviceChangePin.ts +4 -1
  147. package/src/api/device/DeviceRebootToBoardloader.ts +3 -1
  148. package/src/api/device/DeviceRebootToBootloader.ts +3 -1
  149. package/src/api/device/DeviceSettings.ts +34 -20
  150. package/src/api/device/DeviceVerify.ts +25 -0
  151. package/src/api/device/DeviceWipe.ts +4 -1
  152. package/src/api/firmware/FirmwareArtifactSource.ts +41 -14
  153. package/src/api/firmware/FirmwarePreparedResourceArchive.ts +16 -27
  154. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +9 -3
  155. package/src/api/firmware/FirmwareUpdatePlan.ts +37 -77
  156. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +10 -6
  157. package/src/api/firmware/protocolV2Release.ts +7 -2
  158. package/src/api/helpers/base64Data.ts +85 -0
  159. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
  160. package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +6 -28
  161. package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +7 -1
  162. package/src/api/protocol-v2/DeviceInfoGet.ts +3 -3
  163. package/src/api/protocol-v2/DeviceReboot.ts +5 -0
  164. package/src/api/protocol-v2/DeviceUploadNft.ts +61 -9
  165. package/src/api/protocol-v2/DeviceUploadWallpaper.ts +53 -19
  166. package/src/api/protocol-v2/helpers.ts +8 -0
  167. package/src/api/ton/TonSignMessage.ts +5 -3
  168. package/src/core/index.ts +264 -55
  169. package/src/data/messages/messages-protocol-v2.json +140 -13
  170. package/src/data-manager/DataManager.ts +46 -39
  171. package/src/data-manager/TransportManager.ts +3 -1
  172. package/src/device/Device.ts +210 -44
  173. package/src/device/DeviceCommands.ts +27 -18
  174. package/src/device/DeviceConnector.ts +17 -3
  175. package/src/device/DevicePool.ts +9 -2
  176. package/src/device/DeviceStateMapper.ts +30 -24
  177. package/src/deviceProfile/buildDeviceFeatures.ts +10 -5
  178. package/src/events/logBlockEvent.ts +14 -1
  179. package/src/events/ui-request.ts +3 -0
  180. package/src/index.ts +0 -10
  181. package/src/protocols/protocol-v2/features.ts +22 -5
  182. package/src/protocols/protocol-v2/index.ts +2 -0
  183. package/src/protocols/protocol-v2/resources.ts +110 -147
  184. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +13 -1
  185. package/src/protocols/protocol-v2/walletSession.ts +65 -22
  186. package/src/types/api/firmwareUpdate.ts +1 -1
  187. package/src/types/api/firmwareUpdatePlan.ts +2 -2
  188. package/src/types/api/protocolV2.ts +1 -1
  189. package/src/types/device.ts +2 -1
  190. package/src/types/settings.ts +6 -34
  191. package/src/utils/deviceFeaturesCompat.ts +9 -4
  192. package/src/utils/deviceFeaturesUtils.ts +4 -0
  193. package/src/utils/deviceInfoUtils.ts +9 -2
  194. package/src/utils/deviceSettings.ts +11 -4
  195. package/src/utils/index.ts +1 -0
  196. package/src/utils/pro2Nft.ts +31 -8
  197. package/__tests__/firmware-memory-host.test.ts +0 -126
  198. package/dist/api/firmware/FirmwareMemoryHost.d.ts +0 -22
  199. package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +0 -1
  200. package/src/api/firmware/FirmwareMemoryHost.ts +0 -143
@@ -83,15 +83,21 @@ const buildDeviceSessionGetRequest = ({
83
83
  ],
84
84
  });
85
85
 
86
- const askDevicePassphrase = async (device: Device, requestPayload: DeviceSessionAskPassphrase) => {
86
+ const askDevicePassphrase = async (
87
+ device: Device,
88
+ requestPayload: DeviceSessionAskPassphrase,
89
+ onStatusRefreshed?: () => void
90
+ ) => {
87
91
  await device.commands.typedCall('DeviceSessionAskPassphrase', 'Success', requestPayload);
88
92
  await refreshProtocolV2DeviceStatus(device);
93
+ onStatusRefreshed?.();
89
94
  };
90
95
 
91
96
  const selectDeviceSession = async (
92
97
  device: Device,
93
98
  expectedPassphraseState?: string,
94
- deriveCardano?: boolean
99
+ deriveCardano?: boolean,
100
+ onStatusRefreshed?: () => void
95
101
  ) => {
96
102
  const existsAttachPinUser = device.features?.attachToPinEnabled === true;
97
103
  const metadata = {
@@ -153,14 +159,19 @@ const selectDeviceSession = async (
153
159
  emitUiEvent: false,
154
160
  interaction: attachPinInteraction,
155
161
  });
162
+ onStatusRefreshed?.();
156
163
  return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
157
164
  }
158
165
 
159
166
  if (hasHostPassphrase) {
160
- await askDevicePassphrase(device, {
161
- passphrase: hostPassphrase,
162
- on_device: false,
163
- });
167
+ await askDevicePassphrase(
168
+ device,
169
+ {
170
+ passphrase: hostPassphrase,
171
+ on_device: false,
172
+ },
173
+ onStatusRefreshed
174
+ );
164
175
  return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
165
176
  }
166
177
 
@@ -172,7 +183,7 @@ const selectDeviceSession = async (
172
183
  ...metadata,
173
184
  ...(passphraseOnDeviceInteraction ? { interaction: passphraseOnDeviceInteraction } : {}),
174
185
  });
175
- await askDevicePassphrase(device, { on_device: true });
186
+ await askDevicePassphrase(device, { on_device: true }, onStatusRefreshed);
176
187
  return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
177
188
  };
178
189
 
@@ -191,6 +202,8 @@ export async function getProtocolV2WalletSession(
191
202
  deriveCardano?: boolean;
192
203
  /** Read the wallet already selected by Attach PIN without reopening wallet selection. */
193
204
  readCurrentAttachPinSession?: boolean;
205
+ /** The current call already selected the Main PIN during its unlock preflight. */
206
+ mainPinSelected?: boolean;
194
207
  }
195
208
  ) {
196
209
  const forceWalletSelection =
@@ -227,10 +240,16 @@ export async function getProtocolV2WalletSession(
227
240
  : undefined;
228
241
  let response;
229
242
  let resumed = false;
230
- let mainPinSelected =
231
- options?.onlyMainPin === true &&
232
- device.features?.unlocked === true &&
233
- device.features?.unlockedAttachPin === false;
243
+ let walletStatusRefreshed = false;
244
+ const markWalletStatusRefreshed = () => {
245
+ walletStatusRefreshed = true;
246
+ };
247
+ let mainPinAuthenticated =
248
+ options?.mainPinSelected === true ||
249
+ (options?.onlyMainPin === true &&
250
+ device.features?.unlocked === true &&
251
+ device.features?.unlockedAttachPin === false);
252
+ let standardWalletSelected = options?.mainPinSelected === true;
234
253
 
235
254
  const clearCurrentWalletSession = () => {
236
255
  if (options?.onlyMainPin) {
@@ -242,6 +261,7 @@ export async function getProtocolV2WalletSession(
242
261
 
243
262
  const rejectMismatchedAttachPinWallet = async () => {
244
263
  const features = await refreshProtocolV2DeviceStatus(device);
264
+ markWalletStatusRefreshed();
245
265
  if (features.unlockedAttachPin !== true) {
246
266
  return;
247
267
  }
@@ -265,30 +285,42 @@ export async function getProtocolV2WalletSession(
265
285
  }
266
286
 
267
287
  const selectMainPin = async (force = false) => {
268
- if (force || !mainPinSelected) {
288
+ if (force || !mainPinAuthenticated) {
269
289
  await device.unlockDevice(DeviceSessionPinType.Main, {
270
290
  source: 'wallet-session-coordinator',
271
291
  reason: expectedPassphraseState ? 'session-recovery' : 'open-wallet',
272
292
  deviceOnly: true,
273
293
  });
274
- mainPinSelected = true;
294
+ markWalletStatusRefreshed();
295
+ mainPinAuthenticated = true;
296
+ standardWalletSelected = true;
275
297
  }
276
298
  };
277
299
 
278
300
  const selectStandardWallet = async () => {
279
- // Main PIN authenticates the device; an empty host passphrase selects the standard derivation.
280
- await selectMainPin();
281
301
  if (device.features?.passphraseProtection === true) {
282
- await askDevicePassphrase(device, {
283
- passphrase: '',
284
- on_device: false,
285
- });
302
+ // Main PIN authenticates the device; an empty host passphrase selects the standard derivation.
303
+ await selectMainPin();
304
+ await askDevicePassphrase(
305
+ device,
306
+ {
307
+ passphrase: '',
308
+ on_device: false,
309
+ },
310
+ markWalletStatusRefreshed
311
+ );
312
+ standardWalletSelected = true;
313
+ } else if (!standardWalletSelected) {
314
+ // Without passphrase protection there is no empty-passphrase selector.
315
+ // Main PIN selection is the only authoritative switch back to the standard wallet.
316
+ await selectMainPin(true);
286
317
  }
287
318
  };
288
319
 
289
320
  if (readCurrentAttachPinSession) {
290
321
  const status = await requestProtocolV2DeviceStatus(device);
291
322
  device.updateProtocolV2Status(status);
323
+ markWalletStatusRefreshed();
292
324
  if (
293
325
  status.unlocked !== true ||
294
326
  status.passphrase_enabled !== true ||
@@ -372,7 +404,12 @@ export async function getProtocolV2WalletSession(
372
404
  device.clearInternalState();
373
405
  throw ERRORS.TypedError(HardwareErrorCode.WalletSessionInvalid);
374
406
  }
375
- response = await selectDeviceSession(device, expectedPassphraseState, options?.deriveCardano);
407
+ response = await selectDeviceSession(
408
+ device,
409
+ expectedPassphraseState,
410
+ options?.deriveCardano,
411
+ markWalletStatusRefreshed
412
+ );
376
413
  }
377
414
 
378
415
  let { message } = response;
@@ -402,7 +439,12 @@ export async function getProtocolV2WalletSession(
402
439
  );
403
440
  } else {
404
441
  device.clearInternalState();
405
- response = await selectDeviceSession(device, expectedPassphraseState, options?.deriveCardano);
442
+ response = await selectDeviceSession(
443
+ device,
444
+ expectedPassphraseState,
445
+ options?.deriveCardano,
446
+ markWalletStatusRefreshed
447
+ );
406
448
  }
407
449
  message = response.message;
408
450
  try {
@@ -438,7 +480,7 @@ export async function getProtocolV2WalletSession(
438
480
  let unlockedAttachPin: boolean | undefined;
439
481
  if (readCurrentAttachPinSession) {
440
482
  unlockedAttachPin = true;
441
- } else if (mainPinSelected) {
483
+ } else if (mainPinAuthenticated) {
442
484
  unlockedAttachPin = false;
443
485
  }
444
486
 
@@ -447,6 +489,7 @@ export async function getProtocolV2WalletSession(
447
489
  newSession: message.session_id,
448
490
  unlockedAttachPin,
449
491
  resumed,
492
+ walletStatusRefreshed,
450
493
  };
451
494
  }
452
495
 
@@ -158,7 +158,7 @@ export interface FirmwareUpdateV4Params {
158
158
  se02Binary?: ArrayBuffer;
159
159
  se03Binary?: ArrayBuffer;
160
160
  se04Binary?: ArrayBuffer;
161
- /** Complete Protocol V2 resource ZIP for local development; Core converts it to a local PreparedPlan. */
161
+ /** Complete Protocol V2 resource ZIP. Core parses RESC packages and writes only changed files. */
162
162
  resourceArchiveBinary?: ArrayBuffer;
163
163
  forcedUpdateRes?: boolean;
164
164
  artifactReader?: FirmwareArtifactReader;
@@ -20,8 +20,8 @@ export interface FirmwareUpdatePlanArtifact {
20
20
  url: string;
21
21
  container: 'raw' | 'zip';
22
22
  logicalName?: string;
23
- expectedSize: number;
24
- expectedSha256: string;
23
+ expectedSize?: number;
24
+ expectedSha256?: string;
25
25
  targetVersion?: string;
26
26
  }
27
27
 
@@ -68,7 +68,7 @@ export declare function deviceUploadNft(
68
68
  export declare function uploadPortfolio(
69
69
  connectId: string,
70
70
  params: {
71
- packageBytes: ArrayBuffer | Uint8Array | Blob;
71
+ packageBase64: string;
72
72
  timeoutMs?: number | string;
73
73
  }
74
74
  ): Response<FileInfo & { portfolioUpdated: true }>;
@@ -75,7 +75,8 @@ export type SearchDevice = {
75
75
  serialNo?: string | null;
76
76
  /**
77
77
  * @deprecated Ambiguous legacy identifier. Use serialNo for hardware identity
78
- * and connectId for transport routing.
78
+ * and connectId for transport routing. Empty during BLE discovery until the
79
+ * physical serial number is available after initialization.
79
80
  */
80
81
  uuid: string;
81
82
  deviceId: string | null;
@@ -74,40 +74,11 @@ export type IProtocolV2Resources = {
74
74
  source: IProtocolV2ResourceSource;
75
75
  };
76
76
 
77
- export type IProtocolV2ResourceManifestFile = {
78
- archive_path: string;
79
- original_name: string;
80
- device_path: string;
81
- size: number;
82
- sha256: string;
83
- signed: true;
84
- sig_algo: 'ed25519' | 'mldsa65';
85
- payload_version: string | null;
86
- };
87
-
88
- export type IProtocolV2ResourceManifest = {
89
- schema: 1;
90
- artifact_name: string;
91
- release_name: string;
92
- variant: 'resource';
93
- commit: string;
94
- short_sha: string;
95
- timestamp_utc: string;
96
- core_version: string;
97
- key_set: string;
98
- device_root: 'vol0:';
99
- restore_mode: 'bootloader_update';
100
- trees: Array<{
101
- path: string;
102
- device: string;
103
- }>;
104
- files: IProtocolV2ResourceManifestFile[];
105
- };
106
-
107
77
  /** STM32 firmware config */
108
78
  export type IFirmwareReleaseInfo = {
109
79
  required: boolean;
110
- url: string;
80
+ /** Legacy release artifact URL. Protocol V2 releases use component URLs. */
81
+ url?: string;
111
82
  /**
112
83
  * Firmware type (bitcoinonly or universal)
113
84
  * This field is not present in the remote config, but will be inferred from the firmware field name
@@ -131,10 +102,13 @@ export type IFirmwareReleaseInfo = {
131
102
  upgradeType?: 'payload-package-set' | string;
132
103
  components?: Record<string, IProtocolV2FirmwareComponent>;
133
104
  installOrder?: string[];
105
+ /** Protocol V2 resources matched to this firmware release. */
106
+ resources?: IProtocolV2Resources;
134
107
  bootloaderChangelog?: {
135
108
  [k in ILocale]: string;
136
109
  };
137
- fingerprint: string;
110
+ /** Legacy release artifact SHA-256. Protocol V2 releases use component fingerprints. */
111
+ fingerprint?: string;
138
112
  expectedSize?: number;
139
113
  version: IVersionArray;
140
114
  changelog: {
@@ -167,8 +141,6 @@ type IDeviceReleaseInfo = {
167
141
  'firmware-v8'?: IFirmwareReleaseInfo[];
168
142
  'firmware-btc-v8'?: IFirmwareReleaseInfo[];
169
143
  ble?: IBLEFirmwareReleaseInfo[];
170
- /** Independent Protocol V2 resource release configuration. */
171
- resources?: IProtocolV2Resources;
172
144
  };
173
145
 
174
146
  export type DeviceTypeMap = {
@@ -1,4 +1,8 @@
1
- import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
1
+ import {
2
+ EDeviceType,
3
+ EFirmwareType,
4
+ canonicalizePro2BleAdvertisementName,
5
+ } from '@onekeyfe/hd-shared';
2
6
  import { Enum_Capability } from '@onekeyfe/hd-transport';
3
7
 
4
8
  import type { PROTO } from '../constants';
@@ -125,9 +129,10 @@ export const resolveDeviceFirmwareType = (features?: DeviceFeaturesInput): EFirm
125
129
  export const resolveDeviceBleName = (features?: DeviceFeaturesInput): string | null => {
126
130
  if (!features) return null;
127
131
  const compatible = asCompatibleFeatures(features);
128
- return (
129
- firstNonEmptyString(compatible.bleName, compatible.onekey_ble_name, compatible.ble_name) ?? null
130
- );
132
+ const bleName =
133
+ firstNonEmptyString(compatible.bleName, compatible.onekey_ble_name, compatible.ble_name) ??
134
+ null;
135
+ return bleName ? canonicalizePro2BleAdvertisementName(bleName) : null;
131
136
  };
132
137
 
133
138
  export const resolveDeviceFirmwareVersion = (features?: DeviceFeaturesInput): string | null => {
@@ -110,6 +110,7 @@ export const getPassphraseStateWithRefreshDeviceInfo = async (
110
110
  initSession?: boolean;
111
111
  deriveCardano?: boolean;
112
112
  rejectAttachPinForMainWallet?: boolean;
113
+ mainPinSelected?: boolean;
113
114
  }
114
115
  ) => {
115
116
  if (device.isProtocolV2()) {
@@ -127,6 +128,7 @@ export const getPassphraseStateWithRefreshDeviceInfo = async (
127
128
  onlyMainPin: options?.onlyMainPin,
128
129
  deriveCardano: options?.deriveCardano,
129
130
  rejectAttachPinForMainWallet: options?.rejectAttachPinForMainWallet,
131
+ mainPinSelected: options?.mainPinSelected,
130
132
  });
131
133
  }
132
134
 
@@ -194,6 +196,7 @@ export const getPassphraseState = async (
194
196
  initSession?: boolean;
195
197
  deriveCardano?: boolean;
196
198
  rejectAttachPinForMainWallet?: boolean;
199
+ mainPinSelected?: boolean;
197
200
  }
198
201
  ): Promise<{
199
202
  passphraseState: string | undefined;
@@ -216,6 +219,7 @@ export const getPassphraseState = async (
216
219
  onlyMainPin: options?.onlyMainPin,
217
220
  deriveCardano: options?.deriveCardano,
218
221
  rejectAttachPinForMainWallet: options?.rejectAttachPinForMainWallet,
222
+ mainPinSelected: options?.mainPinSelected,
219
223
  });
220
224
  }
221
225
 
@@ -30,8 +30,15 @@ export const getDeviceTypeByBleName = (name?: string): IDeviceType => {
30
30
  if (/^T/i.test(name)) return EDeviceType.Touch;
31
31
  if (/^Touch/i.test(name)) return EDeviceType.Touch;
32
32
 
33
- if (/\bPro\s*2\b/i.test(name) || /^Pro2/i.test(name)) return EDeviceType.Pro2;
34
- if (/\bNeo\b/i.test(name) || /^Neo/i.test(name)) return EDeviceType.Neo;
33
+ const compactName = name.replace(/[\s-]/g, '');
34
+ // Require a 4-hex Pro2 suffix in the compact form. A bare `^Pro2` prefix
35
+ // would also match OneKey Pro names such as "Pro 22D8" / "Pro 2D8F".
36
+ if (/\bPro\s*2\b/i.test(name) || /^(?:OneKey)?Pro2[a-f0-9]{4}$/i.test(compactName)) {
37
+ return EDeviceType.Pro2;
38
+ }
39
+ if (/\bNeo\b/i.test(name) || /^Neo/i.test(name) || /^(?:OneKey)?Neo/i.test(compactName)) {
40
+ return EDeviceType.Neo;
41
+ }
35
42
  if (/\bPro\b/i.test(name) || /^Pro/i.test(name)) return EDeviceType.Pro;
36
43
 
37
44
  return EDeviceType.Unknown;
@@ -39,7 +39,14 @@ export const DEVICE_SETTINGS_V2_ONLY_FIELDS = [
39
39
  'randomKeypad',
40
40
  ] as const satisfies readonly DeviceSettingsField[];
41
41
 
42
- export const PROTOCOL_V2_NEVER_TIMEOUT_MS = 0x10000000;
42
+ export const DEVICE_SETTINGS_NEVER_TIMEOUT_MS = 0x10000000;
43
+ // Keep the protocol-specific name for compatibility with existing SDK consumers.
44
+ export const PROTOCOL_V2_NEVER_TIMEOUT_MS = DEVICE_SETTINGS_NEVER_TIMEOUT_MS;
45
+
46
+ const NEVER_TIMEOUT_MS_BY_PROTOCOL: Record<DeviceSettingsProtocol, number> = {
47
+ V1: DEVICE_SETTINGS_NEVER_TIMEOUT_MS,
48
+ V2: PROTOCOL_V2_NEVER_TIMEOUT_MS,
49
+ };
43
50
 
44
51
  export const normalizeSafetyCheckLevel = (
45
52
  value: SafetyCheckLevel | null | undefined
@@ -148,7 +155,7 @@ export type DeviceSettingsValueOption<T> = {
148
155
  };
149
156
 
150
157
  const durationOption = (valueMs: number): DeviceSettingsDurationOption => {
151
- if (valueMs === 0 || valueMs === PROTOCOL_V2_NEVER_TIMEOUT_MS) {
158
+ if (valueMs === DEVICE_SETTINGS_NEVER_TIMEOUT_MS) {
152
159
  return { label: 'Never', valueMs };
153
160
  }
154
161
  if (valueMs < 60_000) {
@@ -162,7 +169,7 @@ const withNever = (
162
169
  values: readonly number[],
163
170
  protocol: DeviceSettingsProtocol
164
171
  ): DeviceSettingsDurationOption[] =>
165
- [...values, protocol === 'V2' ? PROTOCOL_V2_NEVER_TIMEOUT_MS : 0].map(durationOption);
172
+ [...values, NEVER_TIMEOUT_MS_BY_PROTOCOL[protocol]].map(durationOption);
166
173
 
167
174
  export const getAutoLockOptions = (
168
175
  deviceType: IDeviceType,
@@ -200,7 +207,7 @@ export const getAutoShutDownOptions = (
200
207
  return withNever([60_000, 120_000, 300_000, 600_000], protocol);
201
208
  case EDeviceType.Pro2:
202
209
  case EDeviceType.Neo:
203
- return withNever([60_000, 120_000, 300_000, 600_000, 1_800_000], protocol);
210
+ return withNever([60_000, 120_000, 300_000, 600_000], protocol);
204
211
  default:
205
212
  return [];
206
213
  }
@@ -30,6 +30,7 @@ export {
30
30
  checkNeedUpdateBootForClassicAndMini,
31
31
  } from '../api/firmware/updateBootloader';
32
32
  export {
33
+ DEVICE_SETTINGS_NEVER_TIMEOUT_MS,
33
34
  DEVICE_SETTINGS_SHARED_FIELDS,
34
35
  DEVICE_SETTINGS_V1_ONLY_FIELDS,
35
36
  DEVICE_SETTINGS_V2_ONLY_FIELDS,
@@ -109,6 +109,34 @@ export function buildPro2NftBundle(options: {
109
109
  const { image, thumbnail, title, subtitle, timestampMs } = options;
110
110
  assertImage('image', image, PRO2_NFT_IMAGE_WIDTH, PRO2_NFT_IMAGE_HEIGHT);
111
111
  assertImage('thumbnail', thumbnail, PRO2_NFT_THUMBNAIL_WIDTH, PRO2_NFT_THUMBNAIL_HEIGHT);
112
+ const encodedImage = encodePro2Image({ ...image, alphaMode: 'black-background' }).data;
113
+ const encodedThumbnail = encodePro2Image({
114
+ ...thumbnail,
115
+ alphaMode: 'black-background',
116
+ }).data;
117
+ return buildPro2NftBundleFromEncodedImages({
118
+ image: encodedImage,
119
+ thumbnail: encodedThumbnail,
120
+ title,
121
+ subtitle,
122
+ timestampMs,
123
+ });
124
+ }
125
+
126
+ export function buildPro2NftBundleFromEncodedImages(options: {
127
+ image: Uint8Array;
128
+ thumbnail: Uint8Array;
129
+ title: string;
130
+ subtitle: string;
131
+ timestampMs: number;
132
+ }): Pro2NftBundle {
133
+ const { image, thumbnail, title, subtitle, timestampMs } = options;
134
+ if (!(image instanceof Uint8Array) || image.byteLength === 0) {
135
+ throw invalidParameter('Parameter [image] must contain encoded NFT image data.');
136
+ }
137
+ if (!(thumbnail instanceof Uint8Array) || thumbnail.byteLength === 0) {
138
+ throw invalidParameter('Parameter [thumbnail] must contain encoded NFT thumbnail data.');
139
+ }
112
140
  const titleLength = typeof title === 'string' ? utf8Length(title) : 0;
113
141
  const subtitleLength =
114
142
  typeof subtitle === 'string' ? utf8Length(subtitle) : Number.POSITIVE_INFINITY;
@@ -122,21 +150,16 @@ export function buildPro2NftBundle(options: {
122
150
  throw invalidParameter('Parameter [timestampMs] must be a positive safe integer.');
123
151
  }
124
152
 
125
- const encodedImage = encodePro2Image({ ...image, alphaMode: 'black-background' }).data;
126
- const encodedThumbnail = encodePro2Image({
127
- ...thumbnail,
128
- alphaMode: 'black-background',
129
- }).data;
130
153
  const metadata = new TextEncoder().encode(JSON.stringify({ title, subtitle }));
131
154
  if (metadata.byteLength === 0 || metadata.byteLength > 512) {
132
155
  throw invalidParameter('Pro2 NFT metadata must contain 1 to 512 UTF-8 bytes.');
133
156
  }
134
157
 
135
- const hash8 = bytesToHex(blake2s(encodedImage)).slice(0, 8);
158
+ const hash8 = bytesToHex(blake2s(image)).slice(0, 8);
136
159
  return {
137
160
  basename: `nft-${hash8}-${timestampMs}`,
138
- image: encodedImage,
139
- thumbnail: encodedThumbnail,
161
+ image,
162
+ thumbnail,
140
163
  metadata,
141
164
  };
142
165
  }
@@ -1,126 +0,0 @@
1
- import { prepareFirmwareUpdateV4MemoryHost } from '../src/api/firmware/FirmwareMemoryHost';
2
-
3
- import type { CoreApi } from '../src/types/api';
4
- import type { FirmwareUpdatePlan } from '../src/types/api/firmwareUpdatePlan';
5
-
6
- describe('prepareFirmwareUpdateV4MemoryHost', () => {
7
- test('registers artifact-backed component and resource readers', async () => {
8
- const componentBinary = new Uint8Array([1, 2, 3, 4]).buffer;
9
- const archiveBinary = new Uint8Array([5, 6]).buffer;
10
- const manifestBinary = new TextEncoder().encode('{"schema":1}').buffer;
11
- let artifactReader: Parameters<
12
- CoreApi['registerFirmwareUpdateHostBinding']
13
- >[0]['artifactReader'];
14
- const unregisterFirmwareUpdateHostBinding = jest.fn();
15
- const sdk = {
16
- prepareFirmwareUpdatePlan: jest.fn(({ plan, artifacts }) => ({
17
- schemaVersion: 2,
18
- preparedPlanDigest: 'b'.repeat(64),
19
- planDigest: plan.planDigest,
20
- networkPolicy: 'forbid',
21
- executor: plan.executor,
22
- deviceIdentity: plan.deviceIdentity,
23
- deviceModel: plan.deviceModel,
24
- firmwareType: plan.firmwareType,
25
- platform: plan.platform,
26
- leaseRef: 'test-lease',
27
- targetsToUpdate: plan.targetsToUpdate,
28
- artifacts: plan.artifacts.map(planArtifact => {
29
- const input = artifacts.find(item => item.artifactId === planArtifact.artifactId);
30
- return {
31
- ...planArtifact,
32
- artifact: input?.artifact,
33
- materializedEntries: input?.materializedEntries,
34
- };
35
- }),
36
- })),
37
- registerFirmwareUpdateHostBinding: jest.fn(binding => {
38
- artifactReader = binding.artifactReader;
39
- return 7;
40
- }),
41
- unregisterFirmwareUpdateHostBinding,
42
- } as unknown as Pick<
43
- CoreApi,
44
- | 'prepareFirmwareUpdatePlan'
45
- | 'registerFirmwareUpdateHostBinding'
46
- | 'unregisterFirmwareUpdateHostBinding'
47
- >;
48
- const plan = {
49
- schemaVersion: 2,
50
- planDigest: 'a'.repeat(64),
51
- executor: 'v4',
52
- deviceIdentity: 'device-id',
53
- deviceModel: 'pro2',
54
- firmwareType: 0,
55
- platform: 'web',
56
- targetsToUpdate: ['boot', 'resource'],
57
- artifacts: [
58
- {
59
- artifactId: 'component:boot',
60
- role: 'component',
61
- target: 'boot',
62
- url: 'https://example.com/boot.okpkg',
63
- container: 'raw',
64
- },
65
- {
66
- artifactId: 'resource:archive',
67
- role: 'resourceBundle',
68
- target: 'resource',
69
- url: 'https://example.com/resource.zip',
70
- container: 'zip',
71
- logicalName: 'resource-archive',
72
- },
73
- ],
74
- } as FirmwareUpdatePlan;
75
-
76
- const host = prepareFirmwareUpdateV4MemoryHost({
77
- sdk,
78
- plan,
79
- artifacts: [
80
- { artifactId: 'component:boot', binary: componentBinary },
81
- {
82
- artifactId: 'resource:archive',
83
- binary: archiveBinary,
84
- materializedEntries: [{ entryName: 'manifest.json', binary: manifestBinary }],
85
- },
86
- ],
87
- });
88
-
89
- expect(host.hostBindingGeneration).toBe(7);
90
- expect(sdk.registerFirmwareUpdateHostBinding).toHaveBeenCalledWith(
91
- expect.objectContaining({ preparedPlanDigest: host.preparedPlan.preparedPlanDigest })
92
- );
93
- const componentArtifact = host.preparedPlan.artifacts.find(
94
- artifact => artifact.target === 'boot'
95
- )?.artifact;
96
- const resourceEntryArtifact = host.preparedPlan.artifacts.find(
97
- artifact => artifact.target === 'resource'
98
- )?.materializedEntries?.[0]?.artifact;
99
- expect(componentArtifact?.size).toBe(componentBinary.byteLength);
100
- expect(resourceEntryArtifact?.size).toBe(manifestBinary.byteLength);
101
- if (!artifactReader || !componentArtifact || !resourceEntryArtifact) {
102
- throw new Error('Firmware memory host test setup is incomplete');
103
- }
104
- new Uint8Array(componentBinary).fill(9);
105
- const opened = await artifactReader.open({
106
- artifactRef: componentArtifact.artifactRef,
107
- });
108
- const chunk = await artifactReader.read({
109
- readerId: opened.readerId,
110
- offset: 1,
111
- length: 2,
112
- });
113
- expect(Array.from(new Uint8Array(chunk.data))).toEqual([2, 3]);
114
- await artifactReader.close({ readerId: opened.readerId });
115
-
116
- // Materialized ZIP entries are receipts only. Execution opens the approved
117
- // archive and re-derives these bytes, so the memory host must not retain a
118
- // second readable copy of every expanded resource file.
119
- expect(() => artifactReader.open({ artifactRef: resourceEntryArtifact.artifactRef })).toThrow(
120
- 'Firmware memory artifact is unavailable'
121
- );
122
-
123
- host.release();
124
- expect(unregisterFirmwareUpdateHostBinding).toHaveBeenCalledWith(7);
125
- });
126
- });
@@ -1,22 +0,0 @@
1
- import type { CoreApi } from '../../types/api';
2
- import type { FirmwareUpdatePlan } from '../../types/api/firmwareUpdatePlan';
3
- export type FirmwareMemoryArtifactEntry = {
4
- entryName: string;
5
- binary: ArrayBuffer;
6
- };
7
- export type FirmwareMemoryArtifact = {
8
- artifactId: string;
9
- binary: ArrayBuffer;
10
- materializedEntries?: FirmwareMemoryArtifactEntry[];
11
- };
12
- export type FirmwareUpdateV4MemoryHost = {
13
- preparedPlan: ReturnType<CoreApi['prepareFirmwareUpdatePlan']>;
14
- hostBindingGeneration: number;
15
- release: () => void;
16
- };
17
- export declare function prepareFirmwareUpdateV4MemoryHost({ sdk, plan, artifacts, }: {
18
- sdk: Pick<CoreApi, 'prepareFirmwareUpdatePlan' | 'registerFirmwareUpdateHostBinding' | 'unregisterFirmwareUpdateHostBinding'>;
19
- plan: FirmwareUpdatePlan;
20
- artifacts: FirmwareMemoryArtifact[];
21
- }): FirmwareUpdateV4MemoryHost;
22
- //# sourceMappingURL=FirmwareMemoryHost.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FirmwareMemoryHost.d.ts","sourceRoot":"","sources":["../../../src/api/firmware/FirmwareMemoryHost.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAK/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,MAAM,MAAM,2BAA2B,GAAG;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,mBAAmB,CAAC,EAAE,2BAA2B,EAAE,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,YAAY,EAAE,UAAU,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAC/D,qBAAqB,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAaF,wBAAgB,iCAAiC,CAAC,EAChD,GAAG,EACH,IAAI,EACJ,SAAS,GACV,EAAE;IACD,GAAG,EAAE,IAAI,CACP,OAAO,EACL,2BAA2B,GAC3B,mCAAmC,GACnC,qCAAqC,CACxC,CAAC;IACF,IAAI,EAAE,kBAAkB,CAAC;IACzB,SAAS,EAAE,sBAAsB,EAAE,CAAC;CACrC,GAAG,0BAA0B,CA0F7B"}