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

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 (195) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +0 -78
  2. package/__tests__/DeviceEventRegistration.test.ts +0 -6
  3. package/__tests__/connectSettings.test.ts +47 -5
  4. package/__tests__/firmware-update/check-all-firmware-release.test.ts +175 -0
  5. package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
  6. package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
  7. package/__tests__/firmware-update/firmware-preparation-error.test.ts +27 -0
  8. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
  9. package/__tests__/firmware-update/firmware-update-plan.test.ts +593 -0
  10. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +213 -0
  11. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +59 -31
  12. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +58 -0
  13. package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
  14. package/__tests__/get-device-state.test.ts +12 -132
  15. package/__tests__/homescreen.test.ts +1 -41
  16. package/__tests__/logBlockEvent.test.ts +1 -1
  17. package/__tests__/open-wallet-session.test.ts +18 -259
  18. package/__tests__/protocol-v2-unlock-policy.test.ts +35 -86
  19. package/__tests__/protocol-v2.test.ts +632 -333
  20. package/__tests__/public-pro2-api-boundary.test.ts +0 -1
  21. package/dist/api/BaseMethod.d.ts +1 -3
  22. package/dist/api/BaseMethod.d.ts.map +1 -1
  23. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  24. package/dist/api/FirmwareUpdateV2.d.ts +11 -0
  25. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  26. package/dist/api/FirmwareUpdateV3.d.ts +7 -3
  27. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  28. package/dist/api/FirmwareUpdateV4.d.ts +22 -5
  29. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  30. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  31. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  32. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  33. package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
  34. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  35. package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
  36. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
  37. package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
  38. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
  39. package/dist/api/firmware/FirmwarePreparationError.d.ts +3 -0
  40. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +1 -0
  41. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +8 -0
  42. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  43. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
  44. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
  45. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +25 -0
  46. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
  47. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +30 -0
  48. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
  49. package/dist/api/firmware/getBinary.d.ts +7 -0
  50. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  51. package/dist/api/firmware/progressThrottle.d.ts +3 -0
  52. package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
  53. package/dist/api/firmware/updateBootloader.d.ts +2 -0
  54. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  55. package/dist/api/firmware/uploadFirmware.d.ts +9 -1
  56. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  57. package/dist/api/helpers/protocolV2FileWrite.d.ts +0 -2
  58. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  59. package/dist/api/index.d.ts +0 -1
  60. package/dist/api/index.d.ts.map +1 -1
  61. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  62. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  63. package/dist/core/deviceEventRegistration.d.ts +0 -2
  64. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  65. package/dist/core/index.d.ts.map +1 -1
  66. package/dist/data-manager/DataManager.d.ts +1 -0
  67. package/dist/data-manager/DataManager.d.ts.map +1 -1
  68. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  69. package/dist/device/Device.d.ts +4 -22
  70. package/dist/device/Device.d.ts.map +1 -1
  71. package/dist/events/device.d.ts +0 -4
  72. package/dist/events/device.d.ts.map +1 -1
  73. package/dist/events/logBlockEvent.d.ts.map +1 -1
  74. package/dist/events/ui-request.d.ts +2 -27
  75. package/dist/events/ui-request.d.ts.map +1 -1
  76. package/dist/index.d.ts +181 -88
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +3162 -1614
  79. package/dist/inject.d.ts.map +1 -1
  80. package/dist/lowLevelInject.d.ts.map +1 -1
  81. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  82. package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
  83. package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
  84. package/dist/protocols/protocol-v2/uiInteraction.d.ts +3 -3
  85. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  86. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +3 -1
  87. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  88. package/dist/protocols/protocol-v2/unlockRetry.d.ts +10 -0
  89. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
  90. package/dist/protocols/protocol-v2/walletSession.d.ts +1 -4
  91. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  92. package/dist/topLevelInject.d.ts.map +1 -1
  93. package/dist/types/api/checkAllFirmwareRelease.d.ts +4 -0
  94. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  95. package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
  96. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  97. package/dist/types/api/export.d.ts +4 -1
  98. package/dist/types/api/export.d.ts.map +1 -1
  99. package/dist/types/api/firmwareUpdate.d.ts +69 -0
  100. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  101. package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
  102. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
  103. package/dist/types/api/firmwareUpdatePlan.d.ts +28 -0
  104. package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
  105. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
  106. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
  107. package/dist/types/api/index.d.ts +10 -3
  108. package/dist/types/api/index.d.ts.map +1 -1
  109. package/dist/types/api/protocolV2.d.ts +0 -3
  110. package/dist/types/api/protocolV2.d.ts.map +1 -1
  111. package/dist/types/settings.d.ts +13 -0
  112. package/dist/types/settings.d.ts.map +1 -1
  113. package/dist/utils/deviceFeaturesUtils.d.ts +0 -2
  114. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  115. package/dist/utils/homescreen.d.ts +0 -4
  116. package/dist/utils/homescreen.d.ts.map +1 -1
  117. package/dist/utils/index.d.ts +1 -1
  118. package/dist/utils/index.d.ts.map +1 -1
  119. package/dist/utils/patch.d.ts +1 -1
  120. package/dist/utils/patch.d.ts.map +1 -1
  121. package/dist/utils/pro2Wallpaper.d.ts +0 -10
  122. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  123. package/package.json +4 -4
  124. package/src/api/BaseMethod.ts +10 -8
  125. package/src/api/CheckAllFirmwareRelease.ts +51 -6
  126. package/src/api/FirmwareUpdateV2.ts +298 -120
  127. package/src/api/FirmwareUpdateV3.ts +263 -57
  128. package/src/api/FirmwareUpdateV4.ts +748 -281
  129. package/src/api/GetPassphraseState.ts +1 -7
  130. package/src/api/OpenWalletSession.ts +17 -54
  131. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +11 -32
  132. package/src/api/device/DeviceUnlock.ts +1 -1
  133. package/src/api/device/DeviceUpdateBootloader.ts +122 -6
  134. package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
  135. package/src/api/firmware/FirmwareHostBinding.ts +100 -0
  136. package/src/api/firmware/FirmwarePreparationError.ts +12 -0
  137. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +57 -0
  138. package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
  139. package/src/api/firmware/FirmwareUpdatePlan.ts +745 -0
  140. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +392 -0
  141. package/src/api/firmware/progressThrottle.ts +44 -0
  142. package/src/api/firmware/updateBootloader.ts +19 -4
  143. package/src/api/firmware/uploadFirmware.ts +140 -22
  144. package/src/api/helpers/protocolV2FileWrite.ts +4 -11
  145. package/src/api/index.ts +0 -1
  146. package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -3
  147. package/src/core/deviceEventRegistration.ts +0 -4
  148. package/src/core/index.ts +75 -118
  149. package/src/data/messages/messages-protocol-v2.json +0 -10
  150. package/src/data-manager/DataManager.ts +33 -33
  151. package/src/data-manager/connectSettings.ts +11 -0
  152. package/src/device/Device.ts +21 -193
  153. package/src/events/device.ts +0 -4
  154. package/src/events/logBlockEvent.ts +0 -1
  155. package/src/events/ui-request.ts +2 -32
  156. package/src/index.ts +5 -0
  157. package/src/inject.ts +22 -3
  158. package/src/lowLevelInject.ts +5 -1
  159. package/src/protocols/protocol-v2/features.ts +2 -9
  160. package/src/protocols/protocol-v2/lockedError.ts +10 -0
  161. package/src/protocols/protocol-v2/uiInteraction.ts +5 -31
  162. package/src/protocols/protocol-v2/unlockPolicy.ts +105 -1
  163. package/src/protocols/protocol-v2/unlockRetry.ts +109 -0
  164. package/src/protocols/protocol-v2/walletSession.ts +18 -93
  165. package/src/topLevelInject.ts +5 -1
  166. package/src/types/api/checkAllFirmwareRelease.ts +4 -0
  167. package/src/types/api/deviceUpdateBootloader.ts +6 -0
  168. package/src/types/api/export.ts +18 -0
  169. package/src/types/api/firmwareUpdate.ts +76 -0
  170. package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
  171. package/src/types/api/firmwareUpdatePlan.ts +38 -0
  172. package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
  173. package/src/types/api/index.ts +14 -2
  174. package/src/types/api/protocolV2.ts +0 -13
  175. package/src/types/settings.ts +13 -0
  176. package/src/utils/deviceFeaturesUtils.ts +0 -4
  177. package/src/utils/homescreen.ts +6 -32
  178. package/src/utils/index.ts +1 -6
  179. package/src/utils/pro2Wallpaper.ts +8 -35
  180. package/__tests__/deviceUploadNft.test.ts +0 -187
  181. package/__tests__/pro2Nft.test.ts +0 -108
  182. package/__tests__/protocol-v2-ui-lifecycle.test.ts +0 -56
  183. package/__tests__/uiProgressThrottle.test.ts +0 -74
  184. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +0 -30
  185. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +0 -1
  186. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -22
  187. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +0 -1
  188. package/dist/utils/pro2Nft.d.ts +0 -29
  189. package/dist/utils/pro2Nft.d.ts.map +0 -1
  190. package/dist/utils/uiProgressThrottle.d.ts +0 -3
  191. package/dist/utils/uiProgressThrottle.d.ts.map +0 -1
  192. package/src/api/protocol-v2/DeviceUploadNft.ts +0 -166
  193. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +0 -117
  194. package/src/utils/pro2Nft.ts +0 -91
  195. package/src/utils/uiProgressThrottle.ts +0 -63
