@onekeyfe/hd-core 1.2.0-alpha.19 → 1.2.0-alpha.20
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 +75 -0
- package/__tests__/DeviceCommands.test.ts +143 -7
- package/__tests__/RequestQueue.test.ts +106 -0
- package/__tests__/UploadPortfolio.test.ts +46 -0
- package/__tests__/core-dispose.test.ts +34 -0
- package/__tests__/core-error-output.test.ts +39 -0
- package/__tests__/device-lifecycle-events.test.ts +117 -0
- package/__tests__/device-pool-state.test.ts +20 -1
- package/__tests__/device-settings.test.ts +184 -6
- package/__tests__/device-state-events.test.ts +1 -2
- package/__tests__/device-state-mapper.test.ts +33 -26
- package/__tests__/device-state-store.test.ts +1 -34
- package/__tests__/device-utils.test.ts +106 -0
- package/__tests__/device-wallet-session-store.test.ts +65 -29
- package/__tests__/deviceSettings.test.ts +21 -12
- package/__tests__/evmLedgerLegacySafety.test.ts +2 -2
- package/__tests__/evmSignTypedData.test.ts +80 -0
- package/__tests__/filesystemValidation.test.ts +53 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +402 -0
- package/__tests__/get-device-state.test.ts +77 -41
- package/__tests__/logBlockEvent.test.ts +24 -11
- package/__tests__/networkUtils.test.ts +386 -0
- package/__tests__/open-wallet-session-error-response.test.ts +43 -0
- package/__tests__/open-wallet-session.test.ts +559 -0
- package/__tests__/protocol-v2.test.ts +756 -452
- package/__tests__/public-device-state-api.test.ts +113 -13
- package/__tests__/public-pro2-api-boundary.test.ts +91 -0
- package/__tests__/search-devices.test.ts +43 -0
- package/dist/api/BaseMethod.d.ts +3 -0
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
- package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
- package/dist/api/ClearSessionCache.d.ts.map +1 -1
- package/dist/api/DirList.d.ts.map +1 -1
- package/dist/api/FileRead.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +2 -2
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +3 -2
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts +14 -0
- package/dist/api/OpenWalletSession.d.ts.map +1 -0
- package/dist/api/PathInfo.d.ts.map +1 -1
- package/dist/api/PromptWebDeviceAccess.d.ts.map +1 -1
- package/dist/api/SearchDevices.d.ts +3 -0
- package/dist/api/SearchDevices.d.ts.map +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/DeviceFullyUploadResource.d.ts +1 -2
- package/dist/api/device/DeviceFullyUploadResource.d.ts.map +1 -1
- package/dist/api/device/DeviceSettings.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/device/DeviceWipe.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +7 -3
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/helpers/filesystemValidation.d.ts +3 -0
- package/dist/api/helpers/filesystemValidation.d.ts.map +1 -1
- package/dist/api/helpers/paramsValidator.d.ts +1 -0
- package/dist/api/helpers/paramsValidator.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +7 -11
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceSettingsPageShow.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceSettingsSet.d.ts.map +1 -1
- package/dist/api/utils.d.ts.map +1 -1
- package/dist/core/RequestQueue.d.ts +17 -1
- package/dist/core/RequestQueue.d.ts.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +6 -5
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +5 -5
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DevicePool.d.ts +1 -0
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/device/DeviceStateMapper.d.ts +2 -2
- package/dist/device/DeviceStateMapper.d.ts.map +1 -1
- package/dist/device/DeviceStateProjector.d.ts +1 -2
- package/dist/device/DeviceStateProjector.d.ts.map +1 -1
- package/dist/device/DeviceStateStore.d.ts +1 -3
- package/dist/device/DeviceStateStore.d.ts.map +1 -1
- package/dist/device/DeviceWalletSessionStore.d.ts +6 -1
- package/dist/device/DeviceWalletSessionStore.d.ts.map +1 -1
- package/dist/device/cloneDeviceState.d.ts +2 -0
- package/dist/device/cloneDeviceState.d.ts.map +1 -0
- package/dist/deviceProfile/buildDeviceFeatures.d.ts +3 -1
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/index.d.ts +608 -75
- package/dist/index.js +2287 -1706
- package/dist/inject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/deviceSession.d.ts +7 -0
- package/dist/protocols/protocol-v2/deviceSession.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/features.d.ts +11 -4
- 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/settingsUnlockPolicy.d.ts +16 -0
- package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +8 -3
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -2
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/deviceSettings.d.ts +1 -0
- package/dist/types/api/deviceSettings.d.ts.map +1 -1
- package/dist/types/api/deviceUnlock.d.ts +1 -1
- package/dist/types/api/deviceUnlock.d.ts.map +1 -1
- package/dist/types/api/getFeatures.d.ts.map +1 -1
- package/dist/types/api/getOnekeyFeatures.d.ts.map +1 -1
- package/dist/types/api/getPassphraseState.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +13 -15
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/openWalletSession.d.ts +41 -0
- package/dist/types/api/openWalletSession.d.ts.map +1 -0
- package/dist/types/api/protocolV2.d.ts +6 -11
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts +2 -9
- package/dist/types/device.d.ts.map +1 -1
- package/dist/utils/assets.d.ts +2 -1
- package/dist/utils/assets.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesCompat.d.ts +13 -0
- package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -0
- package/dist/utils/deviceFeaturesUtils.d.ts +11 -1
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts +9 -8
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/deviceSettings.d.ts +2 -0
- package/dist/utils/deviceSettings.d.ts.map +1 -1
- package/dist/utils/deviceVersionUtils.d.ts +6 -5
- package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/networkUtils.d.ts +9 -1
- package/dist/utils/networkUtils.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/pro2Wallpaper.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +17 -10
- package/src/api/CheckBootloaderRelease.ts +1 -2
- package/src/api/CheckFirmwareRelease.ts +1 -2
- package/src/api/ClearSessionCache.ts +0 -4
- package/src/api/DirList.ts +5 -3
- package/src/api/DirMake.ts +3 -3
- package/src/api/DirRemove.ts +3 -3
- package/src/api/FileDelete.ts +3 -3
- package/src/api/FileRead.ts +9 -6
- package/src/api/FileWrite.ts +3 -3
- package/src/api/FirmwareUpdate.ts +4 -4
- package/src/api/FirmwareUpdateV2.ts +133 -45
- package/src/api/FirmwareUpdateV3.ts +3 -5
- package/src/api/FirmwareUpdateV4.ts +192 -154
- package/src/api/GetPassphraseState.ts +10 -16
- package/src/api/OpenWalletSession.ts +221 -0
- package/src/api/PathInfo.ts +5 -3
- package/src/api/PromptWebDeviceAccess.ts +2 -3
- package/src/api/SearchDevices.ts +6 -2
- package/src/api/UploadPortfolio.ts +12 -3
- package/src/api/alephium/AlephiumSignTransaction.ts +2 -2
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +4 -8
- package/src/api/benfen/BenfenGetAddress.ts +1 -1
- package/src/api/btc/BTCGetPublicKey.ts +1 -1
- package/src/api/device/DeviceChangePin.ts +1 -0
- package/src/api/device/DeviceFullyUploadResource.ts +4 -5
- package/src/api/device/DeviceSettings.ts +93 -0
- package/src/api/device/DeviceUpdateBootloader.ts +1 -2
- package/src/api/device/DeviceWipe.ts +1 -0
- package/src/api/evm/EVMSignTypedData.ts +3 -5
- package/src/api/evm/legacyV1/getAddress.ts +2 -2
- package/src/api/evm/legacyV1/getPublicKey.ts +2 -2
- package/src/api/evm/legacyV1/signMessage.ts +2 -2
- package/src/api/evm/legacyV1/signTypedData.ts +2 -2
- package/src/api/evm/legacyV1/signTypedHash.ts +2 -2
- package/src/api/evm/legacyV1/verifyMessage.ts +2 -2
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +3 -3
- package/src/api/firmware/getBinary.ts +8 -3
- package/src/api/helpers/batchGetPublickeys.ts +2 -2
- package/src/api/helpers/filesystemValidation.ts +61 -0
- package/src/api/helpers/paramsValidator.ts +1 -1
- package/src/api/helpers/protocolV2FileWrite.ts +3 -2
- package/src/api/index.ts +9 -12
- package/src/api/nervos/NervosSignTransaction.ts +2 -2
- package/src/api/nexa/NexaSignTransaction.ts +1 -1
- package/src/api/protocol-v2/DeviceFactoryInfoGet.ts +1 -1
- package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
- package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +4 -4
- package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +6 -5
- package/src/api/protocol-v2/DeviceInfoGet.ts +4 -4
- package/src/api/protocol-v2/DeviceReboot.ts +1 -1
- package/src/api/protocol-v2/DeviceSettingsPageShow.ts +11 -8
- package/src/api/protocol-v2/DeviceSettingsSet.ts +4 -11
- package/src/api/protocol-v2/FilesystemFormat.ts +1 -1
- package/src/api/protocol-v2/FilesystemPermissionFix.ts +1 -1
- package/src/api/protocol-v2/Ping.ts +1 -1
- package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -1
- package/src/api/utils.ts +1 -3
- package/src/core/RequestQueue.ts +107 -6
- package/src/core/index.ts +91 -46
- package/src/data/messages/messages-protocol-v2.json +25 -79
- package/src/data-manager/DataManager.ts +6 -6
- package/src/device/Device.ts +186 -102
- package/src/device/DeviceCommands.ts +51 -21
- package/src/device/DeviceFeaturesState.ts +4 -4
- package/src/device/DevicePool.ts +17 -3
- package/src/device/DeviceStateMapper.ts +13 -29
- package/src/device/DeviceStateProjector.ts +11 -8
- package/src/device/DeviceStateStore.ts +11 -52
- package/src/device/DeviceWalletSessionStore.ts +31 -4
- package/src/device/cloneDeviceState.ts +39 -0
- package/src/device/deviceIdentity.ts +2 -2
- package/src/deviceProfile/buildDeviceFeatures.ts +29 -88
- package/src/events/logBlockEvent.ts +8 -1
- package/src/inject.ts +14 -24
- package/src/protocols/protocol-v2/deviceSession.ts +24 -0
- package/src/protocols/protocol-v2/features.ts +37 -49
- package/src/protocols/protocol-v2/firmware.ts +1 -1
- package/src/protocols/protocol-v2/index.ts +2 -3
- package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +61 -0
- package/src/protocols/protocol-v2/uiInteraction.ts +4 -3
- package/src/protocols/protocol-v2/walletSession.ts +57 -146
- package/src/types/api/checkAllFirmwareRelease.ts +1 -2
- package/src/types/api/deviceSettings.ts +1 -0
- package/src/types/api/deviceUnlock.ts +1 -1
- package/src/types/api/firmwareUpdate.ts +5 -5
- package/src/types/api/getDeviceState.ts +1 -1
- package/src/types/api/getFeatures.ts +3 -0
- package/src/types/api/getOnekeyFeatures.ts +3 -0
- package/src/types/api/getPassphraseState.ts +6 -0
- package/src/types/api/index.ts +16 -23
- package/src/types/api/openWalletSession.ts +64 -0
- package/src/types/api/protocolV2.ts +36 -18
- package/src/types/device.ts +20 -14
- package/src/types/params.ts +1 -1
- package/src/types/settings.ts +8 -8
- package/src/utils/assets.ts +4 -1
- package/src/utils/deviceFeaturesCompat.ts +173 -0
- package/src/utils/deviceFeaturesUtils.ts +9 -8
- package/src/utils/deviceInfoUtils.ts +26 -64
- package/src/utils/deviceSettings.ts +18 -11
- package/src/utils/deviceVersionUtils.ts +25 -44
- package/src/utils/findDefectiveBatchDevice.ts +3 -3
- package/src/utils/index.ts +2 -5
- package/src/utils/networkUtils.ts +270 -14
- package/src/utils/pro2Wallpaper.ts +11 -13
- package/src/utils/tracing.ts +2 -2
- package/dist/api/internal.d.ts +0 -4
- package/dist/api/internal.d.ts.map +0 -1
- package/dist/api/protocol-v2/DeviceSessionOpen.d.ts +0 -28
- package/dist/api/protocol-v2/DeviceSessionOpen.d.ts.map +0 -1
- package/src/api/internal.ts +0 -9
- package/src/api/protocol-v2/DeviceSessionOpen.ts +0 -100
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
3
|
+
import { deviceWalletSessionStore } from '../device/DeviceWalletSessionStore';
|
|
4
|
+
import { getProtocolV2WalletSession } from '../protocols/protocol-v2/walletSession';
|
|
5
|
+
import { getPassphraseStateWithRefreshDeviceInfo } from '../utils/deviceFeaturesUtils';
|
|
6
|
+
import { BaseMethod } from './BaseMethod';
|
|
7
|
+
import { invalidParameter } from './helpers/paramsValidator';
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
OpenWalletSessionParams,
|
|
11
|
+
OpenWalletSessionPayload,
|
|
12
|
+
} from '../types/api/openWalletSession';
|
|
13
|
+
|
|
14
|
+
const requiredString = (value: unknown, name: string) => {
|
|
15
|
+
if (value === undefined || value === null) {
|
|
16
|
+
throw invalidParameter(`Missing required parameter: ${name}`);
|
|
17
|
+
}
|
|
18
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
19
|
+
throw invalidParameter(`Parameter [${name}] must be a non-empty string.`);
|
|
20
|
+
}
|
|
21
|
+
return value.trim();
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const optionalBoolean = (value: unknown, name: string) => {
|
|
25
|
+
if (value !== undefined && typeof value !== 'boolean') {
|
|
26
|
+
throw invalidParameter(`Parameter [${name}] must be a boolean.`);
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const wasResumed = (session: unknown) =>
|
|
32
|
+
!!session &&
|
|
33
|
+
typeof session === 'object' &&
|
|
34
|
+
'resumed' in session &&
|
|
35
|
+
(session as { resumed?: unknown }).resumed === true;
|
|
36
|
+
|
|
37
|
+
type NormalizedOpenWalletSessionParams = OpenWalletSessionParams & {
|
|
38
|
+
legacySessionToClear?: {
|
|
39
|
+
deviceId?: string;
|
|
40
|
+
passphraseState: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const normalizeParams = (payload: Record<string, unknown>): NormalizedOpenWalletSessionParams => {
|
|
45
|
+
if (payload.mode !== undefined) {
|
|
46
|
+
if (
|
|
47
|
+
payload.mode !== 'standard' &&
|
|
48
|
+
payload.mode !== 'select-hidden' &&
|
|
49
|
+
payload.mode !== 'resume-hidden'
|
|
50
|
+
) {
|
|
51
|
+
throw invalidParameter(
|
|
52
|
+
'Parameter [mode] must be one of standard, select-hidden, or resume-hidden.'
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
if (payload.useEmptyPassphrase !== undefined || payload.initSession !== undefined) {
|
|
56
|
+
throw invalidParameter(
|
|
57
|
+
'Parameters [useEmptyPassphrase] and [initSession] cannot be used with [mode].'
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
if (payload.mode === 'standard' || payload.mode === 'select-hidden') {
|
|
61
|
+
if (payload.deviceId !== undefined || payload.passphraseState !== undefined) {
|
|
62
|
+
throw invalidParameter(
|
|
63
|
+
'Parameters [deviceId] and [passphraseState] are only allowed with mode [resume-hidden].'
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
return { mode: payload.mode };
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
mode: 'resume-hidden',
|
|
70
|
+
deviceId: requiredString(payload.deviceId, 'deviceId'),
|
|
71
|
+
passphraseState: requiredString(payload.passphraseState, 'passphraseState'),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const useEmptyPassphrase = optionalBoolean(payload.useEmptyPassphrase, 'useEmptyPassphrase');
|
|
76
|
+
const initSession = optionalBoolean(payload.initSession, 'initSession');
|
|
77
|
+
if (useEmptyPassphrase === true) {
|
|
78
|
+
return { mode: 'standard' };
|
|
79
|
+
}
|
|
80
|
+
if (initSession === true) {
|
|
81
|
+
const deviceId =
|
|
82
|
+
payload.deviceId === undefined ? undefined : requiredString(payload.deviceId, 'deviceId');
|
|
83
|
+
const passphraseState =
|
|
84
|
+
payload.passphraseState === undefined
|
|
85
|
+
? undefined
|
|
86
|
+
: requiredString(payload.passphraseState, 'passphraseState');
|
|
87
|
+
return {
|
|
88
|
+
mode: 'select-hidden',
|
|
89
|
+
...(passphraseState
|
|
90
|
+
? {
|
|
91
|
+
legacySessionToClear: {
|
|
92
|
+
deviceId,
|
|
93
|
+
passphraseState,
|
|
94
|
+
},
|
|
95
|
+
}
|
|
96
|
+
: {}),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const hasWalletBinding = payload.deviceId !== undefined || payload.passphraseState !== undefined;
|
|
101
|
+
if (!hasWalletBinding) {
|
|
102
|
+
return { mode: 'select-hidden' };
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
mode: 'resume-hidden',
|
|
106
|
+
deviceId: requiredString(payload.deviceId, 'deviceId'),
|
|
107
|
+
passphraseState: requiredString(payload.passphraseState, 'passphraseState'),
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export default class OpenWalletSession extends BaseMethod<NormalizedOpenWalletSessionParams> {
|
|
112
|
+
init() {
|
|
113
|
+
this.useDevicePassphraseState = false;
|
|
114
|
+
this.skipForceUpdateCheck = true;
|
|
115
|
+
this.params = normalizeParams(this.payload as unknown as Record<string, unknown>);
|
|
116
|
+
this.payload.useEmptyPassphrase = this.params.mode === 'standard';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async run(): Promise<OpenWalletSessionPayload> {
|
|
120
|
+
const state = await this.device.getDeviceState({ refreshSections: ['status'] });
|
|
121
|
+
const currentDeviceId = state.identity.deviceId;
|
|
122
|
+
if (!currentDeviceId) {
|
|
123
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceInitializeFailed);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const { legacySessionToClear } = this.params;
|
|
127
|
+
if (
|
|
128
|
+
legacySessionToClear &&
|
|
129
|
+
(!legacySessionToClear.deviceId || legacySessionToClear.deviceId === currentDeviceId)
|
|
130
|
+
) {
|
|
131
|
+
deviceWalletSessionStore.delete(currentDeviceId, legacySessionToClear.passphraseState);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const protocol = this.device.isProtocolV2() ? 'V2' : 'V1';
|
|
135
|
+
|
|
136
|
+
if (this.params.mode === 'standard') {
|
|
137
|
+
this.device.passphraseState = undefined;
|
|
138
|
+
const session = this.device.isProtocolV2()
|
|
139
|
+
? await getProtocolV2WalletSession(this.device, { onlyMainPin: true })
|
|
140
|
+
: await getPassphraseStateWithRefreshDeviceInfo(this.device, {
|
|
141
|
+
onlyMainPin: true,
|
|
142
|
+
initSession: this.payload.initSession,
|
|
143
|
+
});
|
|
144
|
+
if (session.unlockedAttachPin) {
|
|
145
|
+
try {
|
|
146
|
+
await this.device.lockDevice();
|
|
147
|
+
} catch {
|
|
148
|
+
// The wallet context is rejected even when an older device cannot be locked.
|
|
149
|
+
}
|
|
150
|
+
this.device.clearInternalState();
|
|
151
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckUnlockTypeError);
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
protocol,
|
|
155
|
+
walletType: 'standard',
|
|
156
|
+
deviceId: currentDeviceId,
|
|
157
|
+
passphraseState: null,
|
|
158
|
+
resumed: wasResumed(session),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (this.params.mode === 'resume-hidden') {
|
|
163
|
+
if (currentDeviceId !== this.params.deviceId) {
|
|
164
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
|
|
165
|
+
}
|
|
166
|
+
this.device.passphraseState = this.params.passphraseState;
|
|
167
|
+
const cachedSessionId = deviceWalletSessionStore.get(
|
|
168
|
+
this.params.deviceId,
|
|
169
|
+
this.params.passphraseState
|
|
170
|
+
);
|
|
171
|
+
if (!cachedSessionId) {
|
|
172
|
+
throw ERRORS.TypedError(HardwareErrorCode.WalletSessionInvalid);
|
|
173
|
+
}
|
|
174
|
+
if (!this.device.isProtocolV2()) {
|
|
175
|
+
await this.device.initialize({
|
|
176
|
+
deviceId: this.params.deviceId,
|
|
177
|
+
passphraseState: this.params.passphraseState,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
const session = this.device.isProtocolV2()
|
|
181
|
+
? await getProtocolV2WalletSession(this.device, {
|
|
182
|
+
expectedPassphraseState: this.params.passphraseState,
|
|
183
|
+
})
|
|
184
|
+
: await getPassphraseStateWithRefreshDeviceInfo(this.device, {
|
|
185
|
+
expectPassphraseState: this.params.passphraseState,
|
|
186
|
+
});
|
|
187
|
+
if (!session.passphraseState) {
|
|
188
|
+
this.device.clearInternalState();
|
|
189
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError);
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
protocol,
|
|
193
|
+
walletType: 'hidden',
|
|
194
|
+
deviceId: currentDeviceId,
|
|
195
|
+
passphraseState: session.passphraseState ?? null,
|
|
196
|
+
resumed: wasResumed(session) || session.newSession === cachedSessionId,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
this.device.passphraseState = undefined;
|
|
201
|
+
const session = this.device.isProtocolV2()
|
|
202
|
+
? await getProtocolV2WalletSession(this.device, { initSession: true })
|
|
203
|
+
: await getPassphraseStateWithRefreshDeviceInfo(this.device, { initSession: true });
|
|
204
|
+
const responseBase = {
|
|
205
|
+
protocol,
|
|
206
|
+
deviceId: currentDeviceId,
|
|
207
|
+
resumed: wasResumed(session),
|
|
208
|
+
} as const;
|
|
209
|
+
return session.passphraseState
|
|
210
|
+
? {
|
|
211
|
+
...responseBase,
|
|
212
|
+
walletType: 'hidden',
|
|
213
|
+
passphraseState: session.passphraseState,
|
|
214
|
+
}
|
|
215
|
+
: {
|
|
216
|
+
...responseBase,
|
|
217
|
+
walletType: 'standard',
|
|
218
|
+
passphraseState: null,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
package/src/api/PathInfo.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseMethod } from './BaseMethod';
|
|
2
2
|
import {
|
|
3
|
-
validateNonEmptyString,
|
|
4
3
|
validateOptionalNonNegativeInteger,
|
|
4
|
+
validateProtocolV2FilesystemPath,
|
|
5
5
|
} from './helpers/filesystemValidation';
|
|
6
6
|
|
|
7
7
|
export type PathInfoParams = {
|
|
@@ -11,12 +11,14 @@ export type PathInfoParams = {
|
|
|
11
11
|
|
|
12
12
|
export default class PathInfo extends BaseMethod<PathInfoParams> {
|
|
13
13
|
init() {
|
|
14
|
-
// Protocol V2 (Pro2)
|
|
14
|
+
// Protocol V2 (Pro2) only; Core rejects non-V2 devices.
|
|
15
15
|
this.requireProtocolV2 = true;
|
|
16
16
|
this.skipForceUpdateCheck = true;
|
|
17
17
|
this.useDevicePassphraseState = false;
|
|
18
18
|
this.params = {
|
|
19
|
-
path:
|
|
19
|
+
path: validateProtocolV2FilesystemPath(this.payload.path, 'path', {
|
|
20
|
+
allowVolumeRoot: true,
|
|
21
|
+
}),
|
|
20
22
|
timeoutMs: validateOptionalNonNegativeInteger(this.payload.timeoutMs, 'timeoutMs'),
|
|
21
23
|
};
|
|
22
24
|
}
|
|
@@ -54,9 +54,8 @@ export default class PromptWebDeviceAccess extends BaseMethod {
|
|
|
54
54
|
const usbDevice = device as USBDevice;
|
|
55
55
|
let path = usbDevice.serialNumber ?? '';
|
|
56
56
|
if (!path) {
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
// 这里按 USBDevice 对象身份找回该 path,保证后续 acquire 能匹配。
|
|
57
|
+
// Early Pro2 boards have no USB serial number. Re-enumeration assigns a
|
|
58
|
+
// session-stable mock path, which is recovered by USBDevice identity here.
|
|
60
59
|
const diff = await this.connector?.enumerate();
|
|
61
60
|
const matched = diff?.descriptors?.find(d => (d as any).device === usbDevice);
|
|
62
61
|
path = matched?.path ?? '';
|
package/src/api/SearchDevices.ts
CHANGED
|
@@ -41,6 +41,10 @@ export default class SearchDevices extends BaseMethod {
|
|
|
41
41
|
devices.push({
|
|
42
42
|
...device,
|
|
43
43
|
connectId: device.id,
|
|
44
|
+
serialNo: null,
|
|
45
|
+
// Legacy BLE discovery identifier. The physical serial number is unavailable here.
|
|
46
|
+
uuid: device.id,
|
|
47
|
+
deviceId: null,
|
|
44
48
|
name: bleName || device.name,
|
|
45
49
|
deviceType: getDeviceTypeByBleName(bleName),
|
|
46
50
|
});
|
|
@@ -52,8 +56,8 @@ export default class SearchDevices extends BaseMethod {
|
|
|
52
56
|
const deviceList = [];
|
|
53
57
|
for (const descriptor of devicesDescriptor) {
|
|
54
58
|
try {
|
|
55
|
-
//
|
|
56
|
-
//
|
|
59
|
+
// Discovery is best effort. Browsers may retain WebUSB grants for devices that
|
|
60
|
+
// are offline, busy, or not ready, so one descriptor must not abort the scan.
|
|
57
61
|
const result = await DevicePool.getDevices([descriptor], descriptor.path, {
|
|
58
62
|
connectProtocol: this.payload.connectProtocol,
|
|
59
63
|
refreshRuntimeState: true,
|
|
@@ -8,10 +8,16 @@ export type UploadPortfolioParams = {
|
|
|
8
8
|
|
|
9
9
|
const PORTFOLIO_PENDING_PATH = 'vol1:/portfolio/portfolio.okpkg.pending';
|
|
10
10
|
const PORTFOLIO_CHUNK_SIZE = 2048;
|
|
11
|
+
const PORTFOLIO_RESPONSE_TIMEOUT_MS = 5_000;
|
|
12
|
+
const PORTFOLIO_MAX_ABORT_LATENCY_MS = PORTFOLIO_RESPONSE_TIMEOUT_MS * 2 + 2_000;
|
|
11
13
|
|
|
12
14
|
export default class UploadPortfolio extends FileWrite {
|
|
13
15
|
init() {
|
|
14
16
|
const { packageBytes, timeoutMs } = this.payload as UploadPortfolioParams;
|
|
17
|
+
const responseTimeoutMs = Math.min(
|
|
18
|
+
timeoutMs === undefined ? PORTFOLIO_RESPONSE_TIMEOUT_MS : Number(timeoutMs),
|
|
19
|
+
PORTFOLIO_RESPONSE_TIMEOUT_MS
|
|
20
|
+
);
|
|
15
21
|
this.payload = {
|
|
16
22
|
...this.payload,
|
|
17
23
|
path: PORTFOLIO_PENDING_PATH,
|
|
@@ -21,18 +27,21 @@ export default class UploadPortfolio extends FileWrite {
|
|
|
21
27
|
overwrite: true,
|
|
22
28
|
append: false,
|
|
23
29
|
emitProgress: false,
|
|
24
|
-
timeoutMs,
|
|
30
|
+
timeoutMs: responseTimeoutMs,
|
|
25
31
|
};
|
|
26
32
|
super.init();
|
|
33
|
+
this.executionPriority = 'background';
|
|
34
|
+
this.maxAbortLatencyMs = PORTFOLIO_MAX_ABORT_LATENCY_MS;
|
|
27
35
|
this.unlockPolicy = 'retry-on-locked';
|
|
28
|
-
// Portfolio
|
|
36
|
+
// Portfolio is a background write/apply flow and never synthesizes UI events.
|
|
29
37
|
this.protocolV2UiMode = 'none';
|
|
30
38
|
}
|
|
31
39
|
|
|
32
40
|
async run() {
|
|
33
41
|
const stagedFile = await super.run();
|
|
34
42
|
this.throwIfAborted();
|
|
35
|
-
|
|
43
|
+
const timeoutMs = Number(this.params.timeoutMs);
|
|
44
|
+
await this.device.commands.typedCall('PortfolioUpdate', 'Success', {}, { timeoutMs });
|
|
36
45
|
return {
|
|
37
46
|
...stagedFile,
|
|
38
47
|
portfolioUpdated: true,
|
|
@@ -63,8 +63,8 @@ export default class AlephiumSignTransaction extends BaseMethod<HardwareAlephium
|
|
|
63
63
|
data: Buffer,
|
|
64
64
|
scriptOpt?: Buffer,
|
|
65
65
|
dataOffset = 0
|
|
66
|
-
//
|
|
67
|
-
//
|
|
66
|
+
// The final AlephiumTxRequest may return a signature without data_length or address,
|
|
67
|
+
// so the result accurately uses a union type.
|
|
68
68
|
): Promise<AlephiumSignedTx | AlephiumTxRequest> => {
|
|
69
69
|
const responseType = res.type;
|
|
70
70
|
if (res.type === 'AlephiumSignedTx') {
|
|
@@ -352,6 +352,7 @@ export default abstract class AllNetworkGetAddressBase extends BaseMethod<
|
|
|
352
352
|
};
|
|
353
353
|
|
|
354
354
|
let result: AllNetworkAddress[];
|
|
355
|
+
let requestError: Error | undefined;
|
|
355
356
|
try {
|
|
356
357
|
method.init();
|
|
357
358
|
method.setDevice?.(this.device);
|
|
@@ -394,10 +395,8 @@ export default abstract class AllNetworkGetAddressBase extends BaseMethod<
|
|
|
394
395
|
rootFingerprint,
|
|
395
396
|
},
|
|
396
397
|
}));
|
|
397
|
-
if (method.requestContext) {
|
|
398
|
-
completeRequestContext(method.requestContext.responseID);
|
|
399
|
-
}
|
|
400
398
|
} catch (e: any) {
|
|
399
|
+
requestError = e instanceof Error ? e : new Error(String(e));
|
|
401
400
|
const error = handleSkippableHardwareError(e, this.device, method);
|
|
402
401
|
|
|
403
402
|
if (error) {
|
|
@@ -415,13 +414,10 @@ export default abstract class AllNetworkGetAddressBase extends BaseMethod<
|
|
|
415
414
|
} else {
|
|
416
415
|
throw e;
|
|
417
416
|
}
|
|
417
|
+
} finally {
|
|
418
418
|
if (method.requestContext) {
|
|
419
|
-
completeRequestContext(
|
|
420
|
-
method.requestContext.responseID,
|
|
421
|
-
e instanceof Error ? e : new Error(String(e))
|
|
422
|
-
);
|
|
419
|
+
completeRequestContext(method.requestContext.responseID, requestError);
|
|
423
420
|
}
|
|
424
|
-
} finally {
|
|
425
421
|
this.device.off(DEVICE.BUTTON, buttonListener);
|
|
426
422
|
this.device.off(DEVICE.PIN, onSignalAbort);
|
|
427
423
|
this.device.off(DEVICE.PASSPHRASE, onSignalAbort);
|
|
@@ -78,7 +78,7 @@ export default class BenfenGetAddress extends BaseMethod<HardwareBenfenGetAddres
|
|
|
78
78
|
'BenfenAddress',
|
|
79
79
|
param
|
|
80
80
|
);
|
|
81
|
-
//
|
|
81
|
+
// BenfenAddress.address is optional in proto but always present on success.
|
|
82
82
|
address = addressRes.message.address ?? '';
|
|
83
83
|
} else {
|
|
84
84
|
address = publicKeyToAddress(publicKey);
|
|
@@ -78,7 +78,7 @@ export default class BTCGetPublicKey extends BaseMethod<GetPublicKey[]> {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
for (const param of this.params) {
|
|
81
|
-
// init()
|
|
81
|
+
// init() sets coin_name; keep an empty fallback for the generated optional type.
|
|
82
82
|
const versionBytes = getVersionBytes(param.coin_name ?? '', param.script_type);
|
|
83
83
|
if (!versionBytes) {
|
|
84
84
|
throw new Error(
|
|
@@ -5,12 +5,11 @@ import { UI_REQUEST } from '../../constants/ui-request';
|
|
|
5
5
|
import { BaseMethod } from '../BaseMethod';
|
|
6
6
|
import { getSysResourceBinary } from '../firmware/getBinary';
|
|
7
7
|
import { updateResources } from '../firmware/uploadFirmware';
|
|
8
|
-
import { getDeviceFirmwareVersion, getFirmwareType } from '../../utils';
|
|
9
8
|
import { createUiMessage } from '../../events/ui-request';
|
|
10
9
|
import { DataManager } from '../../data-manager';
|
|
11
10
|
|
|
12
11
|
import type { Deferred } from '@onekeyfe/hd-shared';
|
|
13
|
-
import type {
|
|
12
|
+
import type { KnownDevice } from '../../types';
|
|
14
13
|
import type { DeviceFullyUploadResourceParams } from '../../types/api/deviceFullyUploadResource';
|
|
15
14
|
|
|
16
15
|
export default class DeviceFullyUploadResource extends BaseMethod {
|
|
@@ -33,12 +32,12 @@ export default class DeviceFullyUploadResource extends BaseMethod {
|
|
|
33
32
|
);
|
|
34
33
|
};
|
|
35
34
|
|
|
36
|
-
isSupportResourceUpdate(
|
|
35
|
+
isSupportResourceUpdate(updateType: string) {
|
|
37
36
|
if (updateType !== 'firmware') return false;
|
|
38
37
|
|
|
39
38
|
const deviceType = this.device.getCurrentDeviceType();
|
|
40
39
|
const isTouchMode = deviceType === EDeviceType.Touch || deviceType === EDeviceType.Pro;
|
|
41
|
-
const currentVersion =
|
|
40
|
+
const currentVersion = this.device.getCurrentFirmwareVersionString() ?? '0.0.0';
|
|
42
41
|
|
|
43
42
|
return isTouchMode && semver.gte(currentVersion, '3.4.0');
|
|
44
43
|
}
|
|
@@ -49,7 +48,7 @@ export default class DeviceFullyUploadResource extends BaseMethod {
|
|
|
49
48
|
|
|
50
49
|
const payload = this.payload as DeviceFullyUploadResourceParams;
|
|
51
50
|
|
|
52
|
-
const deviceFirmwareType =
|
|
51
|
+
const deviceFirmwareType = device.getCurrentFirmwareType();
|
|
53
52
|
const firmwareType = payload.firmwareType ?? deviceFirmwareType;
|
|
54
53
|
|
|
55
54
|
if (!device.isBootloader() && features) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HardwareErrorCode, TypedError } from '@onekeyfe/hd-shared';
|
|
2
|
+
import { DeviceSettingsPage } from '@onekeyfe/hd-transport';
|
|
2
3
|
|
|
3
4
|
import { BaseMethod } from '../BaseMethod';
|
|
4
5
|
import { invalidParameter } from '../helpers/filesystemValidation';
|
|
@@ -8,9 +9,23 @@ import {
|
|
|
8
9
|
mapCommonSettingsToProtocolV2,
|
|
9
10
|
mapDeviceSettingsToState,
|
|
10
11
|
} from '../../device/DeviceStateMapper';
|
|
12
|
+
import { getProtocolV2SettingsBehavior } from '../../protocols/protocol-v2/settingsUnlockPolicy';
|
|
11
13
|
import { LANGUAGE_LABELS } from '../../utils/deviceSettings';
|
|
12
14
|
|
|
13
15
|
import type { ApplySettings } from '@onekeyfe/hd-transport';
|
|
16
|
+
import type { DeviceSettingsParams } from '../../types/api/deviceSettings';
|
|
17
|
+
|
|
18
|
+
const settingsPageForPayload = (
|
|
19
|
+
payload: DeviceSettingsParams
|
|
20
|
+
): DeviceSettingsPage.DevicePassphrase | DeviceSettingsPage.DeviceAirgap | undefined => {
|
|
21
|
+
if (payload.usePassphrase !== undefined) {
|
|
22
|
+
return DeviceSettingsPage.DevicePassphrase;
|
|
23
|
+
}
|
|
24
|
+
if (payload.airgapMode !== undefined) {
|
|
25
|
+
return DeviceSettingsPage.DeviceAirgap;
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
};
|
|
14
29
|
|
|
15
30
|
export default class DeviceSettings extends BaseMethod<ApplySettings> {
|
|
16
31
|
init() {
|
|
@@ -33,6 +48,7 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
|
|
|
33
48
|
{ name: 'brightness', type: 'number' },
|
|
34
49
|
{ name: 'hapticFeedback', type: 'boolean' },
|
|
35
50
|
{ name: 'bluetoothEnabled', type: 'boolean' },
|
|
51
|
+
{ name: 'airgapMode', type: 'boolean' },
|
|
36
52
|
{ name: 'animationEnabled', type: 'boolean' },
|
|
37
53
|
{ name: 'tapToWake', type: 'boolean' },
|
|
38
54
|
{ name: 'deviceNameDisplayEnabled', type: 'boolean' },
|
|
@@ -59,6 +75,28 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
|
|
|
59
75
|
: undefined),
|
|
60
76
|
haptic_feedback: this.payload.hapticFeedback,
|
|
61
77
|
};
|
|
78
|
+
const page = settingsPageForPayload(this.payload);
|
|
79
|
+
const directSettings = mapCommonSettingsToProtocolV2(this.payload);
|
|
80
|
+
const hasConflictingPages =
|
|
81
|
+
this.payload.usePassphrase !== undefined && this.payload.airgapMode !== undefined;
|
|
82
|
+
const combinesPageWithDirectSettings =
|
|
83
|
+
page !== undefined && Object.keys(directSettings).length > 0;
|
|
84
|
+
if (hasConflictingPages || combinesPageWithDirectSettings) {
|
|
85
|
+
// V1 may still accept passphrase plus direct settings. Suppress only the
|
|
86
|
+
// Protocol V2 pre-run interaction; run() returns the protocol-specific error.
|
|
87
|
+
this.unlockPolicy = 'none';
|
|
88
|
+
this.protocolV2UiInteraction = undefined;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const behavior =
|
|
92
|
+
page === undefined
|
|
93
|
+
? getProtocolV2SettingsBehavior({
|
|
94
|
+
kind: 'direct',
|
|
95
|
+
settings: directSettings,
|
|
96
|
+
})
|
|
97
|
+
: getProtocolV2SettingsBehavior({ kind: 'page', page });
|
|
98
|
+
this.unlockPolicy = behavior.unlockPolicy;
|
|
99
|
+
this.protocolV2UiInteraction = behavior.uiInteraction;
|
|
62
100
|
}
|
|
63
101
|
|
|
64
102
|
getVersionRange() {
|
|
@@ -76,6 +114,57 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
|
|
|
76
114
|
try {
|
|
77
115
|
if (this.device.isProtocolV2()) {
|
|
78
116
|
const settings = mapCommonSettingsToProtocolV2(this.payload);
|
|
117
|
+
const requestedPassphrase = this.payload.usePassphrase;
|
|
118
|
+
const requestedAirgap = this.payload.airgapMode;
|
|
119
|
+
const hasPassphrasePage = requestedPassphrase !== undefined;
|
|
120
|
+
const hasAirgapPage = requestedAirgap !== undefined;
|
|
121
|
+
|
|
122
|
+
if (hasPassphrasePage && hasAirgapPage) {
|
|
123
|
+
throw invalidParameter(
|
|
124
|
+
'Protocol V2 passphrase and air-gap settings must be changed in separate calls.'
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
if ((hasPassphrasePage || hasAirgapPage) && Object.keys(settings).length > 0) {
|
|
128
|
+
throw invalidParameter(
|
|
129
|
+
'Protocol V2 on-device settings must not be combined with direct settings.'
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
if (requestedPassphrase !== undefined) {
|
|
133
|
+
const current = await this.device.getDeviceState({ refreshSections: ['status'] });
|
|
134
|
+
if (current.status.passphraseProtection === requestedPassphrase) {
|
|
135
|
+
return { message: 'Settings already match requested value.' };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const res = await this.device.commands.typedCall('DeviceSettingsPageShow', 'Success', {
|
|
139
|
+
page: DeviceSettingsPage.DevicePassphrase,
|
|
140
|
+
});
|
|
141
|
+
const updated = await this.device.getDeviceState({ refreshSections: ['status'] });
|
|
142
|
+
if (updated.status.passphraseProtection !== requestedPassphrase) {
|
|
143
|
+
throw TypedError(
|
|
144
|
+
HardwareErrorCode.RuntimeError,
|
|
145
|
+
'Protocol V2 passphrase setting did not reach the requested value.'
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
return res.message;
|
|
149
|
+
}
|
|
150
|
+
if (requestedAirgap !== undefined) {
|
|
151
|
+
const current = await this.device.getDeviceState({ refreshSections: ['settings'] });
|
|
152
|
+
if (current.settings.airgapMode === requestedAirgap) {
|
|
153
|
+
return { message: 'Settings already match requested value.' };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const res = await this.device.commands.typedCall('DeviceSettingsPageShow', 'Success', {
|
|
157
|
+
page: DeviceSettingsPage.DeviceAirgap,
|
|
158
|
+
});
|
|
159
|
+
const updated = await this.device.getDeviceState({ refreshSections: ['settings'] });
|
|
160
|
+
if (updated.settings.airgapMode !== requestedAirgap) {
|
|
161
|
+
throw TypedError(
|
|
162
|
+
HardwareErrorCode.RuntimeError,
|
|
163
|
+
'Protocol V2 air-gap setting did not reach the requested value.'
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
return res.message;
|
|
167
|
+
}
|
|
79
168
|
if (Object.keys(settings).length === 0) {
|
|
80
169
|
throw invalidParameter('No Protocol V2 compatible setting provided.');
|
|
81
170
|
}
|
|
@@ -87,6 +176,10 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
|
|
|
87
176
|
return res.message;
|
|
88
177
|
}
|
|
89
178
|
|
|
179
|
+
if (this.payload.airgapMode !== undefined) {
|
|
180
|
+
throw invalidParameter('Air-gap settings are not supported by Protocol V1.');
|
|
181
|
+
}
|
|
182
|
+
|
|
90
183
|
const res = await this.device.commands.typedCall('ApplySettings', 'Success', {
|
|
91
184
|
...this.params,
|
|
92
185
|
});
|
|
@@ -9,7 +9,6 @@ import { updateBootloader } from '../firmware/uploadFirmware';
|
|
|
9
9
|
import { DeviceModelToTypes } from '../../types';
|
|
10
10
|
import { DataManager } from '../../data-manager';
|
|
11
11
|
import { checkBootloaderLength } from '../firmware/updateBootloader';
|
|
12
|
-
import { getFirmwareType } from '../../utils';
|
|
13
12
|
|
|
14
13
|
import type { DeviceUpdateBootloaderParams } from '../../types/api/deviceUpdateBootloader';
|
|
15
14
|
import type { EFirmwareType } from '@onekeyfe/hd-shared';
|
|
@@ -99,7 +98,7 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
|
|
|
99
98
|
const payload = this.payload as DeviceUpdateBootloaderParams;
|
|
100
99
|
|
|
101
100
|
const deviceType = device.getCurrentDeviceType();
|
|
102
|
-
const deviceFirmwareType =
|
|
101
|
+
const deviceFirmwareType = device.getCurrentFirmwareType();
|
|
103
102
|
const firmwareType = payload.firmwareType ?? deviceFirmwareType;
|
|
104
103
|
|
|
105
104
|
if (DeviceModelToTypes.model_touch.includes(deviceType)) {
|
|
@@ -6,6 +6,7 @@ import type { WipeDevice } from '@onekeyfe/hd-transport';
|
|
|
6
6
|
|
|
7
7
|
export default class DeviceWipe extends BaseMethod<WipeDevice> {
|
|
8
8
|
init() {
|
|
9
|
+
this.unlockPolicy = 'retry-on-locked';
|
|
9
10
|
this.useDevicePassphraseState = false;
|
|
10
11
|
this.protocolV2UiInteraction = {
|
|
11
12
|
request: 'button',
|
|
@@ -32,9 +32,8 @@ import type {
|
|
|
32
32
|
} from '@onekeyfe/hd-transport';
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
* EthereumTypedDataStructAckOneKey
|
|
36
|
-
*
|
|
37
|
-
* 这里做无运行时成本的名义转换,避免在调用点散落 any。
|
|
35
|
+
* EthereumTypedDataStructAckOneKey and EthereumTypedDataStructAck have identical
|
|
36
|
+
* fields and enum values. This zero-cost nominal conversion avoids scattered `any`.
|
|
38
37
|
*/
|
|
39
38
|
const toOneKeyStructAck = (ack: EthereumTypedDataStructAck): EthereumTypedDataStructAckOneKey =>
|
|
40
39
|
ack as unknown as EthereumTypedDataStructAckOneKey;
|
|
@@ -227,8 +226,7 @@ export default class EVMSignTypedData extends BaseMethod<EVMSignTypedDataParams>
|
|
|
227
226
|
if (response.type === 'EthereumGnosisSafeTxRequest') {
|
|
228
227
|
const { data } = this.params;
|
|
229
228
|
const verifyingContract = data.domain?.verifyingContract;
|
|
230
|
-
//
|
|
231
|
-
// Gnosis Safe 签名缺少 verifyingContract 没有意义,这里给出明确的参数错误。
|
|
229
|
+
// verifyingContract is required by proto and essential to a Gnosis Safe signature.
|
|
232
230
|
if (!verifyingContract) {
|
|
233
231
|
throw ERRORS.TypedError(
|
|
234
232
|
HardwareErrorCode.CallMethodInvalidParameter,
|
|
@@ -7,8 +7,8 @@ export default async function ({
|
|
|
7
7
|
typedCall: TypedCall;
|
|
8
8
|
param: EthereumGetAddressOneKey;
|
|
9
9
|
}): Promise<MessageResponse<'EthereumAddress'>> {
|
|
10
|
-
// legacy
|
|
11
|
-
//
|
|
10
|
+
// The generated legacy type omits chain_id, but old firmware accepts the OneKey
|
|
11
|
+
// extension. A non-fresh object preserves that runtime field without a type cast.
|
|
12
12
|
const message = {
|
|
13
13
|
address_n: param.address_n,
|
|
14
14
|
show_display: param.show_display,
|
|
@@ -11,8 +11,8 @@ export default async function ({
|
|
|
11
11
|
typedCall: TypedCall;
|
|
12
12
|
param: EthereumGetPublicKeyOneKey;
|
|
13
13
|
}): Promise<MessageResponse<'EthereumPublicKey'>> {
|
|
14
|
-
// legacy
|
|
15
|
-
//
|
|
14
|
+
// The generated legacy type omits chain_id, but old firmware accepts the OneKey
|
|
15
|
+
// extension. A non-fresh object preserves that runtime field without a type cast.
|
|
16
16
|
const message = {
|
|
17
17
|
address_n: param.address_n,
|
|
18
18
|
show_display: param.show_display,
|
|
@@ -11,8 +11,8 @@ export default async function ({
|
|
|
11
11
|
typedCall: TypedCall;
|
|
12
12
|
params: EthereumSignMessageOneKey;
|
|
13
13
|
}): Promise<EthereumMessageSignature> {
|
|
14
|
-
// legacy
|
|
15
|
-
//
|
|
14
|
+
// The generated legacy type omits chain_id, but old firmware accepts the OneKey
|
|
15
|
+
// extension. A non-fresh object preserves that runtime field without a type cast.
|
|
16
16
|
const message = {
|
|
17
17
|
address_n: params.address_n,
|
|
18
18
|
message: params.message,
|