@onekeyfe/hd-core 1.2.0-alpha.17 → 1.2.0-alpha.19
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__/DeviceEventRegistration.test.ts +3 -0
- package/__tests__/device-features-state.test.ts +78 -0
- package/__tests__/device-identity.test.ts +30 -0
- package/__tests__/device-pool-state.test.ts +113 -0
- package/__tests__/device-settings.test.ts +108 -0
- package/__tests__/device-state-contract.test.ts +27 -0
- package/__tests__/device-state-events.test.ts +163 -0
- package/__tests__/device-state-mapper.test.ts +222 -0
- package/__tests__/device-state-projector.test.ts +94 -0
- package/__tests__/device-state-store.test.ts +115 -0
- package/__tests__/device-wallet-session-store.test.ts +46 -0
- package/__tests__/deviceFeaturesUtils.test.ts +13 -1
- package/__tests__/deviceSettings.test.ts +54 -0
- package/__tests__/get-device-state.test.ts +367 -0
- package/__tests__/kaspaSignTransaction.test.ts +591 -0
- package/__tests__/logBlockEvent.test.ts +13 -0
- package/__tests__/protocol-v2.test.ts +358 -413
- package/__tests__/public-device-state-api.test.ts +153 -0
- package/__tests__/refresh-device-state.test.ts +101 -0
- package/__tests__/request-context-logging.test.ts +16 -0
- package/__tests__/search-devices.test.ts +93 -0
- package/dist/api/ClearSessionCache.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetDeviceState.d.ts +7 -0
- package/dist/api/GetDeviceState.d.ts.map +1 -0
- package/dist/api/GetFeatures.d.ts +1 -1
- package/dist/api/GetFeatures.d.ts.map +1 -1
- package/dist/api/GetOnekeyFeatures.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/api/device/DeviceRebootToBoardloader.d.ts.map +1 -1
- package/dist/api/device/DeviceRebootToBootloader.d.ts.map +1 -1
- package/dist/api/device/DeviceSettings.d.ts.map +1 -1
- package/dist/api/index.d.ts +1 -4
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/internal.d.ts +4 -0
- package/dist/api/internal.d.ts.map +1 -0
- package/dist/api/kaspa/KaspaSignTransaction.d.ts +5 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
- package/dist/api/kaspa/helpers/TransferSerialize.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts +0 -1
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceReboot.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceSettingsGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceSettingsSet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceStatusGet.d.ts.map +1 -1
- package/dist/api/utils.d.ts +2 -1
- package/dist/api/utils.d.ts.map +1 -1
- package/dist/constants/index.d.ts +1 -1
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +22 -3
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +4 -4
- package/dist/device/DeviceFeaturesState.d.ts +4 -0
- package/dist/device/DeviceFeaturesState.d.ts.map +1 -0
- package/dist/device/DevicePool.d.ts +1 -0
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/device/DeviceStateMapper.d.ts +13 -0
- package/dist/device/DeviceStateMapper.d.ts.map +1 -0
- package/dist/device/DeviceStateProjector.d.ts +8 -0
- package/dist/device/DeviceStateProjector.d.ts.map +1 -0
- package/dist/device/DeviceStateStore.d.ts +23 -0
- package/dist/device/DeviceStateStore.d.ts.map +1 -0
- package/dist/device/deviceIdentity.d.ts +5 -0
- package/dist/device/deviceIdentity.d.ts.map +1 -0
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
- package/dist/deviceProfile/index.d.ts +0 -1
- package/dist/deviceProfile/index.d.ts.map +1 -1
- package/dist/events/device.d.ts +7 -2
- package/dist/events/device.d.ts.map +1 -1
- package/dist/index.d.ts +722 -648
- package/dist/index.js +1863 -1033
- package/dist/inject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/features.d.ts +1 -0
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/index.d.ts +1 -1
- package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/types/api/deviceSettings.d.ts +8 -0
- package/dist/types/api/deviceSettings.d.ts.map +1 -1
- package/dist/types/api/getDeviceState.d.ts +12 -0
- package/dist/types/api/getDeviceState.d.ts.map +1 -0
- package/dist/types/api/index.d.ts +4 -7
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/kaspaSignTransaction.d.ts +27 -2
- package/dist/types/api/kaspaSignTransaction.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +1 -6
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts +121 -1
- package/dist/types/device.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/deviceSettings.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/dist/utils/tracing.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/ClearSessionCache.ts +4 -0
- package/src/api/FirmwareUpdateV4.ts +15 -7
- package/src/api/GetDeviceState.ts +55 -0
- package/src/api/GetFeatures.ts +8 -3
- package/src/api/GetOnekeyFeatures.ts +3 -72
- package/src/api/GetPassphraseState.ts +3 -1
- package/src/api/SearchDevices.ts +25 -4
- package/src/api/device/DeviceRebootToBoardloader.ts +1 -0
- package/src/api/device/DeviceRebootToBootloader.ts +1 -0
- package/src/api/device/DeviceSettings.ts +28 -0
- package/src/api/index.ts +1 -4
- package/src/api/internal.ts +9 -0
- package/src/api/kaspa/KaspaSignTransaction.ts +341 -22
- package/src/api/kaspa/helpers/TransferSerialize.ts +14 -0
- package/src/api/protocol-v2/DeviceInfoGet.ts +3 -5
- package/src/api/protocol-v2/DeviceReboot.ts +3 -1
- package/src/api/protocol-v2/DeviceSettingsGet.ts +3 -1
- package/src/api/protocol-v2/DeviceSettingsSet.ts +2 -0
- package/src/api/protocol-v2/DeviceStatusGet.ts +1 -0
- package/src/api/utils.ts +9 -3
- package/src/constants/index.ts +1 -4
- package/src/core/index.ts +7 -1
- package/src/data/messages/messages-protocol-v2.json +22 -13
- package/src/data/messages/messages.json +286 -1
- package/src/device/Device.ts +256 -78
- package/src/device/DeviceFeaturesState.ts +34 -0
- package/src/device/DevicePool.ts +35 -9
- package/src/device/DeviceStateMapper.ts +364 -0
- package/src/device/DeviceStateProjector.ts +92 -0
- package/src/device/DeviceStateStore.ts +242 -0
- package/src/device/deviceIdentity.ts +18 -0
- package/src/deviceProfile/buildDeviceFeatures.ts +166 -109
- package/src/deviceProfile/index.ts +0 -1
- package/src/events/device.ts +13 -1
- package/src/events/logBlockEvent.ts +1 -1
- package/src/inject.ts +4 -5
- package/src/protocols/protocol-v2/features.ts +18 -9
- package/src/protocols/protocol-v2/index.ts +1 -0
- package/src/protocols/protocol-v2/walletSession.ts +5 -7
- package/src/types/api/deviceSettings.ts +8 -0
- package/src/types/api/getDeviceState.ts +19 -0
- package/src/types/api/index.ts +3 -20
- package/src/types/api/kaspaSignTransaction.ts +40 -2
- package/src/types/api/protocolV2.ts +0 -24
- package/src/types/device.ts +148 -1
- package/src/utils/deviceFeaturesUtils.ts +5 -1
- package/src/utils/deviceSettings.ts +41 -0
- package/src/utils/tracing.ts +3 -1
- package/dist/api/GetDeviceInfo.d.ts +0 -9
- package/dist/api/GetDeviceInfo.d.ts.map +0 -1
- package/dist/deviceProfile/buildDeviceProfile.d.ts +0 -22
- package/dist/deviceProfile/buildDeviceProfile.d.ts.map +0 -1
- package/dist/types/api/getDeviceInfo.d.ts +0 -88
- package/dist/types/api/getDeviceInfo.d.ts.map +0 -1
- package/src/api/GetDeviceInfo.ts +0 -152
- package/src/deviceProfile/buildDeviceProfile.ts +0 -370
- package/src/types/api/getDeviceInfo.ts +0 -106
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
mapApplySettingsToState,
|
|
5
|
+
mapDeviceSettingsToState,
|
|
6
|
+
mapProtocolV1FeaturesToState,
|
|
7
|
+
mapProtocolV2DeviceInfoToState,
|
|
8
|
+
mapProtocolV2DeviceStatusToState,
|
|
9
|
+
} from '../src/device/DeviceStateMapper';
|
|
10
|
+
|
|
11
|
+
import type { PROTO } from '../src/constants';
|
|
12
|
+
import type { DeviceSettings, DeviceStatus, ProtocolV2DeviceInfo } from '@onekeyfe/hd-transport';
|
|
13
|
+
|
|
14
|
+
describe('DeviceStateMapper', () => {
|
|
15
|
+
test('maps Protocol V1 Features into structured state sections', () => {
|
|
16
|
+
const patch = mapProtocolV1FeaturesToState({
|
|
17
|
+
onekey_device_type: 'PRO',
|
|
18
|
+
device_id: 'device-1',
|
|
19
|
+
label: 'Pro Wallet',
|
|
20
|
+
initialized: true,
|
|
21
|
+
unlocked: true,
|
|
22
|
+
language: 'en-US',
|
|
23
|
+
major_version: 4,
|
|
24
|
+
minor_version: 10,
|
|
25
|
+
patch_version: 1,
|
|
26
|
+
se_ver: '1.1.0.2',
|
|
27
|
+
} as PROTO.Features);
|
|
28
|
+
|
|
29
|
+
expect(patch).toMatchObject({
|
|
30
|
+
protocol: 'V1',
|
|
31
|
+
identity: {
|
|
32
|
+
deviceType: EDeviceType.Pro,
|
|
33
|
+
deviceId: 'device-1',
|
|
34
|
+
label: 'Pro Wallet',
|
|
35
|
+
},
|
|
36
|
+
status: { mode: 'normal', initialized: true, unlocked: true },
|
|
37
|
+
settings: { language: 'en-US' },
|
|
38
|
+
versions: { firmware: '4.10.1', se: '1.1.0.2' },
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test.each([
|
|
43
|
+
['CLASSIC1S', EDeviceType.Classic1s],
|
|
44
|
+
['TOUCH', EDeviceType.Touch],
|
|
45
|
+
['PRO', EDeviceType.Pro],
|
|
46
|
+
] as const)(
|
|
47
|
+
'keeps the real label separate from display fallbacks for Protocol V1 %s',
|
|
48
|
+
(onekeyDeviceType, expectedDeviceType) => {
|
|
49
|
+
const patch = mapProtocolV1FeaturesToState({
|
|
50
|
+
onekey_device_type: onekeyDeviceType,
|
|
51
|
+
onekey_ble_name: `${onekeyDeviceType} BLE`,
|
|
52
|
+
initialized: true,
|
|
53
|
+
} as PROTO.Features);
|
|
54
|
+
|
|
55
|
+
expect(patch.identity).toMatchObject({
|
|
56
|
+
deviceType: expectedDeviceType,
|
|
57
|
+
label: null,
|
|
58
|
+
bleName: `${onekeyDeviceType} BLE`,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
test.each([
|
|
64
|
+
['CLASSIC1S', EDeviceType.Classic1s],
|
|
65
|
+
['TOUCH', EDeviceType.Touch],
|
|
66
|
+
['PRO', EDeviceType.Pro],
|
|
67
|
+
] as const)(
|
|
68
|
+
'preserves Protocol V1 backup mode semantics for %s',
|
|
69
|
+
(onekeyDeviceType, expectedDeviceType) => {
|
|
70
|
+
const patch = mapProtocolV1FeaturesToState({
|
|
71
|
+
onekey_device_type: onekeyDeviceType,
|
|
72
|
+
initialized: true,
|
|
73
|
+
no_backup: true,
|
|
74
|
+
} as PROTO.Features);
|
|
75
|
+
|
|
76
|
+
expect(patch.identity?.deviceType).toBe(expectedDeviceType);
|
|
77
|
+
expect(patch.status?.mode).toBe('backupMode');
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
test('normalizes legacy Bitcoin-only and Attach PIN fields from Protocol V1', () => {
|
|
82
|
+
const patch = mapProtocolV1FeaturesToState({
|
|
83
|
+
onekey_device_type: 'PRO',
|
|
84
|
+
capabilities: [1],
|
|
85
|
+
attach_to_pin_user: true,
|
|
86
|
+
unlocked_attach_pin: true,
|
|
87
|
+
initialized: true,
|
|
88
|
+
} as PROTO.Features);
|
|
89
|
+
|
|
90
|
+
expect(patch.identity?.firmwareType).toBe(EFirmwareType.BitcoinOnly);
|
|
91
|
+
expect(patch.status).toMatchObject({
|
|
92
|
+
attachToPinEnabled: true,
|
|
93
|
+
unlockedAttachPin: true,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('keeps Protocol V1 universal firmware when the decoded Bitcoin-like capability is present', () => {
|
|
98
|
+
const patch = mapProtocolV1FeaturesToState({
|
|
99
|
+
onekey_device_type: 'CLASSIC1S',
|
|
100
|
+
capabilities: ['Capability_Bitcoin_like'],
|
|
101
|
+
initialized: true,
|
|
102
|
+
} as PROTO.Features);
|
|
103
|
+
|
|
104
|
+
expect(patch.identity?.firmwareType).toBe(EFirmwareType.Universal);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('maps Protocol V2 DeviceInfo without inventing runtime status', () => {
|
|
108
|
+
const patch = mapProtocolV2DeviceInfoToState({
|
|
109
|
+
protocol_version: 2,
|
|
110
|
+
hw: { serial_no: 'SERIAL-1' },
|
|
111
|
+
fw: {
|
|
112
|
+
application: { version: '5.0.0' },
|
|
113
|
+
bootloader: { version: '2.0.0' },
|
|
114
|
+
},
|
|
115
|
+
coprocessor: {
|
|
116
|
+
bt_adv_name: 'Pro2 1234',
|
|
117
|
+
application: { version: '1.2.3' },
|
|
118
|
+
},
|
|
119
|
+
} as ProtocolV2DeviceInfo);
|
|
120
|
+
|
|
121
|
+
expect(patch.identity).toMatchObject({
|
|
122
|
+
deviceType: EDeviceType.Pro2,
|
|
123
|
+
serialNo: 'SERIAL-1',
|
|
124
|
+
bleName: 'Pro2 1234',
|
|
125
|
+
});
|
|
126
|
+
expect(patch.versions).toMatchObject({
|
|
127
|
+
firmware: '5.0.0',
|
|
128
|
+
bootloader: '2.0.0',
|
|
129
|
+
ble: '1.2.3',
|
|
130
|
+
});
|
|
131
|
+
expect(patch).toMatchObject({ protocolVersion: 2 });
|
|
132
|
+
expect(patch.status?.unlocked).toBeUndefined();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('keeps normal mode when Protocol V2 application and SE versions are returned together', () => {
|
|
136
|
+
const patch = mapProtocolV2DeviceInfoToState({
|
|
137
|
+
protocol_version: 2,
|
|
138
|
+
hw: { serial_no: 'SERIAL-NORMAL' },
|
|
139
|
+
fw: {
|
|
140
|
+
application: { version: '5.0.0' },
|
|
141
|
+
bootloader: { version: '2.0.0' },
|
|
142
|
+
},
|
|
143
|
+
se1: {
|
|
144
|
+
application: { version: '1.0.0', build_id: 'se-app', hash: [0x01, 0x02] },
|
|
145
|
+
bootloader: { version: '0.1.0', build_id: 'se-boot', hash: [0x03, 0x04] },
|
|
146
|
+
},
|
|
147
|
+
} as ProtocolV2DeviceInfo);
|
|
148
|
+
|
|
149
|
+
expect(patch.status?.mode).toBe('normal');
|
|
150
|
+
expect(patch.verification).toMatchObject({
|
|
151
|
+
se01BuildId: 'se-app',
|
|
152
|
+
se01Hash: '0102',
|
|
153
|
+
se01BootBuildId: 'se-boot',
|
|
154
|
+
se01BootHash: '0304',
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test.each([
|
|
159
|
+
[
|
|
160
|
+
'bootloader',
|
|
161
|
+
{
|
|
162
|
+
hw: { serial_no: 'SERIAL-BOOT' },
|
|
163
|
+
fw: { bootloader: { version: '2.0.0' } },
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
[
|
|
167
|
+
'romloader',
|
|
168
|
+
{
|
|
169
|
+
hw: { serial_no: 'SERIAL-ROM' },
|
|
170
|
+
fw: {
|
|
171
|
+
romloader: { version: '1.0.0' },
|
|
172
|
+
bootloader: { version: '2.0.0' },
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
] as const)('clears stale device identity in Protocol V2 %s mode', (mode, info) => {
|
|
177
|
+
const patch = mapProtocolV2DeviceInfoToState(info as ProtocolV2DeviceInfo);
|
|
178
|
+
|
|
179
|
+
expect(patch.status?.mode).toBe(mode);
|
|
180
|
+
expect(patch.identity).toMatchObject({ deviceId: null });
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
test('maps Protocol V2 status separately and ignores locked passphrase value', () => {
|
|
184
|
+
const locked = mapProtocolV2DeviceStatusToState({
|
|
185
|
+
device_id: 'device-2',
|
|
186
|
+
init_states: true,
|
|
187
|
+
unlocked: false,
|
|
188
|
+
passphrase_enabled: true,
|
|
189
|
+
backup_required: true,
|
|
190
|
+
} as DeviceStatus);
|
|
191
|
+
|
|
192
|
+
expect(locked.identity?.deviceId).toBe('device-2');
|
|
193
|
+
expect(locked.status).toMatchObject({
|
|
194
|
+
mode: 'normal',
|
|
195
|
+
initialized: true,
|
|
196
|
+
unlocked: false,
|
|
197
|
+
backupRequired: true,
|
|
198
|
+
});
|
|
199
|
+
expect(locked.status).not.toHaveProperty('passphraseProtection');
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test('maps common settings into identity, status and settings sections', () => {
|
|
203
|
+
expect(
|
|
204
|
+
mapApplySettingsToState({ label: 'Renamed', use_passphrase: true, haptic_feedback: false })
|
|
205
|
+
).toEqual({
|
|
206
|
+
identity: { label: 'Renamed' },
|
|
207
|
+
status: { passphraseProtection: true },
|
|
208
|
+
settings: { hapticFeedback: false },
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
expect(
|
|
212
|
+
mapDeviceSettingsToState({
|
|
213
|
+
label: 'Pro2',
|
|
214
|
+
brightness: 80,
|
|
215
|
+
autolock_delay_ms: 30_000,
|
|
216
|
+
} as DeviceSettings)
|
|
217
|
+
).toEqual({
|
|
218
|
+
identity: { label: 'Pro2' },
|
|
219
|
+
settings: { brightness: 80, autoLockDelayMs: 30_000 },
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
3
|
+
import { createEmptyDeviceState } from '../src/device/DeviceStateStore';
|
|
4
|
+
import { projectFeatures } from '../src/device/DeviceStateProjector';
|
|
5
|
+
|
|
6
|
+
describe('DeviceStateProjector', () => {
|
|
7
|
+
test('projects legacy Features from the canonical snapshot', () => {
|
|
8
|
+
const state = createEmptyDeviceState({
|
|
9
|
+
deviceType: EDeviceType.Pro2,
|
|
10
|
+
firmwareType: EFirmwareType.Universal,
|
|
11
|
+
deviceId: 'device-1',
|
|
12
|
+
serialNo: 'SERIAL-1',
|
|
13
|
+
label: 'My Pro2',
|
|
14
|
+
bleName: 'Pro2 1234',
|
|
15
|
+
});
|
|
16
|
+
state.protocol = 'V2';
|
|
17
|
+
state.protocolVersion = 7;
|
|
18
|
+
state.status = {
|
|
19
|
+
...state.status,
|
|
20
|
+
mode: 'normal',
|
|
21
|
+
initialized: true,
|
|
22
|
+
unlocked: true,
|
|
23
|
+
passphraseProtection: false,
|
|
24
|
+
};
|
|
25
|
+
state.settings = {
|
|
26
|
+
...state.settings,
|
|
27
|
+
language: 'en-US',
|
|
28
|
+
brightness: 80,
|
|
29
|
+
autoLockDelayMs: 30_000,
|
|
30
|
+
};
|
|
31
|
+
state.versions = {
|
|
32
|
+
...state.versions,
|
|
33
|
+
firmware: '5.0.0',
|
|
34
|
+
bootloader: '2.0.0',
|
|
35
|
+
ble: '1.2.3',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const features = projectFeatures(state);
|
|
39
|
+
expect(features).toMatchObject({
|
|
40
|
+
protocol: 'V2',
|
|
41
|
+
protocolVersion: 7,
|
|
42
|
+
label: 'My Pro2',
|
|
43
|
+
unlocked: true,
|
|
44
|
+
brightness: 80,
|
|
45
|
+
firmwareVersion: '5.0.0',
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test.each([
|
|
50
|
+
[EDeviceType.Classic1s],
|
|
51
|
+
[EDeviceType.ClassicPure],
|
|
52
|
+
[EDeviceType.Touch],
|
|
53
|
+
[EDeviceType.Pro],
|
|
54
|
+
] as const)('preserves Protocol V1 compatibility defaults for %s', deviceType => {
|
|
55
|
+
const state = createEmptyDeviceState({ deviceType });
|
|
56
|
+
state.protocol = 'V1';
|
|
57
|
+
state.versions.se = '1.1.0.2';
|
|
58
|
+
state.raw = {
|
|
59
|
+
protocolV1Features: {
|
|
60
|
+
onekey_device_type: deviceType,
|
|
61
|
+
initialized: true,
|
|
62
|
+
} as never,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const features = projectFeatures(state);
|
|
66
|
+
|
|
67
|
+
expect(features).toMatchObject({
|
|
68
|
+
protocolVersion: 1,
|
|
69
|
+
label: null,
|
|
70
|
+
bootloaderMode: null,
|
|
71
|
+
bootloader_mode: null,
|
|
72
|
+
seVersion: '1.1.0.2',
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('returns an isolated compatibility snapshot', () => {
|
|
77
|
+
const state = createEmptyDeviceState({ deviceType: EDeviceType.Pro });
|
|
78
|
+
state.protocol = 'V1';
|
|
79
|
+
state.capabilities = [1];
|
|
80
|
+
state.verification = { firmwareBuildId: 'build-1' };
|
|
81
|
+
state.raw = {
|
|
82
|
+
protocolV1Features: { label: 'Original' } as never,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const features = projectFeatures(state);
|
|
86
|
+
features.capabilities.push(2);
|
|
87
|
+
if (features.verify) features.verify.firmwareBuildId = 'mutated';
|
|
88
|
+
if (features.raw?.protocolV1Features) features.raw.protocolV1Features.label = 'Mutated';
|
|
89
|
+
|
|
90
|
+
expect(state.capabilities).toEqual([1]);
|
|
91
|
+
expect(state.verification?.firmwareBuildId).toBe('build-1');
|
|
92
|
+
expect(state.raw.protocolV1Features?.label).toBe('Original');
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
3
|
+
import { DeviceStateStore, createEmptyDeviceState } from '../src/device/DeviceStateStore';
|
|
4
|
+
|
|
5
|
+
describe('DeviceStateStore', () => {
|
|
6
|
+
test('merges patches, ignores undefined and recomputes displayName', () => {
|
|
7
|
+
const store = new DeviceStateStore(
|
|
8
|
+
createEmptyDeviceState({
|
|
9
|
+
deviceType: EDeviceType.Pro2,
|
|
10
|
+
firmwareType: EFirmwareType.Universal,
|
|
11
|
+
})
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
store.update({ identity: { bleName: 'Pro2 1234', label: null } }, 'initialize');
|
|
15
|
+
const result = store.update(
|
|
16
|
+
{ identity: { label: 'My Wallet', bleName: undefined } },
|
|
17
|
+
'apply-settings'
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
expect(result.state.identity).toMatchObject({
|
|
21
|
+
label: 'My Wallet',
|
|
22
|
+
bleName: 'Pro2 1234',
|
|
23
|
+
displayName: 'My Wallet',
|
|
24
|
+
});
|
|
25
|
+
expect(result.revision).toBe(2);
|
|
26
|
+
expect(result.changedKeys).toContain('identity.label');
|
|
27
|
+
expect(result.changedKeys).toContain('identity.displayName');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('does not advance revision when the patch has no real changes', () => {
|
|
31
|
+
const store = new DeviceStateStore(createEmptyDeviceState());
|
|
32
|
+
const first = store.update({ status: { unlocked: null } }, 'device-status');
|
|
33
|
+
const second = store.update({ status: { unlocked: null } }, 'device-status');
|
|
34
|
+
|
|
35
|
+
expect(first.revision).toBe(0);
|
|
36
|
+
expect(second.revision).toBe(0);
|
|
37
|
+
expect(second.changedKeys).toEqual([]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('stores the wire protocol version independently from the protocol family', () => {
|
|
41
|
+
const store = new DeviceStateStore(createEmptyDeviceState());
|
|
42
|
+
|
|
43
|
+
const result = store.update({ protocol: 'V2', protocolVersion: 7 }, 'device-info');
|
|
44
|
+
|
|
45
|
+
expect(result.state.protocol).toBe('V2');
|
|
46
|
+
expect(result.state.protocolVersion).toBe(7);
|
|
47
|
+
expect(result.changedKeys).toContain('protocolVersion');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('clears only ephemeral session state', () => {
|
|
51
|
+
const store = new DeviceStateStore(createEmptyDeviceState());
|
|
52
|
+
store.update(
|
|
53
|
+
{
|
|
54
|
+
identity: { label: 'Kept' },
|
|
55
|
+
session: { sessionId: 'session-1', passphraseState: 'state-1' },
|
|
56
|
+
},
|
|
57
|
+
'initialize'
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const result = store.clearSession('transport-reconnect');
|
|
61
|
+
|
|
62
|
+
expect(result?.state.identity.label).toBe('Kept');
|
|
63
|
+
expect(result?.state.session).toBeUndefined();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('merges raw protocol sources instead of replacing the previous source', () => {
|
|
67
|
+
const store = new DeviceStateStore(createEmptyDeviceState());
|
|
68
|
+
const deviceInfo = { protocol_version: 2, hw: { serial_no: 'SERIAL-1' } };
|
|
69
|
+
const deviceStatus = { device_id: 'DEVICE-1', unlocked: true };
|
|
70
|
+
|
|
71
|
+
store.update({ raw: { protocolV2DeviceInfo: deviceInfo } }, 'device-info');
|
|
72
|
+
const result = store.update({ raw: { protocolV2DeviceStatus: deviceStatus } }, 'device-status');
|
|
73
|
+
|
|
74
|
+
expect(result.state.raw).toEqual({
|
|
75
|
+
protocolV2DeviceInfo: deviceInfo,
|
|
76
|
+
protocolV2DeviceStatus: deviceStatus,
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('removes only the explicitly cleared raw protocol source', () => {
|
|
81
|
+
const store = new DeviceStateStore(createEmptyDeviceState());
|
|
82
|
+
const deviceInfo = { protocol_version: 2, hw: { serial_no: 'SERIAL-1' } };
|
|
83
|
+
const deviceStatus = { device_id: 'DEVICE-1', unlocked: true };
|
|
84
|
+
|
|
85
|
+
store.update(
|
|
86
|
+
{
|
|
87
|
+
raw: {
|
|
88
|
+
protocolV2DeviceInfo: deviceInfo,
|
|
89
|
+
protocolV2DeviceStatus: deviceStatus,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
'initialize'
|
|
93
|
+
);
|
|
94
|
+
const result = store.update({ raw: { protocolV2DeviceStatus: null } }, 'device-info');
|
|
95
|
+
|
|
96
|
+
expect(result.state.raw).toEqual({
|
|
97
|
+
protocolV2DeviceInfo: deviceInfo,
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test.each([
|
|
102
|
+
[EDeviceType.Classic1s, 'OneKey Classic 1S'],
|
|
103
|
+
[EDeviceType.ClassicPure, 'OneKey Classic 1S Pure'],
|
|
104
|
+
[EDeviceType.Touch, 'OneKey Touch'],
|
|
105
|
+
[EDeviceType.Pro, 'OneKey Pro'],
|
|
106
|
+
[EDeviceType.Pro2, 'OneKey Pro 2'],
|
|
107
|
+
] as const)(
|
|
108
|
+
'uses the product display name for %s when label and BLE name are absent',
|
|
109
|
+
(type, name) => {
|
|
110
|
+
const state = createEmptyDeviceState({ deviceType: type });
|
|
111
|
+
|
|
112
|
+
expect(state.identity.displayName).toBe(name);
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
});
|
|
@@ -3,6 +3,8 @@ import {
|
|
|
3
3
|
DeviceWalletSessionStore,
|
|
4
4
|
deviceWalletSessionStore,
|
|
5
5
|
} from '../src/device/DeviceWalletSessionStore';
|
|
6
|
+
import { Device } from '../src/device/Device';
|
|
7
|
+
import { DevicePool } from '../src/device/DevicePool';
|
|
6
8
|
import { createCoreApi } from '../src/inject';
|
|
7
9
|
|
|
8
10
|
jest.mock('../src/data/config', () => ({
|
|
@@ -73,6 +75,50 @@ describe('DeviceWalletSessionStore', () => {
|
|
|
73
75
|
describe('ClearSessionCache', () => {
|
|
74
76
|
beforeEach(() => {
|
|
75
77
|
deviceWalletSessionStore.clear();
|
|
78
|
+
DevicePool.devicesCache = {};
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
afterEach(() => {
|
|
82
|
+
DevicePool.devicesCache = {};
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('clears matching sessions from both runtime stores', async () => {
|
|
86
|
+
const matchingDevice = Device.fromDescriptor({ id: 'one', path: 'one' } as never);
|
|
87
|
+
matchingDevice.updateState(
|
|
88
|
+
{
|
|
89
|
+
protocol: 'V1',
|
|
90
|
+
identity: { deviceId: 'device-1' },
|
|
91
|
+
session: { sessionId: 'session-a', passphraseState: 'hidden-a' },
|
|
92
|
+
},
|
|
93
|
+
'initialize'
|
|
94
|
+
);
|
|
95
|
+
const otherDevice = Device.fromDescriptor({ id: 'two', path: 'two' } as never);
|
|
96
|
+
otherDevice.updateState(
|
|
97
|
+
{
|
|
98
|
+
protocol: 'V1',
|
|
99
|
+
identity: { deviceId: 'device-2' },
|
|
100
|
+
session: { sessionId: 'session-b', passphraseState: 'hidden-a' },
|
|
101
|
+
},
|
|
102
|
+
'initialize'
|
|
103
|
+
);
|
|
104
|
+
DevicePool.devicesCache = { one: matchingDevice, two: otherDevice };
|
|
105
|
+
deviceWalletSessionStore.set('device-1', 'hidden-a', 'session-a');
|
|
106
|
+
|
|
107
|
+
const method = new ClearSessionCache({
|
|
108
|
+
payload: {
|
|
109
|
+
method: 'clearSessionCache',
|
|
110
|
+
deviceId: 'device-1',
|
|
111
|
+
passphraseState: 'hidden-a',
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
method.init();
|
|
115
|
+
await method.run();
|
|
116
|
+
|
|
117
|
+
expect((matchingDevice.state as any)?.session).toBeUndefined();
|
|
118
|
+
expect((otherDevice.state as any)?.session).toEqual({
|
|
119
|
+
sessionId: 'session-b',
|
|
120
|
+
passphraseState: 'hidden-a',
|
|
121
|
+
});
|
|
76
122
|
});
|
|
77
123
|
|
|
78
124
|
test('clears one wallet without using a device', async () => {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { EDeviceType } from '@onekeyfe/hd-shared';
|
|
2
2
|
|
|
3
3
|
import DataManager from '../src/data-manager/DataManager';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
getSupportProtocolV1MessageSchema,
|
|
6
|
+
supportInputPinOnSoftware,
|
|
7
|
+
} from '../src/utils/deviceFeaturesUtils';
|
|
5
8
|
|
|
6
9
|
import type { Features } from '../src/types';
|
|
7
10
|
|
|
@@ -24,4 +27,13 @@ describe('getSupportProtocolV1MessageSchema', () => {
|
|
|
24
27
|
expect(result.protocolV1MessageSchema).toBe('v1CurrentSchema');
|
|
25
28
|
expect(result.messages).toBe(DataManager.messages.v1CurrentSchema);
|
|
26
29
|
});
|
|
30
|
+
|
|
31
|
+
test('Pro2 never supports entering PIN in software', () => {
|
|
32
|
+
const features = {
|
|
33
|
+
deviceType: EDeviceType.Pro2,
|
|
34
|
+
firmwareVersion: '9.9.9',
|
|
35
|
+
} as Features;
|
|
36
|
+
|
|
37
|
+
expect(supportInputPinOnSoftware(features)).toEqual({ support: false });
|
|
38
|
+
});
|
|
27
39
|
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { EDeviceType } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
getAutoLockOptions,
|
|
5
|
+
getAutoShutDownOptions,
|
|
6
|
+
getLanguageConfig,
|
|
7
|
+
} from '../src/utils/deviceSettings';
|
|
8
|
+
|
|
9
|
+
describe('Pro 2 device settings options', () => {
|
|
10
|
+
test('returns the firmware-supported BCP-47 languages', () => {
|
|
11
|
+
expect(getLanguageConfig(EDeviceType.Pro2)).toEqual([
|
|
12
|
+
{ code: 'en-Latn-US', label: 'English' },
|
|
13
|
+
{ code: 'zh-Hans-CN', label: '简体中文' },
|
|
14
|
+
{ code: 'zh-Hant-HK', label: '繁體中文(香港)' },
|
|
15
|
+
{ code: 'zh-Hant-TW', label: '繁體中文(台灣)' },
|
|
16
|
+
{ code: 'ja-Jpan-JP', label: '日本語' },
|
|
17
|
+
{ code: 'ko-Kore-KR', label: '한국어' },
|
|
18
|
+
{ code: 'fr-Latn-FR', label: 'Français' },
|
|
19
|
+
{ code: 'de-Latn-DE', label: 'Deutsch' },
|
|
20
|
+
{ code: 'ru-Cyrl-RU', label: 'Русский' },
|
|
21
|
+
{ code: 'es-Latn-ES', label: 'Español' },
|
|
22
|
+
{ code: 'it-Latn-IT', label: 'Italiano' },
|
|
23
|
+
{ code: 'pt-Latn-BR', label: 'Portuguese (Brazil)' },
|
|
24
|
+
{ code: 'vi-Latn-VN', label: 'Tiếng Việt' },
|
|
25
|
+
{ code: 'tr-Latn-TR', label: 'Türkçe' },
|
|
26
|
+
{ code: 'id-Latn-ID', label: 'Bahasa Indonesia' },
|
|
27
|
+
{ code: 'fil-Latn-PH', label: 'Filipino' },
|
|
28
|
+
{ code: 'uk-Cyrl-UA', label: 'Українська' },
|
|
29
|
+
]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('returns the firmware-supported auto-lock delays', () => {
|
|
33
|
+
expect(getAutoLockOptions(EDeviceType.Pro2)).toEqual([
|
|
34
|
+
{ seconds: 30, minute: 0, hour: 0, day: 0 },
|
|
35
|
+
{ seconds: 0, minute: 1, hour: 0, day: 0 },
|
|
36
|
+
{ seconds: 0, minute: 2, hour: 0, day: 0 },
|
|
37
|
+
{ seconds: 0, minute: 5, hour: 0, day: 0 },
|
|
38
|
+
{ seconds: 0, minute: 10, hour: 0, day: 0 },
|
|
39
|
+
{ seconds: 0, minute: 30, hour: 0, day: 0 },
|
|
40
|
+
{ seconds: 0, minute: 0, hour: 0, day: 0 },
|
|
41
|
+
]);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('returns the firmware-supported auto-shutdown delays', () => {
|
|
45
|
+
expect(getAutoShutDownOptions(EDeviceType.Pro2)).toEqual([
|
|
46
|
+
{ seconds: 0, minute: 1, hour: 0, day: 0 },
|
|
47
|
+
{ seconds: 0, minute: 2, hour: 0, day: 0 },
|
|
48
|
+
{ seconds: 0, minute: 5, hour: 0, day: 0 },
|
|
49
|
+
{ seconds: 0, minute: 10, hour: 0, day: 0 },
|
|
50
|
+
{ seconds: 0, minute: 30, hour: 0, day: 0 },
|
|
51
|
+
{ seconds: 0, minute: 0, hour: 0, day: 0 },
|
|
52
|
+
]);
|
|
53
|
+
});
|
|
54
|
+
});
|