@onekeyfe/hd-core 1.2.0-alpha.99 → 1.2.1-alpha.0
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__/AllNetworkGetAddressBase.tracing.test.ts +20 -4
- package/__tests__/DeviceCommands.test.ts +203 -27
- package/__tests__/base64Data.test.ts +69 -0
- package/__tests__/check-all-firmware-release-protocol-v2.test.ts +48 -2
- package/__tests__/check-firmware-release-protocol-v2.test.ts +82 -13
- package/__tests__/device-connector-protocol.test.ts +21 -0
- package/__tests__/device-lifecycle-events.test.ts +427 -7
- package/__tests__/device-pool-state.test.ts +25 -0
- package/__tests__/device-settings.test.ts +237 -9
- package/__tests__/device-state-events.test.ts +2 -2
- package/__tests__/device-state-mapper.test.ts +61 -5
- package/__tests__/device-utils.test.ts +15 -1
- package/__tests__/device-wallet-session-store.test.ts +147 -21
- package/__tests__/deviceSettings.test.ts +7 -3
- package/__tests__/deviceUploadNft.test.ts +36 -4
- package/__tests__/firmware-update/device-update-bootloader.test.ts +13 -3
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +61 -9
- package/__tests__/firmware-update/firmware-prepared-host-digest.test.ts +19 -9
- package/__tests__/firmware-update/firmware-prepared-resource-archive.test.ts +21 -0
- package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +63 -0
- package/__tests__/firmware-update/firmware-update-plan.test.ts +59 -55
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +19 -5
- package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +116 -0
- package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +979 -0
- package/__tests__/firmware-update/firmware-update-v4-parameters.test.ts +85 -0
- package/__tests__/get-device-state.test.ts +60 -21
- package/__tests__/logBlockEvent.test.ts +13 -1
- package/__tests__/open-wallet-session.test.ts +127 -1
- package/__tests__/protocol-v2-firmware-targets.test.ts +23 -0
- package/__tests__/protocol-v2-resources.test.ts +185 -88
- package/__tests__/protocol-v2-unlock-policy.test.ts +235 -2
- package/__tests__/protocol-v2.test.ts +2199 -486
- package/__tests__/refresh-device-state.test.ts +3 -1
- package/__tests__/resourceBase64Boundary.test.ts +48 -0
- package/__tests__/search-devices.test.ts +79 -32
- package/__tests__/ton-sign-message.test.ts +84 -0
- package/dist/api/BaseMethod.d.ts +2 -1
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +20 -6
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts +1 -1
- package/dist/api/UploadPortfolio.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/device/DeviceChangePin.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/device/DeviceVerify.d.ts +1 -0
- package/dist/api/device/DeviceVerify.d.ts.map +1 -1
- package/dist/api/device/DeviceWipe.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareArtifactSource.d.ts +5 -1
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -1
- package/dist/api/firmware/FirmwarePreparedResourceArchive.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +2 -2
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -15
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +3 -2
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/protocolV2Release.d.ts.map +1 -1
- package/dist/api/helpers/base64Data.d.ts +16 -0
- package/dist/api/helpers/base64Data.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +3 -1
- package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts +1 -1
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceReboot.d.ts +1 -1
- package/dist/api/protocol-v2/DeviceReboot.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts +2 -3
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +2 -3
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
- package/dist/core/index.d.ts +6 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +4 -3
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/TransportManager.d.ts.map +1 -1
- package/dist/device/Device.d.ts +16 -3
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +4 -4
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DeviceConnector.d.ts +1 -1
- package/dist/device/DeviceConnector.d.ts.map +1 -1
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/device/DeviceStateMapper.d.ts.map +1 -1
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +3 -0
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +54 -84
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2150 -1469
- package/dist/protocols/protocol-v2/features.d.ts +13 -5
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/index.d.ts +2 -2
- package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts +12 -7
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +3 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +3 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdatePlan.d.ts +2 -2
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +1 -1
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts.map +1 -1
- package/dist/types/settings.d.ts +3 -31
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +3 -0
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/deviceSettings.d.ts +1 -0
- package/dist/utils/deviceSettings.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.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/pro2Nft.d.ts +7 -0
- package/dist/utils/pro2Nft.d.ts.map +1 -1
- package/package.json +6 -4
- package/src/api/BaseMethod.ts +8 -1
- package/src/api/CheckAllFirmwareRelease.ts +2 -4
- package/src/api/CheckBLEFirmwareRelease.ts +2 -2
- package/src/api/CheckBootloaderRelease.ts +3 -2
- package/src/api/CheckFirmwareRelease.ts +2 -2
- package/src/api/FirmwareUpdateV2.ts +12 -9
- package/src/api/FirmwareUpdateV3.ts +29 -19
- package/src/api/FirmwareUpdateV4.ts +934 -739
- package/src/api/OpenWalletSession.ts +39 -9
- package/src/api/PromptWebDeviceAccess.ts +2 -2
- package/src/api/SearchDevices.ts +6 -3
- package/src/api/UploadPortfolio.ts +9 -2
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +2 -1
- package/src/api/device/DeviceChangePin.ts +4 -1
- package/src/api/device/DeviceRebootToBoardloader.ts +3 -1
- package/src/api/device/DeviceRebootToBootloader.ts +3 -1
- package/src/api/device/DeviceSettings.ts +34 -20
- package/src/api/device/DeviceVerify.ts +25 -0
- package/src/api/device/DeviceWipe.ts +4 -1
- package/src/api/firmware/FirmwareArtifactSource.ts +41 -14
- package/src/api/firmware/FirmwarePreparedResourceArchive.ts +16 -27
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +9 -3
- package/src/api/firmware/FirmwareUpdatePlan.ts +37 -77
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +10 -6
- package/src/api/firmware/protocolV2Release.ts +7 -2
- package/src/api/helpers/base64Data.ts +85 -0
- package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
- package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +6 -28
- package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +7 -1
- package/src/api/protocol-v2/DeviceInfoGet.ts +3 -3
- package/src/api/protocol-v2/DeviceReboot.ts +5 -0
- package/src/api/protocol-v2/DeviceUploadNft.ts +61 -9
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +53 -19
- package/src/api/protocol-v2/helpers.ts +8 -0
- package/src/api/ton/TonSignMessage.ts +5 -3
- package/src/core/index.ts +264 -55
- package/src/data/messages/messages-protocol-v2.json +140 -13
- package/src/data-manager/DataManager.ts +46 -39
- package/src/data-manager/TransportManager.ts +3 -1
- package/src/device/Device.ts +210 -44
- package/src/device/DeviceCommands.ts +27 -18
- package/src/device/DeviceConnector.ts +17 -3
- package/src/device/DevicePool.ts +9 -2
- package/src/device/DeviceStateMapper.ts +30 -24
- package/src/deviceProfile/buildDeviceFeatures.ts +10 -5
- package/src/events/logBlockEvent.ts +14 -1
- package/src/events/ui-request.ts +3 -0
- package/src/index.ts +0 -10
- package/src/protocols/protocol-v2/features.ts +22 -5
- package/src/protocols/protocol-v2/index.ts +2 -0
- package/src/protocols/protocol-v2/resources.ts +110 -147
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +13 -1
- package/src/protocols/protocol-v2/walletSession.ts +65 -22
- package/src/types/api/firmwareUpdate.ts +1 -1
- package/src/types/api/firmwareUpdatePlan.ts +2 -2
- package/src/types/api/protocolV2.ts +1 -1
- package/src/types/device.ts +2 -1
- package/src/types/settings.ts +6 -34
- package/src/utils/deviceFeaturesCompat.ts +9 -4
- package/src/utils/deviceFeaturesUtils.ts +4 -0
- package/src/utils/deviceInfoUtils.ts +9 -2
- package/src/utils/deviceSettings.ts +11 -4
- package/src/utils/index.ts +1 -0
- package/src/utils/pro2Nft.ts +31 -8
- package/__tests__/firmware-memory-host.test.ts +0 -126
- package/dist/api/firmware/FirmwareMemoryHost.d.ts +0 -22
- package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +0 -1
- package/src/api/firmware/FirmwareMemoryHost.ts +0 -143
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
3
|
+
import FirmwareUpdateV4 from '../../src/api/FirmwareUpdateV4';
|
|
4
|
+
|
|
5
|
+
jest.mock('../../src/data/config', () => ({
|
|
6
|
+
getSDKVersion: jest.fn(() => '1.0.0'),
|
|
7
|
+
DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
const createMethod = (params: Record<string, unknown>) =>
|
|
11
|
+
new FirmwareUpdateV4({
|
|
12
|
+
id: 1,
|
|
13
|
+
payload: {
|
|
14
|
+
method: 'firmwareUpdateV4',
|
|
15
|
+
platform: 'desktop',
|
|
16
|
+
...params,
|
|
17
|
+
} as any,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const captureInitError = (method: FirmwareUpdateV4): unknown => {
|
|
21
|
+
try {
|
|
22
|
+
method.init();
|
|
23
|
+
} catch (error) {
|
|
24
|
+
return error;
|
|
25
|
+
}
|
|
26
|
+
throw new Error('Expected FirmwareUpdateV4.init() to throw');
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
describe('FirmwareUpdateV4 parameter migration', () => {
|
|
30
|
+
test('rejects host binding generation when preparedPlan is absent', () => {
|
|
31
|
+
const error = captureInitError(
|
|
32
|
+
createMethod({
|
|
33
|
+
hostBindingGeneration: 1,
|
|
34
|
+
componentArtifacts: {
|
|
35
|
+
boot: {
|
|
36
|
+
artifactRef: 'bootloader',
|
|
37
|
+
size: 3,
|
|
38
|
+
sha256: 'a'.repeat(64),
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
expect(error).toMatchObject({
|
|
45
|
+
errorCode: HardwareErrorCode.CallMethodInvalidParameter,
|
|
46
|
+
message: expect.stringContaining(
|
|
47
|
+
'hostBindingGeneration requires preparedPlan for remote updates'
|
|
48
|
+
),
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test.each(['resourceFiles', 'resourceBundleArtifacts'])(
|
|
53
|
+
'rejects removed %s input with a Remote/Local migration hint',
|
|
54
|
+
removedInput => {
|
|
55
|
+
const error = captureInitError(
|
|
56
|
+
createMethod({
|
|
57
|
+
targetsToUpdate: ['resource'],
|
|
58
|
+
[removedInput]: [],
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
expect(error).toMatchObject({
|
|
63
|
+
errorCode: HardwareErrorCode.CallMethodInvalidParameter,
|
|
64
|
+
message: expect.stringContaining(removedInput),
|
|
65
|
+
});
|
|
66
|
+
expect(error).toMatchObject({
|
|
67
|
+
message: expect.stringContaining('resourceArchiveBinary for local updates'),
|
|
68
|
+
});
|
|
69
|
+
expect(error).toMatchObject({
|
|
70
|
+
message: expect.stringContaining(
|
|
71
|
+
'preparedPlan with hostBindingGeneration for remote updates'
|
|
72
|
+
),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
test('keeps direct Local inputs independent from host bindings', () => {
|
|
78
|
+
const method = createMethod({
|
|
79
|
+
targetsToUpdate: ['boot'],
|
|
80
|
+
bootloaderBinary: new Uint8Array([1, 2, 3]).buffer,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
expect(() => method.init()).not.toThrow();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -123,7 +123,7 @@ describe('getDeviceState', () => {
|
|
|
123
123
|
message: {
|
|
124
124
|
protocol_version: 2,
|
|
125
125
|
hw: { serial_no: 'SERIAL-1' },
|
|
126
|
-
|
|
126
|
+
main_mcu: { application: { version: '5.0.0' } },
|
|
127
127
|
},
|
|
128
128
|
};
|
|
129
129
|
}
|
|
@@ -150,7 +150,7 @@ describe('getDeviceState', () => {
|
|
|
150
150
|
message: {
|
|
151
151
|
protocol_version: 2,
|
|
152
152
|
hw: { serial_no: 'SERIAL-1' },
|
|
153
|
-
|
|
153
|
+
main_mcu: { application: { version: '5.0.0', hash: 'HASH-1' } },
|
|
154
154
|
},
|
|
155
155
|
};
|
|
156
156
|
}
|
|
@@ -182,7 +182,7 @@ describe('getDeviceState', () => {
|
|
|
182
182
|
message: {
|
|
183
183
|
protocol_version: 2,
|
|
184
184
|
hw: { serial_no: 'SERIAL-1' },
|
|
185
|
-
|
|
185
|
+
main_mcu: { application: { version: '5.0.0' } },
|
|
186
186
|
se1: { application: { version: '1.0.0' } },
|
|
187
187
|
},
|
|
188
188
|
});
|
|
@@ -202,25 +202,61 @@ describe('getDeviceState', () => {
|
|
|
202
202
|
expect(state.versions.se01).toBe('1.0.0');
|
|
203
203
|
});
|
|
204
204
|
|
|
205
|
-
test.each([
|
|
206
|
-
'
|
|
207
|
-
|
|
205
|
+
test.each([
|
|
206
|
+
['bootloader', EDeviceType.Pro2, DeviceType.PRO2],
|
|
207
|
+
['romloader', EDeviceType.Pro2, DeviceType.PRO2],
|
|
208
|
+
['bootloader', EDeviceType.Neo, DeviceType.NEO],
|
|
209
|
+
['romloader', EDeviceType.Neo, DeviceType.NEO],
|
|
210
|
+
] as const)(
|
|
211
|
+
'refreshes cached %s state after %s reboots into the application',
|
|
212
|
+
async (mode, deviceType, protocolV2DeviceType) => {
|
|
208
213
|
const typedCall = jest.fn().mockImplementation((requestType: string) => {
|
|
209
|
-
if (requestType === '
|
|
214
|
+
if (requestType === 'ProtocolInfoRequest') {
|
|
215
|
+
return { message: protocolV2ApplicationInfo };
|
|
216
|
+
}
|
|
217
|
+
if (requestType === 'DeviceStatusGet') {
|
|
210
218
|
return {
|
|
211
|
-
message: {
|
|
212
|
-
|
|
213
|
-
|
|
219
|
+
message: { init_states: true, unlocked: true, device_id: 'wallet-1' },
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
throw new Error(`Unexpected request: ${requestType}`);
|
|
223
|
+
});
|
|
224
|
+
const device = createV2Device(typedCall);
|
|
225
|
+
device.updateState(
|
|
226
|
+
{
|
|
227
|
+
protocol: 'V2',
|
|
228
|
+
identity: { deviceType },
|
|
229
|
+
status: { mode },
|
|
230
|
+
raw: {
|
|
231
|
+
protocolV2DeviceInfo: {
|
|
232
|
+
hw: { Device_type: protocolV2DeviceType, serial_no: 'SERIAL-1' },
|
|
233
|
+
main_mcu:
|
|
214
234
|
mode === 'romloader'
|
|
215
235
|
? { romloader: { version: '1.0.0' } }
|
|
216
236
|
: { bootloader: { version: '1.0.0' } },
|
|
217
237
|
},
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
238
|
+
protocolV2ProtocolInfo: getProtocolV2LoaderInfo(mode),
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
'initialize'
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
const state = await device.getDeviceState({ refreshSections: ['status'] });
|
|
245
|
+
|
|
246
|
+
expect(state.status.mode).toBe('normal');
|
|
247
|
+
expect(state.identity.deviceId).toBe('wallet-1');
|
|
248
|
+
expect(typedCall.mock.calls.map(call => call[0])).toEqual([
|
|
249
|
+
'ProtocolInfoRequest',
|
|
250
|
+
'DeviceStatusGet',
|
|
251
|
+
]);
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
test.each(['bootloader', 'romloader'] as const)(
|
|
256
|
+
'keeps live %s mode after refreshing cached loader state',
|
|
257
|
+
async mode => {
|
|
258
|
+
const typedCall = jest.fn().mockResolvedValue({
|
|
259
|
+
message: getProtocolV2LoaderInfo(mode),
|
|
224
260
|
});
|
|
225
261
|
const device = createV2Device(typedCall);
|
|
226
262
|
device.updateState(
|
|
@@ -236,7 +272,10 @@ describe('getDeviceState', () => {
|
|
|
236
272
|
const state = await device.getDeviceState({ refreshSections: ['status'] });
|
|
237
273
|
|
|
238
274
|
expect(state.status.mode).toBe(mode);
|
|
239
|
-
expect(typedCall).
|
|
275
|
+
expect(typedCall).toHaveBeenCalledTimes(1);
|
|
276
|
+
expect(typedCall).toHaveBeenCalledWith('ProtocolInfoRequest', 'ProtocolInfo', {
|
|
277
|
+
eventless_wallet_session: true,
|
|
278
|
+
});
|
|
240
279
|
}
|
|
241
280
|
);
|
|
242
281
|
|
|
@@ -246,7 +285,7 @@ describe('getDeviceState', () => {
|
|
|
246
285
|
return {
|
|
247
286
|
message: {
|
|
248
287
|
hw: { serial_no: 'SERIAL-1' },
|
|
249
|
-
|
|
288
|
+
main_mcu: { application: { version: '5.0.0' } },
|
|
250
289
|
},
|
|
251
290
|
};
|
|
252
291
|
}
|
|
@@ -315,7 +354,7 @@ describe('getDeviceState', () => {
|
|
|
315
354
|
return {
|
|
316
355
|
message: {
|
|
317
356
|
hw: { serial_no: 'SERIAL-1' },
|
|
318
|
-
|
|
357
|
+
main_mcu: { application: { version: '5.0.0' } },
|
|
319
358
|
},
|
|
320
359
|
};
|
|
321
360
|
}
|
|
@@ -358,7 +397,7 @@ describe('getDeviceState', () => {
|
|
|
358
397
|
return {
|
|
359
398
|
message: {
|
|
360
399
|
hw: { serial_no: 'SERIAL-1' },
|
|
361
|
-
|
|
400
|
+
main_mcu: { application: { version: '5.0.0' } },
|
|
362
401
|
},
|
|
363
402
|
};
|
|
364
403
|
}
|
|
@@ -543,7 +582,7 @@ describe('getDeviceState', () => {
|
|
|
543
582
|
message: {
|
|
544
583
|
protocol_version: 1,
|
|
545
584
|
hw: { serial_no: 'SERIAL-1' },
|
|
546
|
-
|
|
585
|
+
main_mcu: { bootloader: { version: '1.0.0' } },
|
|
547
586
|
se1: {},
|
|
548
587
|
},
|
|
549
588
|
};
|
|
@@ -104,7 +104,19 @@ describe('getLogBlockLabel', () => {
|
|
|
104
104
|
});
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
it.each(['deviceUploadNft', 'deviceUploadWallpaper', 'uploadPortfolio'
|
|
107
|
+
it.each(['deviceUploadNft', 'deviceUploadWallpaper', 'uploadPortfolio'])(
|
|
108
|
+
'skips large Base64 resource payload logging for %s',
|
|
109
|
+
method => {
|
|
110
|
+
const request = { method, path: 'resource.bin', data: 'A'.repeat(1024 * 1024) };
|
|
111
|
+
expect(getLogBlockLabel(request)).toBe(method);
|
|
112
|
+
expect(getSafeLogPayload(request, method)).toEqual({
|
|
113
|
+
method,
|
|
114
|
+
payload: '[REDACTED]',
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
it.each(['fileWrite', 'fileRead'])(
|
|
108
120
|
'keeps metadata and replaces binary payloads with their size for %s',
|
|
109
121
|
method => {
|
|
110
122
|
const request = { method, path: 'resource.bin', data: new Uint8Array(1024) };
|
|
@@ -148,7 +148,7 @@ describe('openWalletSession', () => {
|
|
|
148
148
|
});
|
|
149
149
|
});
|
|
150
150
|
|
|
151
|
-
test('
|
|
151
|
+
test('selects the Main PIN before opening the standard wallet when passphrase is disabled', async () => {
|
|
152
152
|
const typedCall = jest.fn((request: string) => {
|
|
153
153
|
if (request === 'ProtocolInfoRequest') {
|
|
154
154
|
return { message: { version: 2 } };
|
|
@@ -167,6 +167,11 @@ describe('openWalletSession', () => {
|
|
|
167
167
|
|
|
168
168
|
await getProtocolV2WalletSession(device as any, { onlyMainPin: true });
|
|
169
169
|
|
|
170
|
+
expect(device.unlockDevice).toHaveBeenCalledWith(DeviceSessionPinType.Main, {
|
|
171
|
+
source: 'wallet-session-coordinator',
|
|
172
|
+
reason: 'open-wallet',
|
|
173
|
+
deviceOnly: true,
|
|
174
|
+
});
|
|
170
175
|
expect(typedCall).not.toHaveBeenCalledWith(
|
|
171
176
|
'DeviceSessionAskPassphrase',
|
|
172
177
|
'Success',
|
|
@@ -177,6 +182,34 @@ describe('openWalletSession', () => {
|
|
|
177
182
|
});
|
|
178
183
|
});
|
|
179
184
|
|
|
185
|
+
test('reuses a Main PIN selected by the current preflight when passphrase is disabled', async () => {
|
|
186
|
+
const typedCall = jest.fn((request: string) => {
|
|
187
|
+
if (request === 'ProtocolInfoRequest') {
|
|
188
|
+
return { message: { version: 2 } };
|
|
189
|
+
}
|
|
190
|
+
if (request === 'DeviceSessionGet') {
|
|
191
|
+
return {
|
|
192
|
+
message: {
|
|
193
|
+
btc_test_address: 'standard-state',
|
|
194
|
+
session_id: 'standard-session',
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
throw new Error(`Unexpected request: ${request}`);
|
|
199
|
+
});
|
|
200
|
+
const device = createDevice({ passphraseProtection: false, typedCall });
|
|
201
|
+
|
|
202
|
+
await getProtocolV2WalletSession(device as any, {
|
|
203
|
+
onlyMainPin: true,
|
|
204
|
+
mainPinSelected: true,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
expect(device.unlockDevice).not.toHaveBeenCalled();
|
|
208
|
+
expect(typedCall).toHaveBeenCalledWith('DeviceSessionGet', 'DeviceSession', {
|
|
209
|
+
seed_domains: [],
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
180
213
|
test('does not treat an Attach PIN DeviceStatus as the Main wallet', async () => {
|
|
181
214
|
const typedCall = jest.fn((request: string) => {
|
|
182
215
|
if (request === 'ProtocolInfoRequest') {
|
|
@@ -1114,6 +1147,68 @@ describe('openWalletSession', () => {
|
|
|
1114
1147
|
expect(device.getDeviceState).toHaveBeenCalledTimes(2);
|
|
1115
1148
|
});
|
|
1116
1149
|
|
|
1150
|
+
test('does not restrict a locked hidden-wallet selection to the Main PIN', async () => {
|
|
1151
|
+
const typedCall = jest
|
|
1152
|
+
.fn()
|
|
1153
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
1154
|
+
.mockResolvedValueOnce({ message: {} })
|
|
1155
|
+
.mockResolvedValueOnce({
|
|
1156
|
+
message: {
|
|
1157
|
+
btc_test_address: 'hidden-state',
|
|
1158
|
+
session_id: 'hidden-session',
|
|
1159
|
+
},
|
|
1160
|
+
});
|
|
1161
|
+
const promptPassphrase = jest.fn().mockResolvedValue({ passphrase: 'host hidden wallet' });
|
|
1162
|
+
const method = new OpenWalletSession({
|
|
1163
|
+
payload: { method: 'openWalletSession', connectId: 'connect-id', mode: 'select-hidden' },
|
|
1164
|
+
});
|
|
1165
|
+
method.init();
|
|
1166
|
+
const device = createDevice({ typedCall, promptPassphrase });
|
|
1167
|
+
device.features.unlocked = false;
|
|
1168
|
+
device.getDeviceState = jest
|
|
1169
|
+
.fn()
|
|
1170
|
+
.mockResolvedValueOnce({
|
|
1171
|
+
identity: { deviceId: undefined },
|
|
1172
|
+
status: { unlocked: false, passphraseProtection: true },
|
|
1173
|
+
})
|
|
1174
|
+
.mockResolvedValueOnce({
|
|
1175
|
+
identity: { deviceId: 'device-1' },
|
|
1176
|
+
status: {
|
|
1177
|
+
unlocked: true,
|
|
1178
|
+
passphraseProtection: true,
|
|
1179
|
+
unlockedAttachPin: false,
|
|
1180
|
+
},
|
|
1181
|
+
})
|
|
1182
|
+
.mockResolvedValueOnce({
|
|
1183
|
+
identity: { deviceId: 'device-1' },
|
|
1184
|
+
status: {
|
|
1185
|
+
unlocked: true,
|
|
1186
|
+
passphraseProtection: true,
|
|
1187
|
+
unlockedAttachPin: false,
|
|
1188
|
+
},
|
|
1189
|
+
});
|
|
1190
|
+
device.unlockDevice = jest.fn().mockImplementation(() => {
|
|
1191
|
+
device.features.unlocked = true;
|
|
1192
|
+
return Promise.resolve(device.features);
|
|
1193
|
+
});
|
|
1194
|
+
method.device = device as any;
|
|
1195
|
+
|
|
1196
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
1197
|
+
walletType: 'hidden',
|
|
1198
|
+
passphraseState: 'hidden-state',
|
|
1199
|
+
});
|
|
1200
|
+
expect(device.unlockDevice).toHaveBeenCalledWith(DeviceSessionPinType.Any, {
|
|
1201
|
+
source: 'unlock-coordinator',
|
|
1202
|
+
reason: 'device-locked',
|
|
1203
|
+
deviceOnly: true,
|
|
1204
|
+
method: 'openWalletSession',
|
|
1205
|
+
});
|
|
1206
|
+
expect(device.unlockDevice).not.toHaveBeenCalledWith(
|
|
1207
|
+
DeviceSessionPinType.Main,
|
|
1208
|
+
expect.anything()
|
|
1209
|
+
);
|
|
1210
|
+
});
|
|
1211
|
+
|
|
1117
1212
|
test('switches from Attach PIN to Main PIN before opening the standard wallet', async () => {
|
|
1118
1213
|
const typedCall = jest
|
|
1119
1214
|
.fn()
|
|
@@ -1208,6 +1303,37 @@ describe('openWalletSession', () => {
|
|
|
1208
1303
|
expect(deviceWalletSessionStore.get('device-1', 'hidden-state')).toBe('hidden-session');
|
|
1209
1304
|
});
|
|
1210
1305
|
|
|
1306
|
+
test('reuses the fresh unlock and wallet-selection statuses', async () => {
|
|
1307
|
+
const typedCall = jest
|
|
1308
|
+
.fn()
|
|
1309
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
1310
|
+
.mockResolvedValueOnce({ message: {} })
|
|
1311
|
+
.mockResolvedValueOnce({
|
|
1312
|
+
message: {
|
|
1313
|
+
btc_test_address: 'hidden-state',
|
|
1314
|
+
session_id: 'hidden-session',
|
|
1315
|
+
},
|
|
1316
|
+
});
|
|
1317
|
+
const promptPassphrase = jest.fn().mockResolvedValue({ passphrase: 'host hidden wallet' });
|
|
1318
|
+
const method = new OpenWalletSession({
|
|
1319
|
+
payload: { method: 'openWalletSession', connectId: 'connect-id', mode: 'select-hidden' },
|
|
1320
|
+
});
|
|
1321
|
+
method.init();
|
|
1322
|
+
method.protocolV2UnlockContext = {
|
|
1323
|
+
preflightCompleted: true,
|
|
1324
|
+
preflightStatusRefreshed: true,
|
|
1325
|
+
};
|
|
1326
|
+
const device = createDevice({ typedCall, promptPassphrase });
|
|
1327
|
+
method.device = device as any;
|
|
1328
|
+
|
|
1329
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
1330
|
+
walletType: 'hidden',
|
|
1331
|
+
passphraseState: 'hidden-state',
|
|
1332
|
+
});
|
|
1333
|
+
|
|
1334
|
+
expect(device.getDeviceState.mock.calls).toEqual([[], []]);
|
|
1335
|
+
});
|
|
1336
|
+
|
|
1211
1337
|
test('gets the prepared session after host passphrase entry', async () => {
|
|
1212
1338
|
const typedCall = jest
|
|
1213
1339
|
.fn()
|
|
@@ -11,6 +11,12 @@ jest.mock('../src/data/config', () => ({
|
|
|
11
11
|
getSDKVersion: () => '0.0.0-test',
|
|
12
12
|
}));
|
|
13
13
|
|
|
14
|
+
const componentArtifact = {
|
|
15
|
+
artifactRef: `fw:${'a'.repeat(64)}`,
|
|
16
|
+
size: 1,
|
|
17
|
+
sha256: 'b'.repeat(64),
|
|
18
|
+
};
|
|
19
|
+
|
|
14
20
|
describe('Protocol V2 firmware target contract', () => {
|
|
15
21
|
test('matches the current firmware-pro2 target ids', () => {
|
|
16
22
|
expect(ProtocolV2FirmwareTargetType).toEqual({
|
|
@@ -63,6 +69,10 @@ describe('Protocol V2 firmware target contract', () => {
|
|
|
63
69
|
targetsToUpdate: ['app_v1'] as Array<'app_v1'>,
|
|
64
70
|
se03Binary: new ArrayBuffer(1),
|
|
65
71
|
se04Binary: new ArrayBuffer(1),
|
|
72
|
+
componentArtifacts: {
|
|
73
|
+
se03: componentArtifact,
|
|
74
|
+
se04: componentArtifact,
|
|
75
|
+
},
|
|
66
76
|
};
|
|
67
77
|
|
|
68
78
|
expect(() =>
|
|
@@ -73,12 +83,25 @@ describe('Protocol V2 firmware target contract', () => {
|
|
|
73
83
|
);
|
|
74
84
|
});
|
|
75
85
|
|
|
86
|
+
test('rejects Neo SE03 and SE04 componentArtifacts without a target list', () => {
|
|
87
|
+
expect(() =>
|
|
88
|
+
assertProtocolV2FirmwareTargetsSupported(EDeviceType.Neo, {
|
|
89
|
+
platform: 'web',
|
|
90
|
+
componentArtifacts: {
|
|
91
|
+
se03: componentArtifact,
|
|
92
|
+
se04: componentArtifact,
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
).toThrow('Neo only supports SE01 and SE02; unsupported firmware targets: se03, se04');
|
|
96
|
+
});
|
|
97
|
+
|
|
76
98
|
test('keeps all four SE firmware targets available on Pro2', () => {
|
|
77
99
|
expect(() =>
|
|
78
100
|
assertProtocolV2FirmwareTargetsSupported(EDeviceType.Pro2, {
|
|
79
101
|
platform: 'web',
|
|
80
102
|
targetsToUpdate: ['se03'],
|
|
81
103
|
se04Binary: new ArrayBuffer(1),
|
|
104
|
+
componentArtifacts: { se04: componentArtifact },
|
|
82
105
|
})
|
|
83
106
|
).not.toThrow();
|
|
84
107
|
});
|