@onekeyfe/hd-core 1.2.0-alpha.22 → 1.2.0-alpha.24
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.
- package/__tests__/DeviceCommands.test.ts +43 -8
- package/__tests__/connectSettings.test.ts +5 -47
- package/__tests__/device-lifecycle-events.test.ts +59 -0
- package/__tests__/device-settings.test.ts +1 -1
- package/__tests__/device-wallet-session-store.test.ts +41 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +30 -39
- package/__tests__/logBlockEvent.test.ts +17 -0
- package/__tests__/open-wallet-session.test.ts +233 -111
- package/__tests__/protocol-v2-ping.test.ts +28 -0
- package/__tests__/protocol-v2.test.ts +513 -313
- package/__tests__/public-pro2-api-boundary.test.ts +22 -0
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +0 -11
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts +3 -7
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +5 -21
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts +1 -8
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/device/DeviceWipe.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -7
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +0 -7
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/updateBootloader.d.ts +0 -2
- package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts +1 -9
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/Ping.d.ts +2 -0
- package/dist/api/protocol-v2/Ping.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +0 -1
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/connectSettings.d.ts.map +1 -1
- package/dist/device/Device.d.ts +3 -2
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/events/device.d.ts +1 -0
- package/dist/events/device.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +1 -0
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +98 -278
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +876 -2647
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockRetry.d.ts +2 -3
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +12 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +0 -3
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +1 -4
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +0 -69
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/getPassphraseState.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +4 -10
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/openWalletSession.d.ts +0 -12
- package/dist/types/api/openWalletSession.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +4 -0
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/settings.d.ts +0 -13
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +3 -16
- package/src/api/FirmwareUpdateV2.ts +119 -284
- package/src/api/FirmwareUpdateV3.ts +55 -248
- package/src/api/FirmwareUpdateV4.ts +293 -751
- package/src/api/GetPassphraseState.ts +11 -5
- package/src/api/OpenWalletSession.ts +23 -86
- package/src/api/device/DeviceUpdateBootloader.ts +6 -114
- package/src/api/device/DeviceWipe.ts +2 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +0 -50
- package/src/api/firmware/updateBootloader.ts +4 -19
- package/src/api/firmware/uploadFirmware.ts +22 -140
- package/src/api/index.ts +1 -0
- package/src/api/protocol-v2/Ping.ts +32 -1
- package/src/core/index.ts +40 -7
- package/src/data/messages/messages-protocol-v2.json +49 -56
- package/src/data-manager/DataManager.ts +33 -33
- package/src/data-manager/connectSettings.ts +0 -11
- package/src/device/Device.ts +29 -8
- package/src/device/DeviceCommands.ts +43 -151
- package/src/events/device.ts +1 -0
- package/src/events/logBlockEvent.ts +1 -15
- package/src/events/ui-request.ts +1 -0
- package/src/index.ts +0 -5
- package/src/inject.ts +4 -22
- package/src/lowLevelInject.ts +1 -5
- package/src/protocols/protocol-v2/deviceSession.ts +1 -1
- package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +0 -1
- package/src/protocols/protocol-v2/unlockRetry.ts +20 -3
- package/src/protocols/protocol-v2/walletSession.ts +57 -18
- package/src/topLevelInject.ts +1 -5
- package/src/types/api/checkAllFirmwareRelease.ts +0 -3
- package/src/types/api/deviceUpdateBootloader.ts +0 -6
- package/src/types/api/export.ts +0 -18
- package/src/types/api/firmwareUpdate.ts +0 -76
- package/src/types/api/getPassphraseState.ts +4 -3
- package/src/types/api/index.ts +3 -14
- package/src/types/api/openWalletSession.ts +0 -19
- package/src/types/api/protocolV2.ts +10 -0
- package/src/types/settings.ts +0 -13
- package/src/utils/deviceInfoUtils.ts +2 -3
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
- package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
- package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
- package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -326
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -200
- package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
- package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -26
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -24
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -25
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
- package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdatePlan.d.ts +0 -27
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
- package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
- package/src/api/firmware/FirmwareHostBinding.ts +0 -100
- package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
- package/src/api/firmware/FirmwareUpdatePlan.ts +0 -621
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -378
- package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
- package/src/types/api/firmwareUpdatePlan.ts +0 -36
- package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
|
@@ -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
|
|
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
|
-
|
|
106
|
-
|
|
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 (
|
|
122
|
+
if (payload.byteLength < HEADER_SIZE) {
|
|
128
123
|
throw ERRORS.TypedError(
|
|
129
124
|
HardwareErrorCode.RuntimeError,
|
|
130
|
-
`firmware payload too small: ${
|
|
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:
|
|
131
|
+
totalSize: payload.byteLength,
|
|
137
132
|
});
|
|
138
133
|
postProgressTip(device, 'UploadingFirmwareHeader', postMessage);
|
|
139
134
|
|
|
140
|
-
const header = new Uint8Array(
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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(
|
|
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,
|
|
270
|
+
const chunkEnd = Math.min(chunkStart + chunkSize, payload.byteLength);
|
|
311
271
|
const chunkLength = chunkEnd - chunkStart;
|
|
312
|
-
const chunk =
|
|
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
|
-
|
|
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
|
|
531
|
+
await updateResource(typedCall, 'bootloader.bin', source, () => {
|
|
650
532
|
postProcessingMessage('resource', postMessage);
|
|
651
533
|
});
|
|
652
534
|
postProgressMessage(device, Math.floor(100), 'installingFirmware', postMessage);
|
package/src/api/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as testInitializeDeviceDuration } from './test/TestInitializeDeviceDuration';
|
|
2
|
+
export { default as testProtocolV2Ping } from './protocol-v2/Ping';
|
|
2
3
|
export { default as preInitialize } from './device/PreInitialize';
|
|
3
4
|
|
|
4
5
|
export { default as searchDevices } from './SearchDevices';
|
|
@@ -1,12 +1,43 @@
|
|
|
1
|
+
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
1
3
|
import { BaseMethod } from '../BaseMethod';
|
|
2
4
|
|
|
5
|
+
// nanopb max_size:64 includes the terminating NUL for string fields.
|
|
6
|
+
export const PROTOCOL_V2_PING_MAX_MESSAGE_BYTES = 63;
|
|
7
|
+
|
|
8
|
+
const getUtf8ByteLength = (value: string) =>
|
|
9
|
+
Array.from(value).reduce((length, character) => {
|
|
10
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
11
|
+
if (codePoint <= 0x7f) return length + 1;
|
|
12
|
+
if (codePoint <= 0x7ff) return length + 2;
|
|
13
|
+
if (codePoint <= 0xffff) return length + 3;
|
|
14
|
+
return length + 4;
|
|
15
|
+
}, 0);
|
|
16
|
+
|
|
17
|
+
export function validateProtocolV2PingMessage(value: unknown): string {
|
|
18
|
+
if (value !== undefined && typeof value !== 'string') {
|
|
19
|
+
throw ERRORS.TypedError(
|
|
20
|
+
HardwareErrorCode.CallMethodInvalidParameter,
|
|
21
|
+
'Protocol V2 Ping message must be a string.'
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
const message = value ?? '';
|
|
25
|
+
if (getUtf8ByteLength(message) > PROTOCOL_V2_PING_MAX_MESSAGE_BYTES) {
|
|
26
|
+
throw ERRORS.TypedError(
|
|
27
|
+
HardwareErrorCode.CallMethodInvalidParameter,
|
|
28
|
+
`Protocol V2 Ping message must not exceed ${PROTOCOL_V2_PING_MAX_MESSAGE_BYTES} UTF-8 bytes.`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return message;
|
|
32
|
+
}
|
|
33
|
+
|
|
3
34
|
export default class Ping extends BaseMethod<{ message?: string }> {
|
|
4
35
|
init() {
|
|
5
36
|
// Protocol V2 (Pro2) only; Core rejects non-V2 devices.
|
|
6
37
|
this.requireProtocolV2 = true;
|
|
7
38
|
this.skipForceUpdateCheck = true;
|
|
8
39
|
this.useDevicePassphraseState = false;
|
|
9
|
-
this.params = { message: this.payload.message };
|
|
40
|
+
this.params = { message: validateProtocolV2PingMessage(this.payload.message) };
|
|
10
41
|
}
|
|
11
42
|
|
|
12
43
|
async run() {
|
package/src/core/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import semver from 'semver';
|
|
2
2
|
import EventEmitter from 'events';
|
|
3
|
+
import { TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
|
|
3
4
|
import {
|
|
4
5
|
ERRORS,
|
|
5
6
|
ERROR_CODES_REQUIRE_RELEASE,
|
|
@@ -70,7 +71,11 @@ import type { CoreMessage, IFrameCallMessage, UiPromise, UiPromiseResponse } fro
|
|
|
70
71
|
import type { DeviceEvents, InitOptions, RunOptions } from '../device/Device';
|
|
71
72
|
import type { SdkTracingContext } from '../utils/tracing';
|
|
72
73
|
import type { Deferred } from '@onekeyfe/hd-shared';
|
|
73
|
-
import type {
|
|
74
|
+
import type {
|
|
75
|
+
LowlevelTransportSharedPlugin,
|
|
76
|
+
OneKeyDeviceInfo,
|
|
77
|
+
TransportDeviceDisconnectEvent,
|
|
78
|
+
} from '@onekeyfe/hd-transport';
|
|
74
79
|
import type { BaseMethod } from '../api/BaseMethod';
|
|
75
80
|
|
|
76
81
|
const Log = getLogger(LoggerNames.Core);
|
|
@@ -173,8 +178,6 @@ export const callAPI = async (context: CoreContext, message: CoreMessage) => {
|
|
|
173
178
|
return createResponseMessage(method?.responseID ?? message.id, false, { error });
|
|
174
179
|
}
|
|
175
180
|
|
|
176
|
-
DevicePool.emitter.on(DEVICE.CONNECT, onDeviceConnectHandler);
|
|
177
|
-
|
|
178
181
|
if (!method.useDevice) {
|
|
179
182
|
updateMethodRequestContext(method, { status: 'running' });
|
|
180
183
|
try {
|
|
@@ -236,7 +239,6 @@ const handlePreWarmSignal = async (
|
|
|
236
239
|
method: BaseMethod
|
|
237
240
|
): Promise<any> => {
|
|
238
241
|
const createAckResponse = () => {
|
|
239
|
-
DevicePool.emitter.removeListener(DEVICE.CONNECT, onDeviceConnectHandler);
|
|
240
242
|
completeMethodRequestContext(method);
|
|
241
243
|
method.dispose();
|
|
242
244
|
return createResponseMessage(method.responseID, true, true);
|
|
@@ -874,8 +876,15 @@ function isRetryableBleProtocolV2ProbeError(method: BaseMethod, error: unknown)
|
|
|
874
876
|
*/
|
|
875
877
|
async function connectDeviceForBle(method: BaseMethod, device: Device, retryCount = 0) {
|
|
876
878
|
try {
|
|
877
|
-
|
|
879
|
+
const shouldAcquire =
|
|
880
|
+
!device.hasDeviceAcquire() || !device.commands || device.commands.disposed;
|
|
881
|
+
if (shouldAcquire) {
|
|
882
|
+
await device.acquire(method.payload.connectProtocol);
|
|
883
|
+
}
|
|
878
884
|
if (method.payload?.onlyConnectBleDevice) {
|
|
885
|
+
if (shouldAcquire) {
|
|
886
|
+
DevicePool.emitter.emit(DEVICE.CONNECT, device);
|
|
887
|
+
}
|
|
879
888
|
return;
|
|
880
889
|
}
|
|
881
890
|
// Skip initialize if conditions are met
|
|
@@ -886,6 +895,9 @@ async function connectDeviceForBle(method: BaseMethod, device: Device, retryCoun
|
|
|
886
895
|
passphraseState: initOptions.passphraseState,
|
|
887
896
|
});
|
|
888
897
|
}
|
|
898
|
+
if (shouldAcquire) {
|
|
899
|
+
DevicePool.emitter.emit(DEVICE.CONNECT, device);
|
|
900
|
+
}
|
|
889
901
|
} catch (err) {
|
|
890
902
|
if (
|
|
891
903
|
(err.errorCode === HardwareErrorCode.BleTimeoutError ||
|
|
@@ -1186,8 +1198,6 @@ const cleanup = () => {
|
|
|
1186
1198
|
|
|
1187
1199
|
const removeDeviceListener = (device: Device) => {
|
|
1188
1200
|
device.removeAllListeners();
|
|
1189
|
-
DevicePool.emitter.removeAllListeners(DEVICE.CONNECT);
|
|
1190
|
-
// DevicePool.emitter.removeListener(DEVICE.DISCONNECT, onDeviceDisconnectHandler);
|
|
1191
1201
|
};
|
|
1192
1202
|
|
|
1193
1203
|
/**
|
|
@@ -1210,6 +1220,20 @@ const onDeviceDisconnectHandler = (device: Device) => {
|
|
|
1210
1220
|
postMessage(createDeviceMessage(DEVICE.DISCONNECT, { device: deviceObject }));
|
|
1211
1221
|
};
|
|
1212
1222
|
|
|
1223
|
+
const onTransportDeviceDisconnectHandler = (event: TransportDeviceDisconnectEvent) => {
|
|
1224
|
+
const device =
|
|
1225
|
+
deviceCacheMap.get(event.connectId) ??
|
|
1226
|
+
DevicePool.devicesCache[event.connectId] ??
|
|
1227
|
+
DevicePool.getDeviceByPath(event.connectId);
|
|
1228
|
+
if (!device) {
|
|
1229
|
+
Log.debug('Ignoring transport disconnect for an unknown device:', event.connectId);
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
device.markTransportDisconnected();
|
|
1234
|
+
DevicePool.emitter.emit(DEVICE.DISCONNECT, device);
|
|
1235
|
+
};
|
|
1236
|
+
|
|
1213
1237
|
const onDevicePinHandler = async (...[device, type, callback]: DeviceEvents['pin']) => {
|
|
1214
1238
|
Log.log('request Input PIN');
|
|
1215
1239
|
// create ui promise
|
|
@@ -1262,6 +1286,7 @@ const onDevicePassphraseHandler = async (
|
|
|
1262
1286
|
device: device.toMessageObject() as KnownDevice,
|
|
1263
1287
|
passphraseState: device.passphraseState,
|
|
1264
1288
|
existsAttachPinUser: requestPayload.existsAttachPinUser,
|
|
1289
|
+
deviceOnly: requestPayload.deviceOnly,
|
|
1265
1290
|
source: requestPayload.source,
|
|
1266
1291
|
reason: requestPayload.reason,
|
|
1267
1292
|
expectedPassphraseState: requestPayload.expectedPassphraseState,
|
|
@@ -1527,7 +1552,15 @@ export const initCore = () => {
|
|
|
1527
1552
|
|
|
1528
1553
|
export const initConnector = () => {
|
|
1529
1554
|
_connector = new DeviceConnector();
|
|
1555
|
+
DevicePool.emitter.removeListener(DEVICE.CONNECT, onDeviceConnectHandler);
|
|
1556
|
+
DevicePool.emitter.removeListener(DEVICE.DISCONNECT, onDeviceDisconnectHandler);
|
|
1557
|
+
DevicePool.emitter.removeListener(
|
|
1558
|
+
TRANSPORT_EVENT.DEVICE_DISCONNECT,
|
|
1559
|
+
onTransportDeviceDisconnectHandler
|
|
1560
|
+
);
|
|
1561
|
+
DevicePool.emitter.on(DEVICE.CONNECT, onDeviceConnectHandler);
|
|
1530
1562
|
DevicePool.emitter.on(DEVICE.DISCONNECT, onDeviceDisconnectHandler);
|
|
1563
|
+
DevicePool.emitter.on(TRANSPORT_EVENT.DEVICE_DISCONNECT, onTransportDeviceDisconnectHandler);
|
|
1531
1564
|
return _connector;
|
|
1532
1565
|
};
|
|
1533
1566
|
|
|
@@ -482,9 +482,10 @@
|
|
|
482
482
|
"MessageType_DeviceStatus": 60603,
|
|
483
483
|
"MessageType_DevGetOnboardingStatus": 60604,
|
|
484
484
|
"MessageType_DevOnboardingStatus": 60605,
|
|
485
|
+
"MessageType_DeviceSessionGet": 60606,
|
|
485
486
|
"MessageType_DeviceSession": 60607,
|
|
486
487
|
"MessageType_DeviceSessionAskPin": 60608,
|
|
487
|
-
"
|
|
488
|
+
"MessageType_DeviceSessionAskPassphrase": 60609,
|
|
488
489
|
"MessageType_FilesystemPermissionFix": 60800,
|
|
489
490
|
"MessageType_FilesystemPathInfo": 60801,
|
|
490
491
|
"MessageType_FilesystemPathInfoQuery": 60802,
|
|
@@ -506,8 +507,7 @@
|
|
|
506
507
|
[90, 92],
|
|
507
508
|
[114, 122],
|
|
508
509
|
[300, 304],
|
|
509
|
-
[309, 312]
|
|
510
|
-
[60606, 60606]
|
|
510
|
+
[309, 312]
|
|
511
511
|
]
|
|
512
512
|
},
|
|
513
513
|
"AlephiumGetAddress": {
|
|
@@ -11506,6 +11506,33 @@
|
|
|
11506
11506
|
}
|
|
11507
11507
|
}
|
|
11508
11508
|
},
|
|
11509
|
+
"UiAnimationType": {
|
|
11510
|
+
"values": {
|
|
11511
|
+
"Unknown": 0,
|
|
11512
|
+
"Signing": 1
|
|
11513
|
+
}
|
|
11514
|
+
},
|
|
11515
|
+
"UiAnimationCommand": {
|
|
11516
|
+
"values": {
|
|
11517
|
+
"CommandUnknown": 0,
|
|
11518
|
+
"Start": 1,
|
|
11519
|
+
"Stop": 2,
|
|
11520
|
+
"Refresh": 3
|
|
11521
|
+
}
|
|
11522
|
+
},
|
|
11523
|
+
"UiAnimationRequest": {
|
|
11524
|
+
"fields": {
|
|
11525
|
+
"command": {
|
|
11526
|
+
"rule": "required",
|
|
11527
|
+
"type": "UiAnimationCommand",
|
|
11528
|
+
"id": 1
|
|
11529
|
+
},
|
|
11530
|
+
"type": {
|
|
11531
|
+
"type": "UiAnimationType",
|
|
11532
|
+
"id": 2
|
|
11533
|
+
}
|
|
11534
|
+
}
|
|
11535
|
+
},
|
|
11509
11536
|
"ViewAmount": {
|
|
11510
11537
|
"fields": {
|
|
11511
11538
|
"is_unlimited": {
|
|
@@ -12446,83 +12473,49 @@
|
|
|
12446
12473
|
"DeviceSessionError_Busy": 5
|
|
12447
12474
|
}
|
|
12448
12475
|
},
|
|
12449
|
-
"
|
|
12476
|
+
"DeviceSessionGet": {
|
|
12450
12477
|
"fields": {
|
|
12451
12478
|
"session_id": {
|
|
12452
|
-
"rule": "required",
|
|
12453
12479
|
"type": "bytes",
|
|
12454
12480
|
"id": 1
|
|
12455
12481
|
}
|
|
12456
12482
|
}
|
|
12457
12483
|
},
|
|
12458
|
-
"
|
|
12459
|
-
"fields": {
|
|
12460
|
-
"passphrase": {
|
|
12461
|
-
"rule": "required",
|
|
12462
|
-
"type": "string",
|
|
12463
|
-
"id": 1
|
|
12464
|
-
}
|
|
12465
|
-
}
|
|
12466
|
-
},
|
|
12467
|
-
"DeviceSessionPassphraseOnDevice": {
|
|
12468
|
-
"fields": {}
|
|
12469
|
-
},
|
|
12470
|
-
"DeviceSessionAttachPinOnDevice": {
|
|
12471
|
-
"fields": {}
|
|
12472
|
-
},
|
|
12473
|
-
"DeviceSessionSelect": {
|
|
12474
|
-
"oneofs": {
|
|
12475
|
-
"access": {
|
|
12476
|
-
"oneof": ["host_passphrase", "passphrase_on_device", "attach_pin_on_device"]
|
|
12477
|
-
}
|
|
12478
|
-
},
|
|
12484
|
+
"DeviceSession": {
|
|
12479
12485
|
"fields": {
|
|
12480
|
-
"
|
|
12481
|
-
"type": "
|
|
12486
|
+
"session_id": {
|
|
12487
|
+
"type": "bytes",
|
|
12482
12488
|
"id": 1
|
|
12483
12489
|
},
|
|
12484
|
-
"
|
|
12485
|
-
"type": "
|
|
12490
|
+
"btc_test_address": {
|
|
12491
|
+
"type": "string",
|
|
12486
12492
|
"id": 2
|
|
12487
|
-
},
|
|
12488
|
-
"attach_pin_on_device": {
|
|
12489
|
-
"type": "DeviceSessionAttachPinOnDevice",
|
|
12490
|
-
"id": 3
|
|
12491
12493
|
}
|
|
12492
12494
|
}
|
|
12493
12495
|
},
|
|
12494
|
-
"
|
|
12495
|
-
"
|
|
12496
|
-
"
|
|
12497
|
-
|
|
12498
|
-
|
|
12499
|
-
}
|
|
12496
|
+
"DeviceSessionPinType": {
|
|
12497
|
+
"values": {
|
|
12498
|
+
"Any": 1,
|
|
12499
|
+
"Main": 2,
|
|
12500
|
+
"AttachToPin": 3
|
|
12501
|
+
}
|
|
12502
|
+
},
|
|
12503
|
+
"DeviceSessionAskPin": {
|
|
12500
12504
|
"fields": {
|
|
12501
|
-
"
|
|
12502
|
-
"type": "
|
|
12505
|
+
"type": {
|
|
12506
|
+
"type": "DeviceSessionPinType",
|
|
12503
12507
|
"id": 1
|
|
12504
|
-
},
|
|
12505
|
-
"select": {
|
|
12506
|
-
"type": "DeviceSessionSelect",
|
|
12507
|
-
"id": 2
|
|
12508
12508
|
}
|
|
12509
12509
|
}
|
|
12510
12510
|
},
|
|
12511
|
-
"
|
|
12511
|
+
"DeviceSessionAskPassphrase": {
|
|
12512
12512
|
"fields": {
|
|
12513
|
-
"
|
|
12514
|
-
"type": "bytes",
|
|
12515
|
-
"id": 1
|
|
12516
|
-
},
|
|
12517
|
-
"btc_test_address": {
|
|
12513
|
+
"passphrase": {
|
|
12518
12514
|
"type": "string",
|
|
12519
|
-
"id":
|
|
12515
|
+
"id": 1
|
|
12520
12516
|
}
|
|
12521
12517
|
}
|
|
12522
12518
|
},
|
|
12523
|
-
"DeviceSessionAskPin": {
|
|
12524
|
-
"fields": {}
|
|
12525
|
-
},
|
|
12526
12519
|
"DeviceSessionAskPin_FailureSubCodes": {
|
|
12527
12520
|
"values": {
|
|
12528
12521
|
"UserCancel": 1
|