@@ -10,6 +10,7 @@ import { bytesToHex } from '../helpers/hexUtils';
10
10
  import { DataManager } from '../../data-manager';
11
11
  import { DevicePool } from '../../device/DevicePool';
12
12
  import { buildProtocolV1FeaturesPayload } from '../../deviceProfile';
13
+ import { openFirmwareByteSource, readFirmwareByteSourceFully } from './FirmwareArtifactSource';
13
14
 
14
15
  import type { KnownDevice } from '../../types';
15
16
  import type { TypedCall, TypedResponseMessage } from '../../device/DeviceCommands';
@@ -17,6 +18,7 @@ import type { PROTO } from '../../constants';
17
18
  import type { CoreMessage, IFirmwareUpdateProgressType } from '../../events';
18
19
  import type { Success } from '@onekeyfe/hd-transport';
19
20
  import type { Device } from '../../device/Device';
21
+ import type { FirmwareByteSource } from './FirmwareArtifactSource';
20
22
 
21
23
  const NEW_BOOT_UPRATE_FIRMWARE_VERSION = '2.4.5';
22
24
  const SESSION_ERROR = 'session not found';
@@ -88,17 +90,20 @@ export const waitBleInstall = async (updateType: string) => {
88
90
  }
89
91
  };
90
92
 
