@onekeyfe/hd-core 1.2.0-alpha.56 → 1.2.0-alpha.58
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 +84 -2
- package/__tests__/DeviceCommands.test.ts +17 -6
- package/__tests__/core-initialization.test.ts +23 -0
- package/__tests__/device-connector-protocol.test.ts +81 -0
- package/__tests__/device-settings.test.ts +39 -18
- package/__tests__/protocol-v2-resources.test.ts +24 -0
- package/__tests__/protocol-v2.test.ts +46 -1
- package/__tests__/protocolV2FileWrite.test.ts +113 -0
- package/dist/api/FirmwareUpdateV4.d.ts +0 -1
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/device/DeviceSettings.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +4 -2
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +7 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +1 -0
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/TransportManager.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DeviceConnector.d.ts +2 -1
- package/dist/device/DeviceConnector.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +448 -336
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +39 -69
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +3 -1
- package/src/api/device/DeviceSettings.ts +5 -4
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +12 -1
- package/src/api/helpers/protocolV2FileWrite.ts +192 -73
- package/src/core/index.ts +9 -6
- package/src/data-manager/DataManager.ts +25 -4
- package/src/data-manager/TransportManager.ts +6 -0
- package/src/device/DeviceCommands.ts +20 -2
- package/src/device/DeviceConnector.ts +33 -13
|
@@ -26,6 +26,7 @@ import type {
|
|
|
26
26
|
Features,
|
|
27
27
|
IDeviceBLEFirmwareStatus,
|
|
28
28
|
IDeviceFirmwareStatus,
|
|
29
|
+
IProtocolV2Resources,
|
|
29
30
|
ITransportStatus,
|
|
30
31
|
IVersionArray,
|
|
31
32
|
RemoteConfigResponse,
|
|
@@ -112,6 +113,8 @@ export default class DataManager {
|
|
|
112
113
|
|
|
113
114
|
static lastCheckTimestamp = 0;
|
|
114
115
|
|
|
116
|
+
static protocolV2ResourcesConfigError: Error | undefined;
|
|
117
|
+
|
|
115
118
|
static getFirmwareStatus = (
|
|
116
119
|
features: Features,
|
|
117
120
|
firmwareType: EFirmwareType
|
|
@@ -400,6 +403,7 @@ export default class DataManager {
|
|
|
400
403
|
|
|
401
404
|
static async load(settings: ConnectSettings): Promise<boolean> {
|
|
402
405
|
this.settings = settings;
|
|
406
|
+
this.protocolV2ResourcesConfigError = undefined;
|
|
403
407
|
if (!settings.fetchConfig) {
|
|
404
408
|
return false;
|
|
405
409
|
}
|
|
@@ -446,9 +450,20 @@ export default class DataManager {
|
|
|
446
450
|
|
|
447
451
|
// 3. Apply config if available
|
|
448
452
|
if (data) {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
453
|
+
let pro2Resources: IProtocolV2Resources | undefined;
|
|
454
|
+
try {
|
|
455
|
+
pro2Resources = parseProtocolV2Resources(
|
|
456
|
+
(data.pro2 as { resources?: unknown } | undefined)?.resources
|
|
457
|
+
);
|
|
458
|
+
} catch (error) {
|
|
459
|
+
// Firmware resource metadata is not required for base communication. If the
|
|
460
|
+
// remote config is temporarily incomplete, disable this resource update only.
|
|
461
|
+
this.protocolV2ResourcesConfigError =
|
|
462
|
+
error instanceof Error ? error : new Error(String(error));
|
|
463
|
+
Log.warn('[DataConfig] Ignoring invalid Pro2 resources config:', error);
|
|
464
|
+
}
|
|
465
|
+
const enrichedPro2Config = this.enrichFirmwareReleaseInfo(data.pro2);
|
|
466
|
+
const { resources: _unvalidatedResources, ...pro2Config } = enrichedPro2Config;
|
|
452
467
|
Log.log(`[DataConfig] Config loaded successfully via [${fetchMethod}]`);
|
|
453
468
|
this.deviceMap = {
|
|
454
469
|
[EDeviceType.Classic]: this.enrichFirmwareReleaseInfo(data.classic),
|
|
@@ -458,7 +473,7 @@ export default class DataManager {
|
|
|
458
473
|
[EDeviceType.Touch]: this.enrichFirmwareReleaseInfo(data.touch),
|
|
459
474
|
[EDeviceType.Pro]: this.enrichFirmwareReleaseInfo(data.pro),
|
|
460
475
|
[EDeviceType.Pro2]: {
|
|
461
|
-
...
|
|
476
|
+
...pro2Config,
|
|
462
477
|
...(pro2Resources ? { resources: pro2Resources } : undefined),
|
|
463
478
|
},
|
|
464
479
|
};
|
|
@@ -505,6 +520,12 @@ export default class DataManager {
|
|
|
505
520
|
'Unable to refresh the latest remote config'
|
|
506
521
|
);
|
|
507
522
|
}
|
|
523
|
+
if (this.protocolV2ResourcesConfigError) {
|
|
524
|
+
throw ERRORS.TypedError(
|
|
525
|
+
HardwareErrorCode.NetworkError,
|
|
526
|
+
`Invalid Pro2 resources config: ${this.protocolV2ResourcesConfigError.message}`
|
|
527
|
+
);
|
|
528
|
+
}
|
|
508
529
|
this.lastCheckTimestamp = getTimeStamp();
|
|
509
530
|
}
|
|
510
531
|
|
|
@@ -121,6 +121,12 @@ export default class TransportManager {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
static setTransport(TransportConstructor: any, plugin?: LowlevelTransportSharedPlugin) {
|
|
124
|
+
if (typeof TransportConstructor !== 'function') {
|
|
125
|
+
throw ERRORS.TypedError(
|
|
126
|
+
HardwareErrorCode.TransportNotConfigured,
|
|
127
|
+
'Transport constructor is not available'
|
|
128
|
+
);
|
|
129
|
+
}
|
|
124
130
|
const env = DataManager.getSettings('env');
|
|
125
131
|
if (env === 'react-native') {
|
|
126
132
|
/** Actually initializes the ReactNativeTransport */
|
|
@@ -55,8 +55,10 @@ const DEVICE_SESSION_CALLS = new Set([
|
|
|
55
55
|
'DeviceSessionAskPassphrase',
|
|
56
56
|
]);
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
const PROTOCOL_V2_ACTION_CANCELLED_SUBCODE = 1;
|
|
59
|
+
|
|
60
|
+
// Older Protocol V2 firmware may omit the cancellation subcode, so retain a
|
|
61
|
+
// narrow message fallback for compatibility.
|
|
60
62
|
const isProtocolV2ActionCancelledMessage = (message: string) =>
|
|
61
63
|
/^(?:cancel(?:led|ed)(?: on device)?|confirm dismissed|user cancel(?:led|ed)(?:\s+.*)?)$/i.test(
|
|
62
64
|
message
|
|
@@ -499,6 +501,15 @@ export class DeviceCommands {
|
|
|
499
501
|
const normalizedMessage = message?.trim() ?? '';
|
|
500
502
|
const isProtocolV2ActionCancelledFailure =
|
|
501
503
|
this.device.isProtocolV2() && isProtocolV2ActionCancelledMessage(normalizedMessage);
|
|
504
|
+
const isProtocolV2ActionCancelledSubcode =
|
|
505
|
+
this.device.isProtocolV2() && subcode === PROTOCOL_V2_ACTION_CANCELLED_SUBCODE;
|
|
506
|
+
// DeviceErrorCode currently reuses subcode 1 for Busy. Resolve that
|
|
507
|
+
// domain-specific exception before applying the common cancellation map.
|
|
508
|
+
const isProtocolV2DeviceBusyFailure =
|
|
509
|
+
this.device.isProtocolV2() &&
|
|
510
|
+
callType.startsWith('Device') &&
|
|
511
|
+
!DEVICE_SESSION_CALLS.has(callType) &&
|
|
512
|
+
subcode === DeviceErrorCode.DeviceError_Busy;
|
|
502
513
|
const isLegacyProtocolV2LockedFailure =
|
|
503
514
|
this.device.isProtocolV2() && /^device (?:is )?locked$/i.test(normalizedMessage);
|
|
504
515
|
if (
|
|
@@ -556,8 +567,15 @@ export class DeviceCommands {
|
|
|
556
567
|
subcode,
|
|
557
568
|
firmwareMessage: message,
|
|
558
569
|
});
|
|
570
|
+
} else if (isProtocolV2DeviceBusyFailure) {
|
|
571
|
+
error = ERRORS.TypedError(HardwareErrorCode.DeviceBusy, message, {
|
|
572
|
+
failureCode: code,
|
|
573
|
+
subcode,
|
|
574
|
+
firmwareMessage: message,
|
|
575
|
+
});
|
|
559
576
|
} else if (
|
|
560
577
|
subcode === DeviceErrorCode.DeviceError_ActionCancelled ||
|
|
578
|
+
isProtocolV2ActionCancelledSubcode ||
|
|
561
579
|
isProtocolV2ActionCancelledFailure
|
|
562
580
|
) {
|
|
563
581
|
error = ERRORS.TypedError(HardwareErrorCode.ActionCancelled, message, {
|
|
@@ -14,7 +14,7 @@ import type { OneKeyDeviceInfo as DeviceDescriptor, Transport } from '@onekeyfe/
|
|
|
14
14
|
const Log = getLogger(LoggerNames.DeviceConnector);
|
|
15
15
|
|
|
16
16
|
export default class DeviceConnector {
|
|
17
|
-
transport
|
|
17
|
+
transport?: Transport;
|
|
18
18
|
|
|
19
19
|
listenTimestamp = 0;
|
|
20
20
|
|
|
@@ -30,9 +30,21 @@ export default class DeviceConnector {
|
|
|
30
30
|
DevicePool.setConnector(this);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
private getActiveTransport(): Transport {
|
|
34
|
+
const transport = this.transport ?? TransportManager.getTransport();
|
|
35
|
+
if (!transport) {
|
|
36
|
+
throw ERRORS.TypedError(
|
|
37
|
+
HardwareErrorCode.TransportNotConfigured,
|
|
38
|
+
'Device connector was created before transport initialization'
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
this.transport = transport;
|
|
42
|
+
return transport;
|
|
43
|
+
}
|
|
44
|
+
|
|
33
45
|
async enumerate() {
|
|
34
46
|
try {
|
|
35
|
-
const descriptors = await this.
|
|
47
|
+
const descriptors = await this.getActiveTransport().enumerate();
|
|
36
48
|
this.upcoming = descriptors;
|
|
37
49
|
this._reportDevicesChange();
|
|
38
50
|
return { descriptors } as DeviceDescriptorDiff;
|
|
@@ -50,11 +62,10 @@ export default class DeviceConnector {
|
|
|
50
62
|
let descriptors: DeviceDescriptor[];
|
|
51
63
|
|
|
52
64
|
try {
|
|
65
|
+
const transport = this.getActiveTransport();
|
|
53
66
|
Log.debug('Start listening', current);
|
|
54
67
|
this.listenTimestamp = new Date().getTime();
|
|
55
|
-
descriptors = waitForEvent
|
|
56
|
-
? await this.transport.listen(current)
|
|
57
|
-
: await this.transport.enumerate();
|
|
68
|
+
descriptors = waitForEvent ? await transport.listen(current) : await transport.enumerate();
|
|
58
69
|
if (!this.listening) return; // do not continue if stop() was called
|
|
59
70
|
|
|
60
71
|
this.upcoming = descriptors;
|
|
@@ -88,16 +99,17 @@ export default class DeviceConnector {
|
|
|
88
99
|
Log.debug('acquire', path, session, expectedProtocol, protocolHint);
|
|
89
100
|
const env = DataManager.getSettings('env');
|
|
90
101
|
try {
|
|
102
|
+
const transport = this.getActiveTransport();
|
|
91
103
|
let res;
|
|
92
104
|
if (DataManager.isBleConnect(env)) {
|
|
93
|
-
res = await
|
|
105
|
+
res = await transport.acquire({
|
|
94
106
|
uuid: path,
|
|
95
107
|
forceCleanRunPromise,
|
|
96
108
|
expectedProtocol,
|
|
97
109
|
protocolHint,
|
|
98
110
|
});
|
|
99
111
|
} else {
|
|
100
|
-
res = await
|
|
112
|
+
res = await transport.acquire({
|
|
101
113
|
path,
|
|
102
114
|
previous: session ?? null,
|
|
103
115
|
expectedProtocol,
|
|
@@ -105,7 +117,13 @@ export default class DeviceConnector {
|
|
|
105
117
|
});
|
|
106
118
|
}
|
|
107
119
|
if (expectedProtocol) {
|
|
108
|
-
|
|
120
|
+
// The acquire response is the stable snapshot from this active probe. A delayed
|
|
121
|
+
// disconnect from an older generation may clear caches, so do not rely on cache alone.
|
|
122
|
+
const acquiredProtocol =
|
|
123
|
+
typeof res === 'object' && res !== null
|
|
124
|
+
? (res as DeviceDescriptor).protocolType
|
|
125
|
+
: undefined;
|
|
126
|
+
const detectedProtocol = acquiredProtocol ?? transport.getProtocolType(path);
|
|
109
127
|
if (detectedProtocol !== expectedProtocol) {
|
|
110
128
|
throw ERRORS.TypedError(
|
|
111
129
|
HardwareErrorCode.RuntimeError,
|
|
@@ -122,7 +140,7 @@ export default class DeviceConnector {
|
|
|
122
140
|
|
|
123
141
|
async release(session: string, onclose: boolean) {
|
|
124
142
|
try {
|
|
125
|
-
const res = await this.
|
|
143
|
+
const res = await this.getActiveTransport().release(session, onclose);
|
|
126
144
|
return res;
|
|
127
145
|
} catch (error) {
|
|
128
146
|
safeThrowError(error);
|
|
@@ -131,8 +149,9 @@ export default class DeviceConnector {
|
|
|
131
149
|
|
|
132
150
|
async disconnect(session: string | undefined | null) {
|
|
133
151
|
try {
|
|
134
|
-
|
|
135
|
-
|
|
152
|
+
const transport = this.getActiveTransport();
|
|
153
|
+
if (transport.disconnect && !!session) {
|
|
154
|
+
await transport.disconnect(session);
|
|
136
155
|
}
|
|
137
156
|
} catch (error) {
|
|
138
157
|
safeThrowError(error);
|
|
@@ -140,10 +159,11 @@ export default class DeviceConnector {
|
|
|
140
159
|
}
|
|
141
160
|
|
|
142
161
|
promptDeviceAccess(): Promise<USBDevice | BluetoothDevice | null> {
|
|
143
|
-
|
|
162
|
+
const transport = this.getActiveTransport();
|
|
163
|
+
if (!transport.promptDeviceAccess) {
|
|
144
164
|
return Promise.resolve(null);
|
|
145
165
|
}
|
|
146
|
-
return
|
|
166
|
+
return transport.promptDeviceAccess();
|
|
147
167
|
}
|
|
148
168
|
|
|
149
169
|
_reportDevicesChange() {
|