@onekeyfe/hd-core 1.2.0-alpha.16 → 1.2.0-alpha.17
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__/deviceFeaturesUtils.test.ts +27 -0
- package/__tests__/evmLedgerLegacySafety.test.ts +3 -0
- package/__tests__/homescreen.test.ts +24 -0
- package/__tests__/protocol-v2.test.ts +1006 -204
- package/__tests__/protocolV2FileWrite.test.ts +28 -3
- package/__tests__/protocolV2UiInteraction.test.ts +266 -0
- package/dist/api/BaseMethod.d.ts +4 -0
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +3 -3
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetDeviceInfo.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts.map +1 -1
- package/dist/api/device/DeviceCancel.d.ts.map +1 -1
- package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
- package/dist/api/device/DeviceLock.d.ts.map +1 -1
- package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
- package/dist/api/device/DeviceWipe.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +1 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceSessionOpen.d.ts +28 -0
- package/dist/api/protocol-v2/DeviceSessionOpen.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceSettingsPageShow.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceSettingsSet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceStatusGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/core/deviceEventRegistration.d.ts +1 -0
- package/dist/core/deviceEventRegistration.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +3 -3
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +3 -1
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DevicePool.d.ts +2 -2
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/deviceProfile/buildDeviceFeatures.d.ts +6 -2
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
- package/dist/deviceProfile/buildDeviceProfile.d.ts +3 -2
- package/dist/deviceProfile/buildDeviceProfile.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/ui-request.d.ts +18 -2
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +56 -11
- package/dist/index.js +1000 -537
- package/dist/protocols/protocol-v2/features.d.ts +6 -18
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/index.d.ts +1 -1
- package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/uiInteraction.d.ts +39 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/unlockRetry.d.ts +5 -3
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +2 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/types/api/getDeviceInfo.d.ts +2 -1
- package/dist/types/api/getDeviceInfo.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +2 -2
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +4 -2
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts +2 -1
- package/dist/types/device.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/homescreen.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 +10 -2
- package/src/api/FirmwareUpdateV4.ts +27 -73
- package/src/api/GetDeviceInfo.ts +9 -2
- package/src/api/GetPassphraseState.ts +5 -2
- package/src/api/UploadPortfolio.ts +2 -0
- package/src/api/device/DeviceCancel.ts +1 -0
- package/src/api/device/DeviceChangePin.ts +23 -0
- package/src/api/device/DeviceLock.ts +1 -0
- package/src/api/device/DeviceUnlock.ts +9 -0
- package/src/api/device/DeviceWipe.ts +18 -0
- package/src/api/helpers/protocolV2FileWrite.ts +35 -11
- package/src/api/index.ts +1 -1
- package/src/api/protocol-v2/DeviceInfoGet.ts +0 -1
- package/src/api/protocol-v2/DeviceSessionOpen.ts +100 -0
- package/src/api/protocol-v2/DeviceSettingsPageShow.ts +9 -1
- package/src/api/protocol-v2/DeviceSettingsSet.ts +11 -1
- package/src/api/protocol-v2/DeviceStatusGet.ts +1 -0
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +2 -1
- package/src/core/deviceEventRegistration.ts +2 -0
- package/src/core/index.ts +36 -3
- package/src/data/messages/messages-protocol-v2.json +122 -23
- package/src/device/Device.ts +33 -41
- package/src/device/DeviceCommands.ts +22 -4
- package/src/device/DevicePool.ts +14 -6
- package/src/deviceProfile/buildDeviceFeatures.ts +21 -9
- package/src/deviceProfile/buildDeviceProfile.ts +27 -11
- package/src/events/device.ts +4 -0
- package/src/events/ui-request.ts +24 -2
- package/src/inject.ts +2 -2
- package/src/protocols/protocol-v2/features.ts +27 -20
- package/src/protocols/protocol-v2/index.ts +0 -1
- package/src/protocols/protocol-v2/uiInteraction.ts +209 -0
- package/src/protocols/protocol-v2/unlockRetry.ts +43 -3
- package/src/protocols/protocol-v2/walletSession.ts +122 -31
- package/src/types/api/getDeviceInfo.ts +6 -1
- package/src/types/api/index.ts +2 -2
- package/src/types/api/protocolV2.ts +5 -3
- package/src/types/device.ts +6 -1
- package/src/utils/deviceFeaturesUtils.ts +13 -0
- package/src/utils/homescreen.ts +10 -0
- package/dist/api/protocol-v2/DeviceSessionGet.d.ts +0 -6
- package/dist/api/protocol-v2/DeviceSessionGet.d.ts.map +0 -1
- package/src/api/protocol-v2/DeviceSessionGet.ts +0 -15
|
@@ -482,7 +482,7 @@
|
|
|
482
482
|
"MessageType_DeviceStatus": 60603,
|
|
483
483
|
"MessageType_DevGetOnboardingStatus": 60604,
|
|
484
484
|
"MessageType_DevOnboardingStatus": 60605,
|
|
485
|
-
"
|
|
485
|
+
"MessageType_DeviceSessionOpen": 60606,
|
|
486
486
|
"MessageType_DeviceSession": 60607,
|
|
487
487
|
"MessageType_DeviceSessionAskPin": 60608,
|
|
488
488
|
"MessageType_FilesystemPermissionFix": 60800,
|
|
@@ -12418,14 +12418,68 @@
|
|
|
12418
12418
|
}
|
|
12419
12419
|
}
|
|
12420
12420
|
},
|
|
12421
|
-
"
|
|
12421
|
+
"DeviceSessionResume": {
|
|
12422
12422
|
"fields": {
|
|
12423
12423
|
"session_id": {
|
|
12424
|
+
"rule": "required",
|
|
12424
12425
|
"type": "bytes",
|
|
12425
12426
|
"id": 1
|
|
12426
12427
|
}
|
|
12427
12428
|
}
|
|
12428
12429
|
},
|
|
12430
|
+
"DeviceHostPassphrase": {
|
|
12431
|
+
"fields": {
|
|
12432
|
+
"passphrase": {
|
|
12433
|
+
"rule": "required",
|
|
12434
|
+
"type": "string",
|
|
12435
|
+
"id": 1
|
|
12436
|
+
}
|
|
12437
|
+
}
|
|
12438
|
+
},
|
|
12439
|
+
"DevicePassphraseOnDevice": {
|
|
12440
|
+
"fields": {}
|
|
12441
|
+
},
|
|
12442
|
+
"DeviceAttachPinOnDevice": {
|
|
12443
|
+
"fields": {}
|
|
12444
|
+
},
|
|
12445
|
+
"DeviceWalletSelect": {
|
|
12446
|
+
"oneofs": {
|
|
12447
|
+
"access": {
|
|
12448
|
+
"oneof": ["host_passphrase", "passphrase_on_device", "attach_pin_on_device"]
|
|
12449
|
+
}
|
|
12450
|
+
},
|
|
12451
|
+
"fields": {
|
|
12452
|
+
"host_passphrase": {
|
|
12453
|
+
"type": "DeviceHostPassphrase",
|
|
12454
|
+
"id": 1
|
|
12455
|
+
},
|
|
12456
|
+
"passphrase_on_device": {
|
|
12457
|
+
"type": "DevicePassphraseOnDevice",
|
|
12458
|
+
"id": 2
|
|
12459
|
+
},
|
|
12460
|
+
"attach_pin_on_device": {
|
|
12461
|
+
"type": "DeviceAttachPinOnDevice",
|
|
12462
|
+
"id": 3
|
|
12463
|
+
}
|
|
12464
|
+
}
|
|
12465
|
+
},
|
|
12466
|
+
"DeviceSessionOpen": {
|
|
12467
|
+
"oneofs": {
|
|
12468
|
+
"mode": {
|
|
12469
|
+
"oneof": ["resume", "select"]
|
|
12470
|
+
}
|
|
12471
|
+
},
|
|
12472
|
+
"fields": {
|
|
12473
|
+
"resume": {
|
|
12474
|
+
"type": "DeviceSessionResume",
|
|
12475
|
+
"id": 1
|
|
12476
|
+
},
|
|
12477
|
+
"select": {
|
|
12478
|
+
"type": "DeviceWalletSelect",
|
|
12479
|
+
"id": 2
|
|
12480
|
+
}
|
|
12481
|
+
}
|
|
12482
|
+
},
|
|
12429
12483
|
"DeviceSession": {
|
|
12430
12484
|
"fields": {
|
|
12431
12485
|
"session_id": {
|
|
@@ -12481,21 +12535,59 @@
|
|
|
12481
12535
|
"DeviceStatusGet": {
|
|
12482
12536
|
"fields": {}
|
|
12483
12537
|
},
|
|
12484
|
-
"
|
|
12538
|
+
"DevOnboardingStep": {
|
|
12539
|
+
"values": {
|
|
12540
|
+
"DEV_ONBOARDING_STEP_UNKNOWN": 0,
|
|
12541
|
+
"DEV_ONBOARDING_STEP_CHECKING": 1,
|
|
12542
|
+
"DEV_ONBOARDING_STEP_PERSONALIZATION": 2,
|
|
12543
|
+
"DEV_ONBOARDING_STEP_PIN": 3,
|
|
12544
|
+
"DEV_ONBOARDING_STEP_SETUP": 4,
|
|
12545
|
+
"DEV_ONBOARDING_STEP_DONE": 5
|
|
12546
|
+
}
|
|
12547
|
+
},
|
|
12548
|
+
"DevOnboardingPhase": {
|
|
12549
|
+
"values": {
|
|
12550
|
+
"DEV_ONBOARDING_PHASE_UNKNOWN": 0,
|
|
12551
|
+
"DEV_ONBOARDING_PHASE_SAFETY_CHECK": 1,
|
|
12552
|
+
"DEV_ONBOARDING_PHASE_PIN_SETUP": 2,
|
|
12553
|
+
"DEV_ONBOARDING_PHASE_FINGERPRINT_SETUP": 3,
|
|
12554
|
+
"DEV_ONBOARDING_PHASE_SETUP_CHOICE": 4,
|
|
12555
|
+
"DEV_ONBOARDING_PHASE_WALLET_CREATE_START": 5,
|
|
12556
|
+
"DEV_ONBOARDING_PHASE_RECOVERY_PHRASE_VIEW": 6,
|
|
12557
|
+
"DEV_ONBOARDING_PHASE_RECOVERY_PHRASE_CONFIRM": 7,
|
|
12558
|
+
"DEV_ONBOARDING_PHASE_RESTORE_METHOD_CHOICE": 8,
|
|
12559
|
+
"DEV_ONBOARDING_PHASE_RECOVERY_PHRASE_RESTORE": 9,
|
|
12560
|
+
"DEV_ONBOARDING_PHASE_SEEDCARD_RESTORE": 10,
|
|
12561
|
+
"DEV_ONBOARDING_PHASE_WALLET_READY": 11,
|
|
12562
|
+
"DEV_ONBOARDING_PHASE_SEEDCARD_BACKUP_PROMPT": 12,
|
|
12563
|
+
"DEV_ONBOARDING_PHASE_SEEDCARD_BACKUP": 13
|
|
12564
|
+
}
|
|
12565
|
+
},
|
|
12566
|
+
"DevOnboardingSetupKind": {
|
|
12485
12567
|
"values": {
|
|
12486
|
-
"
|
|
12487
|
-
"
|
|
12488
|
-
"
|
|
12489
|
-
"
|
|
12490
|
-
|
|
12491
|
-
|
|
12492
|
-
|
|
12493
|
-
|
|
12494
|
-
"
|
|
12495
|
-
"
|
|
12496
|
-
"
|
|
12497
|
-
|
|
12498
|
-
|
|
12568
|
+
"DEV_ONBOARDING_SETUP_KIND_UNKNOWN": 0,
|
|
12569
|
+
"DEV_ONBOARDING_SETUP_KIND_CHOICE": 1,
|
|
12570
|
+
"DEV_ONBOARDING_SETUP_KIND_CREATE": 2,
|
|
12571
|
+
"DEV_ONBOARDING_SETUP_KIND_RESTORE": 3
|
|
12572
|
+
}
|
|
12573
|
+
},
|
|
12574
|
+
"DevOnboardingSetupMethod": {
|
|
12575
|
+
"values": {
|
|
12576
|
+
"DEV_ONBOARDING_SETUP_METHOD_UNKNOWN": 0,
|
|
12577
|
+
"DEV_ONBOARDING_SETUP_METHOD_RECOVERY_PHRASE": 1,
|
|
12578
|
+
"DEV_ONBOARDING_SETUP_METHOD_SEEDCARD": 2
|
|
12579
|
+
}
|
|
12580
|
+
},
|
|
12581
|
+
"DevOnboardingSetupStatus": {
|
|
12582
|
+
"fields": {
|
|
12583
|
+
"kind": {
|
|
12584
|
+
"type": "DevOnboardingSetupKind",
|
|
12585
|
+
"id": 1
|
|
12586
|
+
},
|
|
12587
|
+
"method": {
|
|
12588
|
+
"type": "DevOnboardingSetupMethod",
|
|
12589
|
+
"id": 2
|
|
12590
|
+
}
|
|
12499
12591
|
}
|
|
12500
12592
|
},
|
|
12501
12593
|
"DevGetOnboardingStatus": {
|
|
@@ -12503,18 +12595,25 @@
|
|
|
12503
12595
|
},
|
|
12504
12596
|
"DevOnboardingStatus": {
|
|
12505
12597
|
"fields": {
|
|
12506
|
-
"
|
|
12507
|
-
"
|
|
12508
|
-
"type": "DevOnboardingStage",
|
|
12598
|
+
"step": {
|
|
12599
|
+
"type": "DevOnboardingStep",
|
|
12509
12600
|
"id": 1
|
|
12510
12601
|
},
|
|
12511
|
-
"
|
|
12512
|
-
"type": "
|
|
12602
|
+
"phase": {
|
|
12603
|
+
"type": "DevOnboardingPhase",
|
|
12513
12604
|
"id": 2
|
|
12514
12605
|
},
|
|
12515
|
-
"
|
|
12516
|
-
"type": "
|
|
12606
|
+
"setup": {
|
|
12607
|
+
"type": "DevOnboardingSetupStatus",
|
|
12517
12608
|
"id": 3
|
|
12609
|
+
},
|
|
12610
|
+
"pin_set": {
|
|
12611
|
+
"type": "bool",
|
|
12612
|
+
"id": 4
|
|
12613
|
+
},
|
|
12614
|
+
"wallet_initialized": {
|
|
12615
|
+
"type": "bool",
|
|
12616
|
+
"id": 5
|
|
12518
12617
|
}
|
|
12519
12618
|
}
|
|
12520
12619
|
},
|
package/src/device/Device.ts
CHANGED
|
@@ -52,8 +52,8 @@ import TransportManager from '../data-manager/TransportManager';
|
|
|
52
52
|
import { toHardened } from '../api/helpers/pathUtils';
|
|
53
53
|
import { existCapability } from '../utils/capabilitieUtils';
|
|
54
54
|
import {
|
|
55
|
-
PROTOCOL_V2_STATUS_DEVICE_INFO_REQUEST,
|
|
56
55
|
requestProtocolV2DeviceInfo,
|
|
56
|
+
requestProtocolV2DeviceStatus,
|
|
57
57
|
} from '../protocols/protocol-v2/features';
|
|
58
58
|
import { buildProtocolV1FeaturesPayload, buildProtocolV2FeaturesPayload } from '../deviceProfile';
|
|
59
59
|
|
|
@@ -96,7 +96,8 @@ const Log = getLogger(LoggerNames.Device);
|
|
|
96
96
|
|
|
97
97
|
export interface DeviceEvents {
|
|
98
98
|
[DEVICE.PIN]: [Device, PROTO.PinMatrixRequestType | undefined, (err: any, pin: string) => void];
|
|
99
|
-
[DEVICE.PASSPHRASE_ON_DEVICE]: [Device,
|
|
99
|
+
[DEVICE.PASSPHRASE_ON_DEVICE]: [Device, PassphraseRequestPayload?];
|
|
100
|
+
[DEVICE.ATTACH_PIN_ON_DEVICE]: [Device, PassphraseRequestPayload?];
|
|
100
101
|
[DEVICE.BUTTON]: [Device, DeviceButtonRequestPayload];
|
|
101
102
|
[DEVICE.FEATURES]: [Device, DeviceFeaturesPayload];
|
|
102
103
|
[DEVICE.PASSPHRASE]: [
|
|
@@ -728,10 +729,8 @@ export class Device extends EventEmitter {
|
|
|
728
729
|
if (this.features.bootloaderMode) {
|
|
729
730
|
return;
|
|
730
731
|
}
|
|
731
|
-
//
|
|
732
|
-
//
|
|
733
|
-
// 用字段级合并保留已有版本和 SE 信息。
|
|
734
|
-
await this._refreshProtocolV2Status(options);
|
|
732
|
+
// 普通业务调用复用缓存。动态状态由显式 getFeatures/deviceStatusGet、
|
|
733
|
+
// 解锁流程和设备事件刷新,避免每个 SDK 方法都额外轮询 DeviceStatus。
|
|
735
734
|
return;
|
|
736
735
|
}
|
|
737
736
|
await this._initializeProtocolV2(options);
|
|
@@ -798,9 +797,15 @@ export class Device extends EventEmitter {
|
|
|
798
797
|
commands: this.commands,
|
|
799
798
|
timeoutMs: options?.protocolV2DeviceInfoTimeoutMs,
|
|
800
799
|
});
|
|
800
|
+
const deviceStatus = await requestProtocolV2DeviceStatus({
|
|
801
|
+
commands: this.commands,
|
|
802
|
+
}).catch(error => {
|
|
803
|
+
Log.debug('Protocol V2 status unavailable during initialization:', error);
|
|
804
|
+
return undefined;
|
|
805
|
+
});
|
|
801
806
|
// 默认请求不含 SE/hash 数据,scope 如实标注为 basic;
|
|
802
807
|
// 完整数据由 getDeviceInfo(scope:'verify'|'full') 获取。
|
|
803
|
-
const features = this.updateProtocolV2Features(deviceInfo);
|
|
808
|
+
const features = this.updateProtocolV2Features(deviceInfo, deviceStatus);
|
|
804
809
|
Log.debug('Protocol V2 features:', features);
|
|
805
810
|
this.featuresNeedsReload = false;
|
|
806
811
|
} catch (error) {
|
|
@@ -809,34 +814,15 @@ export class Device extends EventEmitter {
|
|
|
809
814
|
}
|
|
810
815
|
}
|
|
811
816
|
|
|
812
|
-
/**
|
|
813
|
-
* Protocol V2 的轻量状态刷新(每次 run 前调用)。
|
|
814
|
-
*
|
|
815
|
-
* 请求 hw + coprocessor + status(不含 fw/SE target):status 提供 init_states / label /
|
|
816
|
-
* passphrase_enabled 等会在设备端变化的字段;hw/coprocessor 提供 serialNo / bleName。
|
|
817
|
-
* versions 为空时按字段级合并保留旧值,verify 数据不会被降级。
|
|
818
|
-
*/
|
|
819
|
-
private async _refreshProtocolV2Status(options?: InitOptions) {
|
|
820
|
-
try {
|
|
821
|
-
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
822
|
-
commands: this.commands,
|
|
823
|
-
request: PROTOCOL_V2_STATUS_DEVICE_INFO_REQUEST,
|
|
824
|
-
timeoutMs: options?.protocolV2DeviceInfoTimeoutMs,
|
|
825
|
-
});
|
|
826
|
-
const features = this.updateProtocolV2Features(deviceInfo);
|
|
827
|
-
Log.debug('Protocol V2 features (status refresh):', features);
|
|
828
|
-
} catch (error) {
|
|
829
|
-
Log.error('Protocol V2 status refresh failed:', error);
|
|
830
|
-
throw error;
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
|
|
834
817
|
async getFeatures() {
|
|
835
818
|
if (this.isProtocolV2()) {
|
|
836
819
|
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
837
820
|
commands: this.commands,
|
|
838
821
|
});
|
|
839
|
-
|
|
822
|
+
const deviceStatus = await requestProtocolV2DeviceStatus({
|
|
823
|
+
commands: this.commands,
|
|
824
|
+
}).catch(() => undefined);
|
|
825
|
+
return this.updateProtocolV2Features(deviceInfo, deviceStatus);
|
|
840
826
|
}
|
|
841
827
|
|
|
842
828
|
const { message } = await this.commands.typedCall('GetFeatures', 'Features', {});
|
|
@@ -871,10 +857,18 @@ export class Device extends EventEmitter {
|
|
|
871
857
|
this.emit(DEVICE.FEATURES, this, feat);
|
|
872
858
|
}
|
|
873
859
|
|
|
874
|
-
updateProtocolV2Features(deviceInfo?: ProtocolV2DeviceInfo) {
|
|
860
|
+
updateProtocolV2Features(deviceInfo?: ProtocolV2DeviceInfo, deviceStatus?: DeviceStatus | null) {
|
|
875
861
|
const previousCacheDeviceKey = this.getSessionCacheDeviceKey();
|
|
862
|
+
const resolvedDeviceStatus =
|
|
863
|
+
deviceStatus === undefined
|
|
864
|
+
? this.features?.raw?.protocolV2DeviceStatus
|
|
865
|
+
: deviceStatus ?? undefined;
|
|
876
866
|
const features = fixFeaturesFirmwareVersion(
|
|
877
|
-
buildProtocolV2FeaturesPayload(
|
|
867
|
+
buildProtocolV2FeaturesPayload({
|
|
868
|
+
deviceInfo,
|
|
869
|
+
deviceStatus: resolvedDeviceStatus,
|
|
870
|
+
previous: this.features,
|
|
871
|
+
})
|
|
878
872
|
);
|
|
879
873
|
this.features = features;
|
|
880
874
|
const nextCacheDeviceKey = this.getSessionCacheDeviceKey();
|
|
@@ -888,14 +882,10 @@ export class Device extends EventEmitter {
|
|
|
888
882
|
|
|
889
883
|
updateProtocolV2Status(status: DeviceStatus) {
|
|
890
884
|
const previousDeviceInfo = this.features?.raw?.protocolV2DeviceInfo;
|
|
891
|
-
const previousStatus =
|
|
892
|
-
return this.updateProtocolV2Features({
|
|
893
|
-
...
|
|
894
|
-
|
|
895
|
-
status: {
|
|
896
|
-
...previousStatus,
|
|
897
|
-
...status,
|
|
898
|
-
},
|
|
885
|
+
const previousStatus = this.features?.raw?.protocolV2DeviceStatus;
|
|
886
|
+
return this.updateProtocolV2Features(previousDeviceInfo, {
|
|
887
|
+
...previousStatus,
|
|
888
|
+
...status,
|
|
899
889
|
});
|
|
900
890
|
}
|
|
901
891
|
|
|
@@ -1190,7 +1180,9 @@ export class Device extends EventEmitter {
|
|
|
1190
1180
|
async unlockDevice() {
|
|
1191
1181
|
if (this.isProtocolV2()) {
|
|
1192
1182
|
try {
|
|
1193
|
-
await this.commands.typedCall('DeviceSessionAskPin', 'Success'
|
|
1183
|
+
await this.commands.typedCall('DeviceSessionAskPin', 'Success', undefined, {
|
|
1184
|
+
timeoutMs: 120_000,
|
|
1185
|
+
});
|
|
1194
1186
|
} catch (error) {
|
|
1195
1187
|
const errorText =
|
|
1196
1188
|
error instanceof Error
|
|
@@ -663,7 +663,7 @@ export class DeviceCommands {
|
|
|
663
663
|
|
|
664
664
|
if (res.type === 'PassphraseRequest') {
|
|
665
665
|
const existsAttachPinUser = res.message.exists_attach_pin_user;
|
|
666
|
-
return this.
|
|
666
|
+
return this.promptPassphrase({
|
|
667
667
|
existsAttachPinUser,
|
|
668
668
|
}).then(response => {
|
|
669
669
|
const { passphrase, passphraseOnDevice, attachPinOnDevice } = response;
|
|
@@ -761,10 +761,27 @@ export class DeviceCommands {
|
|
|
761
761
|
});
|
|
762
762
|
}
|
|
763
763
|
|
|
764
|
-
|
|
764
|
+
promptPassphrase(
|
|
765
|
+
options: PassphraseRequestPayload,
|
|
766
|
+
promptOptions: { cancelDeviceOnReject?: boolean } = {}
|
|
767
|
+
) {
|
|
765
768
|
return new Promise<PassphrasePromptResponse>((resolve, reject) => {
|
|
766
|
-
const cancelAndReject = (_error?: Error) =>
|
|
767
|
-
|
|
769
|
+
const cancelAndReject = (_error?: Error) => {
|
|
770
|
+
const rejectWithCancelledError = () => {
|
|
771
|
+
reject(
|
|
772
|
+
ERRORS.TypedError(
|
|
773
|
+
HardwareErrorCode.CallQueueActionCancelled,
|
|
774
|
+
`${DEVICE.PASSPHRASE} canceled`
|
|
775
|
+
)
|
|
776
|
+
);
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
if (promptOptions.cancelDeviceOnReject === false) {
|
|
780
|
+
rejectWithCancelledError();
|
|
781
|
+
return Promise.resolve();
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
return cancelDeviceInPrompt(this.device, false)
|
|
768
785
|
.then(onCancel => {
|
|
769
786
|
const error = ERRORS.TypedError(
|
|
770
787
|
HardwareErrorCode.CallQueueActionCancelled,
|
|
@@ -781,6 +798,7 @@ export class DeviceCommands {
|
|
|
781
798
|
.catch(error => {
|
|
782
799
|
reject(error);
|
|
783
800
|
});
|
|
801
|
+
};
|
|
784
802
|
|
|
785
803
|
if (this.device.listenerCount(DEVICE.PASSPHRASE) > 0) {
|
|
786
804
|
this.device.setCancelableAction(cancelAndReject);
|
package/src/device/DevicePool.ts
CHANGED
|
@@ -108,14 +108,19 @@ export class DevicePool extends EventEmitter {
|
|
|
108
108
|
device.updateDescriptor(exist, true);
|
|
109
109
|
devices[connectId] = device;
|
|
110
110
|
deviceList.push(device);
|
|
111
|
-
await this._checkDevicePool(initOptions);
|
|
111
|
+
await this._checkDevicePool(initOptions, connectId);
|
|
112
112
|
return { devices, deviceList };
|
|
113
113
|
}
|
|
114
114
|
Log.debug('found device in cache, but path is different: ', connectId);
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
const matchedDescriptor = connectId
|
|
119
|
+
? descriptorList.find(descriptor => descriptor.path === connectId)
|
|
120
|
+
: undefined;
|
|
121
|
+
const descriptorsToInitialize = matchedDescriptor ? [matchedDescriptor] : descriptorList;
|
|
122
|
+
|
|
123
|
+
for await (const descriptor of descriptorsToInitialize) {
|
|
119
124
|
const device = await this._createDevice(descriptor, initOptions);
|
|
120
125
|
|
|
121
126
|
const connectId = device.getConnectId();
|
|
@@ -133,7 +138,7 @@ export class DevicePool extends EventEmitter {
|
|
|
133
138
|
// Log.debug('get devices result : ', devices, deviceList);
|
|
134
139
|
// console.log('device poll -> connected: ', this.connectedPool);
|
|
135
140
|
// console.log('device poll -> disconnected: ', this.disconnectPool);
|
|
136
|
-
await this._checkDevicePool(initOptions);
|
|
141
|
+
await this._checkDevicePool(initOptions, matchedDescriptor ? connectId : undefined);
|
|
137
142
|
return { devices, deviceList };
|
|
138
143
|
}
|
|
139
144
|
|
|
@@ -157,14 +162,17 @@ export class DevicePool extends EventEmitter {
|
|
|
157
162
|
return device;
|
|
158
163
|
}
|
|
159
164
|
|
|
160
|
-
static async _checkDevicePool(initOptions?: InitOptions) {
|
|
161
|
-
await this._sendConnectMessage(initOptions);
|
|
165
|
+
static async _checkDevicePool(initOptions?: InitOptions, connectId?: string) {
|
|
166
|
+
await this._sendConnectMessage(initOptions, connectId);
|
|
162
167
|
this._sendDisconnectMessage();
|
|
163
168
|
}
|
|
164
169
|
|
|
165
|
-
static async _sendConnectMessage(initOptions?: InitOptions) {
|
|
170
|
+
static async _sendConnectMessage(initOptions?: InitOptions, connectId?: string) {
|
|
166
171
|
for (let i = this.connectedPool.length - 1; i >= 0; i--) {
|
|
167
172
|
const descriptor = this.connectedPool[i];
|
|
173
|
+
if (connectId && descriptor.path !== connectId) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
168
176
|
const device = await this._createDevice(descriptor, initOptions);
|
|
169
177
|
Log.debug('emit DEVICE.CONNECT: ', device?.features);
|
|
170
178
|
this.emitter.emit(DEVICE.CONNECT, device);
|
|
@@ -5,7 +5,11 @@ import {
|
|
|
5
5
|
isProtocolV2RomloaderDeviceInfo,
|
|
6
6
|
} from '../protocols/protocol-v2/features';
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
DeviceFirmwareImageInfo,
|
|
10
|
+
DeviceStatus,
|
|
11
|
+
ProtocolV2DeviceInfo,
|
|
12
|
+
} from '@onekeyfe/hd-transport';
|
|
9
13
|
import type { PROTO } from '../constants';
|
|
10
14
|
import type { DeviceFeaturesMode, Features } from '../types';
|
|
11
15
|
|
|
@@ -222,16 +226,21 @@ export const buildProtocolV1FeaturesPayload = (
|
|
|
222
226
|
* 缓存的同名字段级合并;不存在协议等价语义的字段保持 null/空值,不再通过
|
|
223
227
|
* DeviceProfile 或 transport path 做身份兜底。
|
|
224
228
|
*/
|
|
225
|
-
export const buildProtocolV2FeaturesPayload = (
|
|
226
|
-
deviceInfo
|
|
227
|
-
|
|
228
|
-
|
|
229
|
+
export const buildProtocolV2FeaturesPayload = ({
|
|
230
|
+
deviceInfo,
|
|
231
|
+
deviceStatus,
|
|
232
|
+
previous,
|
|
233
|
+
}: {
|
|
234
|
+
deviceInfo?: ProtocolV2DeviceInfo;
|
|
235
|
+
deviceStatus?: DeviceStatus;
|
|
236
|
+
previous?: Features;
|
|
237
|
+
}): Features => {
|
|
229
238
|
const info = deviceInfo;
|
|
230
239
|
const fwApplication = info?.fw?.application;
|
|
231
240
|
const fwBootloader = info?.fw?.bootloader;
|
|
232
241
|
const fwBoard = info?.fw?.romloader;
|
|
233
242
|
const bleApplication = info?.coprocessor?.application;
|
|
234
|
-
const status =
|
|
243
|
+
const status = deviceStatus;
|
|
235
244
|
|
|
236
245
|
const firmwareVersion = firstMeaningfulVersion(
|
|
237
246
|
getImageVersion(fwApplication),
|
|
@@ -248,15 +257,17 @@ export const buildProtocolV2FeaturesPayload = (
|
|
|
248
257
|
const label = previous?.label ?? null;
|
|
249
258
|
const bleName = firstValue(info?.coprocessor?.bt_adv_name, previous?.bleName);
|
|
250
259
|
const initialized = firstValue(status?.init_states, previous?.initialized) ?? null;
|
|
251
|
-
|
|
260
|
+
// Pro2 在锁定状态下返回的 passphrase_enabled 不是最终钱包状态。
|
|
261
|
+
// 只有完成 PIN 解锁后的 DeviceStatus 才能作为 passphrase 开关真值来源。
|
|
262
|
+
const passphraseProtection = status?.unlocked === true ? status.passphrase_enabled ?? null : null;
|
|
252
263
|
const language = previous?.language ?? null;
|
|
253
264
|
const backupRequired = firstValue(status?.backup_required, previous?.backupRequired) ?? null;
|
|
254
265
|
const bleEnabled = previous?.bleEnabled;
|
|
255
266
|
const unlocked = firstValue(status?.unlocked, previous?.unlocked) ?? null;
|
|
256
267
|
const attachToPinEnabled = status?.attach_to_pin_enabled ?? null;
|
|
257
268
|
const unlockedAttachPin = status?.unlocked_by_attach_to_pin ?? undefined;
|
|
258
|
-
const romloaderMode = isProtocolV2RomloaderDeviceInfo(info);
|
|
259
|
-
const bootloaderMode = isProtocolV2BootloaderDeviceInfo(info);
|
|
269
|
+
const romloaderMode = isProtocolV2RomloaderDeviceInfo(info, status);
|
|
270
|
+
const bootloaderMode = isProtocolV2BootloaderDeviceInfo(info, status);
|
|
260
271
|
let mode: DeviceFeaturesMode = 'unknown';
|
|
261
272
|
if (romloaderMode) {
|
|
262
273
|
mode = 'romloader';
|
|
@@ -376,6 +387,7 @@ export const buildProtocolV2FeaturesPayload = (
|
|
|
376
387
|
unlockedAttachPin,
|
|
377
388
|
raw: {
|
|
378
389
|
protocolV2DeviceInfo: deviceInfo,
|
|
390
|
+
protocolV2DeviceStatus: deviceStatus,
|
|
379
391
|
},
|
|
380
392
|
};
|
|
381
393
|
};
|
|
@@ -29,7 +29,11 @@ import type {
|
|
|
29
29
|
GetDeviceInfoParams,
|
|
30
30
|
} from '../types/api/getDeviceInfo';
|
|
31
31
|
import type { Features, OnekeyFeatures } from '../types';
|
|
32
|
-
import type {
|
|
32
|
+
import type {
|
|
33
|
+
DeviceFirmwareImageInfo,
|
|
34
|
+
DeviceStatus,
|
|
35
|
+
ProtocolV2DeviceInfo,
|
|
36
|
+
} from '@onekeyfe/hd-transport';
|
|
33
37
|
|
|
34
38
|
type BuildProtocolV1ProfileParams = {
|
|
35
39
|
protocol?: DeviceInfoProtocol;
|
|
@@ -42,6 +46,7 @@ type BuildProtocolV1ProfileParams = {
|
|
|
42
46
|
|
|
43
47
|
type BuildProtocolV2ProfileParams = {
|
|
44
48
|
deviceInfo?: ProtocolV2DeviceInfo;
|
|
49
|
+
deviceStatus?: DeviceStatus;
|
|
45
50
|
sources?: DeviceInfoSource[];
|
|
46
51
|
scope?: GetDeviceInfoParams['scope'];
|
|
47
52
|
includeRaw?: boolean;
|
|
@@ -89,10 +94,13 @@ const getDeviceMode = (features?: Features): DeviceInfoStatus['mode'] => {
|
|
|
89
94
|
return 'unknown';
|
|
90
95
|
};
|
|
91
96
|
|
|
92
|
-
const getProtocolV2Mode = (
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
const getProtocolV2Mode = (
|
|
98
|
+
deviceInfo?: ProtocolV2DeviceInfo,
|
|
99
|
+
deviceStatus?: DeviceStatus
|
|
100
|
+
): DeviceInfoStatus['mode'] => {
|
|
101
|
+
if (isProtocolV2RomloaderDeviceInfo(deviceInfo, deviceStatus)) return 'romloader';
|
|
102
|
+
if (isProtocolV2BootloaderDeviceInfo(deviceInfo, deviceStatus)) return 'bootloader';
|
|
103
|
+
const initialized = deviceStatus?.init_states;
|
|
96
104
|
if (initialized === false) return 'notInitialized';
|
|
97
105
|
if (initialized === true) return 'normal';
|
|
98
106
|
return 'unknown';
|
|
@@ -186,11 +194,14 @@ const normalizeV1Status = (features?: Features): DeviceInfoStatus => ({
|
|
|
186
194
|
bleEnabled: features?.bleEnabled ?? null,
|
|
187
195
|
});
|
|
188
196
|
|
|
189
|
-
const normalizeV2Status = (
|
|
190
|
-
|
|
191
|
-
|
|
197
|
+
const normalizeV2Status = (
|
|
198
|
+
deviceInfo?: ProtocolV2DeviceInfo,
|
|
199
|
+
deviceStatus?: DeviceStatus
|
|
200
|
+
): DeviceInfoStatus => {
|
|
201
|
+
const status = deviceStatus;
|
|
202
|
+
const bootloaderMode = isProtocolV2BootloaderDeviceInfo(deviceInfo, deviceStatus);
|
|
192
203
|
return {
|
|
193
|
-
mode: getProtocolV2Mode(deviceInfo),
|
|
204
|
+
mode: getProtocolV2Mode(deviceInfo, deviceStatus),
|
|
194
205
|
initialized: status?.init_states ?? null,
|
|
195
206
|
bootloaderMode,
|
|
196
207
|
unlocked: status?.unlocked ?? null,
|
|
@@ -274,14 +285,17 @@ const normalizeRaw = ({
|
|
|
274
285
|
features,
|
|
275
286
|
protocolV1OneKeyFeatures,
|
|
276
287
|
protocolV2DeviceInfo,
|
|
288
|
+
protocolV2DeviceStatus,
|
|
277
289
|
}: {
|
|
278
290
|
features?: Features;
|
|
279
291
|
protocolV1OneKeyFeatures?: OnekeyFeatures;
|
|
280
292
|
protocolV2DeviceInfo?: ProtocolV2DeviceInfo;
|
|
293
|
+
protocolV2DeviceStatus?: DeviceStatus;
|
|
281
294
|
}): DeviceProfileRaw => ({
|
|
282
295
|
...(features ? { features } : {}),
|
|
283
296
|
...(protocolV1OneKeyFeatures ? { protocolV1OneKeyFeatures } : {}),
|
|
284
297
|
...(protocolV2DeviceInfo ? { protocolV2DeviceInfo } : {}),
|
|
298
|
+
...(protocolV2DeviceStatus ? { protocolV2DeviceStatus } : {}),
|
|
285
299
|
});
|
|
286
300
|
|
|
287
301
|
export function buildProfileFromProtocolV1({
|
|
@@ -320,12 +334,13 @@ export function buildProfileFromProtocolV1({
|
|
|
320
334
|
|
|
321
335
|
export function buildProfileFromProtocolV2({
|
|
322
336
|
deviceInfo,
|
|
337
|
+
deviceStatus,
|
|
323
338
|
sources = ['deviceInfo'],
|
|
324
339
|
scope = 'basic',
|
|
325
340
|
includeRaw = false,
|
|
326
341
|
}: BuildProtocolV2ProfileParams): DeviceProfile {
|
|
327
342
|
const info = deviceInfo;
|
|
328
|
-
const deviceId =
|
|
343
|
+
const deviceId = deviceStatus?.device_id || '';
|
|
329
344
|
const serialNo = deviceInfo?.hw?.serial_no || '';
|
|
330
345
|
const label = null;
|
|
331
346
|
const bleName = info?.coprocessor?.bt_adv_name ?? null;
|
|
@@ -340,13 +355,14 @@ export function buildProfileFromProtocolV2({
|
|
|
340
355
|
serialNo,
|
|
341
356
|
label,
|
|
342
357
|
bleName,
|
|
343
|
-
status: normalizeV2Status(deviceInfo),
|
|
358
|
+
status: normalizeV2Status(deviceInfo, deviceStatus),
|
|
344
359
|
versions: normalizeV2Versions(deviceInfo),
|
|
345
360
|
...(shouldIncludeVerify(scope) ? { verify } : {}),
|
|
346
361
|
...(includeRaw
|
|
347
362
|
? {
|
|
348
363
|
raw: normalizeRaw({
|
|
349
364
|
protocolV2DeviceInfo: deviceInfo,
|
|
365
|
+
protocolV2DeviceStatus: deviceStatus,
|
|
350
366
|
}),
|
|
351
367
|
}
|
|
352
368
|
: {}),
|
package/src/events/device.ts
CHANGED
|
@@ -23,6 +23,7 @@ export const DEVICE = {
|
|
|
23
23
|
PIN: 'pin',
|
|
24
24
|
PASSPHRASE: 'passphrase',
|
|
25
25
|
PASSPHRASE_ON_DEVICE: 'passphrase_on_device',
|
|
26
|
+
ATTACH_PIN_ON_DEVICE: 'attach_pin_on_device',
|
|
26
27
|
WORD: 'word',
|
|
27
28
|
SUPPORT_FEATURES: 'support_features',
|
|
28
29
|
SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE: 'select_device_in_bootloader_for_web_device',
|
|
@@ -47,6 +48,9 @@ export interface DeviceButtonRequestPayload extends Omit<PROTO.ButtonRequest, 'c
|
|
|
47
48
|
|
|
48
49
|
export type PassphraseRequestPayload = {
|
|
49
50
|
existsAttachPinUser?: boolean;
|
|
51
|
+
source?: 'wallet-session-coordinator';
|
|
52
|
+
reason?: 'open-wallet' | 'session-recovery';
|
|
53
|
+
expectedPassphraseState?: string;
|
|
50
54
|
};
|
|
51
55
|
|
|
52
56
|
export interface DeviceButtonRequest {
|
package/src/events/ui-request.ts
CHANGED
|
@@ -49,6 +49,23 @@ export const UI_REQUEST = {
|
|
|
49
49
|
NOT_USE_ONEKEY_DEVICE: 'ui-device_please_use_onekey_device',
|
|
50
50
|
} as const;
|
|
51
51
|
|
|
52
|
+
export type ProtocolV2UiEventSource =
|
|
53
|
+
| 'unlock-coordinator'
|
|
54
|
+
| 'wallet-session-coordinator'
|
|
55
|
+
| 'method-lifecycle';
|
|
56
|
+
|
|
57
|
+
export type ProtocolV2UiCompletion = 'page-accepted' | 'operation-completed';
|
|
58
|
+
|
|
59
|
+
export type ProtocolV2UiEventMetadata = {
|
|
60
|
+
source?: ProtocolV2UiEventSource;
|
|
61
|
+
reason?: string;
|
|
62
|
+
deviceOnly?: boolean;
|
|
63
|
+
completion?: ProtocolV2UiCompletion;
|
|
64
|
+
method?: string;
|
|
65
|
+
page?: string | number;
|
|
66
|
+
operation?: string;
|
|
67
|
+
};
|
|
68
|
+
|
|
52
69
|
export interface UiRequestWithoutPayload {
|
|
53
70
|
type:
|
|
54
71
|
| typeof UI_REQUEST.CLOSE_UI_WINDOW
|
|
@@ -73,7 +90,7 @@ export interface UiRequestFirmwareProgressing {
|
|
|
73
90
|
|
|
74
91
|
export type UiRequestDeviceAction = {
|
|
75
92
|
type: typeof UI_REQUEST.REQUEST_PIN;
|
|
76
|
-
payload: {
|
|
93
|
+
payload: ProtocolV2UiEventMetadata & {
|
|
77
94
|
device: Device;
|
|
78
95
|
type?: PROTO.PinMatrixRequestType | 'ButtonRequest_PinEntry' | 'ButtonRequest_AttachPin';
|
|
79
96
|
};
|
|
@@ -81,7 +98,7 @@ export type UiRequestDeviceAction = {
|
|
|
81
98
|
|
|
82
99
|
export interface UiRequestButton {
|
|
83
100
|
type: typeof UI_REQUEST.REQUEST_BUTTON;
|
|
84
|
-
payload: DeviceButtonRequest['payload'];
|
|
101
|
+
payload: DeviceButtonRequest['payload'] & ProtocolV2UiEventMetadata;
|
|
85
102
|
}
|
|
86
103
|
|
|
87
104
|
export interface UiRequestPassphrase {
|
|
@@ -90,6 +107,9 @@ export interface UiRequestPassphrase {
|
|
|
90
107
|
device: Device;
|
|
91
108
|
passphraseState?: string;
|
|
92
109
|
existsAttachPinUser?: boolean;
|
|
110
|
+
source?: 'wallet-session-coordinator';
|
|
111
|
+
reason?: 'open-wallet' | 'session-recovery';
|
|
112
|
+
expectedPassphraseState?: string;
|
|
93
113
|
};
|
|
94
114
|
}
|
|
95
115
|
|
|
@@ -98,6 +118,8 @@ export interface UiRequestPassphraseOnDevice {
|
|
|
98
118
|
payload: {
|
|
99
119
|
device: Device;
|
|
100
120
|
passphraseState?: string;
|
|
121
|
+
source?: 'wallet-session-coordinator';
|
|
122
|
+
reason?: 'open-wallet' | 'session-recovery';
|
|
101
123
|
};
|
|
102
124
|
}
|
|
103
125
|
|