@onekeyfe/hd-core 1.2.0-alpha.31 → 1.2.0-alpha.32

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 (124) hide show
  1. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +251 -0
  2. package/__tests__/connectSettings.test.ts +5 -47
  3. package/__tests__/device-state-mapper.test.ts +10 -1
  4. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +31 -59
  5. package/__tests__/networkUtils.test.ts +20 -0
  6. package/__tests__/open-wallet-session.test.ts +19 -5
  7. package/__tests__/protocol-v2-firmware-targets.test.ts +18 -0
  8. package/__tests__/protocol-v2.test.ts +58 -240
  9. package/__tests__/public-device-state-api.test.ts +10 -1
  10. package/dist/api/CheckAllFirmwareRelease.d.ts +24 -1
  11. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  12. package/dist/api/FirmwareUpdateV2.d.ts +0 -11
  13. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  14. package/dist/api/FirmwareUpdateV3.d.ts +3 -7
  15. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  16. package/dist/api/FirmwareUpdateV4.d.ts +6 -22
  17. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  18. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  19. package/dist/api/PromptWebDeviceAccess.d.ts.map +1 -1
  20. package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
  21. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  22. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -7
  23. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  24. package/dist/api/firmware/getBinary.d.ts +0 -7
  25. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  26. package/dist/api/firmware/updateBootloader.d.ts +0 -2
  27. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  28. package/dist/api/firmware/uploadFirmware.d.ts +1 -9
  29. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  30. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  31. package/dist/data-manager/DataManager.d.ts +0 -1
  32. package/dist/data-manager/DataManager.d.ts.map +1 -1
  33. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  34. package/dist/device/DeviceStateMapper.d.ts.map +1 -1
  35. package/dist/index.d.ts +43 -179
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1049 -2609
  38. package/dist/inject.d.ts.map +1 -1
  39. package/dist/lowLevelInject.d.ts.map +1 -1
  40. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  41. package/dist/topLevelInject.d.ts.map +1 -1
  42. package/dist/types/api/checkAllFirmwareRelease.d.ts +25 -7
  43. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  44. package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
  45. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  46. package/dist/types/api/export.d.ts +2 -4
  47. package/dist/types/api/export.d.ts.map +1 -1
  48. package/dist/types/api/firmwareUpdate.d.ts +0 -69
  49. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  50. package/dist/types/api/index.d.ts +3 -10
  51. package/dist/types/api/index.d.ts.map +1 -1
  52. package/dist/types/api/openWalletSession.d.ts +9 -3
  53. package/dist/types/api/openWalletSession.d.ts.map +1 -1
  54. package/dist/types/device.d.ts +6 -0
  55. package/dist/types/device.d.ts.map +1 -1
  56. package/dist/types/settings.d.ts +1 -13
  57. package/dist/types/settings.d.ts.map +1 -1
  58. package/dist/utils/networkUtils.d.ts +1 -0
  59. package/dist/utils/networkUtils.d.ts.map +1 -1
  60. package/package.json +4 -4
  61. package/src/api/CheckAllFirmwareRelease.ts +368 -50
  62. package/src/api/FirmwareUpdateV2.ts +120 -298
  63. package/src/api/FirmwareUpdateV3.ts +57 -263
  64. package/src/api/FirmwareUpdateV4.ts +328 -765
  65. package/src/api/OpenWalletSession.ts +12 -8
  66. package/src/api/PromptWebDeviceAccess.ts +2 -6
  67. package/src/api/device/DeviceUpdateBootloader.ts +6 -122
  68. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +0 -50
  69. package/src/api/firmware/updateBootloader.ts +4 -19
  70. package/src/api/firmware/uploadFirmware.ts +22 -140
  71. package/src/data/messages/messages-protocol-v2.json +4 -0
  72. package/src/data-manager/DataManager.ts +33 -33
  73. package/src/data-manager/connectSettings.ts +0 -11
  74. package/src/device/DeviceStateMapper.ts +6 -0
  75. package/src/index.ts +0 -5
  76. package/src/inject.ts +2 -22
  77. package/src/lowLevelInject.ts +1 -5
  78. package/src/protocols/protocol-v2/walletSession.ts +2 -1
  79. package/src/topLevelInject.ts +1 -5
  80. package/src/types/api/checkAllFirmwareRelease.ts +46 -7
  81. package/src/types/api/deviceUpdateBootloader.ts +0 -6
  82. package/src/types/api/export.ts +5 -18
  83. package/src/types/api/firmwareUpdate.ts +0 -76
  84. package/src/types/api/index.ts +6 -15
  85. package/src/types/api/openWalletSession.ts +12 -3
  86. package/src/types/device.ts +6 -0
  87. package/src/types/settings.ts +3 -13
  88. package/src/utils/networkUtils.ts +5 -3
  89. package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -174
  90. package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
  91. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
  92. package/__tests__/firmware-update/firmware-preparation-error.test.ts +0 -27
  93. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
  94. package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
  95. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -213
  96. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +0 -58
  97. package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
  98. package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
  99. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
  100. package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
  101. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
  102. package/dist/api/firmware/FirmwarePreparationError.d.ts +0 -3
  103. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +0 -1
  104. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
  105. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
  106. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -25
  107. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
  108. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -30
  109. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
  110. package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
  111. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
  112. package/dist/types/api/firmwareUpdatePlan.d.ts +0 -28
  113. package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
  114. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
  115. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
  116. package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
  117. package/src/api/firmware/FirmwareHostBinding.ts +0 -100
  118. package/src/api/firmware/FirmwarePreparationError.ts +0 -12
  119. package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
  120. package/src/api/firmware/FirmwareUpdatePlan.ts +0 -745
  121. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -392
  122. package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
  123. package/src/types/api/firmwareUpdatePlan.ts +0 -38
  124. package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