91
- export const uploadFirmware = async (
93
+ const toArrayBuffer = (payload: ArrayBuffer | Buffer): ArrayBuffer => {
94
+ if (payload instanceof ArrayBuffer) {
95
+ return payload;
96
+ }
97
+ return new Uint8Array(payload.buffer, payload.byteOffset, payload.byteLength).slice().buffer;
98
+ };
99
+
100
+ export const uploadFirmwareFromSource = async (
92
101
  updateType: 'firmware' | 'ble',
93
102
  typedCall: TypedCall,
94
103
  postMessage: (message: CoreMessage) => void,
95
104
  device: Device,
96
- {
97
- payload,
98
- rebootOnSuccess,
99
- }: PROTO.FirmwareUpload & {
100
- rebootOnSuccess?: boolean;
101
- },
105
+ source: FirmwareByteSource,
106
+ rebootOnSuccess?: boolean,
102
107
  isUpdateBootloader?: boolean
103
108
  ) => {
104
109
  const deviceType = device.getCurrentDeviceType();
@@ -119,20 +124,20 @@ export const uploadFirmware = async (
119
124
  if (supportUpgradeFileHeader) {
120
125
  // Extract and validate firmware header (first 1KB)
121
126
  const HEADER_SIZE = 1024;
122
- if (payload.byteLength < HEADER_SIZE) {
127
+ if (source.size < HEADER_SIZE) {
123
128
  throw ERRORS.TypedError(
124
129
  HardwareErrorCode.RuntimeError,
125
- `firmware payload too small: ${payload.byteLength} bytes, expected at least ${HEADER_SIZE} bytes`
130
+ `firmware payload too small: ${source.size} bytes, expected at least ${HEADER_SIZE} bytes`
126
131
  );
127
132
  }
128
133
 
129
134
  Log.debug('Uploading firmware header:', {
130
135
  size: HEADER_SIZE,
131
- totalSize: payload.byteLength,
136
+ totalSize: source.size,
132
137
  });
133
138
  postProgressTip(device, 'UploadingFirmwareHeader', postMessage);
134
139
 
135
- const header = new Uint8Array(payload.slice(0, HEADER_SIZE));
140
+ const header = new Uint8Array(await source.readAt(0, HEADER_SIZE));
136
141
 
137
142
  try {
138
143
  const headerRes = await typedCall('UpgradeFileHeader', 'Success', {
@@ -169,6 +174,9 @@ export const uploadFirmware = async (
169
174
  postProgressMessage(device, 0, 'installingFirmware', postMessage);
170
175
  let updateResponse: TypedResponseMessage<'Success'>;
171
176
  try {
177
+ // Classic/Mini bootloaders accept one protobuf payload and do not expose
178
+ // a request-range protocol. Other device families remain fully streamed.
179
+ const payload = await readFirmwareByteSourceFully(source);
172
180
  updateResponse = await typedCall('FirmwareUpload', 'Success', {
173
181
  payload,
174
182
  });
@@ -200,9 +208,7 @@ export const uploadFirmware = async (
200
208
  updateType,
201
209
  postMessage,
202
210
  device,
203
- {
204
- payload,
205
- },
211
+ source,
206
212
  rebootOnSuccess
207
213
  );
208
214
  return response.message;
@@ -211,7 +217,7 @@ export const uploadFirmware = async (
211
217
 
212
218
  postConfirmationMessage(device);
213
219
  postProgressTip(device, 'ConfirmOnDevice', postMessage);
214
- const length = payload.byteLength;
220
+ const length = source.size;
215
221
 
216
222
  let response = await typedCall('FirmwareErase', ['FirmwareRequest', 'Success'], { length });
217
223
  postProgressTip(device, 'FirmwareEraseSuccess', postMessage);
@@ -220,7 +226,7 @@ export const uploadFirmware = async (
220
226
  const start = response.message.offset!;
221
227
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
222
228
  const end = response.message.offset! + response.message.length!;
223
- const chunk = payload.slice(start, end);
229
+ const chunk = await source.readAt(start, end - start);
224
230
 
225
231
  if (start > 0) {
226
232
  postProgressMessage(
@@ -249,11 +255,45 @@ export const uploadFirmware = async (
249
255
  throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'uploadFirmware: unknown device model');
250
256
  };
251
257
 
258
+ export const uploadFirmware = async (
259
+ updateType: 'firmware' | 'ble',
260
+ typedCall: TypedCall,
261
+ postMessage: (message: CoreMessage) => void,
262
+ device: Device,
263
+ {
264
+ payload,
265
+ rebootOnSuccess,
266
+ }: PROTO.FirmwareUpload & {
267
+ rebootOnSuccess?: boolean;
268
+ },
269
+ isUpdateBootloader?: boolean
270
+ ) => {
271
+ const source = await openFirmwareByteSource({
272
+ binary: toArrayBuffer(payload),
273
+ });
274
+ if (!source) {
275
+ throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'firmware payload is empty');
276
+ }
277
+ try {
278
+ return await uploadFirmwareFromSource(
279
+ updateType,
280
+ typedCall,
281
+ postMessage,
282
+ device,
283
+ source,
284
+ rebootOnSuccess,
285
+ isUpdateBootloader
286
+ );
287
+ } finally {
288
+ await source.close();
289
+ }
290
+ };
291
+
252
292
  const newTouchUpdateProcess = async (
253
293
  updateType: 'firmware' | 'ble',
254
294
  postMessage: (message: CoreMessage) => void,
255
295
  device: Device,
256
- { payload }: PROTO.FirmwareUpload,
296
+ source: FirmwareByteSource,
257
297
  rebootOnSuccess = true
258
298
  ) => {
259
299
  let typedCall = device.getCommands().typedCall.bind(device.getCommands());
@@ -263,13 +303,13 @@ const newTouchUpdateProcess = async (
263
303
  const env = DataManager.getSettings('env');
264
304
  const perPackageSize = DataManager.isBleConnect(env) ? 16 : 128;
265
305
  const chunkSize = 1024 * perPackageSize;
266
- const totalChunks = Math.ceil(payload.byteLength / chunkSize);
306
+ const totalChunks = Math.ceil(source.size / chunkSize);
267
307
  let offset = 0;
268
308
  for (let i = 0; i < totalChunks; i++) {
269
309
  const chunkStart = i * chunkSize;
270
- const chunkEnd = Math.min(chunkStart + chunkSize, payload.byteLength);
310
+ const chunkEnd = Math.min(chunkStart + chunkSize, source.size);
271
311
  const chunkLength = chunkEnd - chunkStart;
272
- const chunk = payload.slice(chunkStart, chunkEnd);
312
+ const chunk = await source.readAt(chunkStart, chunkLength);
273
313
  const overwrite = i === 0;
274
314
  const progress = Math.round(((i + 1) / totalChunks) * 100);
275
315
  const writeRes = await emmcFileWriteWithRetry(
@@ -490,6 +530,67 @@ export const updateResource = async (
490
530
  return processResourceRequest(typedCall, res, data);
491
531
  };
492
532
 
533
+ export const updateResourceFromSource = async (
534
+ typedCall: TypedCall,
535
+ fileName: string,
536
+ source: FirmwareByteSource,
537
+ onConfirmAfter?: () => void
538
+ ) => {
539
+ const initialLength = Math.min(INIT_DATA_CHUNK_SIZE, source.size);
540
+ const initialChunk = new Uint8Array(await source.readAt(0, initialLength));
541
+ let response = await typedCall('ResourceUpdate', ['ResourceRequest', 'Success'], {
542
+ file_name: fileName,
543
+ data_length: source.size,
544
+ initial_data_chunk: bytesToHex(initialChunk),
545
+ hash: bytesToHex(blake2s(initialChunk)),
546
+ });
547
+ onConfirmAfter?.();
548
+
549
+ while (response.type !== 'Success') {
550
+ const { offset, data_length: dataLength } = response.message;
551
+ if (
552
+ !Number.isSafeInteger(offset) ||
553
+ offset === undefined ||
554
+ offset < 0 ||
555
+ !Number.isSafeInteger(dataLength) ||
556
+ dataLength === undefined ||
557
+ dataLength <= 0 ||
558
+ offset + dataLength > source.size
559
+ ) {
560
+ throw ERRORS.TypedError(
561
+ HardwareErrorCode.RuntimeError,
562
+ 'Device requested an invalid firmware resource range'
563
+ );
564
+ }
565
+ const chunk = new Uint8Array(await source.readAt(offset, dataLength));
566
+ response = await typedCall('ResourceAck', ['ResourceRequest', 'Success'], {
567
+ data_chunk: bytesToHex(chunk),
568
+ hash: bytesToHex(blake2s(chunk)),
569
+ });
570
+ }
571
+ return response.message;
572
+ };
573
+
574
+ export const updateResourcesFromSources = async (
575
+ typedCall: TypedCall,
576
+ postMessage: (message: CoreMessage) => void,
577
+ device: Device,
578
+ entries: ReadonlyArray<{ entryName: string; source: FirmwareByteSource }>
579
+ ) => {
580
+ postProgressTip(device, 'UpdateSysResource', postMessage);
581
+ for (const [index, entry] of entries.entries()) {
582
+ await updateResourceFromSource(typedCall, entry.entryName, entry.source);
583
+ postProgressMessage(
584
+ device,
585
+ Math.floor(((index + 1) / entries.length) * 100),
586
+ 'installingFirmware',
587
+ postMessage
588
+ );
589
+ }
590
+ postProgressTip(device, 'UpdateSysResourceSuccess', postMessage);
591
+ return true;
592
+ };
593
+
493
594
  export const updateResources = async (
494
595
  typedCall: TypedCall,
495
596
  postMessage: (message: CoreMessage) => void,
@@ -524,11 +625,28 @@ export const updateBootloader = async (
524
625
  typedCall: TypedCall,
525
626
  postMessage: (message: CoreMessage) => void,
526
627
  device: Device,
527
- source: ArrayBuffer
628
+ data: ArrayBuffer
629
+ ) => {
630
+ const source = await openFirmwareByteSource({ binary: data });
631
+ if (!source) {
632
+ throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'bootloader payload is empty');
633
+ }
634
+ try {
635
+ return await updateBootloaderFromSource(typedCall, postMessage, device, source);
636
+ } finally {
637
+ await source.close();
638
+ }
639
+ };
640
+
641
+ export const updateBootloaderFromSource = async (
642
+ typedCall: TypedCall,
643
+ postMessage: (message: CoreMessage) => void,
644
+ device: Device,
645
+ source: FirmwareByteSource
528
646
  ) => {
529
647
  postProgressTip(device, 'UpdateBootloader', postMessage);
530
648
  postProgressMessage(device, Math.floor(0), 'installingFirmware', postMessage);
531
- await updateResource(typedCall, 'bootloader.bin', source, () => {
649
+ await updateResourceFromSource(typedCall, 'bootloader.bin', source, () => {
532
650
  postProcessingMessage('resource', postMessage);
533
651
  });
534
652
  postProgressMessage(device, Math.floor(100), 'installingFirmware', postMessage);
@@ -31,21 +31,19 @@ export type ProtocolV2FileWriteOptions = {
31
31
  uiPercentage?: number;
32
32
  timeoutMs?: number;
33
33
  maxChunkRetries?: number;
34
- paceMs?: number;
35
34
  throwIfAborted?: () => void;
36
35
  onProgress?: (progress: ProtocolV2FileWriteProgress) => void;
37
36
  };
38
37
 
39
38
  const MIN_FILE_CHUNK_SIZE = 64;
40
39
 
41
- export function isProtocolV2ResponseTimeout(error: unknown) {
40
+ function isRetryableFileWriteTimeout(error: unknown) {
42
41
  if (!error || typeof error !== 'object') return false;
43
- const candidate = error as { errorCode?: number; code?: number | string; message?: string };
42
+ const candidate = error as { errorCode?: number; code?: number; message?: string };
44
43
  const code = candidate.errorCode ?? candidate.code;
45
44
  return (
46
45
  code === HardwareErrorCode.BleTimeoutError ||
47
- code === 'response-timeout' ||
48
- /(?:BLE|Lowlevel|Protocol V2) response timeout/i.test(candidate.message ?? '')
46
+ /Lowlevel response timeout/i.test(candidate.message ?? '')
49
47
  );
50
48
  }
51
49
 
@@ -149,7 +147,7 @@ export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
149
147
  );
150
148
  isWritePending = false;
151
149
  } catch (error) {
152
- if (retryCount >= maxChunkRetries || !isProtocolV2ResponseTimeout(error)) throw error;
150
+ if (retryCount >= maxChunkRetries || !isRetryableFileWriteTimeout(error)) throw error;
153
151
  retryCount += 1;
154
152
  options.throwIfAborted?.();
155
153
  }
@@ -188,11 +186,6 @@ export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
188
186
  elapsedMs > 0 ? Math.round((transferredBytes / elapsedMs) * 1000) : undefined,
189
187
  elapsedMs,
190
188
  });
191
- if (options.paceMs && options.paceMs > 0) {
192
- await new Promise(resolve => {
193
- setTimeout(resolve, options.paceMs);
194
- });
195
- }
196
189
  }
197
190
 
198
191
  return {
package/src/api/index.ts CHANGED
@@ -49,7 +49,6 @@ export { default as promptWebDeviceAccess } from './PromptWebDeviceAccess';
49
49
  export { default as deviceReboot } from './protocol-v2/DeviceReboot';
50
50
  export { default as deviceGetOnboardingStatus } from './protocol-v2/DeviceGetOnboardingStatus';
51
51
  export { default as deviceUploadWallpaper } from './protocol-v2/DeviceUploadWallpaper';
52
- export { default as deviceUploadNft } from './protocol-v2/DeviceUploadNft';
53
52
  export { default as uploadPortfolio } from './UploadPortfolio';
54
53
 
55
54
  export { default as cipherKeyValue } from './CipherKeyValue';
@@ -13,9 +13,7 @@ export default class ProtocolInfoRequest extends BaseMethod {
13
13
  }
14
14
 
15
15
  async run() {
16
- const res = await this.device.commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {
17
- eventless_wallet_session: true,
18
- });
16
+ const res = await this.device.commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {});
19
17
  return Promise.resolve(res.message);
20
18
  }
21
19
  }
@@ -4,8 +4,6 @@ import type { Device, DeviceEvents } from '../device/Device';
4
4
 
5
5
  export type HardwareUiEventHandlers = {
6
6
  pin: (...event: DeviceEvents[typeof DEVICE.PIN]) => void;
7
- pinOnDevice: (...event: DeviceEvents[typeof DEVICE.PIN_ON_DEVICE]) => void;
8
- pinOnDeviceComplete: (...event: DeviceEvents[typeof DEVICE.PIN_ON_DEVICE_COMPLETE]) => void;
9
7
  button: (...event: DeviceEvents[typeof DEVICE.BUTTON]) => void;
10
8
  passphrase: (...event: DeviceEvents[typeof DEVICE.PASSPHRASE]) => void;
11
9
  passphraseOnDevice: (...event: DeviceEvents[typeof DEVICE.PASSPHRASE_ON_DEVICE]) => void;
@@ -17,8 +15,6 @@ export function registerHardwareUiEventListeners(
17
15
  handlers: HardwareUiEventHandlers
18
16
  ) {
19
17
  device.on(DEVICE.PIN, handlers.pin);
20
- device.on(DEVICE.PIN_ON_DEVICE, handlers.pinOnDevice);
21
- device.on(DEVICE.PIN_ON_DEVICE_COMPLETE, handlers.pinOnDeviceComplete);
22
18
  device.on(DEVICE.BUTTON, handlers.button);
23
19
  device.on(DEVICE.PASSPHRASE, handlers.passphrase);
24
20
  device.on(DEVICE.PASSPHRASE_ON_DEVICE, handlers.passphraseOnDevice);
package/src/core/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import semver from 'semver';
2
2
  import EventEmitter from 'events';
3
- import { DeviceSessionPinType, TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
3
+ import { TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
4
4
  import {
5
5
  ERRORS,
6
6
  ERROR_CODES_REQUIRE_RELEASE,
@@ -55,12 +55,11 @@ import DeviceConnector from '../device/DeviceConnector';
55
55
  import RequestQueue from './RequestQueue';
56
56
  import { registerHardwareUiEventListeners } from './deviceEventRegistration';
57
57
  import { getSynchronize } from '../utils/getSynchronize';
58
- import { runMethodWithUnlockPolicy } from '../protocols/protocol-v2/unlockPolicyRunner';
58
+ import { runMethodWithUnlockRetry } from '../protocols/protocol-v2/unlockRetry';
59
59
  import {
60
60
  ProtocolV2UiInteractionCoordinator,
61
61
  isProtocolV2UiEnabled,
62
62
  } from '../protocols/protocol-v2/uiInteraction';
63
- import { createUiProgressMessageFilter } from '../utils/uiProgressThrottle';
64
63
 
65
64
  import type { ConnectSettings, Features, KnownDevice } from '../types';
66
65
  import type { CoreMessage, IFrameCallMessage, UiPromise, UiPromiseResponse } from '../events';
@@ -155,12 +154,7 @@ export const callAPI = async (context: CoreContext, message: CoreMessage) => {
155
154
  try {
156
155
  method = findMethod(message as IFrameCallMessage);
157
156
  method.connector = _connector;
158
- const shouldPostMessage = createUiProgressMessageFilter();
159
- method.postMessage = event => {
160
- if (shouldPostMessage(event)) {
161
- postMessage(event);
162
- }
163
- };
157
+ method.postMessage = postMessage;
164
158
  method.setContext?.(context);
165
159
 
166
160
  method.requestContext = createRequestContext(method.responseID, method.name, {
@@ -412,8 +406,6 @@ const onCallDevice = async (
412
406
 
413
407
  registerHardwareUiEventListeners(device, {
414
408
  pin: onDevicePinHandler,
415
- pinOnDevice: onEnterPinOnDeviceHandler,
416
- pinOnDeviceComplete: onPinOnDeviceCompleteHandler,
417
409
  button: onDeviceButtonHandler,
418
410
  passphrase: message.payload.useEmptyPassphrase
419
411
  ? onEmptyPassphraseHandler
@@ -429,7 +421,6 @@ const onCallDevice = async (
429
421
  );
430
422
 
431
423
  const protocolV2UiCoordinator = new ProtocolV2UiInteractionCoordinator(device, postMessage);
432
- device.beginProtocolV2UiInteraction();
433
424
  device.on(
434
425
  DEVICE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE,
435
426
  onSelectDeviceForSwitchFirmwareWebDeviceHandler
@@ -556,92 +547,89 @@ const onCallDevice = async (
556
547
  );
557
548
  }
558
549
 
559
- try {
560
- let deviceIdCheckedDuringUnlockPreflight = false;
561
- const response = await runMethodWithUnlockPolicy<object>(method, device, {
562
- uiCoordinator: protocolV2UiCoordinator,
563
- afterStatusBeforeUnlock: () => {
564
- if (method.deviceId && method.checkDeviceId) {
565
- if (!device.checkDeviceId(method.deviceId)) {
566
- throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
567
- }
568
- deviceIdCheckedDuringUnlockPreflight = true;
569
- }
570
- },
571
- prepare: async () => {
572
- if (method.deviceId && method.checkDeviceId && !deviceIdCheckedDuringUnlockPreflight) {
573
- const isSameDeviceID = await checkLiveDeviceId(device, method.deviceId);
574
- if (!isSameDeviceID) {
575
- throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
576
- }
577
- }
550
+ if (method.deviceId && method.checkDeviceId) {
551
+ const isSameDeviceID = await checkLiveDeviceId(device, method.deviceId);
552
+ if (!isSameDeviceID) {
553
+ return Promise.reject(ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError));
554
+ }
555
+ }
578
556
 
579
- /**
580
- * check firmware release info
581
- */
582
- method.checkFirmwareRelease();
557
+ /**
558
+ * check firmware release info
559
+ */
560
+ method.checkFirmwareRelease();
583
561
 
584
- /**
585
- * check additional supported feature
586
- */
587
- method.checkDeviceSupportFeature();
562
+ /**
563
+ * check additional supported feature
564
+ */
565
+ method.checkDeviceSupportFeature();
588
566
 
589
- // reconfigure messages
590
- if (_deviceList && device.features && !device.isProtocolV2()) {
591
- await TransportManager.reconfigure(device.features);
592
- }
567
+ // reconfigure messages
568
+ if (_deviceList && device.features && !device.isProtocolV2()) {
569
+ await TransportManager.reconfigure(device.features);
570
+ }
571
+
572
+ // Check to see if it is safe to use Passphrase
573
+ checkPassphraseEnableState(method, device.features);
593
574
 
594
- // Check to see if it is safe to use Passphrase
595
- checkPassphraseEnableState(method, device.features);
596
-
597
- if (shouldCheckPassphraseState(method, device)) {
598
- // check version
599
- const support = device.supportNewPassphrase();
600
- if (!support.support) {
601
- throw ERRORS.TypedError(
602
- HardwareErrorCode.DeviceNotSupportPassphrase,
603
- `Device not support passphrase, please update to ${support.require}`,
604
- {
605
- require: support.require,
606
- }
607
- );
575
+ if (shouldCheckPassphraseState(method, device)) {
576
+ // check version
577
+ const support = device.supportNewPassphrase();
578
+ if (!support.support) {
579
+ return Promise.reject(
580
+ ERRORS.TypedError(
581
+ HardwareErrorCode.DeviceNotSupportPassphrase,
582
+ `Device not support passphrase, please update to ${support.require}`,
583
+ {
584
+ require: support.require,
608
585
  }
586
+ )
587
+ );
588
+ }
609
589
 
610
- // Check Device passphrase State after the Protocol V2 pre-unlock gate.
611
- const passphraseStateSafety = await device.checkPassphraseStateSafety(
612
- method.payload?.passphraseState,
613
- method.payload?.useEmptyPassphrase,
614
- method.payload?.skipPassphraseCheck,
615
- hasDeriveCardano(method)
616
- );
590
+ // Check Device passphrase State
591
+ const passphraseStateSafety = await device.checkPassphraseStateSafety(
592
+ method.payload?.passphraseState,
593
+ method.payload?.useEmptyPassphrase,
594
+ method.payload?.skipPassphraseCheck
595
+ );
617
596
 
618
- // Double check, handles the special case of Touch/Pro
619
- checkPassphraseEnableState(method, device.features);
597
+ // Double check, handles the special case of Touch/Pro
598
+ checkPassphraseEnableState(method, device.features);
620
599
 
621
- if (!passphraseStateSafety) {
622
- DevicePool.clearDeviceCache(method.payload.connectId);
623
- throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError);
624
- }
600
+ if (!passphraseStateSafety) {
601
+ DevicePool.clearDeviceCache(method.payload.connectId);
602
+ return Promise.reject(
603
+ ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError)
604
+ );
605
+ }
625
606
 
626
- // Protocol V2 emits the PIN phase completion from DeviceSessionAskPin.
627
- // Keep the legacy compatibility close for Protocol V1 only.
628
- if (!device.isProtocolV2()) {
629
- postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW));
630
- }
631
- }
607
+ // close pin popup window
608
+ postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW));
609
+ }
632
610
 
633
- // Automatic check safety_check level for Kovan, Ropsten, Rinkeby, Goerli test networks.
634
- try {
635
- await method.checkSafetyLevelOnTestNet();
636
- } catch (e) {
637
- throw e instanceof HardwareError
638
- ? e
639
- : ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'open safety check failed.');
640
- }
611
+ // Automatic check safety_check level for Kovan, Ropsten, Rinkeby, Goerli test networks.
612
+ try {
613
+ await method.checkSafetyLevelOnTestNet();
614
+ } catch (e) {
615
+ const error =
616
+ e instanceof HardwareError
617
+ ? e
618
+ : ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'open safety check failed.');
619
+ // messageResponse = createResponseMessage(method.responseID, false, { error });
620
+ // requestQueue.resolveRequest(method.responseID, messageResponse);
621
+ // return;
622
+ throw error;
623
+ }
641
624
 
642
- method.device?.commands?.checkDisposed();
643
- },
644
- });
625
+ method.device?.commands?.checkDisposed();
626
+
627
+ try {
628
+ const response: object = await runMethodWithUnlockRetry(
629
+ method,
630
+ device,
631
+ protocolV2UiCoordinator
632
+ );
645
633
  messageResponse = createResponseMessage(method.responseID, true, response);
646
634
  requestQueue.resolveRequest(method.responseID, messageResponse);
647
635
  completeMethodRequestContext(method);
@@ -1291,7 +1279,6 @@ const onDevicePassphraseHandler = async (
1291
1279
  source: requestPayload.source,
1292
1280
  reason: requestPayload.reason,
1293
1281
  expectedPassphraseState: requestPayload.expectedPassphraseState,
1294
- ...(requestPayload.interaction ? { interaction: requestPayload.interaction } : {}),
1295
1282
  })
1296
1283
  );
1297
1284
  // wait for passphrase
@@ -1321,7 +1308,6 @@ const onEnterPassphraseOnDeviceHandler = (
1321
1308
  passphraseState: device.passphraseState,
1322
1309
  source: requestPayload?.source,
1323
1310
  reason: requestPayload?.reason,
1324
- ...(requestPayload?.interaction ? { interaction: requestPayload.interaction } : {}),
1325
1311
  })
1326
1312
  );
1327
1313
  };
@@ -1335,39 +1321,10 @@ const onEnterAttachPinOnDeviceHandler = (
1335
1321
  type: 'ButtonRequest_AttachPin',
1336
1322
  source: requestPayload?.source,
1337
1323
  reason: requestPayload?.reason,
1338
- ...(requestPayload?.interaction ? { interaction: requestPayload.interaction } : {}),
1339
1324
  })
1340
1325
  );
1341
1326
  };
1342
1327
 
1343
- const onEnterPinOnDeviceHandler = (
1344
- ...[device, pinType, metadata]: [...DeviceEvents['pin_on_device']]
1345
- ) => {
1346
- postMessage(
1347
- createUiMessage(UI_REQUEST.REQUEST_PIN, {
1348
- device: device.toMessageObject() as KnownDevice,
1349
- type:
1350
- pinType === DeviceSessionPinType.AttachToPin
1351
- ? 'ButtonRequest_AttachPin'
1352
- : 'ButtonRequest_PinEntry',
1353
- source: metadata?.source,
1354
- reason: metadata?.reason,
1355
- deviceOnly: metadata?.deviceOnly ?? true,
1356
- completion: metadata?.completion,
1357
- method: metadata?.method,
1358
- page: metadata?.page,
1359
- operation: metadata?.operation,
1360
- ...(metadata?.interaction ? { interaction: metadata.interaction } : {}),
1361
- })
1362
- );
1363
- };
1364
-
1365
- const onPinOnDeviceCompleteHandler = (
1366
- ...[_, metadata]: [...DeviceEvents['pin_on_device_complete']]
1367
- ) => {
1368
- postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW, metadata));
1369
- };
1370
-
1371
1328
  const onSelectDeviceInBootloaderForWebDeviceHandler = async (
1372
1329
  ...[device, callback]: [...DeviceEvents['select_device_in_bootloader_for_web_device']]
1373
1330
  ) => {
@@ -470,7 +470,6 @@
470
470
  "MessageType_DeviceSessionAskPin": 61202,
471
471
  "MessageType_DeviceSessionAskPassphrase": 61203,
472
472
  "MessageType_PortfolioUpdate": 61400,
473
- "MessageType_NftUpdate": 61500,
474
473
  "MessageType_OnboardingStatusGet": 61600,
475
474
  "MessageType_OnboardingStatus": 61601
476
475
  },
@@ -12539,15 +12538,6 @@
12539
12538
  }
12540
12539
  }
12541
12540
  },
12542
- "NftUpdate": {
12543
- "fields": {
12544
- "file_name_no_ext": {
12545
- "rule": "required",
12546
- "type": "string",
12547
- "id": 1
12548
- }
12549
- }
12550
- },
12551
12541
  "OnboardingStep": {
12552
12542
  "values": {
12553
12543
  "ONBOARDING_STEP_UNKNOWN": 0,