@onekeyfe/hardware-cli 1.1.27-patch.1 → 1.2.0-alpha.0
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/dist/cli.js +44 -6
- package/jest.config.js +1 -0
- package/package.json +6 -6
- package/src/cli.ts +61 -6
package/dist/cli.js
CHANGED
|
@@ -5,6 +5,32 @@ const commander_1 = require("commander");
|
|
|
5
5
|
const sdk_1 = require("./sdk");
|
|
6
6
|
const session_1 = require("./session");
|
|
7
7
|
const chains_1 = require("./chains");
|
|
8
|
+
const hd_shared_1 = require("@onekeyfe/hd-shared");
|
|
9
|
+
const hd_core_1 = require("@onekeyfe/hd-core");
|
|
10
|
+
function extractPassphraseSession(payload) {
|
|
11
|
+
if (typeof payload === 'string') {
|
|
12
|
+
return { passphraseState: payload };
|
|
13
|
+
}
|
|
14
|
+
if (!payload || typeof payload !== 'object') {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
const statePayload = payload;
|
|
18
|
+
let passphraseState;
|
|
19
|
+
if (typeof statePayload.passphrase_state === 'string') {
|
|
20
|
+
passphraseState = statePayload.passphrase_state;
|
|
21
|
+
}
|
|
22
|
+
else if (typeof statePayload.passphraseState === 'string') {
|
|
23
|
+
passphraseState = statePayload.passphraseState;
|
|
24
|
+
}
|
|
25
|
+
let sessionId;
|
|
26
|
+
if (typeof statePayload.session_id === 'string') {
|
|
27
|
+
sessionId = statePayload.session_id;
|
|
28
|
+
}
|
|
29
|
+
else if (typeof statePayload.sessionId === 'string') {
|
|
30
|
+
sessionId = statePayload.sessionId;
|
|
31
|
+
}
|
|
32
|
+
return { passphraseState, sessionId };
|
|
33
|
+
}
|
|
8
34
|
const program = new commander_1.Command();
|
|
9
35
|
program
|
|
10
36
|
.name('onekey-hw')
|
|
@@ -537,7 +563,14 @@ sessionCmd
|
|
|
537
563
|
outputResult(globalOpts, psResult);
|
|
538
564
|
return;
|
|
539
565
|
}
|
|
540
|
-
const passphraseState = psResult.payload;
|
|
566
|
+
const { passphraseState, sessionId: passphraseSessionId } = extractPassphraseSession(psResult.payload);
|
|
567
|
+
if (!passphraseState) {
|
|
568
|
+
outputResult(globalOpts, {
|
|
569
|
+
success: false,
|
|
570
|
+
payload: { error: 'getPassphraseState did not return passphraseState' },
|
|
571
|
+
});
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
541
574
|
// 4. Get address to verify + extract deviceId
|
|
542
575
|
const addrResult = await sdk.evmGetAddress(connectId, device.deviceId || '', {
|
|
543
576
|
path: "m/44'/60'/0'/0/0",
|
|
@@ -560,7 +593,7 @@ sessionCmd
|
|
|
560
593
|
});
|
|
561
594
|
const featPayload = featResult?.success ? featResult.payload : undefined;
|
|
562
595
|
const deviceId = featPayload?.device_id || device.deviceId || '';
|
|
563
|
-
const sessionId = featPayload?.session_id || '';
|
|
596
|
+
const sessionId = passphraseSessionId || featPayload?.session_id || '';
|
|
564
597
|
// 6. Save to keychain
|
|
565
598
|
if (passphraseState && deviceId && sessionId) {
|
|
566
599
|
await (0, session_1.saveSessionToKeychain)(deviceId, passphraseState, sessionId);
|
|
@@ -582,7 +615,7 @@ sessionCmd
|
|
|
582
615
|
const searchResult = await sdk.searchDevices();
|
|
583
616
|
const device = // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
584
617
|
searchResult?.payload?.[0];
|
|
585
|
-
const deviceId = device?.
|
|
618
|
+
const deviceId = device?.deviceId || device?.features?.device_id;
|
|
586
619
|
if (deviceId) {
|
|
587
620
|
await (0, session_1.clearSessionFromKeychain)(deviceId);
|
|
588
621
|
}
|
|
@@ -691,6 +724,7 @@ globalOpts) {
|
|
|
691
724
|
// getFeatures failures here are non-fatal — we fall through to Step 3
|
|
692
725
|
// which will fail with a clearer error if the device is truly unreachable.
|
|
693
726
|
let deviceId = device.features?.device_id || device.deviceId || '';
|
|
727
|
+
let deviceType = (0, hd_core_1.getDeviceType)(device.features);
|
|
694
728
|
let unlocked = device.features?.unlocked;
|
|
695
729
|
let passphraseProtection = device.features?.passphrase_protection;
|
|
696
730
|
if (!deviceId || unlocked == null || passphraseProtection == null) {
|
|
@@ -698,6 +732,7 @@ globalOpts) {
|
|
|
698
732
|
const featResult = await sdk.getFeatures(connectId);
|
|
699
733
|
if (featResult?.success && featResult.payload) {
|
|
700
734
|
deviceId = featResult.payload.device_id || deviceId;
|
|
735
|
+
deviceType = (0, hd_core_1.getDeviceType)(featResult.payload) || deviceType;
|
|
701
736
|
unlocked = featResult.payload.unlocked;
|
|
702
737
|
passphraseProtection = featResult.payload.passphrase_protection;
|
|
703
738
|
}
|
|
@@ -723,7 +758,7 @@ globalOpts) {
|
|
|
723
758
|
globalOpts.deviceId = deviceId;
|
|
724
759
|
}
|
|
725
760
|
// ── Step 4: Check passphrase protection ──────────────────────────
|
|
726
|
-
if (passphraseProtection === false) {
|
|
761
|
+
if (passphraseProtection === false && deviceType !== hd_shared_1.EDeviceType.Pro2) {
|
|
727
762
|
return undefined;
|
|
728
763
|
}
|
|
729
764
|
// ── Step 5: Try keychain session reuse ───────────────────────────
|
|
@@ -742,7 +777,10 @@ globalOpts) {
|
|
|
742
777
|
useEmptyPassphrase: false,
|
|
743
778
|
});
|
|
744
779
|
if (psResult.success && psResult.payload) {
|
|
745
|
-
const passphraseState = psResult.payload;
|
|
780
|
+
const { passphraseState, sessionId: passphraseSessionId } = extractPassphraseSession(psResult.payload);
|
|
781
|
+
if (!passphraseState) {
|
|
782
|
+
return undefined;
|
|
783
|
+
}
|
|
746
784
|
globalOpts.passphraseState = passphraseState;
|
|
747
785
|
// Save session to keychain for next invocation.
|
|
748
786
|
//
|
|
@@ -755,7 +793,7 @@ globalOpts) {
|
|
|
755
793
|
passphraseState,
|
|
756
794
|
skipPassphraseCheck: true,
|
|
757
795
|
});
|
|
758
|
-
const sessionId = featAfter?.success ? featAfter.payload?.session_id : undefined;
|
|
796
|
+
const sessionId = passphraseSessionId || (featAfter?.success ? featAfter.payload?.session_id : undefined);
|
|
759
797
|
if (sessionId) {
|
|
760
798
|
await (0, session_1.saveSessionToKeychain)(deviceId, passphraseState, sessionId);
|
|
761
799
|
await (0, session_1.preloadSessionFromKeychain)(deviceId);
|
package/jest.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hardware-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0-alpha.0",
|
|
4
4
|
"description": "OneKey hardware wallet CLI for testing device communication",
|
|
5
5
|
"author": "OneKey",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"test": "jest"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@onekeyfe/hd-common-connect-sdk": "1.
|
|
34
|
-
"@onekeyfe/hd-core": "1.
|
|
35
|
-
"@onekeyfe/hd-shared": "1.
|
|
36
|
-
"@onekeyfe/hd-transport-usb": "1.
|
|
33
|
+
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.0",
|
|
34
|
+
"@onekeyfe/hd-core": "1.2.0-alpha.0",
|
|
35
|
+
"@onekeyfe/hd-shared": "1.2.0-alpha.0",
|
|
36
|
+
"@onekeyfe/hd-transport-usb": "1.2.0-alpha.0",
|
|
37
37
|
"commander": "^12.0.0"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "de9efe20b83666b641ab9e8d945e6350f6450904"
|
|
40
40
|
}
|
package/src/cli.ts
CHANGED
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
resolveSignTransaction,
|
|
15
15
|
} from './chains';
|
|
16
16
|
|
|
17
|
+
import { EDeviceType } from '@onekeyfe/hd-shared';
|
|
18
|
+
import { getDeviceType } from '@onekeyfe/hd-core';
|
|
17
19
|
import type {
|
|
18
20
|
EthereumSignTypedDataMessage,
|
|
19
21
|
EthereumSignTypedDataTypes,
|
|
@@ -25,6 +27,41 @@ import type {
|
|
|
25
27
|
/** SearchDevice enriched with features fetched after discovery */
|
|
26
28
|
type EnrichedSearchDevice = SearchDevice & { features?: Features };
|
|
27
29
|
|
|
30
|
+
function extractPassphraseSession(payload: unknown): {
|
|
31
|
+
passphraseState?: string;
|
|
32
|
+
sessionId?: string;
|
|
33
|
+
} {
|
|
34
|
+
if (typeof payload === 'string') {
|
|
35
|
+
return { passphraseState: payload };
|
|
36
|
+
}
|
|
37
|
+
if (!payload || typeof payload !== 'object') {
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const statePayload = payload as {
|
|
42
|
+
passphrase_state?: unknown;
|
|
43
|
+
passphraseState?: unknown;
|
|
44
|
+
session_id?: unknown;
|
|
45
|
+
sessionId?: unknown;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
let passphraseState: string | undefined;
|
|
49
|
+
if (typeof statePayload.passphrase_state === 'string') {
|
|
50
|
+
passphraseState = statePayload.passphrase_state;
|
|
51
|
+
} else if (typeof statePayload.passphraseState === 'string') {
|
|
52
|
+
passphraseState = statePayload.passphraseState;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let sessionId: string | undefined;
|
|
56
|
+
if (typeof statePayload.session_id === 'string') {
|
|
57
|
+
sessionId = statePayload.session_id;
|
|
58
|
+
} else if (typeof statePayload.sessionId === 'string') {
|
|
59
|
+
sessionId = statePayload.sessionId;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return { passphraseState, sessionId };
|
|
63
|
+
}
|
|
64
|
+
|
|
28
65
|
const program = new Command();
|
|
29
66
|
|
|
30
67
|
program
|
|
@@ -687,7 +724,16 @@ sessionCmd
|
|
|
687
724
|
outputResult(globalOpts, psResult);
|
|
688
725
|
return;
|
|
689
726
|
}
|
|
690
|
-
const passphraseState =
|
|
727
|
+
const { passphraseState, sessionId: passphraseSessionId } = extractPassphraseSession(
|
|
728
|
+
psResult.payload
|
|
729
|
+
);
|
|
730
|
+
if (!passphraseState) {
|
|
731
|
+
outputResult(globalOpts, {
|
|
732
|
+
success: false,
|
|
733
|
+
payload: { error: 'getPassphraseState did not return passphraseState' },
|
|
734
|
+
});
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
691
737
|
|
|
692
738
|
// 4. Get address to verify + extract deviceId
|
|
693
739
|
const addrResult = await sdk.evmGetAddress(connectId, device.deviceId || '', {
|
|
@@ -712,7 +758,7 @@ sessionCmd
|
|
|
712
758
|
});
|
|
713
759
|
const featPayload = featResult?.success ? featResult.payload : undefined;
|
|
714
760
|
const deviceId = featPayload?.device_id || device.deviceId || '';
|
|
715
|
-
const sessionId = featPayload?.session_id || '';
|
|
761
|
+
const sessionId = passphraseSessionId || featPayload?.session_id || '';
|
|
716
762
|
|
|
717
763
|
// 6. Save to keychain
|
|
718
764
|
if (passphraseState && deviceId && sessionId) {
|
|
@@ -739,7 +785,7 @@ sessionCmd
|
|
|
739
785
|
const searchResult = await sdk.searchDevices();
|
|
740
786
|
const device = // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
741
787
|
(searchResult?.payload as any)?.[0];
|
|
742
|
-
const deviceId = device?.
|
|
788
|
+
const deviceId = device?.deviceId || device?.features?.device_id;
|
|
743
789
|
if (deviceId) {
|
|
744
790
|
await clearSessionFromKeychain(deviceId);
|
|
745
791
|
}
|
|
@@ -869,6 +915,7 @@ async function prepareSession(
|
|
|
869
915
|
deviceId?: string;
|
|
870
916
|
features?: {
|
|
871
917
|
device_id?: string;
|
|
918
|
+
onekey_device_type?: string;
|
|
872
919
|
session_id?: string;
|
|
873
920
|
passphrase_protection?: boolean | null;
|
|
874
921
|
unlocked?: boolean | null;
|
|
@@ -883,6 +930,7 @@ async function prepareSession(
|
|
|
883
930
|
// getFeatures failures here are non-fatal — we fall through to Step 3
|
|
884
931
|
// which will fail with a clearer error if the device is truly unreachable.
|
|
885
932
|
let deviceId = device.features?.device_id || device.deviceId || '';
|
|
933
|
+
let deviceType = getDeviceType(device.features as Features | undefined);
|
|
886
934
|
let unlocked = device.features?.unlocked;
|
|
887
935
|
let passphraseProtection = device.features?.passphrase_protection;
|
|
888
936
|
|
|
@@ -891,6 +939,7 @@ async function prepareSession(
|
|
|
891
939
|
const featResult = await sdk.getFeatures(connectId);
|
|
892
940
|
if (featResult?.success && featResult.payload) {
|
|
893
941
|
deviceId = featResult.payload.device_id || deviceId;
|
|
942
|
+
deviceType = getDeviceType(featResult.payload) || deviceType;
|
|
894
943
|
unlocked = featResult.payload.unlocked;
|
|
895
944
|
passphraseProtection = featResult.payload.passphrase_protection;
|
|
896
945
|
}
|
|
@@ -918,7 +967,7 @@ async function prepareSession(
|
|
|
918
967
|
}
|
|
919
968
|
|
|
920
969
|
// ── Step 4: Check passphrase protection ──────────────────────────
|
|
921
|
-
if (passphraseProtection === false) {
|
|
970
|
+
if (passphraseProtection === false && deviceType !== EDeviceType.Pro2) {
|
|
922
971
|
return undefined;
|
|
923
972
|
}
|
|
924
973
|
|
|
@@ -940,7 +989,12 @@ async function prepareSession(
|
|
|
940
989
|
});
|
|
941
990
|
|
|
942
991
|
if (psResult.success && psResult.payload) {
|
|
943
|
-
const passphraseState =
|
|
992
|
+
const { passphraseState, sessionId: passphraseSessionId } = extractPassphraseSession(
|
|
993
|
+
psResult.payload
|
|
994
|
+
);
|
|
995
|
+
if (!passphraseState) {
|
|
996
|
+
return undefined;
|
|
997
|
+
}
|
|
944
998
|
globalOpts.passphraseState = passphraseState;
|
|
945
999
|
|
|
946
1000
|
// Save session to keychain for next invocation.
|
|
@@ -954,7 +1008,8 @@ async function prepareSession(
|
|
|
954
1008
|
passphraseState,
|
|
955
1009
|
skipPassphraseCheck: true,
|
|
956
1010
|
});
|
|
957
|
-
const sessionId =
|
|
1011
|
+
const sessionId =
|
|
1012
|
+
passphraseSessionId || (featAfter?.success ? featAfter.payload?.session_id : undefined);
|
|
958
1013
|
if (sessionId) {
|
|
959
1014
|
await saveSessionToKeychain(deviceId, passphraseState, sessionId);
|
|
960
1015
|
await preloadSessionFromKeychain(deviceId);
|