@@ -5,6 +5,7 @@ import { getProtocolV2WalletSession } from '../protocols/protocol-v2/walletSessi
5
5
  import { getPassphraseStateWithRefreshDeviceInfo } from '../utils/deviceFeaturesUtils';
6
6
  import { BaseMethod } from './BaseMethod';
7
7
  import { invalidParameter } from './helpers/paramsValidator';
8
+ import { OpenWalletSessionMode } from '../types/api/openWalletSession';
8
9
 
9
10
  import type {
10
11
  OpenWalletSessionParams,
@@ -44,9 +45,9 @@ const normalizeParams = (payload: Record<string, unknown>): OpenWalletSessionPar
44
45
  throw invalidParameter('Parameter [mode] is required.');
45
46
  }
46
47
  if (
47
- payload.mode !== 'standard' &&
48
- payload.mode !== 'select-hidden' &&
49
- payload.mode !== 'resume-hidden'
48
+ payload.mode !== OpenWalletSessionMode.Standard &&
49
+ payload.mode !== OpenWalletSessionMode.SelectHidden &&
50
+ payload.mode !== OpenWalletSessionMode.ResumeHidden
50
51
  ) {
51
52
  throw invalidParameter(
52
53
  'Parameter [mode] must be one of standard, select-hidden, or resume-hidden.'
@@ -57,7 +58,10 @@ const normalizeParams = (payload: Record<string, unknown>): OpenWalletSessionPar
57
58
  'Legacy parameters [useEmptyPassphrase] and [initSession] are not supported by openWalletSession.'
58
59
  );
59
60
  }
