@onekeyfe/hd-core 1.2.0-alpha.0 → 1.2.0-alpha.1
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__/protocol-v2.test.ts +147 -264
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +2 -2
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetDeviceInfo.d.ts.map +1 -1
- package/dist/api/GetFeatures.d.ts +1 -1
- package/dist/api/GetOnekeyFeatures.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts +4 -4
- package/dist/api/device/DeviceUnlock.d.ts +1 -1
- package/dist/api/firmware/bootloaderHelper.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/protocol-v2/helpers.d.ts +2 -3
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/constants/index.d.ts +2 -1
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/connectSettings.d.ts.map +1 -1
- package/dist/device/Device.d.ts +11 -15
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/deviceProfile/buildDeviceFeatures.d.ts +6 -0
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -0
- package/dist/deviceProfile/buildDeviceProfile.d.ts +3 -4
- package/dist/deviceProfile/buildDeviceProfile.d.ts.map +1 -1
- package/dist/deviceProfile/index.d.ts +1 -1
- package/dist/deviceProfile/index.d.ts.map +1 -1
- package/dist/index.d.ts +579 -502
- package/dist/index.js +881 -931
- package/dist/protocols/protocol-v2/features.d.ts +2 -2
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/types/api/getDeviceInfo.d.ts +2 -2
- package/dist/types/api/getDeviceInfo.d.ts.map +1 -1
- package/dist/types/api/getPassphraseState.d.ts +4 -4
- package/dist/types/api/getPassphraseState.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +3 -3
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts +87 -8
- package/dist/types/device.d.ts.map +1 -1
- package/dist/types/settings.d.ts +1 -0
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/capabilitieUtils.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
- package/dist/utils/findDefectiveBatchDevice.d.ts +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/FirmwareUpdateV2.ts +9 -2
- package/src/api/FirmwareUpdateV3.ts +2 -1
- package/src/api/FirmwareUpdateV4.ts +24 -31
- package/src/api/GetDeviceInfo.ts +6 -13
- package/src/api/GetOnekeyFeatures.ts +3 -14
- package/src/api/GetPassphraseState.ts +4 -4
- package/src/api/firmware/bootloaderHelper.ts +3 -2
- package/src/api/firmware/getBinary.ts +1 -1
- package/src/api/firmware/releaseHelper.ts +3 -3
- package/src/api/firmware/uploadFirmware.ts +5 -2
- package/src/api/protocol-v2/DeviceReboot.ts +3 -3
- package/src/api/protocol-v2/helpers.ts +1 -26
- package/src/constants/index.ts +10 -1
- package/src/core/index.ts +5 -7
- package/src/data/messages/messages-protocol-v2.json +329 -323
- package/src/data-manager/DataManager.ts +4 -4
- package/src/data-manager/connectSettings.ts +6 -0
- package/src/device/Device.ts +86 -241
- package/src/device/DevicePool.ts +9 -9
- package/src/deviceProfile/buildDeviceFeatures.ts +368 -0
- package/src/deviceProfile/buildDeviceProfile.ts +101 -155
- package/src/deviceProfile/index.ts +4 -1
- package/src/protocols/protocol-v2/features.ts +14 -16
- package/src/types/api/getDeviceInfo.ts +2 -2
- package/src/types/api/getPassphraseState.ts +4 -4
- package/src/types/api/protocolV2.ts +2 -3
- package/src/types/device.ts +97 -34
- package/src/types/settings.ts +5 -0
- package/src/utils/capabilitieUtils.ts +1 -2
- package/src/utils/deviceFeaturesUtils.ts +11 -17
- package/src/utils/deviceInfoUtils.ts +11 -29
- package/src/utils/deviceVersionUtils.ts +7 -25
- package/src/utils/findDefectiveBatchDevice.ts +6 -6
- package/dist/deviceProfile/legacyFeaturesView.d.ts +0 -5
- package/dist/deviceProfile/legacyFeaturesView.d.ts.map +0 -1
- package/src/deviceProfile/legacyFeaturesView.ts +0 -123
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
} from '../src/protocols/protocol-v2/features';
|
|
52
52
|
import {
|
|
53
53
|
buildProfileFromProtocolV2,
|
|
54
|
-
|
|
54
|
+
buildProtocolV2FeaturesPayload,
|
|
55
55
|
} from '../src/deviceProfile';
|
|
56
56
|
import {
|
|
57
57
|
getDeviceType,
|
|
@@ -91,44 +91,34 @@ const descriptor = {
|
|
|
91
91
|
*/
|
|
92
92
|
function stubDevice<T extends Record<string, any>>(device: T): T {
|
|
93
93
|
const d = device as any;
|
|
94
|
-
d.isProtocolV2 ??= () =>
|
|
95
|
-
d.profile?.protocol === 'V2' || d.originalDescriptor?.protocolType === 'V2';
|
|
94
|
+
d.isProtocolV2 ??= () => d.originalDescriptor?.protocolType === 'V2';
|
|
96
95
|
d.getProtocol ??= () => (d.isProtocolV2() ? 'V2' : 'V1');
|
|
97
|
-
d.getCurrentDeviceType ??= () =>
|
|
98
|
-
d.getCurrentFirmwareType ??= () =>
|
|
96
|
+
d.getCurrentDeviceType ??= () => getDeviceType(d.features);
|
|
97
|
+
d.getCurrentFirmwareType ??= () => getFirmwareType(d.features);
|
|
99
98
|
d.getCurrentFirmwareVersionString ??= () =>
|
|
100
|
-
d.
|
|
101
|
-
|
|
102
|
-
d.
|
|
103
|
-
d.
|
|
104
|
-
d.
|
|
105
|
-
d.getCurrentSerialNo ??= () => d.profile?.serialNo || '';
|
|
99
|
+
d.features ? getDeviceFirmwareVersion(d.features).join('.') : undefined;
|
|
100
|
+
d.getCurrentBLEFirmwareVersionString ??= () => d.features?.bleVersion;
|
|
101
|
+
d.getCurrentSafetyChecks ??= () => d.features?.safetyChecks;
|
|
102
|
+
d.getCurrentDeviceId ??= () => d.features?.deviceId || undefined;
|
|
103
|
+
d.getCurrentSerialNo ??= () => d.features?.serialNo || '';
|
|
106
104
|
d.getCurrentPassphraseProtection ??= () =>
|
|
107
|
-
d.
|
|
105
|
+
d.features?.passphraseProtection;
|
|
108
106
|
d.getCurrentMethodVersionRange ??= (fn: (model: any) => any) => {
|
|
109
107
|
const deviceType = d.getCurrentDeviceType();
|
|
110
108
|
const range = fn(deviceType);
|
|
111
109
|
if (range) return range;
|
|
112
110
|
return getMethodVersionRange(d.features, fn);
|
|
113
111
|
};
|
|
114
|
-
d.
|
|
115
|
-
d.
|
|
116
|
-
|
|
117
|
-
d.applyProfileUpdate ??= (p: any) => {
|
|
118
|
-
d.profile = p;
|
|
119
|
-
return p;
|
|
112
|
+
d.updateProtocolV2Features ??= (deviceInfo?: ProtocolV2DeviceInfo) => {
|
|
113
|
+
d.features = buildProtocolV2FeaturesPayload(deviceInfo, d.features);
|
|
114
|
+
return d.features;
|
|
120
115
|
};
|
|
121
116
|
return device;
|
|
122
117
|
}
|
|
123
118
|
|
|
124
119
|
// 直接复用生产映射函数,避免测试内副本与实现漂移(之前的手抄副本已缺失 se boot 字段)
|
|
125
120
|
function normalizeProtocolV2Features(_descriptor: unknown, deviceInfo?: ProtocolV2DeviceInfo) {
|
|
126
|
-
|
|
127
|
-
deviceInfo,
|
|
128
|
-
sources: ['deviceInfo'],
|
|
129
|
-
scope: 'verify',
|
|
130
|
-
});
|
|
131
|
-
return buildProtocolV2GetFeaturesPayload(profile, deviceInfo);
|
|
121
|
+
return buildProtocolV2FeaturesPayload(deviceInfo);
|
|
132
122
|
}
|
|
133
123
|
|
|
134
124
|
async function requestProtocolV2LegacyFeatures({
|
|
@@ -152,15 +142,13 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
152
142
|
});
|
|
153
143
|
expect(typedCall).not.toHaveBeenCalled();
|
|
154
144
|
expect(deviceInfo).toEqual(buildMockProtocolV2DeviceInfo());
|
|
155
|
-
// 空 serial_no + fallbackSerialNo:身份字段回退 transport path
|
|
156
145
|
const profile = buildProfileFromProtocolV2({
|
|
157
146
|
deviceInfo,
|
|
158
|
-
fallbackSerialNo: 'usb-path',
|
|
159
147
|
});
|
|
160
148
|
expect(profile).toMatchObject({
|
|
161
149
|
protocol: 'V2',
|
|
162
|
-
deviceId: '
|
|
163
|
-
serialNo: '
|
|
150
|
+
deviceId: '',
|
|
151
|
+
serialNo: '',
|
|
164
152
|
status: { initialized: true },
|
|
165
153
|
versions: { firmware: '0.1.0' },
|
|
166
154
|
});
|
|
@@ -174,6 +162,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
174
162
|
protocol_version: 1,
|
|
175
163
|
hw: {
|
|
176
164
|
serial_no: 'PR2SERIAL',
|
|
165
|
+
device_id: 'PRO2-DEVICE-ID',
|
|
177
166
|
},
|
|
178
167
|
fw: {
|
|
179
168
|
board: {
|
|
@@ -223,40 +212,34 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
223
212
|
},
|
|
224
213
|
});
|
|
225
214
|
|
|
226
|
-
expect(features.
|
|
227
|
-
expect(features.
|
|
228
|
-
expect(features.
|
|
229
|
-
expect(features.
|
|
230
|
-
expect(features.
|
|
231
|
-
expect(features.
|
|
232
|
-
expect(features.
|
|
233
|
-
expect(features.
|
|
234
|
-
expect(features.
|
|
235
|
-
expect(features.
|
|
236
|
-
expect(features.
|
|
237
|
-
expect(features.
|
|
238
|
-
expect(features.
|
|
239
|
-
expect(features.
|
|
240
|
-
expect(features.
|
|
241
|
-
expect(features.
|
|
242
|
-
expect(features.onekey_ble_version).toBe('4.5.6');
|
|
243
|
-
expect(features.onekey_ble_hash).toBe('0c0d');
|
|
244
|
-
expect(features.onekey_se01_version).toBe('7.8.9');
|
|
245
|
-
expect(features.onekey_se01_hash).toBe('0e0f');
|
|
246
|
-
expect(features.onekey_se01_state).toBe('APP');
|
|
247
|
-
expect(features.onekey_se02_state).toBe('BOOT');
|
|
215
|
+
expect(features.deviceId).toBe('PRO2-DEVICE-ID');
|
|
216
|
+
expect(features.serialNo).toBe('PR2SERIAL');
|
|
217
|
+
expect(features.deviceType).toBe('pro2');
|
|
218
|
+
expect(features.protocolVersion).toBe(1);
|
|
219
|
+
expect(features.firmwareVersion).toBe('1.2.3');
|
|
220
|
+
expect(features.verify?.firmwareBuildId).toBe('app-build');
|
|
221
|
+
expect(features.verify?.firmwareHash).toBe('abc123');
|
|
222
|
+
expect(features.bootloaderVersion).toBe('0.2.0');
|
|
223
|
+
expect(features.verify?.bootloaderBuildId).toBe('boot-build');
|
|
224
|
+
expect(features.verify?.bootloaderHash).toBe('0a0b');
|
|
225
|
+
expect(features.verify?.boardHash).toBe('0102ff');
|
|
226
|
+
expect(features.bleName).toBe('Pro2 BLE');
|
|
227
|
+
expect(features.bleVersion).toBe('4.5.6');
|
|
228
|
+
expect(features.verify?.bleHash).toBe('0c0d');
|
|
229
|
+
expect(features.se01Version).toBe('7.8.9');
|
|
230
|
+
expect(features.verify?.se01Hash).toBe('0e0f');
|
|
248
231
|
expect(features.label).toBe('My Pro2');
|
|
249
232
|
expect(features.language).toBe('en-US');
|
|
250
233
|
expect(features.initialized).toBe(false);
|
|
251
|
-
expect(features.
|
|
252
|
-
expect(features.
|
|
253
|
-
expect(features.
|
|
234
|
+
expect(features.backupRequired).toBe(true);
|
|
235
|
+
expect(features.passphraseProtection).toBe(true);
|
|
236
|
+
expect(features.bleEnabled).toBe(true);
|
|
254
237
|
});
|
|
255
238
|
|
|
256
239
|
test('uses GetPassphraseState payloads compatible with Pro series passphrase flow', async () => {
|
|
257
240
|
const features = normalizeProtocolV2Features(descriptor as any);
|
|
258
241
|
// Pro2 版本线独立于 Pro 系列:V2 设备无论固件版本都支持 GetPassphraseState
|
|
259
|
-
features.
|
|
242
|
+
features.firmwareVersion = '1.2.3';
|
|
260
243
|
const typedCall = jest.fn().mockResolvedValue({
|
|
261
244
|
type: 'PassphraseState',
|
|
262
245
|
message: {
|
|
@@ -296,12 +279,12 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
296
279
|
|
|
297
280
|
test('returns unified GetPassphraseState object payload for existing Pro devices', async () => {
|
|
298
281
|
const features = {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
282
|
+
deviceId: 'pro-device-id',
|
|
283
|
+
deviceType: 'pro',
|
|
284
|
+
firmwareVersion: '4.15.0',
|
|
285
|
+
passphraseProtection: true,
|
|
286
|
+
sessionId: 'feature-session',
|
|
287
|
+
unlockedAttachPin: true,
|
|
305
288
|
};
|
|
306
289
|
const typedCall = jest.fn().mockResolvedValue({
|
|
307
290
|
type: 'PassphraseState',
|
|
@@ -319,6 +302,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
319
302
|
},
|
|
320
303
|
});
|
|
321
304
|
method.device = stubDevice({
|
|
305
|
+
originalDescriptor: { ...descriptor, protocolType: 'V2' },
|
|
322
306
|
features,
|
|
323
307
|
commands: { typedCall },
|
|
324
308
|
updateInternalState,
|
|
@@ -327,10 +311,10 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
327
311
|
}) as any;
|
|
328
312
|
|
|
329
313
|
await expect(method.run()).resolves.toEqual({
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
314
|
+
passphraseState: 'state-pro',
|
|
315
|
+
sessionId: 'session-pro',
|
|
316
|
+
unlockedAttachPin: false,
|
|
317
|
+
passphraseProtection: true,
|
|
334
318
|
});
|
|
335
319
|
expect(updateInternalState).toHaveBeenCalledWith(
|
|
336
320
|
true,
|
|
@@ -341,14 +325,14 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
341
325
|
);
|
|
342
326
|
});
|
|
343
327
|
|
|
344
|
-
test('
|
|
328
|
+
test('uses features for GetPassphraseState response metadata', async () => {
|
|
345
329
|
const features = {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
330
|
+
deviceId: null,
|
|
331
|
+
deviceType: 'pro2',
|
|
332
|
+
firmwareVersion: '4.15.0',
|
|
333
|
+
passphraseProtection: true,
|
|
334
|
+
sessionId: 'feature-session',
|
|
335
|
+
unlockedAttachPin: true,
|
|
352
336
|
};
|
|
353
337
|
const typedCall = jest.fn().mockResolvedValue({
|
|
354
338
|
type: 'PassphraseState',
|
|
@@ -367,51 +351,26 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
367
351
|
},
|
|
368
352
|
});
|
|
369
353
|
method.device = stubDevice({
|
|
354
|
+
originalDescriptor: { ...descriptor, protocolType: 'V2' },
|
|
370
355
|
features,
|
|
371
|
-
profile: {
|
|
372
|
-
protocol: 'V2',
|
|
373
|
-
sources: ['deviceInfo'],
|
|
374
|
-
deviceType: 'pro2',
|
|
375
|
-
firmwareType: 'universal',
|
|
376
|
-
deviceId: 'PR2SERIAL',
|
|
377
|
-
serialNo: 'PR2SERIAL',
|
|
378
|
-
label: null,
|
|
379
|
-
bleName: null,
|
|
380
|
-
status: {
|
|
381
|
-
mode: 'normal',
|
|
382
|
-
initialized: true,
|
|
383
|
-
bootloaderMode: false,
|
|
384
|
-
unlocked: null,
|
|
385
|
-
passphraseProtection: true,
|
|
386
|
-
backupRequired: false,
|
|
387
|
-
noBackup: null,
|
|
388
|
-
language: null,
|
|
389
|
-
},
|
|
390
|
-
versions: {
|
|
391
|
-
firmware: '4.15.0',
|
|
392
|
-
bootloader: null,
|
|
393
|
-
board: null,
|
|
394
|
-
ble: null,
|
|
395
|
-
},
|
|
396
|
-
},
|
|
397
356
|
commands: { typedCall },
|
|
398
357
|
updateInternalState,
|
|
399
358
|
getFeatures,
|
|
400
359
|
getCurrentDeviceType: () => 'pro2',
|
|
401
|
-
getCurrentDeviceId: () =>
|
|
360
|
+
getCurrentDeviceId: () => undefined,
|
|
402
361
|
getCurrentPassphraseProtection: () => true,
|
|
403
362
|
}) as any;
|
|
404
363
|
|
|
405
364
|
await expect(method.run()).resolves.toEqual({
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
365
|
+
passphraseState: 'state-pro2',
|
|
366
|
+
sessionId: 'session-pro2',
|
|
367
|
+
unlockedAttachPin: false,
|
|
368
|
+
passphraseProtection: true,
|
|
410
369
|
});
|
|
411
370
|
expect(getFeatures).not.toHaveBeenCalled();
|
|
412
371
|
});
|
|
413
372
|
|
|
414
|
-
test('
|
|
373
|
+
test('stores Pro2 passphrase session cache without synthetic device id', async () => {
|
|
415
374
|
const device = Device.fromDescriptor({ ...descriptor, protocolType: 'V2' } as any);
|
|
416
375
|
const typedCall = jest.fn().mockResolvedValue({
|
|
417
376
|
type: 'PassphraseState',
|
|
@@ -459,8 +418,8 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
459
418
|
hw: { serial_no: 'PR2SERIAL' },
|
|
460
419
|
}
|
|
461
420
|
);
|
|
462
|
-
(device as any).features.
|
|
463
|
-
(device as any).features.
|
|
421
|
+
(device as any).features.firmwareVersion = '4.15.0';
|
|
422
|
+
(device as any).features.passphraseProtection = true;
|
|
464
423
|
(device as any).features.unlocked = true;
|
|
465
424
|
(device as any).commands = { typedCall };
|
|
466
425
|
|
|
@@ -470,8 +429,8 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
470
429
|
});
|
|
471
430
|
|
|
472
431
|
expect(device.passphraseState).toBeUndefined();
|
|
473
|
-
expect(device.features?.
|
|
474
|
-
expect(device.features?.
|
|
432
|
+
expect(device.features?.passphraseProtection).toBe(true);
|
|
433
|
+
expect(device.features?.sessionId).toBeNull();
|
|
475
434
|
expect(device.getInternalState()).toBeUndefined();
|
|
476
435
|
device.passphraseState = 'state-auto';
|
|
477
436
|
expect(device.getInternalState()).toBe('session-auto');
|
|
@@ -501,7 +460,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
501
460
|
},
|
|
502
461
|
}
|
|
503
462
|
);
|
|
504
|
-
(device as any).features.
|
|
463
|
+
(device as any).features.firmwareVersion = '4.15.0';
|
|
505
464
|
(device as any).features.unlocked = true;
|
|
506
465
|
(device as any).commands = { typedCall };
|
|
507
466
|
|
|
@@ -512,8 +471,8 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
512
471
|
newSession: 'main-pin-session',
|
|
513
472
|
});
|
|
514
473
|
|
|
515
|
-
expect(device.features?.
|
|
516
|
-
expect(device.features?.
|
|
474
|
+
expect(device.features?.passphraseProtection).toBe(false);
|
|
475
|
+
expect(device.features?.sessionId).toBeNull();
|
|
517
476
|
expect(device.getInternalState()).toBeUndefined();
|
|
518
477
|
expect(typedCall).toHaveBeenLastCalledWith('GetPassphraseState', 'PassphraseState', {
|
|
519
478
|
_only_main_pin: true,
|
|
@@ -535,8 +494,8 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
535
494
|
...descriptor,
|
|
536
495
|
protocolType: 'V2',
|
|
537
496
|
} as any);
|
|
538
|
-
(device as any).features.
|
|
539
|
-
(device as any).features.
|
|
497
|
+
(device as any).features.firmwareVersion = '4.15.0';
|
|
498
|
+
(device as any).features.passphraseProtection = true;
|
|
540
499
|
(device as any).commands = { typedCall };
|
|
541
500
|
|
|
542
501
|
await expect(device.checkPassphraseStateSafety('expected-state', false, true)).resolves.toBe(
|
|
@@ -552,15 +511,14 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
552
511
|
test('marks fallback features as unavailable when DeviceInfo is missing', () => {
|
|
553
512
|
const features = normalizeProtocolV2Features(descriptor as any);
|
|
554
513
|
|
|
555
|
-
expect(features.
|
|
556
|
-
expect(features.
|
|
557
|
-
expect(features.
|
|
558
|
-
expect(features.
|
|
559
|
-
expect(features.
|
|
560
|
-
expect(features.firmware_present).toBe(false);
|
|
514
|
+
expect(features.deviceId).toBeNull();
|
|
515
|
+
expect(features.serialNo).toBe('');
|
|
516
|
+
expect(features.initialized).toBeNull();
|
|
517
|
+
expect(features.unlocked).toBeNull();
|
|
518
|
+
expect(features.firmwarePresent).toBeNull();
|
|
561
519
|
});
|
|
562
520
|
|
|
563
|
-
test('uses Protocol V2
|
|
521
|
+
test('uses Protocol V2 hw.device_id and does not fall back to serial_no', () => {
|
|
564
522
|
const features = normalizeProtocolV2Features(
|
|
565
523
|
{
|
|
566
524
|
id: 'PR2000000000',
|
|
@@ -570,108 +528,69 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
570
528
|
{
|
|
571
529
|
hw: {
|
|
572
530
|
serial_no: 'PR9999999999',
|
|
531
|
+
device_id: 'DEVICE-ID-9999',
|
|
573
532
|
},
|
|
574
533
|
}
|
|
575
534
|
);
|
|
576
535
|
|
|
577
|
-
expect(features.
|
|
578
|
-
expect(features.
|
|
579
|
-
expect(features.serial_no).toBe('PR9999999999');
|
|
536
|
+
expect(features.deviceId).toBe('DEVICE-ID-9999');
|
|
537
|
+
expect(features.serialNo).toBe('PR9999999999');
|
|
580
538
|
});
|
|
581
539
|
|
|
582
|
-
test('does not
|
|
540
|
+
test('does not use Protocol V2 serial_no as deviceId when hw.device_id is absent', () => {
|
|
541
|
+
const features = normalizeProtocolV2Features(
|
|
542
|
+
{
|
|
543
|
+
id: 'PR2000000000',
|
|
544
|
+
path: 'PR2000000000',
|
|
545
|
+
protocolType: 'V2',
|
|
546
|
+
} as any,
|
|
547
|
+
{
|
|
548
|
+
hw: {
|
|
549
|
+
serial_no: 'PR9999999999',
|
|
550
|
+
},
|
|
551
|
+
}
|
|
552
|
+
);
|
|
553
|
+
|
|
554
|
+
expect(features.deviceId).toBeNull();
|
|
555
|
+
expect(features.serialNo).toBe('PR9999999999');
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
test('uses Protocol V2 features directly when profile is absent', () => {
|
|
583
559
|
const device = Device.fromDescriptor({ ...descriptor, protocolType: 'V2' } as any);
|
|
584
560
|
(device as any).features = {
|
|
585
561
|
...normalizeProtocolV2Features({ ...descriptor, protocolType: 'V2' } as any),
|
|
586
|
-
|
|
587
|
-
serial_no: 'LEGACY-SERIAL',
|
|
562
|
+
serialNo: 'LEGACY-SERIAL',
|
|
588
563
|
label: 'Legacy Label',
|
|
589
|
-
|
|
590
|
-
|
|
564
|
+
bleName: 'Legacy BLE',
|
|
565
|
+
passphraseProtection: true,
|
|
591
566
|
};
|
|
592
|
-
device.updateProfile({
|
|
593
|
-
protocol: 'V2',
|
|
594
|
-
sources: ['deviceInfo'],
|
|
595
|
-
deviceType: 'pro2',
|
|
596
|
-
firmwareType: 'universal',
|
|
597
|
-
deviceId: '',
|
|
598
|
-
serialNo: '',
|
|
599
|
-
label: null,
|
|
600
|
-
bleName: null,
|
|
601
|
-
status: {
|
|
602
|
-
mode: 'normal',
|
|
603
|
-
initialized: true,
|
|
604
|
-
bootloaderMode: false,
|
|
605
|
-
unlocked: null,
|
|
606
|
-
passphraseProtection: null,
|
|
607
|
-
backupRequired: false,
|
|
608
|
-
noBackup: null,
|
|
609
|
-
language: null,
|
|
610
|
-
},
|
|
611
|
-
versions: {
|
|
612
|
-
firmware: null,
|
|
613
|
-
bootloader: null,
|
|
614
|
-
board: null,
|
|
615
|
-
ble: null,
|
|
616
|
-
},
|
|
617
|
-
});
|
|
618
567
|
|
|
619
568
|
expect(device.toMessageObject()).toMatchObject({
|
|
620
|
-
uuid: '',
|
|
569
|
+
uuid: 'LEGACY-SERIAL',
|
|
621
570
|
deviceId: null,
|
|
622
|
-
bleName:
|
|
623
|
-
label: '
|
|
571
|
+
bleName: 'Legacy BLE',
|
|
572
|
+
label: 'Legacy Label',
|
|
624
573
|
deviceType: 'pro2',
|
|
625
574
|
});
|
|
626
|
-
expect(device.getCurrentPassphraseProtection()).
|
|
575
|
+
expect(device.getCurrentPassphraseProtection()).toBe(true);
|
|
627
576
|
expect(device.hasUsePassphrase()).toBe(true);
|
|
628
|
-
expect(device.isInitialized()).toBe(true);
|
|
629
|
-
expect(device.getMode()).toBe('normal');
|
|
630
|
-
expect(device.getFirmwareVersion()).toBeNull();
|
|
631
577
|
});
|
|
632
578
|
|
|
633
|
-
test('
|
|
579
|
+
test('syncs Protocol V2 cached features without cached profile', () => {
|
|
634
580
|
const cached = Device.fromDescriptor({ ...descriptor, protocolType: 'V2' } as any);
|
|
635
581
|
(cached as any).features = {
|
|
636
582
|
...normalizeProtocolV2Features({ ...descriptor, protocolType: 'V2' } as any),
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
onekey_serial_no: 'LEGACY-SERIAL',
|
|
583
|
+
deviceId: null,
|
|
584
|
+
serialNo: 'LEGACY-SERIAL',
|
|
640
585
|
};
|
|
641
|
-
cached.updateProfile({
|
|
642
|
-
protocol: 'V2',
|
|
643
|
-
sources: ['deviceInfo'],
|
|
644
|
-
deviceType: 'pro2',
|
|
645
|
-
firmwareType: 'universal',
|
|
646
|
-
deviceId: '',
|
|
647
|
-
serialNo: '',
|
|
648
|
-
label: null,
|
|
649
|
-
bleName: null,
|
|
650
|
-
status: {
|
|
651
|
-
mode: 'normal',
|
|
652
|
-
initialized: true,
|
|
653
|
-
bootloaderMode: false,
|
|
654
|
-
unlocked: null,
|
|
655
|
-
passphraseProtection: null,
|
|
656
|
-
backupRequired: false,
|
|
657
|
-
noBackup: null,
|
|
658
|
-
language: null,
|
|
659
|
-
},
|
|
660
|
-
versions: {
|
|
661
|
-
firmware: null,
|
|
662
|
-
bootloader: null,
|
|
663
|
-
board: null,
|
|
664
|
-
ble: null,
|
|
665
|
-
},
|
|
666
|
-
});
|
|
667
586
|
|
|
668
587
|
const current = Device.fromDescriptor({ ...descriptor, protocolType: 'V2' } as any);
|
|
669
588
|
current.updateFromCache(cached);
|
|
670
589
|
|
|
671
590
|
expect(current.getCurrentDeviceId()).toBeUndefined();
|
|
672
|
-
expect(current.getCurrentSerialNo()).toBe('');
|
|
591
|
+
expect(current.getCurrentSerialNo()).toBe('LEGACY-SERIAL');
|
|
673
592
|
expect(current.toMessageObject()).toMatchObject({
|
|
674
|
-
uuid: '',
|
|
593
|
+
uuid: 'LEGACY-SERIAL',
|
|
675
594
|
deviceId: null,
|
|
676
595
|
});
|
|
677
596
|
});
|
|
@@ -695,9 +614,9 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
695
614
|
descriptor: descriptor as any,
|
|
696
615
|
});
|
|
697
616
|
|
|
698
|
-
expect(features.
|
|
617
|
+
expect(features.deviceId).toBeNull();
|
|
699
618
|
expect(features.initialized).toBe(true);
|
|
700
|
-
expect(features.
|
|
619
|
+
expect(features.passphraseProtection).toBe(true);
|
|
701
620
|
expect(commands.typedCall).toHaveBeenCalledTimes(1);
|
|
702
621
|
expect(commands.typedCall).toHaveBeenNthCalledWith(
|
|
703
622
|
1,
|
|
@@ -776,7 +695,6 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
776
695
|
},
|
|
777
696
|
commands: { typedCall },
|
|
778
697
|
_updateFeatures: jest.fn(),
|
|
779
|
-
updateProfile: jest.fn(),
|
|
780
698
|
});
|
|
781
699
|
|
|
782
700
|
const result = await method.run();
|
|
@@ -801,7 +719,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
801
719
|
expect(result).toMatchObject({
|
|
802
720
|
protocol: 'V2',
|
|
803
721
|
deviceType: 'pro2',
|
|
804
|
-
deviceId: '
|
|
722
|
+
deviceId: '',
|
|
805
723
|
serialNo: 'PR2SERIAL',
|
|
806
724
|
label: 'Raw Pro2',
|
|
807
725
|
bleName: 'Raw Pro2 BLE',
|
|
@@ -846,17 +764,16 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
846
764
|
onekey_ble_version: '2.3.4',
|
|
847
765
|
},
|
|
848
766
|
commands: { typedCall },
|
|
849
|
-
updateProfile: jest.fn(),
|
|
850
767
|
});
|
|
851
768
|
|
|
852
769
|
const result = await method.run();
|
|
853
770
|
|
|
854
771
|
expect(result).toMatchObject({
|
|
855
772
|
protocol: 'V2',
|
|
856
|
-
// 身份字段不得取自 legacy features(LEGACY-ID / LEGACY-SERIAL
|
|
857
|
-
// hw.serial_no
|
|
858
|
-
deviceId: '
|
|
859
|
-
serialNo: '
|
|
773
|
+
// 身份字段不得取自 legacy features(LEGACY-ID / LEGACY-SERIAL),
|
|
774
|
+
// hw.serial_no 缺失时也不回退 descriptor.path。
|
|
775
|
+
deviceId: '',
|
|
776
|
+
serialNo: '',
|
|
860
777
|
label: null,
|
|
861
778
|
bleName: null,
|
|
862
779
|
status: {
|
|
@@ -948,7 +865,6 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
948
865
|
originalDescriptor: { ...descriptor, protocolType: 'V2' },
|
|
949
866
|
features: normalizeProtocolV2Features({ ...descriptor, protocolType: 'V2' } as any),
|
|
950
867
|
commands: { typedCall },
|
|
951
|
-
updateProfile: jest.fn(),
|
|
952
868
|
});
|
|
953
869
|
|
|
954
870
|
const result = await method.run();
|
|
@@ -1088,7 +1004,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
1088
1004
|
});
|
|
1089
1005
|
});
|
|
1090
1006
|
|
|
1091
|
-
test('
|
|
1007
|
+
test('does not call legacy OnekeyGetFeatures for Protocol V2 devices', async () => {
|
|
1092
1008
|
const method = new GetOnekeyFeatures({
|
|
1093
1009
|
id: 1,
|
|
1094
1010
|
payload: {
|
|
@@ -1124,17 +1040,11 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
1124
1040
|
}),
|
|
1125
1041
|
expect.anything()
|
|
1126
1042
|
);
|
|
1127
|
-
expect(message).
|
|
1128
|
-
onekey_device_type: 'pro2',
|
|
1129
|
-
onekey_firmware_version: '1.2.3',
|
|
1130
|
-
onekey_firmware_build_id: 'app-build',
|
|
1131
|
-
onekey_serial_no: 'PR2SERIAL',
|
|
1132
|
-
onekey_ble_name: 'Pro2 BLE',
|
|
1133
|
-
});
|
|
1043
|
+
expect(message).toEqual({});
|
|
1134
1044
|
expect(message).not.toHaveProperty('label');
|
|
1135
1045
|
});
|
|
1136
1046
|
|
|
1137
|
-
test('refreshes cached Protocol V2
|
|
1047
|
+
test('refreshes cached Protocol V2 features with a lightweight status request on later runs', async () => {
|
|
1138
1048
|
const device = Device.fromDescriptor({
|
|
1139
1049
|
path: 'usb-path',
|
|
1140
1050
|
protocolType: 'V2',
|
|
@@ -1169,17 +1079,17 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
1169
1079
|
await device.initialize();
|
|
1170
1080
|
|
|
1171
1081
|
expect(device.features).toMatchObject({
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1082
|
+
deviceId: null,
|
|
1083
|
+
firmwareVersion: '1.2.3',
|
|
1084
|
+
passphraseProtection: false,
|
|
1175
1085
|
label: 'renamed',
|
|
1176
1086
|
});
|
|
1177
|
-
expect(device.profile
|
|
1087
|
+
expect((device as any).profile).toBeUndefined();
|
|
1178
1088
|
// status 字段被第二次刷新更新
|
|
1179
|
-
expect(device.
|
|
1180
|
-
expect(device.
|
|
1089
|
+
expect(device.features?.passphraseProtection).toBe(false);
|
|
1090
|
+
expect(device.features?.label).toBe('renamed');
|
|
1181
1091
|
// 轻量刷新不含 fw target,已有版本信息按字段级合并保留
|
|
1182
|
-
expect(device.
|
|
1092
|
+
expect(device.features?.firmwareVersion).toBe('1.2.3');
|
|
1183
1093
|
expect(typedCall).toHaveBeenCalledTimes(2);
|
|
1184
1094
|
expect(typedCall).toHaveBeenNthCalledWith(
|
|
1185
1095
|
1,
|
|
@@ -1253,15 +1163,15 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
1253
1163
|
const features = await device.getFeatures();
|
|
1254
1164
|
|
|
1255
1165
|
expect(device.features).toMatchObject({
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1166
|
+
deviceId: null,
|
|
1167
|
+
firmwareVersion: '1.2.4',
|
|
1168
|
+
passphraseProtection: true,
|
|
1259
1169
|
});
|
|
1260
1170
|
expect(features).toMatchObject({
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1171
|
+
deviceType: 'pro2',
|
|
1172
|
+
serialNo: 'PR2SERIAL',
|
|
1173
|
+
firmwareVersion: '1.2.4',
|
|
1174
|
+
passphraseProtection: true,
|
|
1265
1175
|
});
|
|
1266
1176
|
expect(typedCall).toHaveBeenCalledTimes(2);
|
|
1267
1177
|
expect(typedCall).toHaveBeenNthCalledWith(
|
|
@@ -1319,7 +1229,6 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
1319
1229
|
});
|
|
1320
1230
|
method.init();
|
|
1321
1231
|
(method as any).device = stubDevice({
|
|
1322
|
-
profile: device.profile,
|
|
1323
1232
|
features: device.features,
|
|
1324
1233
|
commands: { typedCall: jest.fn() },
|
|
1325
1234
|
});
|
|
@@ -1358,14 +1267,14 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
1358
1267
|
expect(typedCall).not.toHaveBeenCalledWith('GetAddress', 'Address', expect.anything());
|
|
1359
1268
|
expect(typedCall).not.toHaveBeenCalledWith('GetFeatures', 'Features', {});
|
|
1360
1269
|
expect(features).toMatchObject({
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1270
|
+
deviceType: 'pro2',
|
|
1271
|
+
deviceId: null,
|
|
1272
|
+
firmwareVersion: '1.2.3',
|
|
1364
1273
|
unlocked: true,
|
|
1365
1274
|
});
|
|
1366
1275
|
});
|
|
1367
1276
|
|
|
1368
|
-
test('syncs Protocol V2
|
|
1277
|
+
test('syncs Protocol V2 features passphrase state after unlock response', async () => {
|
|
1369
1278
|
const device = Device.fromDescriptor({ ...descriptor, protocolType: 'V2' } as any);
|
|
1370
1279
|
(device as any).features = normalizeProtocolV2Features(
|
|
1371
1280
|
{ ...descriptor, protocolType: 'V2' } as any,
|
|
@@ -1375,32 +1284,6 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
1375
1284
|
status: { passphrase_protection: false },
|
|
1376
1285
|
}
|
|
1377
1286
|
);
|
|
1378
|
-
device.updateProfile({
|
|
1379
|
-
protocol: 'V2',
|
|
1380
|
-
sources: ['deviceInfo'],
|
|
1381
|
-
deviceType: 'pro2',
|
|
1382
|
-
firmwareType: 'universal',
|
|
1383
|
-
deviceId: 'PR2SERIAL',
|
|
1384
|
-
serialNo: 'PR2SERIAL',
|
|
1385
|
-
label: null,
|
|
1386
|
-
bleName: null,
|
|
1387
|
-
status: {
|
|
1388
|
-
mode: 'normal',
|
|
1389
|
-
initialized: true,
|
|
1390
|
-
bootloaderMode: false,
|
|
1391
|
-
unlocked: null,
|
|
1392
|
-
passphraseProtection: false,
|
|
1393
|
-
backupRequired: false,
|
|
1394
|
-
noBackup: null,
|
|
1395
|
-
language: null,
|
|
1396
|
-
},
|
|
1397
|
-
versions: {
|
|
1398
|
-
firmware: '4.15.0',
|
|
1399
|
-
bootloader: null,
|
|
1400
|
-
board: null,
|
|
1401
|
-
ble: null,
|
|
1402
|
-
},
|
|
1403
|
-
});
|
|
1404
1287
|
const typedCall = jest.fn().mockResolvedValue({
|
|
1405
1288
|
type: 'UnLockDeviceResponse',
|
|
1406
1289
|
message: {
|
|
@@ -1412,8 +1295,8 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
1412
1295
|
|
|
1413
1296
|
await device.unlockDevice();
|
|
1414
1297
|
|
|
1415
|
-
expect(device.profile
|
|
1416
|
-
expect(device.features?.
|
|
1298
|
+
expect((device as any).profile).toBeUndefined();
|
|
1299
|
+
expect(device.features?.passphraseProtection).toBe(true);
|
|
1417
1300
|
});
|
|
1418
1301
|
});
|
|
1419
1302
|
|
|
@@ -1432,7 +1315,7 @@ describe('API compatibility handling', () => {
|
|
|
1432
1315
|
method.init();
|
|
1433
1316
|
(method as any).device = stubDevice({
|
|
1434
1317
|
features: {
|
|
1435
|
-
|
|
1318
|
+
deviceType: 'pro2',
|
|
1436
1319
|
},
|
|
1437
1320
|
originalDescriptor: {
|
|
1438
1321
|
protocolType: 'V2',
|
|
@@ -1470,7 +1353,7 @@ describe('API compatibility handling', () => {
|
|
|
1470
1353
|
|
|
1471
1354
|
test('does not mark Pro2 Tron, Solana, TON, SUI and Polkadot methods as unsupported', () => {
|
|
1472
1355
|
const features = {
|
|
1473
|
-
|
|
1356
|
+
deviceType: 'pro2',
|
|
1474
1357
|
} as Features;
|
|
1475
1358
|
|
|
1476
1359
|
const tronMethod = new TronGetAddress({
|
|
@@ -1621,7 +1504,7 @@ describe('API compatibility handling', () => {
|
|
|
1621
1504
|
|
|
1622
1505
|
test('allows Pro2 Solana signing methods through Protocol V2 version checks', () => {
|
|
1623
1506
|
const features = {
|
|
1624
|
-
|
|
1507
|
+
deviceType: 'pro2',
|
|
1625
1508
|
} as Features;
|
|
1626
1509
|
|
|
1627
1510
|
const solSignMessageMethod = new SolSignMessage({
|
|
@@ -1715,7 +1598,7 @@ describe('API compatibility handling', () => {
|
|
|
1715
1598
|
method.init();
|
|
1716
1599
|
(method as any).device = stubDevice({
|
|
1717
1600
|
features: {
|
|
1718
|
-
|
|
1601
|
+
deviceType: 'pro2',
|
|
1719
1602
|
},
|
|
1720
1603
|
originalDescriptor: {
|
|
1721
1604
|
protocolType: 'V2',
|
|
@@ -2589,7 +2472,7 @@ describe('Protocol V2 reboot methods', () => {
|
|
|
2589
2472
|
});
|
|
2590
2473
|
});
|
|
2591
2474
|
|
|
2592
|
-
test('sends
|
|
2475
|
+
test('sends DevReboot from deviceReboot', async () => {
|
|
2593
2476
|
const typedCall = jest.fn().mockResolvedValue({ message: { message: 'ok' } });
|
|
2594
2477
|
const method = new DeviceReboot({
|
|
2595
2478
|
id: 1,
|
|
@@ -2603,7 +2486,7 @@ describe('Protocol V2 reboot methods', () => {
|
|
|
2603
2486
|
|
|
2604
2487
|
await method.run();
|
|
2605
2488
|
|
|
2606
|
-
expect(typedCall).toHaveBeenCalledWith('
|
|
2489
|
+
expect(typedCall).toHaveBeenCalledWith('DevReboot', 'Success', {
|
|
2607
2490
|
reboot_type: 2,
|
|
2608
2491
|
});
|
|
2609
2492
|
});
|