@onekeyfe/hd-core 1.2.8 → 1.2.9
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/README.md +27 -0
- package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +13 -4
- package/__tests__/DeviceCommands.test.ts +91 -13
- package/__tests__/allNetworkGetAddress-privacy-networks.test.ts +77 -0
- package/__tests__/allNetworkGetAddress-skippable.test.ts +49 -0
- package/__tests__/btc-derive-context-hash.test.ts +200 -0
- package/__tests__/core-dispose.test.ts +114 -1
- package/__tests__/core-error-output.test.ts +55 -3
- package/__tests__/device-connector-protocol.test.ts +5 -2
- package/__tests__/device-lifecycle-events.test.ts +191 -27
- package/__tests__/device-pool-state.test.ts +50 -0
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +11 -0
- package/__tests__/logBlockEvent.test.ts +331 -9
- package/__tests__/logger.test.ts +18 -0
- package/__tests__/monero-get-address.test.ts +147 -0
- package/__tests__/monero-key-image-sync.test.ts +272 -0
- package/__tests__/monero-sign-transaction.test.ts +436 -0
- package/__tests__/protocol-v2-bootloader-mode.test.ts +43 -2
- package/__tests__/protocol-v2-key-export-confirmation.test.ts +75 -0
- package/__tests__/protocol-v2-resources.test.ts +14 -0
- package/__tests__/protocol-v2.test.ts +841 -46
- package/__tests__/protocolV2FileWrite.test.ts +454 -7
- package/__tests__/refresh-device-state.test.ts +19 -17
- package/__tests__/search-devices.test.ts +36 -0
- package/__tests__/sol-sign-offchain-message.test.ts +8 -0
- package/__tests__/usb-identity-probe.test.ts +358 -0
- package/__tests__/zcash-protobuf.test.ts +152 -0
- package/__tests__/zcash-sign-pczt.test.ts +525 -0
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/FileWrite.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +5 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetDeviceState.d.ts.map +1 -1
- package/dist/api/SearchDevices.d.ts +21 -1
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts +3 -0
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/btc/BTCDeriveContextHash.d.ts +16 -0
- package/dist/api/btc/BTCDeriveContextHash.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -1
- package/dist/api/helpers/pathUtils.d.ts +1 -0
- package/dist/api/helpers/pathUtils.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +5 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +8 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/monero/MoneroGetAddress.d.ts +11 -0
- package/dist/api/monero/MoneroGetAddress.d.ts.map +1 -0
- package/dist/api/monero/MoneroGetWatchKey.d.ts +11 -0
- package/dist/api/monero/MoneroGetWatchKey.d.ts.map +1 -0
- package/dist/api/monero/MoneroKeyImageSync.d.ts +20 -0
- package/dist/api/monero/MoneroKeyImageSync.d.ts.map +1 -0
- package/dist/api/monero/MoneroSignTransaction.d.ts +17 -0
- package/dist/api/monero/MoneroSignTransaction.d.ts.map +1 -0
- package/dist/api/monero/helpers.d.ts +5 -0
- package/dist/api/monero/helpers.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceReboot.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/zcash/ZcashGetAddress.d.ts +12 -0
- package/dist/api/zcash/ZcashGetAddress.d.ts.map +1 -0
- package/dist/api/zcash/ZcashGetFullViewingKey.d.ts +12 -0
- package/dist/api/zcash/ZcashGetFullViewingKey.d.ts.map +1 -0
- package/dist/api/zcash/ZcashSignPczt.d.ts +16 -0
- package/dist/api/zcash/ZcashSignPczt.d.ts.map +1 -0
- package/dist/api/zcash/helpers.d.ts +2 -0
- package/dist/api/zcash/helpers.d.ts.map +1 -0
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +3 -0
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +4 -4
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts +10 -0
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +2 -0
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +206 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4456 -2801
- package/dist/inject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts +1 -0
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/uiInteraction.d.ts +1 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
- package/dist/types/api/allNetworkGetAddress.d.ts +4 -1
- package/dist/types/api/allNetworkGetAddress.d.ts.map +1 -1
- package/dist/types/api/btcDeriveContextHash.d.ts +10 -0
- package/dist/types/api/btcDeriveContextHash.d.ts.map +1 -0
- package/dist/types/api/export.d.ts +8 -0
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +16 -0
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/moneroGetAddress.d.ts +15 -0
- package/dist/types/api/moneroGetAddress.d.ts.map +1 -0
- package/dist/types/api/moneroGetWatchKey.d.ts +15 -0
- package/dist/types/api/moneroGetWatchKey.d.ts.map +1 -0
- package/dist/types/api/moneroKeyImageSync.d.ts +24 -0
- package/dist/types/api/moneroKeyImageSync.d.ts.map +1 -0
- package/dist/types/api/moneroSignTransaction.d.ts +32 -0
- package/dist/types/api/moneroSignTransaction.d.ts.map +1 -0
- package/dist/types/api/zcashGetAddress.d.ts +20 -0
- package/dist/types/api/zcashGetAddress.d.ts.map +1 -0
- package/dist/types/api/zcashGetFullViewingKey.d.ts +13 -0
- package/dist/types/api/zcashGetFullViewingKey.d.ts.map +1 -0
- package/dist/types/api/zcashSignPczt.d.ts +9 -0
- package/dist/types/api/zcashSignPczt.d.ts.map +1 -0
- package/dist/types/device.d.ts +10 -0
- package/dist/types/device.d.ts.map +1 -1
- package/dist/types/params.d.ts +1 -0
- package/dist/types/params.d.ts.map +1 -1
- package/dist/utils/logger.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/BaseMethod.ts +2 -0
- package/src/api/FileWrite.ts +7 -1
- package/src/api/FirmwareUpdateV4.ts +366 -99
- package/src/api/GetDeviceState.ts +2 -5
- package/src/api/SearchDevices.ts +172 -7
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +55 -15
- package/src/api/btc/BTCDeriveContextHash.ts +90 -0
- package/src/api/firmware/FirmwareArtifactSource.ts +12 -3
- package/src/api/helpers/pathUtils.ts +23 -0
- package/src/api/helpers/protocolV2FileWrite.ts +382 -111
- package/src/api/index.ts +9 -0
- package/src/api/monero/MoneroGetAddress.ts +71 -0
- package/src/api/monero/MoneroGetWatchKey.ts +75 -0
- package/src/api/monero/MoneroKeyImageSync.ts +170 -0
- package/src/api/monero/MoneroSignTransaction.ts +319 -0
- package/src/api/monero/helpers.ts +28 -0
- package/src/api/protocol-v2/DeviceReboot.ts +2 -0
- package/src/api/protocol-v2/DeviceUploadNft.ts +6 -1
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +15 -1
- package/src/api/zcash/ZcashGetAddress.ts +108 -0
- package/src/api/zcash/ZcashGetFullViewingKey.ts +78 -0
- package/src/api/zcash/ZcashSignPczt.ts +152 -0
- package/src/api/zcash/helpers.ts +16 -0
- package/src/core/index.ts +52 -24
- package/src/data/messages/messages-protocol-v2.json +152 -0
- package/src/data/messages/messages.json +51 -0
- package/src/device/Device.ts +32 -4
- package/src/device/DeviceCommands.ts +32 -1
- package/src/device/DeviceConnector.ts +4 -4
- package/src/device/DevicePool.ts +12 -2
- package/src/events/core.ts +2 -2
- package/src/events/logBlockEvent.ts +58 -3
- package/src/events/ui-request.ts +2 -0
- package/src/index.ts +1 -0
- package/src/inject.ts +17 -0
- package/src/protocols/protocol-v2/resources.ts +6 -1
- package/src/protocols/protocol-v2/uiInteraction.ts +1 -1
- package/src/types/api/allNetworkGetAddress.ts +8 -1
- package/src/types/api/btcDeriveContextHash.ts +15 -0
- package/src/types/api/export.ts +17 -0
- package/src/types/api/index.ts +24 -0
- package/src/types/api/moneroGetAddress.ts +27 -0
- package/src/types/api/moneroGetWatchKey.ts +28 -0
- package/src/types/api/moneroKeyImageSync.ts +45 -0
- package/src/types/api/moneroSignTransaction.ts +54 -0
- package/src/types/api/zcashGetAddress.ts +32 -0
- package/src/types/api/zcashGetFullViewingKey.ts +24 -0
- package/src/types/api/zcashSignPczt.ts +18 -0
- package/src/types/device.ts +18 -0
- package/src/types/params.ts +1 -1
- package/src/utils/logger.ts +4 -0
|
@@ -27,7 +27,10 @@ import {
|
|
|
27
27
|
import { BaseMethod } from '../BaseMethod';
|
|
28
28
|
import { decodeJpegBase64ToRgba } from '../helpers/base64Data';
|
|
29
29
|
import { invalidParameter } from '../helpers/filesystemValidation';
|
|
30
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
createProtocolV2AssetFileWriteRecovery,
|
|
32
|
+
writeProtocolV2File,
|
|
33
|
+
} from '../helpers/protocolV2FileWrite';
|
|
31
34
|
|
|
32
35
|
export type DeviceUploadNftParams = {
|
|
33
36
|
imageJpegBase64: string;
|
|
@@ -238,6 +241,8 @@ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
|
|
|
238
241
|
chunkSize: this.params.chunkSize,
|
|
239
242
|
timeoutMs: this.params.timeoutMs,
|
|
240
243
|
paceMs: this.params.paceMs,
|
|
244
|
+
maxChunkRetries: 3,
|
|
245
|
+
recoverConnection: createProtocolV2AssetFileWriteRecovery(this),
|
|
241
246
|
overwrite: true,
|
|
242
247
|
append: false,
|
|
243
248
|
throwIfAborted: () => this.throwIfAborted(),
|
|
@@ -6,7 +6,11 @@ import { DeviceSessionPinType } from '@onekeyfe/hd-transport';
|
|
|
6
6
|
import { BaseMethod } from '../BaseMethod';
|
|
7
7
|
import { decodeJpegBase64ToRgba } from '../helpers/base64Data';
|
|
8
8
|
import { invalidParameter } from '../helpers/filesystemValidation';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
createProtocolV2AssetFileWriteRecovery,
|
|
11
|
+
writeProtocolV2File,
|
|
12
|
+
} from '../helpers/protocolV2FileWrite';
|
|
13
|
+
import { ProtocolV2UiInteractionCoordinator } from '../../protocols/protocol-v2/uiInteraction';
|
|
10
14
|
import { UI_REQUEST, createUiMessage } from '../../events/ui-request';
|
|
11
15
|
import { supportsProtocolV2Message } from '../../protocols/protocol-v2/features';
|
|
12
16
|
import { LoggerNames, getLogger } from '../../utils';
|
|
@@ -142,6 +146,7 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
142
146
|
chunkSize: this.params.chunkSize,
|
|
143
147
|
bleChunkSizeLimit,
|
|
144
148
|
maxChunkRetries: 3,
|
|
149
|
+
recoverConnection: createProtocolV2AssetFileWriteRecovery(this),
|
|
145
150
|
overwrite: true,
|
|
146
151
|
append: false,
|
|
147
152
|
throwIfAborted: () => this.throwIfAborted(),
|
|
@@ -171,6 +176,15 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
171
176
|
data,
|
|
172
177
|
useHostAssetPackage ? WALLPAPER_PACKAGE_BLE_CHUNK_SIZE : undefined
|
|
173
178
|
);
|
|
179
|
+
this.throwIfAborted();
|
|
180
|
+
new ProtocolV2UiInteractionCoordinator(this.device, this.postMessage).enterMethodInteraction({
|
|
181
|
+
request: 'button',
|
|
182
|
+
source: 'method-lifecycle',
|
|
183
|
+
reason: 'device-management',
|
|
184
|
+
completion: 'operation-completed',
|
|
185
|
+
deviceOnly: true,
|
|
186
|
+
operation: this.name,
|
|
187
|
+
});
|
|
174
188
|
const response = await this.device.commands.typedCall('DeviceSettingsSet', 'Success', {
|
|
175
189
|
settings: { wallpaper_path: this.path },
|
|
176
190
|
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { ZcashAddressScope, ZcashAddressType } from '@onekeyfe/hd-transport';
|
|
2
|
+
|
|
3
|
+
import { BaseMethod } from '../BaseMethod';
|
|
4
|
+
import { serializedPath } from '../helpers/pathUtils';
|
|
5
|
+
import { invalidParameter, validateParams, validateResult } from '../helpers/paramsValidator';
|
|
6
|
+
import { UI_REQUEST } from '../../constants/ui-request';
|
|
7
|
+
import { validateZcashAccountPath } from './helpers';
|
|
8
|
+
|
|
9
|
+
import type { ZcashGetAddress as HardwareZcashGetAddress } from '@onekeyfe/hd-transport';
|
|
10
|
+
import type { ZcashAddress, ZcashGetAddressParams } from '../../types/api/zcashGetAddress';
|
|
11
|
+
import type { DeviceFirmwareRange } from '../../types';
|
|
12
|
+
|
|
13
|
+
export default class ZcashGetAddress extends BaseMethod<HardwareZcashGetAddress[]> {
|
|
14
|
+
hasBundle = false;
|
|
15
|
+
|
|
16
|
+
getSupportedProtocols() {
|
|
17
|
+
return ['V2'] as const;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
init() {
|
|
21
|
+
this.checkDeviceId = true;
|
|
22
|
+
this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
|
|
23
|
+
this.strictCheckDeviceSupport = true;
|
|
24
|
+
|
|
25
|
+
this.hasBundle = !!this.payload?.bundle;
|
|
26
|
+
const payload = this.hasBundle ? this.payload : { bundle: [this.payload] };
|
|
27
|
+
|
|
28
|
+
validateParams(payload, [{ name: 'bundle', type: 'array' }]);
|
|
29
|
+
|
|
30
|
+
this.params = [];
|
|
31
|
+
payload.bundle.forEach((batch: ZcashGetAddressParams) => {
|
|
32
|
+
const addressN = validateZcashAccountPath(batch.path);
|
|
33
|
+
const addressType = batch.addressType ?? ZcashAddressType.UNIFIED_ORCHARD_P2PKH;
|
|
34
|
+
const scope = batch.scope ?? ZcashAddressScope.EXTERNAL;
|
|
35
|
+
const diversifierIndex = batch.diversifierIndex ?? 0;
|
|
36
|
+
if (
|
|
37
|
+
![
|
|
38
|
+
ZcashAddressType.UNIFIED_ORCHARD_P2PKH,
|
|
39
|
+
ZcashAddressType.TRANSPARENT_P2PKH,
|
|
40
|
+
ZcashAddressType.UNIFIED_ORCHARD,
|
|
41
|
+
].includes(addressType) ||
|
|
42
|
+
![ZcashAddressScope.EXTERNAL, ZcashAddressScope.INTERNAL].includes(scope)
|
|
43
|
+
) {
|
|
44
|
+
throw invalidParameter('Invalid Zcash address type or scope');
|
|
45
|
+
}
|
|
46
|
+
const maxIndex = addressType === ZcashAddressType.UNIFIED_ORCHARD ? 0xffffffff : 0x7fffffff;
|
|
47
|
+
if (
|
|
48
|
+
!Number.isSafeInteger(diversifierIndex) ||
|
|
49
|
+
diversifierIndex < 0 ||
|
|
50
|
+
diversifierIndex > maxIndex
|
|
51
|
+
) {
|
|
52
|
+
throw invalidParameter('Invalid Zcash diversifier index');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
validateParams(batch, [
|
|
56
|
+
{ name: 'path', required: true },
|
|
57
|
+
{ name: 'showOnOneKey', type: 'boolean' },
|
|
58
|
+
{ name: 'includeSeedFingerprint', type: 'boolean' },
|
|
59
|
+
]);
|
|
60
|
+
|
|
61
|
+
this.params.push({
|
|
62
|
+
address_n: addressN,
|
|
63
|
+
address_type: addressType,
|
|
64
|
+
scope,
|
|
65
|
+
diversifier_index: diversifierIndex,
|
|
66
|
+
show_display: batch.showOnOneKey ?? true,
|
|
67
|
+
include_seed_fingerprint: batch.includeSeedFingerprint ?? false,
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getVersionRange(): DeviceFirmwareRange {
|
|
73
|
+
return {
|
|
74
|
+
model_pro2: {
|
|
75
|
+
min: '1.0.4',
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async run() {
|
|
81
|
+
const responses: ZcashAddress[] = [];
|
|
82
|
+
|
|
83
|
+
for (let i = 0; i < this.params.length; i++) {
|
|
84
|
+
const param = this.params[i];
|
|
85
|
+
|
|
86
|
+
const res = await this.device.commands.typedCall('ZcashGetAddress', 'ZcashAddress', {
|
|
87
|
+
...param,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const path = serializedPath(param.address_n);
|
|
91
|
+
// The V2 decoder returns null for absent optional fields; omit them instead.
|
|
92
|
+
const { address, seed_fingerprint: seedFingerprint } = res.message;
|
|
93
|
+
responses.push({
|
|
94
|
+
path,
|
|
95
|
+
address,
|
|
96
|
+
...(seedFingerprint ? { seedFingerprint } : {}),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
this.postPreviousAddressMessage({ address, path });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
validateResult(responses, ['address'], {
|
|
103
|
+
expectedLength: this.params.length,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return Promise.resolve(this.hasBundle ? responses : responses[0]);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { BaseMethod } from '../BaseMethod';
|
|
2
|
+
import { serializedPath } from '../helpers/pathUtils';
|
|
3
|
+
import { validateParams, validateResult } from '../helpers/paramsValidator';
|
|
4
|
+
import { UI_REQUEST } from '../../constants/ui-request';
|
|
5
|
+
import { createMethodInteraction } from '../../protocols/protocol-v2/uiInteraction';
|
|
6
|
+
import { validateZcashAccountPath } from './helpers';
|
|
7
|
+
|
|
8
|
+
import type { ZcashGetFullViewingKey as HardwareZcashGetFullViewingKey } from '@onekeyfe/hd-transport';
|
|
9
|
+
import type {
|
|
10
|
+
ZcashFullViewingKey,
|
|
11
|
+
ZcashGetFullViewingKeyParams,
|
|
12
|
+
} from '../../types/api/zcashGetFullViewingKey';
|
|
13
|
+
import type { DeviceFirmwareRange } from '../../types';
|
|
14
|
+
|
|
15
|
+
// The device exports the UFVK only after the user confirms it on screen.
|
|
16
|
+
export default class ZcashGetFullViewingKey extends BaseMethod<HardwareZcashGetFullViewingKey[]> {
|
|
17
|
+
hasBundle = false;
|
|
18
|
+
|
|
19
|
+
getSupportedProtocols() {
|
|
20
|
+
return ['V2'] as const;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
init() {
|
|
24
|
+
this.checkDeviceId = true;
|
|
25
|
+
this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
|
|
26
|
+
this.strictCheckDeviceSupport = true;
|
|
27
|
+
// The name matches no Protocol V2 confirmation rule, so the export prompt is declared here.
|
|
28
|
+
this.protocolV2UiInteraction = createMethodInteraction(
|
|
29
|
+
'public-key-confirmation',
|
|
30
|
+
'zcashGetFullViewingKey'
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
this.hasBundle = !!this.payload?.bundle;
|
|
34
|
+
const payload = this.hasBundle ? this.payload : { bundle: [this.payload] };
|
|
35
|
+
|
|
36
|
+
validateParams(payload, [{ name: 'bundle', type: 'array' }]);
|
|
37
|
+
|
|
38
|
+
this.params = [];
|
|
39
|
+
payload.bundle.forEach((batch: ZcashGetFullViewingKeyParams) => {
|
|
40
|
+
validateParams(batch, [{ name: 'path', required: true }]);
|
|
41
|
+
this.params.push({ address_n: validateZcashAccountPath(batch.path) });
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
getVersionRange(): DeviceFirmwareRange {
|
|
46
|
+
return {
|
|
47
|
+
model_pro2: {
|
|
48
|
+
min: '1.0.4',
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async run() {
|
|
54
|
+
// Missing fields stay undefined so validateResult rejects them.
|
|
55
|
+
const responses: Partial<ZcashFullViewingKey>[] = [];
|
|
56
|
+
|
|
57
|
+
for (let i = 0; i < this.params.length; i++) {
|
|
58
|
+
const param = this.params[i];
|
|
59
|
+
|
|
60
|
+
const res = await this.device.commands.typedCall(
|
|
61
|
+
'ZcashGetFullViewingKey',
|
|
62
|
+
'ZcashFullViewingKey',
|
|
63
|
+
{ ...param }
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
responses.push({
|
|
67
|
+
path: serializedPath(param.address_n),
|
|
68
|
+
ufvk: res.message.ufvk,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
validateResult(responses, ['ufvk'], {
|
|
73
|
+
expectedLength: this.params.length,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return Promise.resolve(this.hasBundle ? responses : responses[0]);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
2
|
+
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
3
|
+
|
|
4
|
+
import { BaseMethod } from '../BaseMethod';
|
|
5
|
+
import { invalidParameter, validateParams } from '../helpers/paramsValidator';
|
|
6
|
+
import { stripHexPrefix } from '../helpers/hexUtils';
|
|
7
|
+
import { UI_REQUEST } from '../../constants/ui-request';
|
|
8
|
+
|
|
9
|
+
import type { ZcashSignPczt as HardwareZcashSignPczt } from '@onekeyfe/hd-transport';
|
|
10
|
+
import type { TypedCall, TypedResponseMessage } from '../../device/DeviceCommands';
|
|
11
|
+
import type { ZcashSignedPczt } from '../../types/api/zcashSignPczt';
|
|
12
|
+
import type { DeviceFirmwareRange } from '../../types';
|
|
13
|
+
|
|
14
|
+
const CHUNK_BYTE_SIZE = 1024;
|
|
15
|
+
// Host memory sanity bound on the device-announced length, not a device limit.
|
|
16
|
+
const SIGNED_PCZT_SANITY_MAX_BYTES = 16 * 1024 * 1024;
|
|
17
|
+
|
|
18
|
+
export default class ZcashSignPczt extends BaseMethod<HardwareZcashSignPczt> {
|
|
19
|
+
pczt: Buffer = Buffer.alloc(0);
|
|
20
|
+
|
|
21
|
+
getSupportedProtocols() {
|
|
22
|
+
return ['V2'] as const;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
init() {
|
|
26
|
+
this.checkDeviceId = true;
|
|
27
|
+
this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
|
|
28
|
+
this.strictCheckDeviceSupport = true;
|
|
29
|
+
|
|
30
|
+
validateParams(this.payload, [{ name: 'pczt', type: 'hexString', required: true }]);
|
|
31
|
+
|
|
32
|
+
// Reject odd-length hex instead of left-padding it, which would shift every nibble.
|
|
33
|
+
const pcztHex = stripHexPrefix(this.payload.pczt);
|
|
34
|
+
if (pcztHex.length % 2 !== 0) {
|
|
35
|
+
throw invalidParameter('pczt hex must have an even length');
|
|
36
|
+
}
|
|
37
|
+
this.pczt = Buffer.from(pcztHex, 'hex');
|
|
38
|
+
if (this.pczt.length === 0) {
|
|
39
|
+
throw invalidParameter('pczt is empty');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.params = {
|
|
43
|
+
pczt_length: this.pczt.length,
|
|
44
|
+
pczt_initial_chunk: bytesToHex(this.pczt.subarray(0, CHUNK_BYTE_SIZE)),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
getVersionRange(): DeviceFirmwareRange {
|
|
49
|
+
return {
|
|
50
|
+
model_pro2: {
|
|
51
|
+
min: '1.0.4',
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Upload: the device decides every chunk length via ZcashPcztChunkRequest and
|
|
57
|
+
// the host must answer with exactly that many bytes.
|
|
58
|
+
uploadPczt = async (
|
|
59
|
+
typedCall: TypedCall,
|
|
60
|
+
first: TypedResponseMessage<'ZcashSignedPczt'> | TypedResponseMessage<'ZcashPcztChunkRequest'>,
|
|
61
|
+
initialOffset: number
|
|
62
|
+
): Promise<TypedResponseMessage<'ZcashSignedPczt'>> => {
|
|
63
|
+
let res = first;
|
|
64
|
+
let offset = initialOffset;
|
|
65
|
+
while (res.type === 'ZcashPcztChunkRequest') {
|
|
66
|
+
const { chunk_length: chunkLength } = res.message;
|
|
67
|
+
if (
|
|
68
|
+
!Number.isSafeInteger(chunkLength) ||
|
|
69
|
+
chunkLength <= 0 ||
|
|
70
|
+
offset + chunkLength > this.pczt.length
|
|
71
|
+
) {
|
|
72
|
+
throw ERRORS.TypedError(
|
|
73
|
+
HardwareErrorCode.ResponseUnexpectTypeError,
|
|
74
|
+
`device requested ${chunkLength} bytes at offset ${offset} of ${this.pczt.length}`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const chunk = this.pczt.subarray(offset, offset + chunkLength);
|
|
79
|
+
res = await typedCall('ZcashPcztChunkAck', ['ZcashSignedPczt', 'ZcashPcztChunkRequest'], {
|
|
80
|
+
data_chunk: bytesToHex(chunk),
|
|
81
|
+
});
|
|
82
|
+
offset += chunkLength;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (offset !== this.pczt.length) {
|
|
86
|
+
throw ERRORS.TypedError(
|
|
87
|
+
HardwareErrorCode.ResponseUnexpectTypeError,
|
|
88
|
+
'device completed signing before receiving the whole pczt'
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return res;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Download: the host decides chunk lengths via ZcashSignedPcztChunkRequest
|
|
95
|
+
// until the announced pczt_length has been received.
|
|
96
|
+
downloadSignedPczt = async (
|
|
97
|
+
typedCall: TypedCall,
|
|
98
|
+
res: TypedResponseMessage<'ZcashSignedPczt'>
|
|
99
|
+
): Promise<Buffer> => {
|
|
100
|
+
const { pczt_length: total, pczt_initial_chunk: initial } = res.message;
|
|
101
|
+
if (!Number.isSafeInteger(total) || total <= 0 || total > SIGNED_PCZT_SANITY_MAX_BYTES) {
|
|
102
|
+
throw ERRORS.TypedError(
|
|
103
|
+
HardwareErrorCode.ResponseUnexpectTypeError,
|
|
104
|
+
`device announced invalid signed pczt length ${total}`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const parts: Buffer[] = [Buffer.from(initial ?? '', 'hex')];
|
|
109
|
+
let received = parts[0].length;
|
|
110
|
+
if (received > total) {
|
|
111
|
+
throw ERRORS.TypedError(
|
|
112
|
+
HardwareErrorCode.ResponseUnexpectTypeError,
|
|
113
|
+
'device returned more initial pczt bytes than announced'
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
while (received < total) {
|
|
118
|
+
const chunkLength = Math.min(CHUNK_BYTE_SIZE, total - received);
|
|
119
|
+
const ack = await typedCall('ZcashSignedPcztChunkRequest', 'ZcashPcztChunkAck', {
|
|
120
|
+
chunk_length: chunkLength,
|
|
121
|
+
});
|
|
122
|
+
const chunk = Buffer.from(ack.message.data_chunk ?? '', 'hex');
|
|
123
|
+
if (chunk.length !== chunkLength) {
|
|
124
|
+
throw ERRORS.TypedError(
|
|
125
|
+
HardwareErrorCode.ResponseUnexpectTypeError,
|
|
126
|
+
`device returned ${chunk.length} of ${chunkLength} requested bytes at offset ${received} of ${total}`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
parts.push(chunk);
|
|
130
|
+
received += chunk.length;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return Buffer.concat(parts);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
async run(): Promise<ZcashSignedPczt> {
|
|
137
|
+
const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
|
|
138
|
+
|
|
139
|
+
const first = await typedCall('ZcashSignPczt', ['ZcashSignedPczt', 'ZcashPcztChunkRequest'], {
|
|
140
|
+
...this.params,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const signed = await this.uploadPczt(
|
|
144
|
+
typedCall,
|
|
145
|
+
first,
|
|
146
|
+
Math.min(CHUNK_BYTE_SIZE, this.pczt.length)
|
|
147
|
+
);
|
|
148
|
+
const pczt = await this.downloadSignedPczt(typedCall, signed);
|
|
149
|
+
|
|
150
|
+
return { pczt: bytesToHex(pczt) };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { toHardened, validateStrictPath } from '../helpers/pathUtils';
|
|
2
|
+
import { invalidParameter } from '../helpers/paramsValidator';
|
|
3
|
+
|
|
4
|
+
// ZIP-32 account path: m/32'/133'/account'
|
|
5
|
+
export function validateZcashAccountPath(path: string | number[]): number[] {
|
|
6
|
+
const addressN = validateStrictPath(path, 3);
|
|
7
|
+
if (
|
|
8
|
+
addressN.length !== 3 ||
|
|
9
|
+
addressN[0] !== toHardened(32) ||
|
|
10
|
+
addressN[1] !== toHardened(133) ||
|
|
11
|
+
addressN[2] < toHardened(0)
|
|
12
|
+
) {
|
|
13
|
+
throw invalidParameter("Zcash requires a ZIP-32 account path m/32'/133'/account'");
|
|
14
|
+
}
|
|
15
|
+
return addressN;
|
|
16
|
+
}
|
package/src/core/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import semver from 'semver';
|
|
2
|
+
import { getOwnedUsbDeviceIdentity } from '../api/SearchDevices';
|
|
2
3
|
import EventEmitter from 'events';
|
|
3
4
|
import {
|
|
4
5
|
DeviceSessionPinType,
|
|
@@ -23,7 +24,6 @@ import {
|
|
|
23
24
|
createNeedUpgradeFirmwareHardwareError,
|
|
24
25
|
createNewFirmwareForceUpdateHardwareError,
|
|
25
26
|
createNewFirmwareUnReleaseHardwareError,
|
|
26
|
-
isBleStaleBondHardwareError,
|
|
27
27
|
} from '@onekeyfe/hd-shared';
|
|
28
28
|
|
|
29
29
|
import { LoggerNames, enableLog, getLogger, setLoggerPostMessage, wait } from '../utils';
|
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
formatLogMethodLabel,
|
|
62
62
|
getLogBlockLabel,
|
|
63
63
|
getSafeLogPayload,
|
|
64
|
+
getSafeLogTask,
|
|
64
65
|
} from '../events';
|
|
65
66
|
import TransportManager from '../data-manager/TransportManager';
|
|
66
67
|
import DeviceConnector from '../device/DeviceConnector';
|
|
@@ -126,6 +127,8 @@ const parseInitOptions = (method?: BaseMethod): InitOptions => ({
|
|
|
126
127
|
});
|
|
127
128
|
|
|
128
129
|
let _core: Core | undefined;
|
|
130
|
+
let transportSwitchGeneration = 0;
|
|
131
|
+
let pendingTransportSwitch: Promise<void> = Promise.resolve();
|
|
129
132
|
let _deviceList: DeviceList | undefined;
|
|
130
133
|
let _connector: DeviceConnector | undefined;
|
|
131
134
|
let _uiPromises: UiPromise<UiPromiseResponse['type']>[] = []; // Waiting for ui response
|
|
@@ -991,15 +994,11 @@ function canSkipInitialize(method: BaseMethod, device: Device): boolean {
|
|
|
991
994
|
}
|
|
992
995
|
|
|
993
996
|
export function isRetryableBleProtocolV2ProbeError(method: BaseMethod, error: unknown) {
|
|
994
|
-
const typedError = error as { errorCode?: unknown;
|
|
995
|
-
const message =
|
|
996
|
-
typeof typedError?.message === 'string' ? typedError.message : String(error ?? '');
|
|
997
|
+
const typedError = error as { errorCode?: unknown; params?: { expectedProtocol?: unknown } };
|
|
997
998
|
return (
|
|
998
999
|
method.payload.connectProtocol === 'V2' &&
|
|
999
|
-
typedError?.errorCode === HardwareErrorCode.
|
|
1000
|
-
|
|
1001
|
-
message.includes('expected V2') &&
|
|
1002
|
-
message.includes('did not respond to expected protocol')
|
|
1000
|
+
typedError?.errorCode === HardwareErrorCode.TransportProtocolProbeFailed &&
|
|
1001
|
+
typedError.params?.expectedProtocol === 'V2'
|
|
1003
1002
|
);
|
|
1004
1003
|
}
|
|
1005
1004
|
|
|
@@ -1009,7 +1008,7 @@ export function isRetryableBleConnectionError(method: BaseMethod, error: unknown
|
|
|
1009
1008
|
}
|
|
1010
1009
|
const typedError = error as {
|
|
1011
1010
|
errorCode?: unknown;
|
|
1012
|
-
params?: { acquireDeadlineExceeded?: unknown };
|
|
1011
|
+
params?: { acquireDeadlineExceeded?: unknown; expectedProtocol?: unknown };
|
|
1013
1012
|
};
|
|
1014
1013
|
if (
|
|
1015
1014
|
typedError?.errorCode === HardwareErrorCode.BleTimeoutError &&
|
|
@@ -1020,6 +1019,8 @@ export function isRetryableBleConnectionError(method: BaseMethod, error: unknown
|
|
|
1020
1019
|
return (
|
|
1021
1020
|
typedError?.errorCode === HardwareErrorCode.BleTimeoutError ||
|
|
1022
1021
|
typedError?.errorCode === HardwareErrorCode.BleConnectedError ||
|
|
1022
|
+
(typedError?.errorCode === HardwareErrorCode.TransportProtocolProbeFailed &&
|
|
1023
|
+
!typedError.params?.expectedProtocol) ||
|
|
1023
1024
|
isRetryableBleProtocolV2ProbeError(method, error) ||
|
|
1024
1025
|
isMissingDetectedProtocolV2Error(method, error)
|
|
1025
1026
|
);
|
|
@@ -1035,10 +1036,6 @@ export function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unkn
|
|
|
1035
1036
|
);
|
|
1036
1037
|
}
|
|
1037
1038
|
|
|
1038
|
-
export function isTerminalBleStaleBondError(error: unknown) {
|
|
1039
|
-
return isBleStaleBondHardwareError(error);
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
1039
|
export function isDeviceIdentityMismatchError(error: unknown) {
|
|
1043
1040
|
return (
|
|
1044
1041
|
(error as { errorCode?: unknown })?.errorCode === HardwareErrorCode.DeviceCheckDeviceIdError
|
|
@@ -1277,6 +1274,9 @@ const ensureConnected = async (
|
|
|
1277
1274
|
HardwareErrorCode.BridgeNotInstalled,
|
|
1278
1275
|
HardwareErrorCode.BridgeTimeoutError,
|
|
1279
1276
|
HardwareErrorCode.BridgeNeedsPermission,
|
|
1277
|
+
HardwareErrorCode.WebUsbDeviceAccessError,
|
|
1278
|
+
HardwareErrorCode.TransportProtocolProbeFailed,
|
|
1279
|
+
HardwareErrorCode.TransportProtocolMismatch,
|
|
1280
1280
|
].includes(error.errorCode)
|
|
1281
1281
|
) {
|
|
1282
1282
|
_deviceList = undefined;
|
|
@@ -1363,6 +1363,9 @@ const ensureConnected = async (
|
|
|
1363
1363
|
HardwareErrorCode.DeviceDetectInBootloaderMode,
|
|
1364
1364
|
HardwareErrorCode.BleCharacteristicNotifyChangeFailure,
|
|
1365
1365
|
HardwareErrorCode.BridgeNeedsPermission,
|
|
1366
|
+
HardwareErrorCode.WebUsbDeviceAccessError,
|
|
1367
|
+
HardwareErrorCode.TransportProtocolProbeFailed,
|
|
1368
|
+
HardwareErrorCode.TransportProtocolMismatch,
|
|
1366
1369
|
HardwareErrorCode.DeviceInterruptedFromUser,
|
|
1367
1370
|
HardwareErrorCode.CallQueueActionCancelled,
|
|
1368
1371
|
].includes(error.errorCode) ||
|
|
@@ -1370,7 +1373,6 @@ const ensureConnected = async (
|
|
|
1370
1373
|
[HardwareErrorCode.BleDeviceDisconnected, HardwareErrorCode.PollingTimeout].includes(
|
|
1371
1374
|
error.errorCode
|
|
1372
1375
|
)) ||
|
|
1373
|
-
isTerminalBleStaleBondError(error) ||
|
|
1374
1376
|
isDeviceIdentityMismatchError(error)
|
|
1375
1377
|
) {
|
|
1376
1378
|
reject(error);
|
|
@@ -1450,7 +1452,7 @@ export const cancel = (context: CoreContext, connectId?: string) => {
|
|
|
1450
1452
|
};
|
|
1451
1453
|
for (const requestId of requestIds) {
|
|
1452
1454
|
const task = requestQueue.getTask(requestId);
|
|
1453
|
-
Log.debug('Cancel Api connect task: ', task);
|
|
1455
|
+
Log.debug('Cancel Api connect task: ', getSafeLogTask(task));
|
|
1454
1456
|
if (task) {
|
|
1455
1457
|
// During ensureConnected the method has a connectId but device is
|
|
1456
1458
|
// assigned only after the poll succeeds. Interrupt the cached BLE
|
|
@@ -1485,7 +1487,7 @@ export const cancel = (context: CoreContext, connectId?: string) => {
|
|
|
1485
1487
|
};
|
|
1486
1488
|
for (const requestId of requestQueue.getRequestTasksId()) {
|
|
1487
1489
|
const task = requestQueue.getTask(requestId);
|
|
1488
|
-
Log.debug('Cancel Api connect task: ', task);
|
|
1490
|
+
Log.debug('Cancel Api connect task: ', getSafeLogTask(task));
|
|
1489
1491
|
if (task) {
|
|
1490
1492
|
interruptDevice(task.method?.device);
|
|
1491
1493
|
if (task.method.connectId) {
|
|
@@ -1593,7 +1595,7 @@ const onDeviceConnectHandler = (device: Device) => {
|
|
|
1593
1595
|
|
|
1594
1596
|
const onDeviceDisconnectHandler = (device: Device) => {
|
|
1595
1597
|
device.clearPreInitialized();
|
|
1596
|
-
const deviceObject = device.
|
|
1598
|
+
const deviceObject = device.toDisconnectMessageObject();
|
|
1597
1599
|
if (!deviceObject) return;
|
|
1598
1600
|
postMessage(createDeviceMessage(DEVICE.DISCONNECT, { device: deviceObject }));
|
|
1599
1601
|
};
|
|
@@ -1830,6 +1832,10 @@ export default class Core extends EventEmitter {
|
|
|
1830
1832
|
|
|
1831
1833
|
private requestQueue = new RequestQueue();
|
|
1832
1834
|
|
|
1835
|
+
getOwnedUsbDeviceIdentity(descriptor: Parameters<typeof getOwnedUsbDeviceIdentity>[0]) {
|
|
1836
|
+
return getOwnedUsbDeviceIdentity(descriptor, this.requestQueue);
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1833
1839
|
private disposePromise?: Promise<void>;
|
|
1834
1840
|
|
|
1835
1841
|
// background task
|
|
@@ -1944,7 +1950,7 @@ export default class Core extends EventEmitter {
|
|
|
1944
1950
|
break;
|
|
1945
1951
|
}
|
|
1946
1952
|
case IFRAME.CALLBACK: {
|
|
1947
|
-
Log.log('callback message: ', message);
|
|
1953
|
+
Log.log('callback message: ', getSafeLogPayload(message));
|
|
1948
1954
|
postMessage(message);
|
|
1949
1955
|
break;
|
|
1950
1956
|
}
|
|
@@ -1963,6 +1969,8 @@ export default class Core extends EventEmitter {
|
|
|
1963
1969
|
|
|
1964
1970
|
private async disposeResources(): Promise<void> {
|
|
1965
1971
|
Log.debug(`[Core] Disposing SDK instance: ${this.sdkInstanceId}`);
|
|
1972
|
+
transportSwitchGeneration += 1;
|
|
1973
|
+
pendingTransportSwitch = Promise.resolve();
|
|
1966
1974
|
pollingManager.stopAll();
|
|
1967
1975
|
this.requestQueue.abortAllRequests();
|
|
1968
1976
|
cleanup();
|
|
@@ -1997,6 +2005,8 @@ export default class Core extends EventEmitter {
|
|
|
1997
2005
|
}
|
|
1998
2006
|
|
|
1999
2007
|
export const initCore = () => {
|
|
2008
|
+
transportSwitchGeneration += 1;
|
|
2009
|
+
pendingTransportSwitch = Promise.resolve();
|
|
2000
2010
|
const core = new Core();
|
|
2001
2011
|
_core = core;
|
|
2002
2012
|
return core;
|
|
@@ -2026,6 +2036,8 @@ export const init = async (
|
|
|
2026
2036
|
plugin?: LowlevelTransportSharedPlugin
|
|
2027
2037
|
) => {
|
|
2028
2038
|
try {
|
|
2039
|
+
transportSwitchGeneration += 1;
|
|
2040
|
+
pendingTransportSwitch = Promise.resolve();
|
|
2029
2041
|
await DataManager.load(settings);
|
|
2030
2042
|
initTransport(Transport, plugin);
|
|
2031
2043
|
enableLog(DataManager.getSettings('debug'));
|
|
@@ -2051,10 +2063,26 @@ export const switchTransport = ({
|
|
|
2051
2063
|
Transport: any;
|
|
2052
2064
|
plugin?: LowlevelTransportSharedPlugin;
|
|
2053
2065
|
}) => {
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2066
|
+
const generation = transportSwitchGeneration;
|
|
2067
|
+
// Preserve request order while native transport cleanup is pending.
|
|
2068
|
+
const switching = pendingTransportSwitch
|
|
2069
|
+
.catch(() => undefined)
|
|
2070
|
+
.then(async () => {
|
|
2071
|
+
if (generation !== transportSwitchGeneration) {
|
|
2072
|
+
throw ERRORS.TypedError(HardwareErrorCode.NotInitialized);
|
|
2073
|
+
}
|
|
2074
|
+
_connector?.stop();
|
|
2075
|
+
await TransportManager.getTransport()?.stop?.();
|
|
2076
|
+
if (generation !== transportSwitchGeneration) {
|
|
2077
|
+
throw ERRORS.TypedError(HardwareErrorCode.NotInitialized);
|
|
2078
|
+
}
|
|
2079
|
+
DataManager.updateEnv(env);
|
|
2080
|
+
TransportManager.setTransport(Transport, plugin);
|
|
2081
|
+
_deviceList = undefined;
|
|
2082
|
+
DevicePool.resetState();
|
|
2083
|
+
_connector = undefined;
|
|
2084
|
+
initConnector();
|
|
2085
|
+
});
|
|
2086
|
+
pendingTransportSwitch = switching;
|
|
2087
|
+
return switching;
|
|
2060
2088
|
};
|