@onekeyfe/hd-core 1.2.0-alpha.67 → 1.2.0-alpha.68
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 +313 -0
- package/__tests__/DeviceCommands.test.ts +59 -13
- package/__tests__/DeviceEventRegistration.test.ts +6 -0
- package/__tests__/check-all-firmware-release-protocol-v2.test.ts +198 -3
- package/__tests__/core-initialization.test.ts +23 -0
- package/__tests__/device-connector-protocol.test.ts +81 -0
- package/__tests__/device-lifecycle-events.test.ts +105 -3
- package/__tests__/device-pool-state.test.ts +22 -0
- package/__tests__/device-settings.test.ts +39 -18
- package/__tests__/device-state-contract.test.ts +1 -0
- package/__tests__/device-state-mapper.test.ts +13 -1
- package/__tests__/device-utils.test.ts +48 -1
- package/__tests__/deviceSettings.test.ts +11 -1
- package/__tests__/deviceUploadNft.test.ts +316 -0
- package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +5 -0
- package/__tests__/get-device-state.test.ts +132 -12
- package/__tests__/homescreen.test.ts +41 -1
- package/__tests__/kaspa-use-tweak-pro2.test.ts +2 -2
- package/__tests__/kaspaSignTransaction.test.ts +3 -26
- package/__tests__/logBlockEvent.test.ts +1 -1
- package/__tests__/method-protocol-support.test.ts +19 -0
- package/__tests__/open-wallet-session.test.ts +568 -37
- package/__tests__/pro2Nft.test.ts +108 -0
- package/__tests__/protocol-binding.test.ts +89 -0
- package/__tests__/protocol-v2-resources.test.ts +340 -0
- package/__tests__/protocol-v2-ui-lifecycle.test.ts +91 -0
- package/__tests__/protocol-v2-unlock-policy.test.ts +300 -37
- package/__tests__/protocol-v2.test.ts +1449 -867
- package/__tests__/protocolV2FileWrite.test.ts +152 -0
- package/__tests__/protocolV2UiInteraction.test.ts +63 -0
- package/__tests__/public-pro2-api-boundary.test.ts +1 -0
- package/__tests__/search-devices.test.ts +12 -3
- package/__tests__/tron-sign-message-init.test.ts +2 -2
- package/__tests__/uiProgressThrottle.test.ts +74 -0
- package/__tests__/uiPromiseRegistry.test.ts +115 -0
- package/dist/api/BaseMethod.d.ts +3 -1
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts +2 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/DetectDeviceConnectProtocol.d.ts +7 -0
- package/dist/api/DetectDeviceConnectProtocol.d.ts.map +1 -0
- package/dist/api/FirmwareUpdate.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +11 -4
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/SearchDevices.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/device/DeviceUnlock.d.ts +2 -2
- package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +4 -3
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +9 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/kaspa/KaspaGetAddress.d.ts +1 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts +1 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
- package/dist/api/polkadot/PolkadotGetAddress.d.ts +1 -1
- package/dist/api/polkadot/networks.d.ts +1 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts +31 -0
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
- package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/api/solana/SolSignMessage.d.ts +1 -1
- package/dist/api/solana/SolSignOffchainMessage.d.ts +1 -1
- package/dist/api/solana/SolSignTransaction.d.ts +2 -2
- package/dist/api/sui/SuiGetAddress.d.ts +1 -1
- package/dist/api/sui/SuiGetPublicKey.d.ts +1 -1
- package/dist/api/sui/SuiSignMessage.d.ts +1 -1
- package/dist/api/sui/SuiSignTransaction.d.ts +1 -1
- package/dist/api/ton/TonGetAddress.d.ts +1 -1
- package/dist/api/ton/TonSignMessage.d.ts +1 -1
- package/dist/api/ton/TonSignProof.d.ts +1 -1
- package/dist/api/tron/TronSignMessage.d.ts +2 -2
- package/dist/api/tron/TronSignTransaction.d.ts +1 -1
- package/dist/core/deviceEventRegistration.d.ts +2 -0
- package/dist/core/deviceEventRegistration.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/uiPromiseRegistry.d.ts +6 -0
- package/dist/core/uiPromiseRegistry.d.ts.map +1 -0
- package/dist/data-manager/DataManager.d.ts +9 -3
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/TransportManager.d.ts.map +1 -1
- package/dist/device/Device.d.ts +29 -5
- 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/DeviceConnector.d.ts +2 -1
- package/dist/device/DeviceConnector.d.ts.map +1 -1
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/deviceProfile/protocolV2DeviceIdentity.d.ts.map +1 -1
- package/dist/events/device.d.ts +4 -0
- package/dist/events/device.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-promise.d.ts +4 -2
- package/dist/events/ui-promise.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +31 -2
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/events/ui-response.d.ts +10 -2
- package/dist/events/ui-response.d.ts.map +1 -1
- package/dist/index.d.ts +243 -69
- package/dist/index.js +2563 -1217
- package/dist/inject.d.ts +6 -1
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/features.d.ts +0 -4
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts +30 -0
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts +7 -4
- package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts +1 -3
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts +6 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +3 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/detectDeviceConnectProtocol.d.ts +4 -0
- package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +1 -0
- package/dist/types/api/deviceUnlock.d.ts +5 -1
- package/dist/types/api/deviceUnlock.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +1 -0
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +4 -2
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +6 -1
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +3 -0
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts +2 -2
- 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/types/settings.d.ts +38 -8
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +4 -0
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/deviceSettings.d.ts.map +1 -1
- package/dist/utils/homescreen.d.ts +4 -0
- package/dist/utils/homescreen.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/dist/utils/pro2Nft.d.ts +31 -0
- package/dist/utils/pro2Nft.d.ts.map +1 -0
- package/dist/utils/pro2Wallpaper.d.ts +10 -0
- package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
- package/dist/utils/uiProgressThrottle.d.ts +3 -0
- package/dist/utils/uiProgressThrottle.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +8 -10
- package/src/api/CheckAllFirmwareRelease.ts +61 -11
- package/src/api/DetectDeviceConnectProtocol.ts +18 -0
- package/src/api/FirmwareUpdate.ts +6 -2
- package/src/api/FirmwareUpdateV2.ts +5 -2
- package/src/api/FirmwareUpdateV3.ts +6 -2
- package/src/api/FirmwareUpdateV4.ts +463 -258
- package/src/api/GetPassphraseState.ts +7 -1
- package/src/api/OpenWalletSession.ts +71 -17
- package/src/api/SearchDevices.ts +3 -1
- package/src/api/allnetwork/AllNetworkGetAddress.ts +21 -21
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +36 -11
- package/src/api/device/DeviceSettings.ts +5 -4
- package/src/api/device/DeviceUnlock.ts +8 -3
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +27 -12
- package/src/api/firmware/uploadFirmware.ts +17 -4
- package/src/api/helpers/protocolV2FileWrite.ts +202 -63
- package/src/api/index.ts +2 -0
- package/src/api/kaspa/KaspaGetAddress.ts +1 -1
- package/src/api/kaspa/KaspaSignTransaction.ts +2 -13
- package/src/api/polkadot/networks.ts +3 -3
- package/src/api/protocol-v2/DeviceUploadNft.ts +197 -0
- package/src/api/protocol-v2/ProtocolInfoRequest.ts +3 -1
- package/src/api/protocol-v2/helpers.ts +1 -1
- package/src/api/solana/SolSignMessage.ts +1 -1
- package/src/api/solana/SolSignOffchainMessage.ts +1 -1
- package/src/api/solana/SolSignTransaction.ts +2 -2
- package/src/api/sui/SuiGetAddress.ts +1 -1
- package/src/api/sui/SuiGetPublicKey.ts +1 -1
- package/src/api/sui/SuiSignMessage.ts +1 -1
- package/src/api/sui/SuiSignTransaction.ts +1 -1
- package/src/api/ton/TonGetAddress.ts +1 -1
- package/src/api/ton/TonSignMessage.ts +1 -1
- package/src/api/ton/TonSignProof.ts +1 -1
- package/src/api/tron/TronSignMessage.ts +2 -2
- package/src/api/tron/TronSignTransaction.ts +1 -1
- package/src/core/deviceEventRegistration.ts +4 -0
- package/src/core/index.ts +213 -111
- package/src/core/uiPromiseRegistry.ts +63 -0
- package/src/data/messages/messages-protocol-v2.json +25 -0
- package/src/data-manager/DataManager.ts +88 -11
- package/src/data-manager/TransportManager.ts +6 -0
- package/src/device/Device.ts +273 -43
- package/src/device/DeviceCommands.ts +31 -4
- package/src/device/DeviceConnector.ts +33 -13
- package/src/device/DevicePool.ts +21 -7
- package/src/deviceProfile/buildDeviceFeatures.ts +2 -2
- package/src/deviceProfile/protocolV2DeviceIdentity.ts +3 -0
- package/src/events/device.ts +4 -0
- package/src/events/logBlockEvent.ts +1 -0
- package/src/events/ui-promise.ts +4 -2
- package/src/events/ui-request.ts +36 -2
- package/src/events/ui-response.ts +12 -2
- package/src/inject.ts +58 -2
- package/src/lowLevelInject.ts +6 -3
- package/src/protocols/protocol-v2/features.ts +10 -7
- package/src/protocols/protocol-v2/firmware.ts +2 -0
- package/src/protocols/protocol-v2/resources.ts +390 -0
- package/src/protocols/protocol-v2/uiInteraction.ts +46 -6
- package/src/protocols/protocol-v2/unlockPolicy.ts +1 -105
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +131 -0
- package/src/protocols/protocol-v2/walletSession.ts +214 -36
- package/src/topLevelInject.ts +6 -3
- package/src/types/api/checkAllFirmwareRelease.ts +3 -1
- package/src/types/api/detectDeviceConnectProtocol.ts +6 -0
- package/src/types/api/deviceUnlock.ts +12 -1
- package/src/types/api/export.ts +1 -0
- package/src/types/api/firmwareUpdate.ts +6 -3
- package/src/types/api/index.ts +13 -0
- package/src/types/api/protocolV2.ts +13 -0
- package/src/types/device.ts +15 -3
- package/src/types/params.ts +7 -1
- package/src/types/settings.ts +60 -9
- package/src/utils/deviceFeaturesCompat.ts +5 -0
- package/src/utils/deviceFeaturesUtils.ts +14 -3
- package/src/utils/deviceInfoUtils.ts +2 -0
- package/src/utils/deviceSettings.ts +3 -0
- package/src/utils/homescreen.ts +32 -6
- package/src/utils/index.ts +6 -1
- package/src/utils/pro2Nft.ts +142 -0
- package/src/utils/pro2Wallpaper.ts +35 -8
- package/src/utils/uiProgressThrottle.ts +63 -0
- package/dist/api/firmware/progressThrottle.d.ts +0 -3
- package/dist/api/firmware/progressThrottle.d.ts.map +0 -1
- package/dist/protocols/protocol-v2/lockedError.d.ts +0 -2
- package/dist/protocols/protocol-v2/lockedError.d.ts.map +0 -1
- package/dist/protocols/protocol-v2/unlockRetry.d.ts +0 -10
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +0 -1
- package/src/api/firmware/progressThrottle.ts +0 -44
- package/src/protocols/protocol-v2/lockedError.ts +0 -10
- package/src/protocols/protocol-v2/unlockRetry.ts +0 -109
package/src/device/Device.ts
CHANGED
|
@@ -74,7 +74,9 @@ import type { DeviceStateReadOptions } from '../types/api/getDeviceState';
|
|
|
74
74
|
import type {
|
|
75
75
|
DeviceButtonRequestPayload,
|
|
76
76
|
DeviceFeaturesPayload,
|
|
77
|
+
HardwareUiInteractionMeta,
|
|
77
78
|
PassphraseRequestPayload,
|
|
79
|
+
ProtocolV2UiEventMetadata,
|
|
78
80
|
} from '../events';
|
|
79
81
|
import type { PassphrasePromptResponse } from './DeviceCommands';
|
|
80
82
|
import type { Deferred, HardwareConnectProtocol } from '@onekeyfe/hd-shared';
|
|
@@ -93,6 +95,7 @@ export type InitOptions = {
|
|
|
93
95
|
passphraseState?: string;
|
|
94
96
|
deriveCardano?: boolean;
|
|
95
97
|
connectProtocol?: HardwareConnectProtocol;
|
|
98
|
+
forceProtocolDetection?: boolean;
|
|
96
99
|
protocolV2DeviceInfoTimeoutMs?: number;
|
|
97
100
|
/** Refresh Protocol V2 runtime state before returning discovery results. */
|
|
98
101
|
refreshRuntimeState?: boolean;
|
|
@@ -137,6 +140,8 @@ const isProtocolV2DeviceStatusUnsupportedError = (error: unknown) => {
|
|
|
137
140
|
|
|
138
141
|
export interface DeviceEvents {
|
|
139
142
|
[DEVICE.PIN]: [Device, PROTO.PinMatrixRequestType | undefined, (err: any, pin: string) => void];
|
|
143
|
+
[DEVICE.PIN_ON_DEVICE]: [Device, DeviceSessionPinType, ProtocolV2UiEventMetadata?];
|
|
144
|
+
[DEVICE.PIN_ON_DEVICE_COMPLETE]: [Device, HardwareUiInteractionMeta];
|
|
140
145
|
[DEVICE.PASSPHRASE_ON_DEVICE]: [Device, PassphraseRequestPayload?];
|
|
141
146
|
[DEVICE.ATTACH_PIN_ON_DEVICE]: [Device, PassphraseRequestPayload?];
|
|
142
147
|
[DEVICE.BUTTON]: [Device, DeviceButtonRequestPayload];
|
|
@@ -235,6 +240,24 @@ export class Device extends EventEmitter {
|
|
|
235
240
|
/** Force the next initialization to reload DeviceInfo after reconnect or reboot. */
|
|
236
241
|
private protocolV2StateNeedsReload = false;
|
|
237
242
|
|
|
243
|
+
/** Runtime context negotiated once per active Protocol V2 link. */
|
|
244
|
+
private protocolV2RuntimeContext?: ProtocolInfo;
|
|
245
|
+
|
|
246
|
+
/** Coalesces concurrent first-use runtime negotiation on the same active link. */
|
|
247
|
+
private protocolV2RuntimeContextPromise?: Promise<ProtocolInfo>;
|
|
248
|
+
|
|
249
|
+
/** Invalidates an in-flight runtime-context response without adding a transport epoch. */
|
|
250
|
+
private protocolV2RuntimeContextRequestToken?: object;
|
|
251
|
+
|
|
252
|
+
private protocolV2UiInteraction?: {
|
|
253
|
+
interactionId: string;
|
|
254
|
+
phaseCounter: number;
|
|
255
|
+
sequence: number;
|
|
256
|
+
opened: boolean;
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
private protocolV2UiInteractionCounter = 0;
|
|
260
|
+
|
|
238
261
|
get state() {
|
|
239
262
|
return this.stateStore.getState();
|
|
240
263
|
}
|
|
@@ -342,7 +365,7 @@ export class Device extends EventEmitter {
|
|
|
342
365
|
deviceId,
|
|
343
366
|
path: this.originalDescriptor?.path,
|
|
344
367
|
bleName,
|
|
345
|
-
name:
|
|
368
|
+
name: bleName || displayName || `OneKey ${deviceType?.toUpperCase()}`,
|
|
346
369
|
// Keep the legacy top-level field string-compatible while preserving
|
|
347
370
|
// the canonical nullable value at state.identity.label.
|
|
348
371
|
label: displayName ?? '',
|
|
@@ -360,7 +383,10 @@ export class Device extends EventEmitter {
|
|
|
360
383
|
* Device connect
|
|
361
384
|
* @returns {Promise<boolean>}
|
|
362
385
|
*/
|
|
363
|
-
connect(
|
|
386
|
+
connect(
|
|
387
|
+
connectProtocol?: HardwareConnectProtocol,
|
|
388
|
+
options?: { forceProtocolDetection?: boolean }
|
|
389
|
+
) {
|
|
364
390
|
const env = DataManager.getSettings('env');
|
|
365
391
|
// eslint-disable-next-line no-async-promise-executor
|
|
366
392
|
return new Promise<boolean>(async (resolve, reject) => {
|
|
@@ -370,7 +396,7 @@ export class Device extends EventEmitter {
|
|
|
370
396
|
return;
|
|
371
397
|
}
|
|
372
398
|
try {
|
|
373
|
-
await this.acquire(connectProtocol);
|
|
399
|
+
await this.acquire(connectProtocol, options);
|
|
374
400
|
resolve(true);
|
|
375
401
|
} catch (error) {
|
|
376
402
|
reject(error);
|
|
@@ -380,7 +406,7 @@ export class Device extends EventEmitter {
|
|
|
380
406
|
// 不存在 Session ID 或存在 Session ID 但设备在别处使用,都需要 acquire 获取最新 sessionID
|
|
381
407
|
if (!this.mainId || (!this.isUsedHere() && this.originalDescriptor)) {
|
|
382
408
|
try {
|
|
383
|
-
await this.acquire(connectProtocol);
|
|
409
|
+
await this.acquire(connectProtocol, options);
|
|
384
410
|
resolve(true);
|
|
385
411
|
} catch (error) {
|
|
386
412
|
reject(error);
|
|
@@ -397,11 +423,16 @@ export class Device extends EventEmitter {
|
|
|
397
423
|
|
|
398
424
|
async acquire(
|
|
399
425
|
expectedProtocol?: HardwareConnectProtocol,
|
|
400
|
-
options?: { throwOnRunPromiseError?: boolean }
|
|
426
|
+
options?: { throwOnRunPromiseError?: boolean; forceProtocolDetection?: boolean }
|
|
401
427
|
) {
|
|
402
428
|
const env = DataManager.getSettings('env');
|
|
403
429
|
const mainIdKey = DataManager.isBleConnect(env) ? 'id' : 'session';
|
|
404
|
-
const
|
|
430
|
+
const previousProtocol = this.originalDescriptor.protocolType;
|
|
431
|
+
// A protocol stored after a successful probe is authoritative. Only the explicit
|
|
432
|
+
// first-connection/recovery path may bypass it and probe both protocols again.
|
|
433
|
+
const strictProtocol = options?.forceProtocolDetection
|
|
434
|
+
? undefined
|
|
435
|
+
: expectedProtocol ?? this.originalDescriptor.protocolType;
|
|
405
436
|
try {
|
|
406
437
|
let acquireResult: unknown;
|
|
407
438
|
if (DataManager.isBleConnect(env)) {
|
|
@@ -413,8 +444,8 @@ export class Device extends EventEmitter {
|
|
|
413
444
|
this.originalDescriptor.id,
|
|
414
445
|
undefined,
|
|
415
446
|
true,
|
|
416
|
-
|
|
417
|
-
|
|
447
|
+
strictProtocol,
|
|
448
|
+
undefined
|
|
418
449
|
);
|
|
419
450
|
this.mainId = (acquireResult as any)?.uuid ?? '';
|
|
420
451
|
Log.debug('Expected uuid:', this.mainId);
|
|
@@ -423,24 +454,31 @@ export class Device extends EventEmitter {
|
|
|
423
454
|
this.originalDescriptor.path,
|
|
424
455
|
this.originalDescriptor.session,
|
|
425
456
|
undefined,
|
|
426
|
-
|
|
427
|
-
|
|
457
|
+
strictProtocol,
|
|
458
|
+
undefined
|
|
428
459
|
);
|
|
429
460
|
this.mainId = acquireResult as string | undefined;
|
|
430
461
|
Log.debug('Expected session id:', this.mainId);
|
|
431
462
|
}
|
|
432
|
-
this.deviceAcquired = true;
|
|
433
|
-
this.updateDescriptor({ [mainIdKey]: this.mainId } as unknown as DeviceDescriptor);
|
|
434
|
-
|
|
435
463
|
// Propagate protocol version detected during acquire.
|
|
436
464
|
const detectedProtocol =
|
|
437
465
|
(acquireResult as { protocolType?: HardwareConnectProtocol } | undefined)?.protocolType ??
|
|
438
466
|
TransportManager.transport?.getProtocolType?.(
|
|
439
467
|
DataManager.isBleConnect(env) ? this.originalDescriptor.id : this.originalDescriptor.path
|
|
440
468
|
);
|
|
469
|
+
if (options?.forceProtocolDetection && !detectedProtocol) {
|
|
470
|
+
throw ERRORS.TypedError(
|
|
471
|
+
HardwareErrorCode.RuntimeError,
|
|
472
|
+
`Active protocol detection returned no protocol for ${
|
|
473
|
+
this.originalDescriptor.path || this.originalDescriptor.id
|
|
474
|
+
}`
|
|
475
|
+
);
|
|
476
|
+
}
|
|
441
477
|
if (detectedProtocol) {
|
|
442
478
|
this.originalDescriptor.protocolType = detectedProtocol;
|
|
443
479
|
}
|
|
480
|
+
this.deviceAcquired = true;
|
|
481
|
+
this.updateDescriptor({ [mainIdKey]: this.mainId } as unknown as DeviceDescriptor);
|
|
444
482
|
|
|
445
483
|
if (this.commands) {
|
|
446
484
|
await this.commands.dispose(false);
|
|
@@ -448,6 +486,22 @@ export class Device extends EventEmitter {
|
|
|
448
486
|
|
|
449
487
|
this.commands = new DeviceCommands(this, this.mainId ?? '');
|
|
450
488
|
} catch (error) {
|
|
489
|
+
if (options?.forceProtocolDetection) {
|
|
490
|
+
this.originalDescriptor.protocolType = previousProtocol;
|
|
491
|
+
const failedSession = this.mainId;
|
|
492
|
+
this.deviceAcquired = false;
|
|
493
|
+
if (failedSession) {
|
|
494
|
+
try {
|
|
495
|
+
await this.deviceConnector?.release?.(failedSession, false);
|
|
496
|
+
} catch (releaseError) {
|
|
497
|
+
Log.debug('Failed to release an unsuccessful protocol probe', releaseError);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
if (!DataManager.isBleConnect(env)) {
|
|
501
|
+
this.mainId = null;
|
|
502
|
+
this.updateDescriptor({ session: null } as DeviceDescriptor);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
451
505
|
if (options?.throwOnRunPromiseError) {
|
|
452
506
|
throw error;
|
|
453
507
|
}
|
|
@@ -647,6 +701,7 @@ export class Device extends EventEmitter {
|
|
|
647
701
|
// Most-specific model first; must match getMethodVersionRange in deviceInfoUtils,
|
|
648
702
|
// otherwise e.g. Classic1s resolves the looser model_mini range before model_classic1s.
|
|
649
703
|
const modelFallbacks: IDeviceModel[] = [
|
|
704
|
+
'model_pro2',
|
|
650
705
|
'model_classic1s',
|
|
651
706
|
'model_classic',
|
|
652
707
|
'model_mini',
|
|
@@ -666,7 +721,8 @@ export class Device extends EventEmitter {
|
|
|
666
721
|
if (
|
|
667
722
|
deviceType === EDeviceType.Touch ||
|
|
668
723
|
deviceType === EDeviceType.Pro ||
|
|
669
|
-
deviceType === EDeviceType.Pro2
|
|
724
|
+
deviceType === EDeviceType.Pro2 ||
|
|
725
|
+
deviceType === EDeviceType.Neo
|
|
670
726
|
) {
|
|
671
727
|
return { support: true };
|
|
672
728
|
}
|
|
@@ -683,7 +739,8 @@ export class Device extends EventEmitter {
|
|
|
683
739
|
if (
|
|
684
740
|
deviceType === EDeviceType.Touch ||
|
|
685
741
|
deviceType === EDeviceType.Pro ||
|
|
686
|
-
deviceType === EDeviceType.Pro2
|
|
742
|
+
deviceType === EDeviceType.Pro2 ||
|
|
743
|
+
deviceType === EDeviceType.Neo
|
|
687
744
|
) {
|
|
688
745
|
return { support: false };
|
|
689
746
|
}
|
|
@@ -969,7 +1026,10 @@ export class Device extends EventEmitter {
|
|
|
969
1026
|
await this.getFeatures();
|
|
970
1027
|
}
|
|
971
1028
|
|
|
972
|
-
|
|
1029
|
+
const supportsProtocolV1OnekeyFeatures =
|
|
1030
|
+
this.getCurrentDeviceType() === EDeviceType.Touch ||
|
|
1031
|
+
this.getCurrentDeviceType() === EDeviceType.Pro;
|
|
1032
|
+
if (!this.isProtocolV2() && refresh.has('verification') && supportsProtocolV1OnekeyFeatures) {
|
|
973
1033
|
const { message } = await this.commands.typedCall('OnekeyGetFeatures', 'OnekeyFeatures');
|
|
974
1034
|
this.updateState(mapProtocolV1OnekeyFeaturesToState(message), 'device-info');
|
|
975
1035
|
}
|
|
@@ -992,13 +1052,7 @@ export class Device extends EventEmitter {
|
|
|
992
1052
|
}
|
|
993
1053
|
|
|
994
1054
|
if (refresh.has('status') && !initializedWithDeviceInfo) {
|
|
995
|
-
|
|
996
|
-
refreshedDeviceInfo ??
|
|
997
|
-
(await requestProtocolV2DeviceInfo({
|
|
998
|
-
commands: this.commands,
|
|
999
|
-
request: getProtocolV2DeviceInfoRequest(),
|
|
1000
|
-
}));
|
|
1001
|
-
await this.probeProtocolV2RuntimeState(deviceInfo);
|
|
1055
|
+
await this.probeProtocolV2RuntimeState(refreshedDeviceInfo);
|
|
1002
1056
|
}
|
|
1003
1057
|
|
|
1004
1058
|
if (refresh.has('settings') && this.state?.status.mode === 'normal') {
|
|
@@ -1069,19 +1123,66 @@ export class Device extends EventEmitter {
|
|
|
1069
1123
|
return this.features;
|
|
1070
1124
|
}
|
|
1071
1125
|
|
|
1072
|
-
async
|
|
1073
|
-
const
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1126
|
+
async ensureProtocolV2RuntimeContext(timeoutMs?: number): Promise<ProtocolInfo> {
|
|
1127
|
+
const cachedProtocolInfo =
|
|
1128
|
+
this.protocolV2RuntimeContext ??
|
|
1129
|
+
(!this.protocolV2StateNeedsReload
|
|
1130
|
+
? this.state?.raw?.protocolV2ProtocolInfo ?? undefined
|
|
1131
|
+
: undefined);
|
|
1132
|
+
if (cachedProtocolInfo) {
|
|
1133
|
+
this.protocolV2RuntimeContext = cachedProtocolInfo;
|
|
1134
|
+
return cachedProtocolInfo;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
if (this.protocolV2RuntimeContextPromise) {
|
|
1138
|
+
return this.protocolV2RuntimeContextPromise;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
const requestToken = {};
|
|
1142
|
+
const pendingRequest = (async () => {
|
|
1143
|
+
const protocolInfo = await requestProtocolV2ProtocolInfo({
|
|
1144
|
+
commands: this.commands,
|
|
1145
|
+
timeoutMs,
|
|
1146
|
+
});
|
|
1147
|
+
if (this.protocolV2RuntimeContextRequestToken !== requestToken) {
|
|
1148
|
+
throw ERRORS.TypedError(
|
|
1149
|
+
HardwareErrorCode.DeviceInitializeFailed,
|
|
1150
|
+
'Protocol V2 runtime context was invalidated while loading.'
|
|
1151
|
+
);
|
|
1152
|
+
}
|
|
1153
|
+
this.protocolV2RuntimeContext = protocolInfo;
|
|
1154
|
+
return protocolInfo;
|
|
1155
|
+
})();
|
|
1156
|
+
this.protocolV2RuntimeContextRequestToken = requestToken;
|
|
1157
|
+
this.protocolV2RuntimeContextPromise = pendingRequest;
|
|
1158
|
+
|
|
1159
|
+
try {
|
|
1160
|
+
return await pendingRequest;
|
|
1161
|
+
} finally {
|
|
1162
|
+
if (this.protocolV2RuntimeContextPromise === pendingRequest) {
|
|
1163
|
+
this.protocolV2RuntimeContextPromise = undefined;
|
|
1164
|
+
}
|
|
1165
|
+
if (this.protocolV2RuntimeContextRequestToken === requestToken) {
|
|
1166
|
+
this.protocolV2RuntimeContextRequestToken = undefined;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
async probeProtocolV2RuntimeState(deviceInfo?: ProtocolV2DeviceInfo, timeoutMs?: number) {
|
|
1172
|
+
const protocolInfo = await this.ensureProtocolV2RuntimeContext(timeoutMs);
|
|
1077
1173
|
const runtimeMode = getProtocolV2RuntimeMode(protocolInfo);
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1174
|
+
const runtimeDeviceInfo = deviceInfo ?? this.state?.raw?.protocolV2DeviceInfo;
|
|
1175
|
+
const protocolV2DeviceType = runtimeDeviceInfo
|
|
1176
|
+
? resolveProtocolV2DeviceIdentity(runtimeDeviceInfo.hw?.Device_type).deviceType
|
|
1177
|
+
: this.getCurrentDeviceType();
|
|
1178
|
+
if (
|
|
1179
|
+
runtimeMode === 'romloader' &&
|
|
1180
|
+
protocolV2DeviceType !== EDeviceType.Pro2 &&
|
|
1181
|
+
protocolV2DeviceType !== EDeviceType.Neo
|
|
1182
|
+
) {
|
|
1082
1183
|
throw ERRORS.TypedError(
|
|
1083
1184
|
HardwareErrorCode.DeviceInitializeFailed,
|
|
1084
|
-
'Protocol V2 romloader mode is only supported for Pro2.'
|
|
1185
|
+
'Protocol V2 romloader mode is only supported for Pro2 and Neo.'
|
|
1085
1186
|
);
|
|
1086
1187
|
}
|
|
1087
1188
|
const deviceStatusSupported = supportsProtocolV2Message(
|
|
@@ -1152,6 +1253,9 @@ export class Device extends EventEmitter {
|
|
|
1152
1253
|
this.deviceAcquired = false;
|
|
1153
1254
|
if (!this.isProtocolV2()) return;
|
|
1154
1255
|
this.protocolV2StateNeedsReload = true;
|
|
1256
|
+
this.protocolV2RuntimeContext = undefined;
|
|
1257
|
+
this.protocolV2RuntimeContextPromise = undefined;
|
|
1258
|
+
this.protocolV2RuntimeContextRequestToken = undefined;
|
|
1155
1259
|
this.clearPreInitialized();
|
|
1156
1260
|
}
|
|
1157
1261
|
|
|
@@ -1160,9 +1264,14 @@ export class Device extends EventEmitter {
|
|
|
1160
1264
|
if (deviceId) {
|
|
1161
1265
|
deviceWalletSessionStore.deleteDevice(deviceId);
|
|
1162
1266
|
}
|
|
1163
|
-
if (this.isProtocolV2()
|
|
1164
|
-
|
|
1267
|
+
if (this.isProtocolV2()) {
|
|
1268
|
+
if (this.originalDescriptor.path !== deviceId) {
|
|
1269
|
+
deviceWalletSessionStore.deleteDevice(this.originalDescriptor.path);
|
|
1270
|
+
}
|
|
1165
1271
|
this.protocolV2StateNeedsReload = true;
|
|
1272
|
+
this.protocolV2RuntimeContext = undefined;
|
|
1273
|
+
this.protocolV2RuntimeContextPromise = undefined;
|
|
1274
|
+
this.protocolV2RuntimeContextRequestToken = undefined;
|
|
1166
1275
|
}
|
|
1167
1276
|
|
|
1168
1277
|
this.passphraseState = undefined;
|
|
@@ -1175,6 +1284,9 @@ export class Device extends EventEmitter {
|
|
|
1175
1284
|
if (!this.isProtocolV2()) return;
|
|
1176
1285
|
|
|
1177
1286
|
this.protocolV2StateNeedsReload = true;
|
|
1287
|
+
this.protocolV2RuntimeContext = undefined;
|
|
1288
|
+
this.protocolV2RuntimeContextPromise = undefined;
|
|
1289
|
+
this.protocolV2RuntimeContextRequestToken = undefined;
|
|
1178
1290
|
this.clearPreInitialized();
|
|
1179
1291
|
let loaderMode: 'bootloader' | 'romloader' | undefined;
|
|
1180
1292
|
if (rebootType === DeviceRebootType.Bootloader) {
|
|
@@ -1281,11 +1393,17 @@ export class Device extends EventEmitter {
|
|
|
1281
1393
|
}
|
|
1282
1394
|
};
|
|
1283
1395
|
|
|
1284
|
-
|
|
1285
|
-
|
|
1396
|
+
const env = DataManager.getSettings('env');
|
|
1397
|
+
if (options.forceProtocolDetection && env !== 'react-native' && this.isUsedHere()) {
|
|
1398
|
+
await this.release();
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
if (options.forceProtocolDetection || !this.isUsedHere() || this.commands.disposed) {
|
|
1286
1402
|
if (env !== 'react-native') {
|
|
1287
1403
|
try {
|
|
1288
|
-
await this.acquire(options.connectProtocol
|
|
1404
|
+
await this.acquire(options.connectProtocol, {
|
|
1405
|
+
forceProtocolDetection: options.forceProtocolDetection,
|
|
1406
|
+
});
|
|
1289
1407
|
} catch (error) {
|
|
1290
1408
|
clearRunPromise();
|
|
1291
1409
|
runPromise.reject(error);
|
|
@@ -1463,7 +1581,8 @@ export class Device extends EventEmitter {
|
|
|
1463
1581
|
if (!this.state) return undefined;
|
|
1464
1582
|
return (
|
|
1465
1583
|
this.isProtocolV2() &&
|
|
1466
|
-
this.getCurrentDeviceType() === EDeviceType.Pro2
|
|
1584
|
+
(this.getCurrentDeviceType() === EDeviceType.Pro2 ||
|
|
1585
|
+
this.getCurrentDeviceType() === EDeviceType.Neo) &&
|
|
1467
1586
|
this.state.status.mode === 'romloader'
|
|
1468
1587
|
);
|
|
1469
1588
|
}
|
|
@@ -1509,7 +1628,8 @@ export class Device extends EventEmitter {
|
|
|
1509
1628
|
const isModeT =
|
|
1510
1629
|
deviceType === EDeviceType.Touch ||
|
|
1511
1630
|
deviceType === EDeviceType.Pro ||
|
|
1512
|
-
deviceType === EDeviceType.Pro2
|
|
1631
|
+
deviceType === EDeviceType.Pro2 ||
|
|
1632
|
+
deviceType === EDeviceType.Neo;
|
|
1513
1633
|
const unlocked = this.state?.status.unlocked;
|
|
1514
1634
|
const preCheckTouch = isModeT && unlocked === false;
|
|
1515
1635
|
const passphraseProtection = this.getCurrentPassphraseProtection();
|
|
@@ -1527,6 +1647,85 @@ export class Device extends EventEmitter {
|
|
|
1527
1647
|
return res.message;
|
|
1528
1648
|
}
|
|
1529
1649
|
|
|
1650
|
+
beginProtocolV2UiInteraction() {
|
|
1651
|
+
if (!this.isProtocolV2()) return;
|
|
1652
|
+
this.protocolV2UiInteraction = {
|
|
1653
|
+
interactionId: `${this.instanceId}:${Date.now()}:${++this.protocolV2UiInteractionCounter}`,
|
|
1654
|
+
phaseCounter: 0,
|
|
1655
|
+
sequence: 0,
|
|
1656
|
+
opened: false,
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
createProtocolV2UiPhaseMetadata(
|
|
1661
|
+
phase: HardwareUiInteractionMeta['phase'],
|
|
1662
|
+
transition: HardwareUiInteractionMeta['transition'],
|
|
1663
|
+
options?: {
|
|
1664
|
+
phaseId?: string;
|
|
1665
|
+
outcome?: HardwareUiInteractionMeta['outcome'];
|
|
1666
|
+
}
|
|
1667
|
+
): HardwareUiInteractionMeta | undefined {
|
|
1668
|
+
if (!this.isProtocolV2()) return undefined;
|
|
1669
|
+
if (!this.protocolV2UiInteraction) this.beginProtocolV2UiInteraction();
|
|
1670
|
+
|
|
1671
|
+
const interaction = this.protocolV2UiInteraction;
|
|
1672
|
+
if (!interaction) return undefined;
|
|
1673
|
+
const phaseId =
|
|
1674
|
+
options?.phaseId ?? `${interaction.interactionId}:phase-${++interaction.phaseCounter}`;
|
|
1675
|
+
interaction.opened = true;
|
|
1676
|
+
interaction.sequence += 1;
|
|
1677
|
+
|
|
1678
|
+
return {
|
|
1679
|
+
interactionId: interaction.interactionId,
|
|
1680
|
+
phaseId,
|
|
1681
|
+
sequence: interaction.sequence,
|
|
1682
|
+
phase,
|
|
1683
|
+
transition,
|
|
1684
|
+
...(options?.outcome ? { outcome: options.outcome } : {}),
|
|
1685
|
+
protocol: 'V2',
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
completeProtocolV2UiPhase(
|
|
1690
|
+
phase: HardwareUiInteractionMeta,
|
|
1691
|
+
outcome: HardwareUiInteractionMeta['outcome'] = 'succeeded'
|
|
1692
|
+
) {
|
|
1693
|
+
return this.createProtocolV2UiPhaseMetadata(phase.phase, 'complete', {
|
|
1694
|
+
phaseId: phase.phaseId,
|
|
1695
|
+
outcome,
|
|
1696
|
+
});
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
finishProtocolV2UiInteraction(
|
|
1700
|
+
outcome?: HardwareUiInteractionMeta['outcome'],
|
|
1701
|
+
options?: { ensureMetadata?: boolean }
|
|
1702
|
+
) {
|
|
1703
|
+
const interaction = this.protocolV2UiInteraction;
|
|
1704
|
+
if (!interaction || (!interaction.opened && !options?.ensureMetadata)) {
|
|
1705
|
+
this.protocolV2UiInteraction = undefined;
|
|
1706
|
+
return undefined;
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
const phaseId = `${interaction.interactionId}:phase-${Math.max(interaction.phaseCounter, 1)}`;
|
|
1710
|
+
interaction.opened = true;
|
|
1711
|
+
interaction.sequence += 1;
|
|
1712
|
+
const metadata: HardwareUiInteractionMeta = {
|
|
1713
|
+
interactionId: interaction.interactionId,
|
|
1714
|
+
phaseId,
|
|
1715
|
+
sequence: interaction.sequence,
|
|
1716
|
+
phase: 'processing',
|
|
1717
|
+
transition: 'finish',
|
|
1718
|
+
outcome: outcome ?? 'succeeded',
|
|
1719
|
+
protocol: 'V2',
|
|
1720
|
+
};
|
|
1721
|
+
this.protocolV2UiInteraction = undefined;
|
|
1722
|
+
return metadata;
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
hasOpenProtocolV2UiInteraction() {
|
|
1726
|
+
return this.protocolV2UiInteraction?.opened === true;
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1530
1729
|
supportUnlockVersionRange(): DeviceFirmwareRange {
|
|
1531
1730
|
// This range applies to Protocol V1 Pro devices; Pro2 has a dedicated unlock flow.
|
|
1532
1731
|
return {
|
|
@@ -1536,10 +1735,33 @@ export class Device extends EventEmitter {
|
|
|
1536
1735
|
};
|
|
1537
1736
|
}
|
|
1538
1737
|
|
|
1539
|
-
async unlockDevice(
|
|
1738
|
+
async unlockDevice(
|
|
1739
|
+
pinType?: DeviceSessionPinType,
|
|
1740
|
+
options?: ProtocolV2UiEventMetadata & { emitUiEvent?: boolean }
|
|
1741
|
+
) {
|
|
1540
1742
|
if (this.isProtocolV2()) {
|
|
1743
|
+
const requestedPinType = pinType ?? DeviceSessionPinType.Main;
|
|
1744
|
+
const interaction =
|
|
1745
|
+
options?.interaction ??
|
|
1746
|
+
(options?.emitUiEvent === false
|
|
1747
|
+
? undefined
|
|
1748
|
+
: this.createProtocolV2UiPhaseMetadata('pin', 'start'));
|
|
1749
|
+
if (options?.emitUiEvent !== false) {
|
|
1750
|
+
this.emit(DEVICE.PIN_ON_DEVICE, this, requestedPinType, {
|
|
1751
|
+
source: options?.source ?? 'unlock-coordinator',
|
|
1752
|
+
reason: options?.reason ?? 'device-unlock',
|
|
1753
|
+
deviceOnly: options?.deviceOnly ?? true,
|
|
1754
|
+
completion: options?.completion,
|
|
1755
|
+
method: options?.method,
|
|
1756
|
+
page: options?.page,
|
|
1757
|
+
operation: options?.operation,
|
|
1758
|
+
interaction: options?.interaction ?? interaction,
|
|
1759
|
+
});
|
|
1760
|
+
}
|
|
1541
1761
|
try {
|
|
1542
|
-
await this.commands.typedCall('DeviceSessionAskPin', 'Success', {
|
|
1762
|
+
await this.commands.typedCall('DeviceSessionAskPin', 'Success', {
|
|
1763
|
+
type: requestedPinType,
|
|
1764
|
+
});
|
|
1543
1765
|
} catch (error) {
|
|
1544
1766
|
const errorText =
|
|
1545
1767
|
error instanceof Error
|
|
@@ -1551,6 +1773,11 @@ export class Device extends EventEmitter {
|
|
|
1551
1773
|
throw error;
|
|
1552
1774
|
}
|
|
1553
1775
|
|
|
1776
|
+
const completion = interaction ? this.completeProtocolV2UiPhase(interaction) : undefined;
|
|
1777
|
+
if (completion) {
|
|
1778
|
+
this.emit(DEVICE.PIN_ON_DEVICE_COMPLETE, this, completion);
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1554
1781
|
const status = await requestProtocolV2DeviceStatus({ commands: this.commands });
|
|
1555
1782
|
return this.updateProtocolV2Status(status);
|
|
1556
1783
|
}
|
|
@@ -1612,7 +1839,8 @@ export class Device extends EventEmitter {
|
|
|
1612
1839
|
async checkPassphraseStateSafety(
|
|
1613
1840
|
passphraseState?: string,
|
|
1614
1841
|
useEmptyPassphrase?: boolean,
|
|
1615
|
-
skipPassphraseCheck?: boolean
|
|
1842
|
+
skipPassphraseCheck?: boolean,
|
|
1843
|
+
deriveCardano?: boolean
|
|
1616
1844
|
) {
|
|
1617
1845
|
if (this.isUnacquired()) return false;
|
|
1618
1846
|
|
|
@@ -1621,6 +1849,8 @@ export class Device extends EventEmitter {
|
|
|
1621
1849
|
await getPassphraseStateWithRefreshDeviceInfo(this, {
|
|
1622
1850
|
expectPassphraseState: expectedPassphraseState,
|
|
1623
1851
|
onlyMainPin: useEmptyPassphrase,
|
|
1852
|
+
deriveCardano,
|
|
1853
|
+
rejectAttachPinForMainWallet: useEmptyPassphrase === true,
|
|
1624
1854
|
});
|
|
1625
1855
|
|
|
1626
1856
|
// Main wallet and unlock Attach Pin, throw safe error
|
|
@@ -54,9 +54,19 @@ const DEVICE_SESSION_CALLS = new Set([
|
|
|
54
54
|
'DeviceSessionAskPin',
|
|
55
55
|
'DeviceSessionAskPassphrase',
|
|
56
56
|
]);
|
|
57
|
+
const DEVICE_CONTROL_CALLS = new Set([
|
|
58
|
+
'DeviceReboot',
|
|
59
|
+
'DeviceSettingsGet',
|
|
60
|
+
'DeviceSettingsSet',
|
|
61
|
+
'DeviceSettingsPageShow',
|
|
62
|
+
'DeviceCertificateWrite',
|
|
63
|
+
'DeviceCertificateRead',
|
|
64
|
+
'DeviceCertificateSign',
|
|
65
|
+
'DeviceMiscUsbMscControl',
|
|
66
|
+
]);
|
|
57
67
|
|
|
58
|
-
// Protocol V2
|
|
59
|
-
//
|
|
68
|
+
// Older Protocol V2 firmware may omit the cancellation subcode, so retain a
|
|
69
|
+
// narrow message fallback for compatibility.
|
|
60
70
|
const isProtocolV2ActionCancelledMessage = (message: string) =>
|
|
61
71
|
/^(?:cancel(?:led|ed)(?: on device)?|confirm dismissed|user cancel(?:led|ed)(?:\s+.*)?)$/i.test(
|
|
62
72
|
message
|
|
@@ -435,7 +445,13 @@ export class DeviceCommands {
|
|
|
435
445
|
if (!shouldReduceDebugForCall(callType)) {
|
|
436
446
|
Log.debug('_filterCommonTypes: ', {
|
|
437
447
|
request: callType,
|
|
438
|
-
response:
|
|
448
|
+
response:
|
|
449
|
+
callType === 'DeviceFirmwareUpdateStatusGet'
|
|
450
|
+
? {
|
|
451
|
+
type: res.type,
|
|
452
|
+
message: getSafeTransportLogPayload(res.message, res.type),
|
|
453
|
+
}
|
|
454
|
+
: res.type,
|
|
439
455
|
});
|
|
440
456
|
}
|
|
441
457
|
} catch (error) {
|
|
@@ -493,6 +509,10 @@ export class DeviceCommands {
|
|
|
493
509
|
const normalizedMessage = message?.trim() ?? '';
|
|
494
510
|
const isProtocolV2ActionCancelledFailure =
|
|
495
511
|
this.device.isProtocolV2() && isProtocolV2ActionCancelledMessage(normalizedMessage);
|
|
512
|
+
const isProtocolV2DeviceBusyFailure =
|
|
513
|
+
this.device.isProtocolV2() &&
|
|
514
|
+
DEVICE_CONTROL_CALLS.has(callType) &&
|
|
515
|
+
subcode === DeviceErrorCode.DeviceError_Busy;
|
|
496
516
|
const isLegacyProtocolV2LockedFailure =
|
|
497
517
|
this.device.isProtocolV2() && /^device (?:is )?locked$/i.test(normalizedMessage);
|
|
498
518
|
if (
|
|
@@ -550,8 +570,15 @@ export class DeviceCommands {
|
|
|
550
570
|
subcode,
|
|
551
571
|
firmwareMessage: message,
|
|
552
572
|
});
|
|
573
|
+
} else if (isProtocolV2DeviceBusyFailure) {
|
|
574
|
+
error = ERRORS.TypedError(HardwareErrorCode.DeviceBusy, message, {
|
|
575
|
+
failureCode: code,
|
|
576
|
+
subcode,
|
|
577
|
+
firmwareMessage: message,
|
|
578
|
+
});
|
|
553
579
|
} else if (
|
|
554
|
-
|
|
580
|
+
(DEVICE_CONTROL_CALLS.has(callType) &&
|
|
581
|
+
subcode === DeviceErrorCode.DeviceError_ActionCancelled) ||
|
|
555
582
|
isProtocolV2ActionCancelledFailure
|
|
556
583
|
) {
|
|
557
584
|
error = ERRORS.TypedError(HardwareErrorCode.ActionCancelled, message, {
|