60
- if (payload.mode === 'standard' || payload.mode === 'select-hidden') {
61
+ if (
62
+ payload.mode === OpenWalletSessionMode.Standard ||
63
+ payload.mode === OpenWalletSessionMode.SelectHidden
64
+ ) {
61
65
  if (payload.deviceId !== undefined || payload.passphraseState !== undefined) {
62
66
  throw invalidParameter(
63
67
  'Parameters [deviceId] and [passphraseState] are only allowed with mode [resume-hidden].'
@@ -66,7 +70,7 @@ const normalizeParams = (payload: Record<string, unknown>): OpenWalletSessionPar
66
70
  return { mode: payload.mode };
67
71
  }
68
72
  return {
69
- mode: 'resume-hidden',
73
+ mode: OpenWalletSessionMode.ResumeHidden,
70
74
  deviceId: requiredString(payload.deviceId, 'deviceId'),
71
75
  passphraseState: requiredString(payload.passphraseState, 'passphraseState'),
72
76
  };
@@ -81,7 +85,7 @@ export default class OpenWalletSession extends BaseMethod<OpenWalletSessionParam
81
85
  this.useDevicePassphraseState = false;
82
86
  this.skipForceUpdateCheck = true;
83
87
  this.params = normalizeParams(this.payload as unknown as Record<string, unknown>);
84
- this.payload.useEmptyPassphrase = this.params.mode === 'standard';
88
+ this.payload.useEmptyPassphrase = this.params.mode === OpenWalletSessionMode.Standard;
85
89
  }
86
90
 
87
91
  async run(): Promise<OpenWalletSessionPayload> {
@@ -102,7 +106,7 @@ export default class OpenWalletSession extends BaseMethod<OpenWalletSessionParam
102
106
 
103
107
  const protocol = isProtocolV2 ? 'V2' : 'V1';
104
108
 
105
- if (this.params.mode === 'standard') {
109
+ if (this.params.mode === OpenWalletSessionMode.Standard) {
106
110
  this.device.passphraseState = undefined;
107
111
  const session = isProtocolV2
108
112
  ? await getProtocolV2WalletSession(this.device, { onlyMainPin: true })
@@ -129,7 +133,7 @@ export default class OpenWalletSession extends BaseMethod<OpenWalletSessionParam
129
133
  };
130
134
  }
131
135
 
132
- if (this.params.mode === 'resume-hidden') {
136
+ if (this.params.mode === OpenWalletSessionMode.ResumeHidden) {
133
137
  if (isProtocolV2) {
134
138
  if (this.device.features?.unlocked === false) {
135
139
  await this.device.unlockDevice();
@@ -52,13 +52,9 @@ export default class PromptWebDeviceAccess extends BaseMethod {
52
52
 
53
53
  if (isWebUsbEnv) {
54
54
  const usbDevice = device as USBDevice;
55
- let path = usbDevice.serialNumber ?? '';
55
+ const path = usbDevice.serialNumber;
56
56
  if (!path) {
57
- // Early Pro2 boards have no USB serial number. Re-enumeration assigns a
58
- // session-stable mock path, which is recovered by USBDevice identity here.
59
- const diff = await this.connector?.enumerate();
60
- const matched = diff?.descriptors?.find(d => (d as any).device === usbDevice);
61
- path = matched?.path ?? '';
57
+ throw ERRORS.TypedError(HardwareErrorCode.WebDevicePromptAccessError);
62
58
  }
63
59
  devicesDescriptor = [
64
60
  {
@@ -5,23 +5,15 @@ import { UI_REQUEST } from '../../constants/ui-request';
5
5
  import { FirmwareUpdateTipMessage } from '../../events/ui-request';
6
6
  import { FirmwareUpdateBaseMethod } from '../firmware/FirmwareUpdateBaseMethod';
7
7
  import { getSysResourceBinary } from '../firmware/getBinary';
8
- import { updateBootloader, updateBootloaderFromSource } from '../firmware/uploadFirmware';
8
+ import { updateBootloader } from '../firmware/uploadFirmware';
9
9
  import { DeviceModelToTypes } from '../../types';
10
10
  import { DataManager } from '../../data-manager';
11
- import { checkBootloaderLength, checkBootloaderSourceLength } from '../firmware/updateBootloader';
12
- import { openFirmwareByteSource } from '../firmware/FirmwareArtifactSource';
13
- import { resolveFirmwareUpdateHostBinding } from '../firmware/FirmwareHostBinding';
14
- import {
15
- assertFirmwareUpdatePreparedPlanBinding,
16
- assertFirmwareUpdatePreparedPlanDeviceIdentity,
17
- } from '../firmware/FirmwareUpdatePreparedPlan';
18
- import { getDeviceUUID } from '../../utils';
11
+ import { checkBootloaderLength } from '../firmware/updateBootloader';
19
12
 
20
13
  import type { DeviceUpdateBootloaderParams } from '../../types/api/deviceUpdateBootloader';
21
14
  import type { EFirmwareType } from '@onekeyfe/hd-shared';
22
15
  import type { Device } from '../../device/Device';
23
16
  import type { Features } from '../../types';
24
- import type { FirmwareByteSource } from '../firmware/FirmwareArtifactSource';
25
17
 
26
18
  export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any> {
27
19
  init() {
@@ -51,68 +43,17 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
51
43
  return true;
52
44
  }
53
45
 
54
- async updateBootloaderWithEmmcFileWriteFromSource(_device: Device, source: FirmwareByteSource) {
55
- const filePath = '0:boot/bootloader.bin';
56
-
57
- this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
58
- await this.emmcCommonUpdateProcessFromSource({
59
- source,
60
- filePath,
61
- });
62
- this.postTipMessage(FirmwareUpdateTipMessage.ConfirmOnDevice);
63
- await this.reboot(RebootType.Normal);
64
- this.postTipMessage(FirmwareUpdateTipMessage.UpdateBootloaderSuccess);
65
- return true;
66
- }
67
-
68
46
  async updateTouchBootloader({
69
47
  device,
70
48
  features,
71
49
  firmwareType,
72
- binary: preparedBinary,
73
- source: preparedSource,
74
50
  }: {
75
51
  device: Device;
76
52
  features?: Features;
77
53
  firmwareType: EFirmwareType;
78
- binary?: ArrayBuffer;
79
- source?: FirmwareByteSource;
80
54
  }) {
81
- if (preparedSource) {
82
- if (!(await checkBootloaderSourceLength(preparedSource))) {
83
- throw ERRORS.TypedError(HardwareErrorCode.CheckDownloadFileError);
84
- }
85
- if (features && device.isBootloader()) {
86
- this.postTipMessage(FirmwareUpdateTipMessage.UpdateBootloader);
87
- const result = await this.updateBootloaderWithEmmcFileWriteFromSource(
88
- device,
89
- preparedSource
90
- );
91
- return result;
92
- }
93
- if (features && !device.isBootloader()) {
94
- await updateBootloaderFromSource(
95
- this.device.getCommands().typedCall.bind(this.device.getCommands()),
96
- this.postMessage,
97
- device,
98
- preparedSource
99
- );
100
- return true;
101
- }
102
- }
103
-
104
- let binary = preparedBinary;
55
+ let { binary } = this.payload;
105
56
  if (!binary) {
106
- if (DataManager.getSettings('firmwareManifestMode') === 'external-only') {
107
- throw ERRORS.TypedError(
108
- HardwareErrorCode.RuntimeError,
109
- 'Bootloader must be prepared by the external firmware host',
110
- {
111
- firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
112
- artifactName: 'bootloader',
113
- }
114
- );
115
- }
116
57
  this.postTipMessage(FirmwareUpdateTipMessage.CheckLatestUiResource);
117
58
  const resourceUrl = features
118
59
  ? DataManager.getBootloaderResource(features, firmwareType)
@@ -127,7 +68,7 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
127
68
  }
128
69
  }
129
70
 
130
- if (!binary || !checkBootloaderLength(binary)) {
71
+ if (!checkBootloaderLength(binary)) {
131
72
  throw ERRORS.TypedError(HardwareErrorCode.CheckDownloadFileError);
132
73
  }
133
74
 
@@ -135,8 +76,7 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
135
76
  if (features && device.isBootloader()) {
136
77
  // Use emmcFileWrite + reboot logic for bootloader mode
137
78
  this.postTipMessage(FirmwareUpdateTipMessage.UpdateBootloader);
138
- const result = await this.updateBootloaderWithEmmcFileWrite(device, binary);
139
- return result;
79
+ return this.updateBootloaderWithEmmcFileWrite(device, binary);
140
80
  }
141
81
 
142
82
  if (features && !device.isBootloader()) {
@@ -156,69 +96,13 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
156
96
  const { features } = device;
157
97
 
158
98
  const payload = this.payload as DeviceUpdateBootloaderParams;
159
- const hostBinding = payload.artifact
160
- ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
161
- : undefined;
162
- const executionParams = {
163
- ...payload,
164
- artifactReader: hostBinding?.artifactReader ?? payload.artifactReader,
165
- };
166
- if (payload.artifact) {
167
- assertFirmwareUpdatePreparedPlanDeviceIdentity({
168
- preparedPlan: payload.preparedPlan,
169
- deviceIdentity: getDeviceUUID(features) || undefined,
170
- });
171
- assertFirmwareUpdatePreparedPlanBinding({
172
- preparedPlan: payload.preparedPlan,
173
- executor: 'v2',
174
- scopeTargets: ['bootloader'],
175
- bindings: [
176
- {
177
- target: 'bootloader',
178
- artifact: payload.artifact,
179
- },
180
- ],
181
- });
182
- const source = await openFirmwareByteSource({
183
- artifact: payload.artifact,
184
- reader: executionParams.artifactReader,
185
- });
186
- if (!source) {
187
- throw ERRORS.TypedError(
188
- HardwareErrorCode.RuntimeError,
189
- 'Bootloader artifact is not prepared'
190
- );
191
- }
192
- try {
193
- const deviceType = device.getCurrentDeviceType();
194
- const deviceFirmwareType = device.getCurrentFirmwareType();
195
- const firmwareType = payload.firmwareType ?? deviceFirmwareType;
196
- if (DeviceModelToTypes.model_touch.includes(deviceType)) {
197
- return await this.updateTouchBootloader({
198
- device,
199
- features,
200
- firmwareType,
201
- source,
202
- });
203
- }
204
- return true;
205
- } finally {
206
- await source.close();
207
- }
208
- }
209
99
 
210
- const { binary } = payload;
211
100
  const deviceType = device.getCurrentDeviceType();
212
101
  const deviceFirmwareType = device.getCurrentFirmwareType();
213
102
  const firmwareType = payload.firmwareType ?? deviceFirmwareType;
214
103
 
215
104
  if (DeviceModelToTypes.model_touch.includes(deviceType)) {
216
- return this.updateTouchBootloader({
217
- device,
218
- features,
219
- firmwareType,
220
- binary,
221
- });
105
+ return this.updateTouchBootloader({ device, features, firmwareType });
222
106
  }
223
107
 
224
108
  return Promise.resolve(true);
@@ -14,7 +14,6 @@ import { DataManager } from '../../data-manager';
14
14
  import { BaseMethod } from '../BaseMethod';
15
15
  import { DEVICE } from '../../events';
16
16
  import { createFirmwareProgressThrottle } from './progressThrottle';
17
- import { writeFirmwareByteSource } from './FirmwareArtifactSource';
18
17
 
19
18
  import type {
20
19
  IFirmwareUpdateProgressType,
@@ -25,7 +24,6 @@ import type { RebootType } from '@onekeyfe/hd-transport';
25
24
  import type { Deferred } from '@onekeyfe/hd-shared';
26
25
  import type { KnownDevice } from '../../types';
27
26
  import type { TypedResponseMessage } from '../../device/DeviceCommands';
28
- import type { FirmwareByteSource } from './FirmwareArtifactSource';
29
27
 
30
28
  const Log = getLogger(LoggerNames.Method);
31
29
  const SESSION_ERROR = 'session not found';
@@ -389,54 +387,6 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
389
387
  return totalSize !== undefined ? (processedSize ?? 0) + payload.byteLength : 0;
390
388
  }
391
389
 
392
- async emmcCommonUpdateProcessFromSource({
393
- source,
394
- filePath,
395
- processedSize,
396
- totalSize,
397
- }: {
398
- source: FirmwareByteSource;
399
- filePath: string;
400
- processedSize?: number;
401
- totalSize?: number;
402
- }) {
403
- if (!filePath.startsWith('0:')) {
404
- throw new Error('filePath must start with 0:');
405
- }
406
- const env = DataManager.getSettings('env');
407
- const chunkSize = 1024 * (DataManager.isBleConnect(env) ? 16 : 128);
408
-
409
- await writeFirmwareByteSource({
410
- source,
411
- chunkSize,
412
- write: async ({ data, sourceOffset, length, first }) => {
413
- const progress =
414
- totalSize !== undefined && processedSize !== undefined
415
- ? Math.min(Math.ceil(((processedSize + sourceOffset + length) / totalSize) * 100), 99)
416
- : Math.min(Math.ceil(((sourceOffset + length) / source.size) * 100), 99);
417
- const writeRes = await this.emmcFileWriteWithRetry(
418
- filePath,
419
- length,
420
- sourceOffset,
421
- data,
422
- first,
423
- progress
424
- );
425
- if (!writeRes) {
426
- throw ERRORS.TypedError(
427
- HardwareErrorCode.EmmcFileWriteFirmwareError,
428
- 'transfer data error'
429
- );
430
- }
431
- const processedBytes = Number(writeRes.message.processed_byte);
432
- this.postProgressMessage(progress, 'transferData');
433
- return Number.isFinite(processedBytes) ? processedBytes : length;
434
- },
435
- });
436
-
437
- return totalSize !== undefined ? (processedSize ?? 0) + source.size : 0;
438
- }
439
-
440
390
  async emmcFileWriteWithRetry(
441
391
  filePath: string,
442
392
  chunkLength: number,
@@ -8,7 +8,6 @@ import { shouldUpdateBootloaderForClassicAndMini } from './bootloaderHelper';
8
8
 
9
9
  import type { Features } from '../../types';
10
10
  import type { EFirmwareType } from '@onekeyfe/hd-shared';
11
- import type { FirmwareByteSource } from './FirmwareArtifactSource';
12
11
 
13
12
  export function checkNeedUpdateBootForTouch(features: Features, firmwareType: EFirmwareType) {
14
13
  const deviceType = getDeviceType(features);
@@ -63,7 +62,8 @@ export function checkNeedUpdateBootForClassicAndMini({
63
62
  }
64
63
 
65
64
  const INIT_DATA_CHUNK_SIZE = 16 * 1024;
66
- const readBootloaderLength = (chunk: Uint8Array) => {
65
+ export function checkBootloaderLength(data: ArrayBuffer) {
66
+ const chunk = new Uint8Array(data.slice(0, Math.min(INIT_DATA_CHUNK_SIZE, data.byteLength)));
67
67
  const buffer = ByteBuffer.wrap(chunk, undefined, undefined, true);
68
68
  buffer.LE();
69
69
  // byte 'O', 'K', 'T', 'B'
@@ -77,21 +77,6 @@ const readBootloaderLength = (chunk: Uint8Array) => {
77
77
  buffer.readUint32();
78
78
  // codelen
79
79
  const codelen = buffer.readUint32();
80
- return hdrlen + codelen;
81
- };
82
-
83
- export function checkBootloaderLength(data: ArrayBuffer) {
84
- if (data.byteLength < 16) {
85
- return false;
86
- }
87
- const chunk = new Uint8Array(data.slice(0, Math.min(INIT_DATA_CHUNK_SIZE, data.byteLength)));
88
- return readBootloaderLength(chunk) === data.byteLength;
80
+ const bootloaderLength = hdrlen + codelen;
81
+ return bootloaderLength === data.byteLength;
89
82
  }
90
-
91
- export const checkBootloaderSourceLength = async (source: FirmwareByteSource) => {
92
- if (source.size < 16) {
93
- return false;
94
- }
95
- const chunk = new Uint8Array(await source.readAt(0, Math.min(INIT_DATA_CHUNK_SIZE, source.size)));
96
- return readBootloaderLength(chunk) === source.size;
97
- };
@@ -10,7 +10,6 @@ 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';
14
13
 
15
14
  import type { KnownDevice } from '../../types';
16
15
  import type { TypedCall, TypedResponseMessage } from '../../device/DeviceCommands';
@@ -18,7 +17,6 @@ import type { PROTO } from '../../constants';
18
17
  import type { CoreMessage, IFirmwareUpdateProgressType } from '../../events';
19
18
  import type { Success } from '@onekeyfe/hd-transport';
20
19
  import type { Device } from '../../device/Device';
21
- import type { FirmwareByteSource } from './FirmwareArtifactSource';
22
20
 
23
21
  const NEW_BOOT_UPRATE_FIRMWARE_VERSION = '2.4.5';
24
22
  const SESSION_ERROR = 'session not found';
@@ -90,20 +88,17 @@ export const waitBleInstall = async (updateType: string) => {
90
88
  }
91
89
  };
92
90
 
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 (
91
+ export const uploadFirmware = async (
101
92
  updateType: 'firmware' | 'ble',
102
93
  typedCall: TypedCall,
103
94
  postMessage: (message: CoreMessage) => void,
104
95
  device: Device,
105
- source: FirmwareByteSource,
106
- rebootOnSuccess?: boolean,
96
+ {
97
+ payload,
98
+ rebootOnSuccess,
99
+ }: PROTO.FirmwareUpload & {
100
+ rebootOnSuccess?: boolean;
101
+ },
107
102
  isUpdateBootloader?: boolean
108
103
  ) => {
109
104
  const deviceType = device.getCurrentDeviceType();
@@ -124,20 +119,20 @@ export const uploadFirmwareFromSource = async (
124
119
  if (supportUpgradeFileHeader) {
125
120
  // Extract and validate firmware header (first 1KB)
126
121
  const HEADER_SIZE = 1024;
127
- if (source.size < HEADER_SIZE) {
122
+ if (payload.byteLength < HEADER_SIZE) {
128
123
  throw ERRORS.TypedError(
129
124
  HardwareErrorCode.RuntimeError,
130
- `firmware payload too small: ${source.size} bytes, expected at least ${HEADER_SIZE} bytes`
125
+ `firmware payload too small: ${payload.byteLength} bytes, expected at least ${HEADER_SIZE} bytes`
131
126
  );
132
127
  }
133
128
 
134
129
  Log.debug('Uploading firmware header:', {
135
130
  size: HEADER_SIZE,
136
- totalSize: source.size,
131
+ totalSize: payload.byteLength,
137
132
  });
138
133
  postProgressTip(device, 'UploadingFirmwareHeader', postMessage);
139
134
 
140
- const header = new Uint8Array(await source.readAt(0, HEADER_SIZE));
135
+ const header = new Uint8Array(payload.slice(0, HEADER_SIZE));
141
136
 
142
137
  try {
143
138
  const headerRes = await typedCall('UpgradeFileHeader', 'Success', {
@@ -174,9 +169,6 @@ export const uploadFirmwareFromSource = async (
174
169
  postProgressMessage(device, 0, 'installingFirmware', postMessage);
175
170
  let updateResponse: TypedResponseMessage<'Success'>;
176
171
  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);
180
172
  updateResponse = await typedCall('FirmwareUpload', 'Success', {
181
173
  payload,
182
174
  });
@@ -208,7 +200,9 @@ export const uploadFirmwareFromSource = async (
208
200
  updateType,
209
201
  postMessage,
210
202
  device,
211
- source,
203
+ {
204
+ payload,
205
+ },
212
206
  rebootOnSuccess
213
207
  );
214
208
  return response.message;
@@ -217,7 +211,7 @@ export const uploadFirmwareFromSource = async (
217
211
 
218
212
  postConfirmationMessage(device);
219
213
  postProgressTip(device, 'ConfirmOnDevice', postMessage);
220
- const length = source.size;
214
+ const length = payload.byteLength;
221
215
 
222
216
  let response = await typedCall('FirmwareErase', ['FirmwareRequest', 'Success'], { length });
223
217
  postProgressTip(device, 'FirmwareEraseSuccess', postMessage);
@@ -226,7 +220,7 @@ export const uploadFirmwareFromSource = async (
226
220
  const start = response.message.offset!;
227
221
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
228
222
  const end = response.message.offset! + response.message.length!;
229
- const chunk = await source.readAt(start, end - start);
223
+ const chunk = payload.slice(start, end);
230
224
 
231
225
  if (start > 0) {
232
226
  postProgressMessage(
@@ -255,45 +249,11 @@ export const uploadFirmwareFromSource = async (
255
249
  throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'uploadFirmware: unknown device model');
256
250
  };
257
251
 
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
-
292
252
  const newTouchUpdateProcess = async (
293
253
  updateType: 'firmware' | 'ble',
294
254
  postMessage: (message: CoreMessage) => void,
295
255
  device: Device,
296
- source: FirmwareByteSource,
256
+ { payload }: PROTO.FirmwareUpload,
297
257
  rebootOnSuccess = true
298
258
  ) => {
299
259
  let typedCall = device.getCommands().typedCall.bind(device.getCommands());
@@ -303,13 +263,13 @@ const newTouchUpdateProcess = async (
303
263
  const env = DataManager.getSettings('env');
304
264
  const perPackageSize = DataManager.isBleConnect(env) ? 16 : 128;
305
265
  const chunkSize = 1024 * perPackageSize;
306
- const totalChunks = Math.ceil(source.size / chunkSize);
266
+ const totalChunks = Math.ceil(payload.byteLength / chunkSize);
307
267
  let offset = 0;
308
268
  for (let i = 0; i < totalChunks; i++) {
309
269
  const chunkStart = i * chunkSize;
310
- const chunkEnd = Math.min(chunkStart + chunkSize, source.size);
270
+ const chunkEnd = Math.min(chunkStart + chunkSize, payload.byteLength);
311
271
  const chunkLength = chunkEnd - chunkStart;
312
- const chunk = await source.readAt(chunkStart, chunkLength);
272
+ const chunk = payload.slice(chunkStart, chunkEnd);
313
273
  const overwrite = i === 0;
314
274
  const progress = Math.round(((i + 1) / totalChunks) * 100);
315
275
  const writeRes = await emmcFileWriteWithRetry(
@@ -530,67 +490,6 @@ export const updateResource = async (
530
490
  return processResourceRequest(typedCall, res, data);
531
491
  };
532
492
 
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
-
594
493
  export const updateResources = async (
595
494
  typedCall: TypedCall,
596
495
  postMessage: (message: CoreMessage) => void,
@@ -625,28 +524,11 @@ export const updateBootloader = async (
625
524
  typedCall: TypedCall,
626
525
  postMessage: (message: CoreMessage) => void,
627
526
  device: Device,
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
527
+ source: ArrayBuffer
646
528
  ) => {
647
529
  postProgressTip(device, 'UpdateBootloader', postMessage);
648
530
  postProgressMessage(device, Math.floor(0), 'installingFirmware', postMessage);
649
- await updateResourceFromSource(typedCall, 'bootloader.bin', source, () => {
531
+ await updateResource(typedCall, 'bootloader.bin', source, () => {
650
532
  postProcessingMessage('resource', postMessage);
651
533
  });
652
534
  postProgressMessage(device, Math.floor(100), 'installingFirmware', postMessage);
@@ -12513,6 +12513,10 @@
12513
12513
  "passphrase": {
12514
12514
  "type": "string",
12515
12515
  "id": 1
12516
+ },
12517
+ "on_device": {
12518
+ "type": "bool",
12519
+ "id": 2
12516
12520
  }
12517
12521
  }
12518
12522
  },