@onekeyfe/hd-core 1.2.0-alpha.133 → 1.2.0-alpha.134
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__/DeviceCommands.test.ts +0 -7
- package/__tests__/device-lifecycle-events.test.ts +2 -91
- package/__tests__/device-settings.test.ts +9 -167
- package/__tests__/device-wallet-session-store.test.ts +79 -21
- package/__tests__/protocol-v2.test.ts +1 -34
- package/dist/api/device/DeviceSettings.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/core/index.d.ts +1 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +0 -2
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.js +206 -268
- package/package.json +4 -4
- package/src/api/device/DeviceSettings.ts +16 -2
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +0 -11
- package/src/core/index.ts +25 -67
- package/src/device/Device.ts +42 -42
- package/src/device/DeviceCommands.ts +1 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-core",
|
|
3
|
-
"version": "1.2.0-alpha.
|
|
3
|
+
"version": "1.2.0-alpha.134",
|
|
4
4
|
"description": "Core processes and APIs for communicating with OneKey hardware devices.",
|
|
5
5
|
"author": "OneKey",
|
|
6
6
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@onekeyfe/hd-shared": "1.2.0-alpha.
|
|
29
|
-
"@onekeyfe/hd-transport": "1.2.0-alpha.
|
|
28
|
+
"@onekeyfe/hd-shared": "1.2.0-alpha.134",
|
|
29
|
+
"@onekeyfe/hd-transport": "1.2.0-alpha.134",
|
|
30
30
|
"axios": "1.15.2",
|
|
31
31
|
"bignumber.js": "^9.0.2",
|
|
32
32
|
"buffer": "^6.0.3",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"@types/w3c-web-usb": "^1.0.10",
|
|
47
47
|
"@types/web-bluetooth": "^0.0.21"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "47de2b0244584f6a541a84b0f94e4676bf63221a"
|
|
50
50
|
}
|
|
@@ -168,7 +168,8 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
|
|
|
168
168
|
async run() {
|
|
169
169
|
try {
|
|
170
170
|
if (this.device.isProtocolV2()) {
|
|
171
|
-
const refreshStatusAndSettings = () =>
|
|
171
|
+
const refreshStatusAndSettings = () =>
|
|
172
|
+
this.device.getDeviceState({ refreshSections: ['status', 'settings'] });
|
|
172
173
|
assertSettingsSupported(this.payload, DEVICE_SETTINGS_V1_ONLY_FIELDS, 'Protocol V2');
|
|
173
174
|
const capabilities = getDeviceSettingsCapabilities(
|
|
174
175
|
this.device.getCurrentDeviceType(),
|
|
@@ -200,7 +201,20 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
|
|
|
200
201
|
const res = await this.device.commands.typedCall('DeviceSettingsPageShow', 'Success', {
|
|
201
202
|
page: DeviceSettingsPage.DevicePassphrase,
|
|
202
203
|
});
|
|
203
|
-
await refreshStatusAndSettings();
|
|
204
|
+
const updated = await refreshStatusAndSettings();
|
|
205
|
+
const lockedAfterDisabling =
|
|
206
|
+
requestedPassphrase === false &&
|
|
207
|
+
current.status.unlocked === true &&
|
|
208
|
+
updated.status.unlocked === false;
|
|
209
|
+
if (
|
|
210
|
+
updated.status.passphraseProtection !== requestedPassphrase &&
|
|
211
|
+
!lockedAfterDisabling
|
|
212
|
+
) {
|
|
213
|
+
throw TypedError(
|
|
214
|
+
HardwareErrorCode.RuntimeError,
|
|
215
|
+
'Protocol V2 passphrase setting did not reach the requested value.'
|
|
216
|
+
);
|
|
217
|
+
}
|
|
204
218
|
return res.message;
|
|
205
219
|
}
|
|
206
220
|
if (requestedAirgap !== undefined) {
|
|
@@ -8,7 +8,6 @@ import { invalidParameter } from '../helpers/filesystemValidation';
|
|
|
8
8
|
import { writeProtocolV2File } from '../helpers/protocolV2FileWrite';
|
|
9
9
|
import { UI_REQUEST, createUiMessage } from '../../events/ui-request';
|
|
10
10
|
import { supportsProtocolV2Message } from '../../protocols/protocol-v2/features';
|
|
11
|
-
import { LoggerNames, getLogger } from '../../utils';
|
|
12
11
|
import {
|
|
13
12
|
PRO2_WALLPAPER_HEIGHT,
|
|
14
13
|
PRO2_WALLPAPER_WIDTH,
|
|
@@ -34,7 +33,6 @@ const SAFE_FILE_NAME = /^[A-Za-z0-9_-]+(?:\.bin)?$/;
|
|
|
34
33
|
const DEVICE_SETTINGS_SET_MESSAGE_TYPE = 60412;
|
|
35
34
|
const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
|
|
36
35
|
const FILESYSTEM_DIR_MAKE_MESSAGE_TYPE = 60809;
|
|
37
|
-
const Log = getLogger(LoggerNames.Method);
|
|
38
36
|
|
|
39
37
|
function normalizeFileName(fileName: string | undefined, data: Uint8Array): string {
|
|
40
38
|
if (fileName !== undefined && (!fileName || !SAFE_FILE_NAME.test(fileName))) {
|
|
@@ -145,15 +143,6 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
145
143
|
const response = await this.device.commands.typedCall('DeviceSettingsSet', 'Success', {
|
|
146
144
|
settings: { wallpaper_path: this.path },
|
|
147
145
|
});
|
|
148
|
-
try {
|
|
149
|
-
await this.device.refreshProtocolV2SettingsAfterMutation();
|
|
150
|
-
} catch (error) {
|
|
151
|
-
// The wallpaper is already applied. A transient read-back failure must not
|
|
152
|
-
// make callers retry the completed file upload.
|
|
153
|
-
Log.warn('Protocol V2 wallpaper settings refresh failed after apply', {
|
|
154
|
-
error: error instanceof Error ? error.message : String(error),
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
146
|
return {
|
|
158
147
|
path: this.path,
|
|
159
148
|
size: encoded.data.byteLength,
|
package/src/core/index.ts
CHANGED
|
@@ -83,7 +83,6 @@ import type { BaseMethod } from '../api/BaseMethod';
|
|
|
83
83
|
|
|
84
84
|
const Log = getLogger(LoggerNames.Core);
|
|
85
85
|
const PRE_INITIALIZE_TTL_MS = 60 * 1000;
|
|
86
|
-
const PRE_PENDING_CALL_TIMEOUT_MS = 15 * 1000;
|
|
87
86
|
|
|
88
87
|
// Dedup/coalesce state for "pre-warm signal" methods (isPreWarmSignal),
|
|
89
88
|
// keyed by getPreWarmKey(): coalesce in-flight, skip if warmed within TTL.
|
|
@@ -297,35 +296,26 @@ const handlePreWarmSignal = async (
|
|
|
297
296
|
}
|
|
298
297
|
};
|
|
299
298
|
|
|
299
|
+
const waitWithTimeout = async (promise: Promise<any>, timeout: number) => {
|
|
300
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
301
|
+
setTimeout(() => reject(new Error('Request timeout')), timeout);
|
|
302
|
+
});
|
|
303
|
+
return Promise.race([promise, timeoutPromise]);
|
|
304
|
+
};
|
|
305
|
+
|
|
300
306
|
const waitForPendingPromise = async (
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
removePrePendingCallPromise?: (connectId: string, promise: Promise<void>) => void
|
|
307
|
+
getPrePendingCallPromise: () => Promise<void> | undefined,
|
|
308
|
+
removePrePendingCallPromise?: (promise: Promise<void> | undefined) => void
|
|
304
309
|
) => {
|
|
305
|
-
const pendingPromise = getPrePendingCallPromise(
|
|
310
|
+
const pendingPromise = getPrePendingCallPromise();
|
|
306
311
|
if (pendingPromise) {
|
|
307
312
|
Log.debug('pre pending call promise before call method, wait for it');
|
|
308
|
-
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
309
|
-
let timedOut = false;
|
|
310
313
|
try {
|
|
311
|
-
await
|
|
312
|
-
pendingPromise,
|
|
313
|
-
new Promise<void>(resolve => {
|
|
314
|
-
timer = setTimeout(() => {
|
|
315
|
-
timedOut = true;
|
|
316
|
-
resolve();
|
|
317
|
-
}, PRE_PENDING_CALL_TIMEOUT_MS);
|
|
318
|
-
}),
|
|
319
|
-
]);
|
|
314
|
+
await waitWithTimeout(pendingPromise, 5 * 1000);
|
|
320
315
|
} catch (error) {
|
|
321
|
-
//
|
|
322
|
-
} finally {
|
|
323
|
-
if (timer) clearTimeout(timer);
|
|
324
|
-
removePrePendingCallPromise?.(connectId, pendingPromise);
|
|
325
|
-
}
|
|
326
|
-
if (timedOut) {
|
|
327
|
-
Log.warn('pre pending call promise timed out before call method', { connectId });
|
|
316
|
+
// ignore timeout error
|
|
328
317
|
}
|
|
318
|
+
removePrePendingCallPromise?.(pendingPromise);
|
|
329
319
|
Log.debug('pre pending call promise before call method done');
|
|
330
320
|
}
|
|
331
321
|
};
|
|
@@ -337,7 +327,7 @@ const onCallDevice = async (
|
|
|
337
327
|
): Promise<any> => {
|
|
338
328
|
let messageResponse: any;
|
|
339
329
|
|
|
340
|
-
const { requestQueue, getPrePendingCallPromise,
|
|
330
|
+
const { requestQueue, getPrePendingCallPromise, setPrePendingCallPromise } = context;
|
|
341
331
|
|
|
342
332
|
updateMethodRequestContext(method, { status: 'running' });
|
|
343
333
|
|
|
@@ -365,11 +355,7 @@ const onCallDevice = async (
|
|
|
365
355
|
await context.waitForCallbackTasks(method.connectId);
|
|
366
356
|
}
|
|
367
357
|
|
|
368
|
-
await waitForPendingPromise(
|
|
369
|
-
method.connectId ?? '',
|
|
370
|
-
getPrePendingCallPromise,
|
|
371
|
-
removePrePendingCallPromise
|
|
372
|
-
);
|
|
358
|
+
await waitForPendingPromise(getPrePendingCallPromise, setPrePendingCallPromise);
|
|
373
359
|
|
|
374
360
|
const task = requestQueue.createTask(method);
|
|
375
361
|
|
|
@@ -468,11 +454,7 @@ const onCallDevice = async (
|
|
|
468
454
|
await context.waitForCallbackTasks(method.connectId, preWarmCallbackTask);
|
|
469
455
|
}
|
|
470
456
|
|
|
471
|
-
await waitForPendingPromise(
|
|
472
|
-
method.connectId ?? '',
|
|
473
|
-
getPrePendingCallPromise,
|
|
474
|
-
removePrePendingCallPromise
|
|
475
|
-
);
|
|
457
|
+
await waitForPendingPromise(getPrePendingCallPromise, setPrePendingCallPromise);
|
|
476
458
|
|
|
477
459
|
const inner = async (): Promise<void> => {
|
|
478
460
|
// Protocol is established from an active device response during acquire/initialize.
|
|
@@ -924,16 +906,6 @@ function isRetryableBleProtocolV2ProbeError(method: BaseMethod, error: unknown)
|
|
|
924
906
|
);
|
|
925
907
|
}
|
|
926
908
|
|
|
927
|
-
export function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unknown) {
|
|
928
|
-
const typedError = error as { errorCode?: unknown; message?: unknown };
|
|
929
|
-
return (
|
|
930
|
-
method.payload.connectProtocol === 'V2' &&
|
|
931
|
-
typedError?.errorCode === HardwareErrorCode.RuntimeError &&
|
|
932
|
-
typeof typedError.message === 'string' &&
|
|
933
|
-
typedError.message.includes('Device protocol has not been detected')
|
|
934
|
-
);
|
|
935
|
-
}
|
|
936
|
-
|
|
937
909
|
/**
|
|
938
910
|
* If the Bluetooth connection times out, retry up to 6 times
|
|
939
911
|
* @param retryCount - Current retry count (default 0)
|
|
@@ -971,13 +943,12 @@ async function connectDeviceForBle(method: BaseMethod, device: Device, retryCoun
|
|
|
971
943
|
DevicePool.emitter.emit(DEVICE.CONNECT, device);
|
|
972
944
|
}
|
|
973
945
|
} catch (err) {
|
|
974
|
-
const requiresColdReconnect = isMissingDetectedProtocolV2Error(method, err);
|
|
975
946
|
// Device.run()'s REQUIRE_DISCONNECT handling never sees acquire/initialize
|
|
976
947
|
// failures, so with keep-alive a wedged link would be reused by every retry
|
|
977
948
|
// (field case: Initialize timing out at 25s per attempt, forever). Drop it
|
|
978
949
|
// here so the next retry cold-connects.
|
|
979
950
|
if (
|
|
980
|
-
|
|
951
|
+
ERROR_CODES_REQUIRE_DISCONNECT.includes(err.errorCode) &&
|
|
981
952
|
device.mainId &&
|
|
982
953
|
device.deviceConnector
|
|
983
954
|
) {
|
|
@@ -990,12 +961,11 @@ async function connectDeviceForBle(method: BaseMethod, device: Device, retryCoun
|
|
|
990
961
|
if (
|
|
991
962
|
(err.errorCode === HardwareErrorCode.BleTimeoutError ||
|
|
992
963
|
err.errorCode === HardwareErrorCode.BleConnectedError ||
|
|
993
|
-
isRetryableBleProtocolV2ProbeError(method, err)
|
|
994
|
-
requiresColdReconnect) &&
|
|
964
|
+
isRetryableBleProtocolV2ProbeError(method, err)) &&
|
|
995
965
|
retryCount < 6
|
|
996
966
|
) {
|
|
997
967
|
const nextRetry = retryCount + 1;
|
|
998
|
-
Log.debug(`Bluetooth
|
|
968
|
+
Log.debug(`Bluetooth connect timeout and will retry, retry count: ${nextRetry}`);
|
|
999
969
|
await wait(3000);
|
|
1000
970
|
await connectDeviceForBle(method, device, nextRetry);
|
|
1001
971
|
} else {
|
|
@@ -1207,10 +1177,7 @@ export const cancel = (context: CoreContext, connectId?: string) => {
|
|
|
1207
1177
|
if (task && task.method?.device) {
|
|
1208
1178
|
if (!canceledDevices.includes(task.method.device)) {
|
|
1209
1179
|
const { device } = task.method;
|
|
1210
|
-
setPrePendingCallPromise(
|
|
1211
|
-
task.method.connectId ?? connectId,
|
|
1212
|
-
device.interruptionFromUser()
|
|
1213
|
-
);
|
|
1180
|
+
setPrePendingCallPromise(device?.interruptionFromUser());
|
|
1214
1181
|
canceledDevices.push(device);
|
|
1215
1182
|
}
|
|
1216
1183
|
requestQueue.rejectRequest(
|
|
@@ -1564,7 +1531,7 @@ export default class Core extends EventEmitter {
|
|
|
1564
1531
|
private disposePromise?: Promise<void>;
|
|
1565
1532
|
|
|
1566
1533
|
// background task
|
|
1567
|
-
private
|
|
1534
|
+
private prePendingCallPromise: Promise<void> | undefined;
|
|
1568
1535
|
|
|
1569
1536
|
private methodSynchronize = getSynchronize();
|
|
1570
1537
|
|
|
@@ -1581,18 +1548,9 @@ export default class Core extends EventEmitter {
|
|
|
1581
1548
|
tracingContext: this.tracingContext,
|
|
1582
1549
|
requestQueue: this.requestQueue,
|
|
1583
1550
|
methodSynchronize: this.methodSynchronize,
|
|
1584
|
-
getPrePendingCallPromise: (
|
|
1585
|
-
setPrePendingCallPromise: (
|
|
1586
|
-
|
|
1587
|
-
this.prePendingCallPromises.delete(connectId);
|
|
1588
|
-
return;
|
|
1589
|
-
}
|
|
1590
|
-
this.prePendingCallPromises.set(connectId, promise);
|
|
1591
|
-
},
|
|
1592
|
-
removePrePendingCallPromise: (connectId: string, promise: Promise<void>) => {
|
|
1593
|
-
if (this.prePendingCallPromises.get(connectId) === promise) {
|
|
1594
|
-
this.prePendingCallPromises.delete(connectId);
|
|
1595
|
-
}
|
|
1551
|
+
getPrePendingCallPromise: () => this.prePendingCallPromise,
|
|
1552
|
+
setPrePendingCallPromise: (promise: Promise<void> | undefined) => {
|
|
1553
|
+
this.prePendingCallPromise = promise;
|
|
1596
1554
|
},
|
|
1597
1555
|
// callback 任务管理
|
|
1598
1556
|
registerCallbackTask: (connectId: string, callbackPromise: Deferred<any>) => {
|
|
@@ -1707,7 +1665,7 @@ export default class Core extends EventEmitter {
|
|
|
1707
1665
|
preWarmInflight.clear();
|
|
1708
1666
|
preWarmDoneAt.clear();
|
|
1709
1667
|
preConnectCache = { passphraseState: undefined };
|
|
1710
|
-
this.
|
|
1668
|
+
this.prePendingCallPromise = undefined;
|
|
1711
1669
|
this.removeAllListeners();
|
|
1712
1670
|
cleanupSdkInstance(this.sdkInstanceId);
|
|
1713
1671
|
if (_core === this) _core = undefined;
|
package/src/device/Device.ts
CHANGED
|
@@ -284,9 +284,6 @@ export class Device extends EventEmitter {
|
|
|
284
284
|
|
|
285
285
|
runPromise?: Deferred<void> | null;
|
|
286
286
|
|
|
287
|
-
/** Resolves only after the active run has completed its release path. */
|
|
288
|
-
private runCleanupPromise?: Promise<void>;
|
|
289
|
-
|
|
290
287
|
externalState: string[] = [];
|
|
291
288
|
|
|
292
289
|
unavailableCapabilities: UnavailableCapabilities = {};
|
|
@@ -930,17 +927,6 @@ export class Device extends EventEmitter {
|
|
|
930
927
|
};
|
|
931
928
|
|
|
932
929
|
const expectedDeviceId = options?.deviceId;
|
|
933
|
-
if (expectedDeviceId) {
|
|
934
|
-
// 先只读校验物理设备身份;钱包上下文仍由下方携带完整参数的
|
|
935
|
-
// Initialize 选择,避免标准钱包请求复用此前的隐藏钱包上下文。
|
|
936
|
-
this.passphraseState = undefined;
|
|
937
|
-
const { message } = await this.commands.typedCall('GetFeatures', 'Features', {});
|
|
938
|
-
this._updateFeatures(message);
|
|
939
|
-
await TransportManager.reconfigure(this.features);
|
|
940
|
-
if (!this.checkDeviceId(expectedDeviceId)) {
|
|
941
|
-
throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
930
|
|
|
945
931
|
this.passphraseState = options?.passphraseState;
|
|
946
932
|
|
|
@@ -960,7 +946,46 @@ export class Device extends EventEmitter {
|
|
|
960
946
|
payload.derive_cardano = true;
|
|
961
947
|
}
|
|
962
948
|
|
|
963
|
-
|
|
949
|
+
if (this.features) {
|
|
950
|
+
// Re-sync the V1 message schema for THIS device before encoding
|
|
951
|
+
// Initialize: the process-global schema may still reflect another
|
|
952
|
+
// device (e.g. legacy-firmware Touch/Mini) on multi-device setups, and
|
|
953
|
+
// a stale legacy schema would silently strip passphrase_state /
|
|
954
|
+
// is_contains_attach from the wire message. Local operation, no wire
|
|
955
|
+
// I/O; a no-op when the schema is unchanged.
|
|
956
|
+
await TransportManager.reconfigure(this.features);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// Initialize's own Features response carries device_id, so the physical
|
|
960
|
+
// device identity is validated on the same round trip instead of via a
|
|
961
|
+
// separate read-only GetFeatures preflight (which doubled the wire cost
|
|
962
|
+
// of every deviceId-carrying call). The method fn has not run yet, so a
|
|
963
|
+
// mismatch still fails before any wallet data can be derived, with the
|
|
964
|
+
// same DeviceCheckDeviceIdError. Wallet-context selection is unchanged:
|
|
965
|
+
// it is decided by the Initialize payload above either way.
|
|
966
|
+
const assertExpectedDeviceIdentity = () => {
|
|
967
|
+
if (expectedDeviceId && !this.checkDeviceId(expectedDeviceId)) {
|
|
968
|
+
// The mismatched Initialize may have cached a session under the wrong
|
|
969
|
+
// device's identity; drop it so no wallet context survives from it.
|
|
970
|
+
// (This also evicts any session the wrong device legitimately cached
|
|
971
|
+
// under the same passphraseState — a deliberate conservative purge
|
|
972
|
+
// after a physical-swap event, consistent with
|
|
973
|
+
// reconcileDeviceIdentity purging the previous device's sessions.)
|
|
974
|
+
this.clearInternalState();
|
|
975
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
|
|
979
|
+
try {
|
|
980
|
+
await callInitialize(payload, options?.initSession);
|
|
981
|
+
} catch (error) {
|
|
982
|
+
// callInitialize can fail AFTER the wire call cached the session (e.g.
|
|
983
|
+
// TransportManager.reconfigure rejecting); the identity check must
|
|
984
|
+
// still run so a wrong-device session never survives the error path.
|
|
985
|
+
assertExpectedDeviceIdentity();
|
|
986
|
+
throw error;
|
|
987
|
+
}
|
|
988
|
+
assertExpectedDeviceIdentity();
|
|
964
989
|
} catch (error) {
|
|
965
990
|
Log.error('Initialization failed:', error);
|
|
966
991
|
throw error;
|
|
@@ -1082,10 +1107,6 @@ export class Device extends EventEmitter {
|
|
|
1082
1107
|
return params.includeRaw ? cloneDeviceState(this.state) : createPublicDeviceState(this.state);
|
|
1083
1108
|
}
|
|
1084
1109
|
|
|
1085
|
-
async refreshProtocolV2SettingsAfterMutation() {
|
|
1086
|
-
return this.getDeviceState({ refreshSections: ['status', 'settings'] });
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
1110
|
_updateFeatures(protoFeatures: PROTO.Features | Features, initSession?: boolean) {
|
|
1090
1111
|
const previousDeviceId = this.getCurrentDeviceId();
|
|
1091
1112
|
let feat =
|
|
@@ -1403,20 +1424,12 @@ export class Device extends EventEmitter {
|
|
|
1403
1424
|
|
|
1404
1425
|
const runPromise = createDeferred<void>();
|
|
1405
1426
|
this.runPromise = runPromise;
|
|
1406
|
-
|
|
1427
|
+
this._runInner(fn, options, runPromise).catch(error => {
|
|
1407
1428
|
if (this.runPromise === runPromise) {
|
|
1408
1429
|
this.runPromise = null;
|
|
1409
1430
|
}
|
|
1410
1431
|
runPromise.reject(error);
|
|
1411
1432
|
});
|
|
1412
|
-
this.runCleanupPromise = cleanupPromise;
|
|
1413
|
-
cleanupPromise
|
|
1414
|
-
.finally(() => {
|
|
1415
|
-
if (this.runCleanupPromise === cleanupPromise) {
|
|
1416
|
-
this.runCleanupPromise = undefined;
|
|
1417
|
-
}
|
|
1418
|
-
})
|
|
1419
|
-
.catch(() => undefined);
|
|
1420
1433
|
return runPromise.promise;
|
|
1421
1434
|
}
|
|
1422
1435
|
|
|
@@ -1528,26 +1541,13 @@ export class Device extends EventEmitter {
|
|
|
1528
1541
|
|
|
1529
1542
|
async interruptionFromUser() {
|
|
1530
1543
|
const error = ERRORS.TypedError(HardwareErrorCode.DeviceInterruptedFromUser);
|
|
1531
|
-
|
|
1532
|
-
const { cancelableAction } = this;
|
|
1533
|
-
if (cancelableAction) {
|
|
1534
|
-
await cancelableAction(error);
|
|
1535
|
-
} else if (
|
|
1536
|
-
this.isProtocolV2() &&
|
|
1537
|
-
DataManager.isBleConnect(DataManager.getSettings('env')) &&
|
|
1538
|
-
this.hasDeviceAcquire()
|
|
1539
|
-
) {
|
|
1540
|
-
await this.commands?.cancelDevice?.().catch(cancelError => {
|
|
1541
|
-
Log.debug('Protocol V2 BLE fallback cancel error', cancelError);
|
|
1542
|
-
});
|
|
1543
|
-
}
|
|
1544
|
+
await this.cancelableAction?.(error);
|
|
1544
1545
|
await this.commands?.cancel();
|
|
1545
1546
|
|
|
1546
1547
|
if (this.runPromise) {
|
|
1547
1548
|
this.runPromise.reject(error);
|
|
1548
1549
|
this.runPromise = null;
|
|
1549
1550
|
}
|
|
1550
|
-
await cleanupPromise?.catch(() => undefined);
|
|
1551
1551
|
}
|
|
1552
1552
|
|
|
1553
1553
|
setCancelableAction(callback: (err?: Error) => Promise<unknown>) {
|
|
@@ -264,7 +264,6 @@ export class DeviceCommands {
|
|
|
264
264
|
}
|
|
265
265
|
const activeCall = this.callPromise;
|
|
266
266
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
267
|
-
let timedOut = false;
|
|
268
267
|
const cancellation = (async () => {
|
|
269
268
|
await this.dispose(true);
|
|
270
269
|
await activeCall?.catch(() => undefined);
|
|
@@ -274,23 +273,11 @@ export class DeviceCommands {
|
|
|
274
273
|
await Promise.race([
|
|
275
274
|
cancellation,
|
|
276
275
|
new Promise<void>(resolve => {
|
|
277
|
-
timer = setTimeout(
|
|
278
|
-
timedOut = true;
|
|
279
|
-
resolve();
|
|
280
|
-
}, 10 * 1000);
|
|
276
|
+
timer = setTimeout(resolve, 10 * 1000);
|
|
281
277
|
}),
|
|
282
278
|
]);
|
|
283
279
|
} finally {
|
|
284
280
|
if (timer) clearTimeout(timer);
|
|
285
|
-
if (
|
|
286
|
-
timedOut &&
|
|
287
|
-
this.transport.name === 'ReactNativeBleTransport' &&
|
|
288
|
-
this.transport.disconnect
|
|
289
|
-
) {
|
|
290
|
-
await this.transport.disconnect(this.mainId).catch(error => {
|
|
291
|
-
Log.debug('BLE cancellation timeout disconnect error (ignored)', error);
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
281
|
if (this.callPromise === activeCall) {
|
|
295
282
|
this.callPromise = undefined;
|
|
296
283
|
}
|