@onekeyfe/hd-core 1.2.2-alpha.1 → 1.2.2-alpha.100
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 +4 -20
- package/__tests__/DeviceCommands.test.ts +0 -13
- package/__tests__/check-all-firmware-release-protocol-v2.test.ts +2 -0
- package/__tests__/check-firmware-release-protocol-v2.test.ts +2 -0
- package/__tests__/device-lifecycle-events.test.ts +0 -19
- package/__tests__/deviceUploadNft.test.ts +0 -68
- package/__tests__/evmSignTypedData.test.ts +0 -42
- package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +12 -825
- package/__tests__/open-wallet-session.test.ts +1 -127
- package/__tests__/protocol-v2-resources.test.ts +4 -7
- package/__tests__/protocol-v2-unlock-policy.test.ts +1 -35
- package/__tests__/protocol-v2.test.ts +27 -710
- package/dist/api/FirmwareUpdateV4.d.ts +0 -4
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTypedData.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/getBinary.d.ts +2 -2
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +1 -1
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceConnector.d.ts +1 -1
- package/dist/device/DeviceConnector.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +0 -3
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +5 -21
- package/dist/index.js +402 -1136
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -2
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +0 -3
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/types/settings.d.ts +2 -2
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +0 -3
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +75 -434
- package/src/api/OpenWalletSession.ts +9 -39
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +1 -2
- package/src/api/evm/EVMSignTypedData.ts +0 -1
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +3 -9
- package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +1 -7
- package/src/api/protocol-v2/DeviceUploadNft.ts +8 -31
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +8 -27
- package/src/api/protocol-v2/helpers.ts +0 -8
- package/src/core/index.ts +10 -121
- package/src/data/messages/messages-protocol-v2.json +1 -111
- package/src/device/Device.ts +1 -3
- package/src/device/DeviceConnector.ts +3 -7
- package/src/events/ui-request.ts +0 -3
- package/src/protocols/protocol-v2/resources.ts +1 -9
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +1 -8
- package/src/protocols/protocol-v2/walletSession.ts +22 -65
- package/src/types/settings.ts +2 -4
- package/src/utils/deviceFeaturesUtils.ts +0 -4
- package/__tests__/pro2HostAssetPackage.test.ts +0 -58
- package/dist/utils/pro2HostAssetPackage.d.ts +0 -8
- package/dist/utils/pro2HostAssetPackage.d.ts.map +0 -1
- package/src/utils/pro2HostAssetPackage.ts +0 -354
|
@@ -29,12 +29,6 @@ const wasResumed = (session: unknown) =>
|
|
|
29
29
|
'resumed' in session &&
|
|
30
30
|
(session as { resumed?: unknown }).resumed === true;
|
|
31
31
|
|
|
32
|
-
const wasWalletStatusRefreshed = (session: unknown) =>
|
|
33
|
-
!!session &&
|
|
34
|
-
typeof session === 'object' &&
|
|
35
|
-
'walletStatusRefreshed' in session &&
|
|
36
|
-
(session as { walletStatusRefreshed?: unknown }).walletStatusRefreshed === true;
|
|
37
|
-
|
|
38
32
|
const requireHiddenWalletResponse = (session: { passphraseState?: string }) => {
|
|
39
33
|
if (!session.passphraseState) {
|
|
40
34
|
throw ERRORS.TypedError(
|
|
@@ -93,20 +87,12 @@ export default class OpenWalletSession extends BaseMethod<OpenWalletSessionParam
|
|
|
93
87
|
this.unlockPolicy = 'unlock-before-run';
|
|
94
88
|
this.skipForceUpdateCheck = true;
|
|
95
89
|
this.params = normalizeParams(this.payload as unknown as Record<string, unknown>);
|
|
96
|
-
this.protocolV2PreUnlockPinType =
|
|
97
|
-
this.params.mode === OpenWalletSessionMode.SelectHidden
|
|
98
|
-
? DeviceSessionPinType.Any
|
|
99
|
-
: DeviceSessionPinType.Main;
|
|
100
90
|
this.payload.useEmptyPassphrase = this.params.mode === OpenWalletSessionMode.Standard;
|
|
101
91
|
}
|
|
102
92
|
|
|
103
93
|
async run(): Promise<OpenWalletSessionPayload> {
|
|
104
94
|
const isProtocolV2 = this.device.isProtocolV2();
|
|
105
|
-
|
|
106
|
-
isProtocolV2 && this.protocolV2UnlockContext?.preflightStatusRefreshed === true;
|
|
107
|
-
let state = reusePreflightStatus
|
|
108
|
-
? await this.device.getDeviceState()
|
|
109
|
-
: await this.device.getDeviceState({ refreshSections: ['status'] });
|
|
95
|
+
let state = await this.device.getDeviceState({ refreshSections: ['status'] });
|
|
110
96
|
let currentDeviceId = state.identity.deviceId;
|
|
111
97
|
const hasAuthoritativeProtocolV2WalletStatus = (candidate: typeof state) =>
|
|
112
98
|
candidate.status.unlocked === true &&
|
|
@@ -129,25 +115,14 @@ export default class OpenWalletSession extends BaseMethod<OpenWalletSessionParam
|
|
|
129
115
|
currentDeviceId = state.identity.deviceId;
|
|
130
116
|
return state;
|
|
131
117
|
};
|
|
132
|
-
const resolveProtocolV2DeviceStateAfterSession = async (session: unknown) => {
|
|
133
|
-
if (!wasWalletStatusRefreshed(session)) {
|
|
134
|
-
return refreshProtocolV2DeviceState();
|
|
135
|
-
}
|
|
136
|
-
state = await this.device.getDeviceState();
|
|
137
|
-
currentDeviceId = state.identity.deviceId;
|
|
138
|
-
return state;
|
|
139
|
-
};
|
|
140
118
|
const ensureProtocolV2WalletStatus = async () => {
|
|
141
119
|
if (isProtocolV2 && !hasAuthoritativeProtocolV2WalletStatus(state)) {
|
|
142
|
-
await this.device.unlockDevice(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
method: 'openWalletSession',
|
|
149
|
-
}
|
|
150
|
-
);
|
|
120
|
+
await this.device.unlockDevice(DeviceSessionPinType.Main, {
|
|
121
|
+
source: 'unlock-coordinator',
|
|
122
|
+
reason: 'device-locked',
|
|
123
|
+
deviceOnly: true,
|
|
124
|
+
method: 'openWalletSession',
|
|
125
|
+
});
|
|
151
126
|
requireAuthoritativeProtocolV2WalletStatus(await refreshProtocolV2DeviceState());
|
|
152
127
|
}
|
|
153
128
|
return state;
|
|
@@ -164,16 +139,13 @@ export default class OpenWalletSession extends BaseMethod<OpenWalletSessionParam
|
|
|
164
139
|
selectMainWalletBeforeRestore:
|
|
165
140
|
!hasAuthoritativeProtocolV2WalletStatus(state) ||
|
|
166
141
|
state.status.unlockedAttachPin === true,
|
|
167
|
-
mainPinSelected: this.protocolV2UnlockContext?.preflightMainPinSelected,
|
|
168
142
|
})
|
|
169
143
|
: await getPassphraseStateWithRefreshDeviceInfo(this.device, {
|
|
170
144
|
onlyMainPin: true,
|
|
171
145
|
initSession: this.payload.initSession,
|
|
172
146
|
});
|
|
173
147
|
const refreshedState = isProtocolV2
|
|
174
|
-
? requireAuthoritativeProtocolV2WalletStatus(
|
|
175
|
-
await resolveProtocolV2DeviceStateAfterSession(session)
|
|
176
|
-
)
|
|
148
|
+
? requireAuthoritativeProtocolV2WalletStatus(await refreshProtocolV2DeviceState())
|
|
177
149
|
: state;
|
|
178
150
|
const deviceId = requireDeviceId();
|
|
179
151
|
if (
|
|
@@ -261,9 +233,7 @@ export default class OpenWalletSession extends BaseMethod<OpenWalletSessionParam
|
|
|
261
233
|
})
|
|
262
234
|
: await getPassphraseStateWithRefreshDeviceInfo(this.device, { initSession: true });
|
|
263
235
|
const refreshedState = isProtocolV2
|
|
264
|
-
? requireAuthoritativeProtocolV2WalletStatus(
|
|
265
|
-
await resolveProtocolV2DeviceStateAfterSession(session)
|
|
266
|
-
)
|
|
236
|
+
? requireAuthoritativeProtocolV2WalletStatus(await refreshProtocolV2DeviceState())
|
|
267
237
|
: state;
|
|
268
238
|
const deviceId = requireDeviceId();
|
|
269
239
|
if (isProtocolV2 && refreshedState.status.passphraseProtection !== true) {
|
|
@@ -400,8 +400,7 @@ export default abstract class AllNetworkGetAddressBase extends BaseMethod<
|
|
|
400
400
|
this.payload.passphraseState,
|
|
401
401
|
useEmptyPassphrase,
|
|
402
402
|
this.payload.skipPassphraseCheck,
|
|
403
|
-
deriveCardano
|
|
404
|
-
this.protocolV2UnlockContext?.preflightMainPinSelected
|
|
403
|
+
deriveCardano
|
|
405
404
|
);
|
|
406
405
|
if (!passphraseStateSafety) {
|
|
407
406
|
throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError);
|
|
@@ -360,7 +360,6 @@ export default class EVMSignTypedData extends BaseMethod<EVMSignTypedDataParams>
|
|
|
360
360
|
|
|
361
361
|
const supportBiggerData =
|
|
362
362
|
DeviceModelToTypes.model_classic1s.includes(currentDeviceType) ||
|
|
363
|
-
DeviceModelToTypes.model_pro2.includes(currentDeviceType) ||
|
|
364
363
|
(DeviceModelToTypes.model_touch.includes(currentDeviceType) &&
|
|
365
364
|
semver.gte(currentVersion, supportBiggerDataVersion));
|
|
366
365
|
|
|
@@ -41,15 +41,9 @@ const FIRMWARE_UPDATE_CONFIRM = 'Firmware install confirmed';
|
|
|
41
41
|
*/
|
|
42
42
|
export const BOOTLOADER_POLL_INITIALIZE_TIMEOUT_MS = 5000;
|
|
43
43
|
|
|
44
|
-
type
|
|
44
|
+
type FirmwareTransferMetrics = Pick<
|
|
45
45
|
FirmwareProgress['payload'],
|
|
46
|
-
| '
|
|
47
|
-
| 'totalBytes'
|
|
48
|
-
| 'rateBytesPerSecond'
|
|
49
|
-
| 'elapsedMs'
|
|
50
|
-
| 'installTargetId'
|
|
51
|
-
| 'installPhase'
|
|
52
|
-
| 'installPhaseProgress'
|
|
46
|
+
'transferredBytes' | 'totalBytes' | 'rateBytesPerSecond' | 'elapsedMs'
|
|
53
47
|
>;
|
|
54
48
|
|
|
55
49
|
const isDeviceDisconnectedError = (error: unknown) => {
|
|
@@ -109,7 +103,7 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
|
|
|
109
103
|
postProgressMessage = (
|
|
110
104
|
progress: number,
|
|
111
105
|
progressType: IFirmwareUpdateProgressType,
|
|
112
|
-
metrics?:
|
|
106
|
+
metrics?: FirmwareTransferMetrics
|
|
113
107
|
) => {
|
|
114
108
|
this.postMessage(
|
|
115
109
|
createUiMessage(UI_REQUEST.FIRMWARE_PROGRESS, {
|
|
@@ -4,13 +4,7 @@ import { invalidParameter } from '../helpers/filesystemValidation';
|
|
|
4
4
|
import type { DeviceFirmwareUpdateStatusGetParams } from './helpers';
|
|
5
5
|
import type { DeviceFirmwareUpdateRecordFields } from '@onekeyfe/hd-transport';
|
|
6
6
|
|
|
7
|
-
const DEVICE_FIRMWARE_UPDATE_STATUS_FIELDS = [
|
|
8
|
-
'status',
|
|
9
|
-
'progress_percent',
|
|
10
|
-
'phase_info',
|
|
11
|
-
'payload_version',
|
|
12
|
-
'path',
|
|
13
|
-
] as const;
|
|
7
|
+
const DEVICE_FIRMWARE_UPDATE_STATUS_FIELDS = ['status', 'payload_version', 'path'] as const;
|
|
14
8
|
|
|
15
9
|
function normalizeStatusFields(
|
|
16
10
|
fields: DeviceFirmwareUpdateStatusGetParams['fields']
|
|
@@ -20,10 +20,6 @@ import {
|
|
|
20
20
|
getCompletePro2NftBasenames,
|
|
21
21
|
} from '../../utils/pro2Nft';
|
|
22
22
|
import { encodePro2Image } from '../../utils/pro2Wallpaper';
|
|
23
|
-
import {
|
|
24
|
-
buildPro2HostAssetPackage,
|
|
25
|
-
supportsPro2HostAssetPackage,
|
|
26
|
-
} from '../../utils/pro2HostAssetPackage';
|
|
27
23
|
import { BaseMethod } from '../BaseMethod';
|
|
28
24
|
import { decodeJpegBase64ToRgba } from '../helpers/base64Data';
|
|
29
25
|
import { invalidParameter } from '../helpers/filesystemValidation';
|
|
@@ -42,11 +38,8 @@ export type DeviceUploadNftParams = {
|
|
|
42
38
|
|
|
43
39
|
export type DeviceUploadNftResponse = {
|
|
44
40
|
basename: string;
|
|
45
|
-
/** Final image path after firmware extracts a host-asset package. */
|
|
46
41
|
imagePath: string;
|
|
47
|
-
/** Final thumbnail path after firmware extracts a host-asset package. */
|
|
48
42
|
thumbnailPath: string;
|
|
49
|
-
/** Final metadata path after firmware extracts a host-asset package. */
|
|
50
43
|
metadataPath: string;
|
|
51
44
|
totalSize: number;
|
|
52
45
|
nftUpdated: true;
|
|
@@ -145,7 +138,7 @@ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
|
|
|
145
138
|
this.useDevicePassphraseState = false;
|
|
146
139
|
}
|
|
147
140
|
|
|
148
|
-
private async assertCapabilities(
|
|
141
|
+
private async assertCapabilities() {
|
|
149
142
|
const protocolInfo = await this.device.ensureProtocolV2RuntimeContext();
|
|
150
143
|
const hasFileWrite = supportsProtocolV2Message(
|
|
151
144
|
protocolInfo,
|
|
@@ -157,7 +150,7 @@ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
|
|
|
157
150
|
);
|
|
158
151
|
const hasDirList = supportsProtocolV2Message(protocolInfo, FILESYSTEM_DIR_LIST_MESSAGE_TYPE);
|
|
159
152
|
const hasNftUpdate = supportsProtocolV2Message(protocolInfo, NFT_UPDATE_MESSAGE_TYPE);
|
|
160
|
-
if (!hasFileWrite || !
|
|
153
|
+
if (!hasFileWrite || !hasPathInfo || !hasDirList || !hasNftUpdate) {
|
|
161
154
|
throw createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
|
|
162
155
|
}
|
|
163
156
|
}
|
|
@@ -199,32 +192,16 @@ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
|
|
|
199
192
|
const { bundle } = this;
|
|
200
193
|
if (!bundle) throw invalidParameter('NFT data has not been initialized.');
|
|
201
194
|
|
|
202
|
-
|
|
203
|
-
this.device.state?.versions.firmware ?? undefined
|
|
204
|
-
);
|
|
205
|
-
await this.assertCapabilities(useHostAssetPackage);
|
|
195
|
+
await this.assertCapabilities();
|
|
206
196
|
this.throwIfAborted();
|
|
207
|
-
|
|
197
|
+
await this.assertStorageCapacity(bundle.basename);
|
|
208
198
|
this.throwIfAborted();
|
|
209
199
|
|
|
210
|
-
const
|
|
200
|
+
const files = [
|
|
211
201
|
{ path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}.bin`, data: bundle.image },
|
|
212
202
|
{ path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}_m.bin`, data: bundle.thumbnail },
|
|
213
203
|
{ path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}.json`, data: bundle.metadata },
|
|
214
204
|
];
|
|
215
|
-
const files = useHostAssetPackage
|
|
216
|
-
? [
|
|
217
|
-
{
|
|
218
|
-
path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}.okpkg`,
|
|
219
|
-
data: buildPro2HostAssetPackage(
|
|
220
|
-
extractedFiles.map(file => ({
|
|
221
|
-
name: file.path.slice(`${PRO2_NFT_DIRECTORY}/`.length),
|
|
222
|
-
data: file.data,
|
|
223
|
-
}))
|
|
224
|
-
),
|
|
225
|
-
},
|
|
226
|
-
]
|
|
227
|
-
: extractedFiles;
|
|
228
205
|
const totalSize = files.reduce((sum, file) => sum + file.data.byteLength, 0);
|
|
229
206
|
let transferredBeforeFile = 0;
|
|
230
207
|
|
|
@@ -261,9 +238,9 @@ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
|
|
|
261
238
|
const response = await this.updateNft(bundle.basename);
|
|
262
239
|
return {
|
|
263
240
|
basename: bundle.basename,
|
|
264
|
-
imagePath:
|
|
265
|
-
thumbnailPath:
|
|
266
|
-
metadataPath:
|
|
241
|
+
imagePath: files[0].path,
|
|
242
|
+
thumbnailPath: files[1].path,
|
|
243
|
+
metadataPath: files[2].path,
|
|
267
244
|
totalSize,
|
|
268
245
|
nftUpdated: true,
|
|
269
246
|
message: response.message?.message,
|
|
@@ -16,26 +16,14 @@ import {
|
|
|
16
16
|
type Pro2WallpaperColorFormat,
|
|
17
17
|
encodePro2Wallpaper,
|
|
18
18
|
} from '../../utils/pro2Wallpaper';
|
|
19
|
-
import {
|
|
20
|
-
buildPro2HostAssetPackage,
|
|
21
|
-
supportsPro2HostAssetPackage,
|
|
22
|
-
} from '../../utils/pro2HostAssetPackage';
|
|
23
19
|
|
|
24
20
|
export type DeviceUploadWallpaperParams = {
|
|
25
21
|
jpegBase64: string;
|
|
26
|
-
/**
|
|
27
|
-
* Legacy firmware uses this name for the uploaded `.bin` file. Firmware
|
|
28
|
-
* 1.0.1+ always consumes the fixed `wallpaper.okpkg` package path.
|
|
29
|
-
*/
|
|
30
22
|
fileName?: string;
|
|
31
23
|
chunkSize?: number;
|
|
32
24
|
};
|
|
33
25
|
|
|
34
26
|
export type DeviceUploadWallpaperResponse = {
|
|
35
|
-
/**
|
|
36
|
-
* Filesystem path sent to `DeviceSettingsSet`. On firmware 1.0.1+ this is
|
|
37
|
-
* the temporary package path; firmware extracts and persists wallpaper.bin.
|
|
38
|
-
*/
|
|
39
27
|
path: string;
|
|
40
28
|
size: number;
|
|
41
29
|
colorFormat: Pro2WallpaperColorFormat;
|
|
@@ -43,8 +31,6 @@ export type DeviceUploadWallpaperResponse = {
|
|
|
43
31
|
};
|
|
44
32
|
|
|
45
33
|
const WALLPAPER_DIRECTORY = 'vol1:/wallpapers';
|
|
46
|
-
const WALLPAPER_PACKAGE_PATH = `${WALLPAPER_DIRECTORY}/wallpaper.okpkg`;
|
|
47
|
-
const WALLPAPER_PACKAGE_ENTRY = 'wallpaper.bin';
|
|
48
34
|
const SAFE_FILE_NAME = /^[A-Za-z0-9_-]+(?:\.bin)?$/;
|
|
49
35
|
const DEVICE_SETTINGS_SET_MESSAGE_TYPE = 60412;
|
|
50
36
|
const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
|
|
@@ -130,14 +116,16 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
130
116
|
this.directoryReady = true;
|
|
131
117
|
}
|
|
132
118
|
|
|
133
|
-
private async upload(
|
|
119
|
+
private async upload() {
|
|
134
120
|
if (this.uploaded) return;
|
|
121
|
+
const { encoded } = this;
|
|
122
|
+
if (!encoded) throw invalidParameter('Wallpaper data has not been initialized.');
|
|
135
123
|
|
|
136
124
|
await writeProtocolV2File({
|
|
137
125
|
commands: this.device.commands,
|
|
138
|
-
path,
|
|
139
|
-
data,
|
|
140
|
-
totalSize: data.byteLength,
|
|
126
|
+
path: this.path,
|
|
127
|
+
data: encoded.data,
|
|
128
|
+
totalSize: encoded.data.byteLength,
|
|
141
129
|
chunkSize: this.params.chunkSize,
|
|
142
130
|
maxChunkRetries: 3,
|
|
143
131
|
overwrite: true,
|
|
@@ -157,14 +145,7 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
157
145
|
if (!encoded) throw invalidParameter('Wallpaper data has not been initialized.');
|
|
158
146
|
await this.assertCapabilities();
|
|
159
147
|
await this.ensureDirectory();
|
|
160
|
-
|
|
161
|
-
this.device.state?.versions.firmware ?? undefined
|
|
162
|
-
);
|
|
163
|
-
const data = useHostAssetPackage
|
|
164
|
-
? buildPro2HostAssetPackage([{ name: WALLPAPER_PACKAGE_ENTRY, data: encoded.data }])
|
|
165
|
-
: encoded.data;
|
|
166
|
-
if (useHostAssetPackage) this.path = WALLPAPER_PACKAGE_PATH;
|
|
167
|
-
await this.upload(this.path, data);
|
|
148
|
+
await this.upload();
|
|
168
149
|
const response = await this.device.commands.typedCall('DeviceSettingsSet', 'Success', {
|
|
169
150
|
settings: { wallpaper_path: this.path },
|
|
170
151
|
});
|
|
@@ -179,7 +160,7 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
179
160
|
}
|
|
180
161
|
return {
|
|
181
162
|
path: this.path,
|
|
182
|
-
size: data.byteLength,
|
|
163
|
+
size: encoded.data.byteLength,
|
|
183
164
|
colorFormat: encoded.colorFormat,
|
|
184
165
|
message: response.message?.message,
|
|
185
166
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { DeviceRebootType } from '@onekeyfe/hd-transport';
|
|
2
|
-
import { HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
3
2
|
|
|
4
3
|
import { invalidParameter, validateNonEmptyString } from '../helpers/filesystemValidation';
|
|
5
4
|
import { ProtocolV2FirmwareTargetType } from '../../protocols/protocol-v2/firmware';
|
|
@@ -104,13 +103,6 @@ export const getProtocolV2UnknownErrorText = (error: unknown) => {
|
|
|
104
103
|
};
|
|
105
104
|
|
|
106
105
|
export const isProtocolV2DeviceDisconnectedError = (error: unknown) => {
|
|
107
|
-
const errorCode =
|
|
108
|
-
error && typeof error === 'object'
|
|
109
|
-
? (error as { errorCode?: number; code?: number }).errorCode ??
|
|
110
|
-
(error as { errorCode?: number; code?: number }).code
|
|
111
|
-
: undefined;
|
|
112
|
-
if (errorCode === HardwareErrorCode.BleDeviceDisconnected) return true;
|
|
113
|
-
|
|
114
106
|
const message = getProtocolV2UnknownErrorText(error).toLowerCase();
|
|
115
107
|
const compactMessage = message.replace(/\s+/g, '');
|
|
116
108
|
return (
|
package/src/core/index.ts
CHANGED
|
@@ -415,13 +415,6 @@ const onCallDevice = async (
|
|
|
415
415
|
if (method.payload?.onlyConnectBleDevice) {
|
|
416
416
|
preWarmCallbackTask?.resolve();
|
|
417
417
|
Log.debug('Call API - only connect ble device: ', device?.mainId);
|
|
418
|
-
// This early return bypasses the normal-path bookkeeping at the end of the
|
|
419
|
-
// call. Without it the task leaks and haunts every later queue snapshot
|
|
420
|
-
// and cancel sweep (field log: a completed task lingered for 6 minutes),
|
|
421
|
-
// and the request stays in the active maps, so repeated preconnects pile
|
|
422
|
-
// up phantom work in diagnostics.
|
|
423
|
-
completeMethodRequestContext(method);
|
|
424
|
-
requestQueue.releaseTask(method.responseID);
|
|
425
418
|
return createResponseMessage(method.responseID, true, null);
|
|
426
419
|
}
|
|
427
420
|
|
|
@@ -651,8 +644,7 @@ const onCallDevice = async (
|
|
|
651
644
|
method.payload?.passphraseState,
|
|
652
645
|
method.payload?.useEmptyPassphrase,
|
|
653
646
|
method.payload?.skipPassphraseCheck,
|
|
654
|
-
hasDeriveCardano(method)
|
|
655
|
-
method.protocolV2UnlockContext?.preflightMainPinSelected
|
|
647
|
+
hasDeriveCardano(method)
|
|
656
648
|
);
|
|
657
649
|
|
|
658
650
|
// Double check, handles the special case of Touch/Pro
|
|
@@ -958,72 +950,11 @@ export function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unkn
|
|
|
958
950
|
);
|
|
959
951
|
}
|
|
960
952
|
|
|
961
|
-
export function isProtocolV2PeerRemovedPairingError(method: BaseMethod, error: unknown) {
|
|
962
|
-
return (
|
|
963
|
-
method.payload.connectProtocol === 'V2' &&
|
|
964
|
-
(error as { errorCode?: unknown })?.errorCode ===
|
|
965
|
-
HardwareErrorCode.BlePeerRemovedPairingInformation
|
|
966
|
-
);
|
|
967
|
-
}
|
|
968
|
-
|
|
969
953
|
/**
|
|
970
954
|
* If the Bluetooth connection times out, retry up to 6 times
|
|
971
955
|
* @param retryCount - Current retry count (default 0)
|
|
972
956
|
*/
|
|
973
|
-
|
|
974
|
-
// transport that never settles (field case: Electron main lost an IPC reply,
|
|
975
|
-
// "reply was never sent" after 5 minutes) hangs the call forever and cancel()
|
|
976
|
-
// only takes effect at poll checkpoints. Race acquire against a deadline and
|
|
977
|
-
// the caller's abort signal so the hang is bounded and cancel is immediate.
|
|
978
|
-
const BLE_ACQUIRE_DEADLINE_MS = 60 * 1000;
|
|
979
|
-
|
|
980
|
-
function raceBleAcquire<T>(acquirePromise: Promise<T>, abortSignal?: AbortSignal): Promise<T> {
|
|
981
|
-
return new Promise<T>((resolve, reject) => {
|
|
982
|
-
let settled = false;
|
|
983
|
-
const settle = (fn: () => void) => {
|
|
984
|
-
if (settled) return;
|
|
985
|
-
settled = true;
|
|
986
|
-
clearTimeout(deadline);
|
|
987
|
-
abortSignal?.removeEventListener('abort', onAbort);
|
|
988
|
-
fn();
|
|
989
|
-
};
|
|
990
|
-
const onAbort = () =>
|
|
991
|
-
settle(() => reject(ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)));
|
|
992
|
-
const deadline = setTimeout(
|
|
993
|
-
() =>
|
|
994
|
-
settle(() =>
|
|
995
|
-
reject(
|
|
996
|
-
ERRORS.TypedError(
|
|
997
|
-
HardwareErrorCode.BleTimeoutError,
|
|
998
|
-
`BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`
|
|
999
|
-
)
|
|
1000
|
-
)
|
|
1001
|
-
),
|
|
1002
|
-
BLE_ACQUIRE_DEADLINE_MS
|
|
1003
|
-
);
|
|
1004
|
-
// Attach before any early return so a late settlement of acquirePromise
|
|
1005
|
-
// is always consumed — an abort or deadline must never leave the acquire
|
|
1006
|
-
// rejection unhandled.
|
|
1007
|
-
acquirePromise.then(
|
|
1008
|
-
value => settle(() => resolve(value)),
|
|
1009
|
-
error => settle(() => reject(error))
|
|
1010
|
-
);
|
|
1011
|
-
if (abortSignal) {
|
|
1012
|
-
if (abortSignal.aborted) {
|
|
1013
|
-
onAbort();
|
|
1014
|
-
return;
|
|
1015
|
-
}
|
|
1016
|
-
abortSignal.addEventListener('abort', onAbort);
|
|
1017
|
-
}
|
|
1018
|
-
});
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
async function connectDeviceForBle(
|
|
1022
|
-
method: BaseMethod,
|
|
1023
|
-
device: Device,
|
|
1024
|
-
abortSignal?: AbortSignal,
|
|
1025
|
-
retryCount = 0
|
|
1026
|
-
) {
|
|
957
|
+
async function connectDeviceForBle(method: BaseMethod, device: Device, retryCount = 0) {
|
|
1027
958
|
try {
|
|
1028
959
|
if (device.wasInterruptedByUser()) {
|
|
1029
960
|
throw ERRORS.TypedError(HardwareErrorCode.DeviceInterruptedFromUser);
|
|
@@ -1037,43 +968,9 @@ async function connectDeviceForBle(
|
|
|
1037
968
|
!device.commands ||
|
|
1038
969
|
device.commands.disposed;
|
|
1039
970
|
if (shouldAcquire) {
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
// legitimately block on a user-driven system bonding prompt for longer
|
|
1044
|
-
// than any sane deadline. Other envs keep the plain acquire unchanged.
|
|
1045
|
-
const useAcquireGuards = DataManager.getSettings('env') === 'desktop-web-ble';
|
|
1046
|
-
// A cancel landing during the retry backoff must not start a new acquire.
|
|
1047
|
-
if (useAcquireGuards && abortSignal?.aborted) {
|
|
1048
|
-
throw ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled);
|
|
1049
|
-
}
|
|
1050
|
-
if (!useAcquireGuards) {
|
|
1051
|
-
await device.acquire(method.payload.connectProtocol, {
|
|
1052
|
-
forceProtocolDetection: method.payload.forceProtocolDetection,
|
|
1053
|
-
});
|
|
1054
|
-
} else {
|
|
1055
|
-
try {
|
|
1056
|
-
await raceBleAcquire(
|
|
1057
|
-
device.acquire(method.payload.connectProtocol, {
|
|
1058
|
-
forceProtocolDetection: method.payload.forceProtocolDetection,
|
|
1059
|
-
}),
|
|
1060
|
-
abortSignal
|
|
1061
|
-
);
|
|
1062
|
-
} catch (err) {
|
|
1063
|
-
// A deadline hit means the transport is wedged mid-acquire; drop the
|
|
1064
|
-
// link before the retry so it cold-connects instead of stacking a
|
|
1065
|
-
// second connect onto the half-open one.
|
|
1066
|
-
if (
|
|
1067
|
-
err.errorCode === HardwareErrorCode.BleTimeoutError &&
|
|
1068
|
-
device.mainId &&
|
|
1069
|
-
device.deviceConnector
|
|
1070
|
-
) {
|
|
1071
|
-
await device.deviceConnector.disconnect(device.mainId).catch(() => undefined);
|
|
1072
|
-
device.markTransportDisconnected();
|
|
1073
|
-
}
|
|
1074
|
-
throw err;
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
971
|
+
await device.acquire(method.payload.connectProtocol, {
|
|
972
|
+
forceProtocolDetection: method.payload.forceProtocolDetection,
|
|
973
|
+
});
|
|
1077
974
|
}
|
|
1078
975
|
if (method.payload?.onlyConnectBleDevice) {
|
|
1079
976
|
if (shouldAcquire) {
|
|
@@ -1113,7 +1010,7 @@ async function connectDeviceForBle(
|
|
|
1113
1010
|
const nextRetry = retryCount + 1;
|
|
1114
1011
|
Log.debug(`Bluetooth connection will retry, retry count: ${nextRetry}`);
|
|
1115
1012
|
await wait(3000);
|
|
1116
|
-
await connectDeviceForBle(method, device,
|
|
1013
|
+
await connectDeviceForBle(method, device, nextRetry);
|
|
1117
1014
|
} else {
|
|
1118
1015
|
throw err;
|
|
1119
1016
|
}
|
|
@@ -1223,7 +1120,7 @@ const ensureConnected = async (
|
|
|
1223
1120
|
if (tryCount === 1) {
|
|
1224
1121
|
device.beginConnectionAttempt();
|
|
1225
1122
|
}
|
|
1226
|
-
await connectDeviceForBle(method, device
|
|
1123
|
+
await connectDeviceForBle(method, device);
|
|
1227
1124
|
}
|
|
1228
1125
|
resolve(device);
|
|
1229
1126
|
return;
|
|
@@ -1267,8 +1164,7 @@ const ensureConnected = async (
|
|
|
1267
1164
|
HardwareErrorCode.BridgeNeedsPermission,
|
|
1268
1165
|
HardwareErrorCode.DeviceInterruptedFromUser,
|
|
1269
1166
|
HardwareErrorCode.CallQueueActionCancelled,
|
|
1270
|
-
].includes(error.errorCode)
|
|
1271
|
-
isProtocolV2PeerRemovedPairingError(method, error)
|
|
1167
|
+
].includes(error.errorCode)
|
|
1272
1168
|
) {
|
|
1273
1169
|
reject(error);
|
|
1274
1170
|
return;
|
|
@@ -1324,9 +1220,6 @@ export const cancel = (context: CoreContext, connectId?: string) => {
|
|
|
1324
1220
|
','
|
|
1325
1221
|
)}`
|
|
1326
1222
|
);
|
|
1327
|
-
// Abort before rejecting: rejectRequest releases the task and would make
|
|
1328
|
-
// its AbortController unreachable to an in-flight method loop.
|
|
1329
|
-
requestQueue.abortRequestsByConnectId(connectId);
|
|
1330
1223
|
const canceledDevices: Device[] = [];
|
|
1331
1224
|
const interruptDevice = (device: Device | undefined, deviceConnectId: string) => {
|
|
1332
1225
|
if (!device || canceledDevices.includes(device)) {
|
|
@@ -1351,6 +1244,7 @@ export const cancel = (context: CoreContext, connectId?: string) => {
|
|
|
1351
1244
|
}
|
|
1352
1245
|
}
|
|
1353
1246
|
interruptDevice(deviceCacheMap.get(connectId), connectId);
|
|
1247
|
+
requestQueue.abortRequestsByConnectId(connectId);
|
|
1354
1248
|
pollingManager.stop(connectId);
|
|
1355
1249
|
} catch (e) {
|
|
1356
1250
|
Log.error('Cancel API Error: ', e);
|
|
@@ -1359,8 +1253,6 @@ export const cancel = (context: CoreContext, connectId?: string) => {
|
|
|
1359
1253
|
const env = DataManager.getSettings('env');
|
|
1360
1254
|
if (DataManager.isBleConnect(env)) {
|
|
1361
1255
|
Log.debug('Cancel Api all _deviceList: ');
|
|
1362
|
-
// Keep method abort signals observable until every active task is rejected.
|
|
1363
|
-
requestQueue.abortAllRequests();
|
|
1364
1256
|
const canceledDevices: Device[] = [];
|
|
1365
1257
|
const interruptDevice = (device?: Device) => {
|
|
1366
1258
|
if (!device || canceledDevices.includes(device)) {
|
|
@@ -1385,6 +1277,7 @@ export const cancel = (context: CoreContext, connectId?: string) => {
|
|
|
1385
1277
|
}
|
|
1386
1278
|
}
|
|
1387
1279
|
deviceCacheMap.forEach(interruptDevice);
|
|
1280
|
+
requestQueue.abortAllRequests();
|
|
1388
1281
|
pollingManager.stopAll();
|
|
1389
1282
|
} else {
|
|
1390
1283
|
_deviceList?.allDevices().forEach(device => {
|
|
@@ -1435,10 +1328,6 @@ const checkPassphraseEnableState = (method: BaseMethod, features?: Features) =>
|
|
|
1435
1328
|
const shouldCheckPassphraseState = (method: BaseMethod, device: Device) => {
|
|
1436
1329
|
if (!method.useDevicePassphraseState) return false;
|
|
1437
1330
|
|
|
1438
|
-
if (device.isProtocolV2() && method.payload?.useEmptyPassphrase === true) {
|
|
1439
|
-
return true;
|
|
1440
|
-
}
|
|
1441
|
-
|
|
1442
1331
|
return device.hasUsePassphrase();
|
|
1443
1332
|
};
|
|
1444
1333
|
|