@onekeyfe/hardware-cli 1.1.28 → 1.2.0-alpha.1

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 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')
@@ -33,8 +59,8 @@ program
33
59
  const features = await sdk.getFeatures(device.connectId);
34
60
  if (features?.success && features.payload) {
35
61
  device.features = features.payload;
36
- device.name = features.payload.label || features.payload.ble_name || device.name;
37
- const devType = features.payload.onekey_device_type?.toLowerCase();
62
+ device.name = features.payload.label || features.payload.bleName || device.name;
63
+ const devType = features.payload.deviceType?.toLowerCase();
38
64
  if (devType) {
39
65
  device.deviceType = devType;
40
66
  }
@@ -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",
@@ -559,8 +592,8 @@ sessionCmd
559
592
  skipPassphraseCheck: true,
560
593
  });
561
594
  const featPayload = featResult?.success ? featResult.payload : undefined;
562
- const deviceId = featPayload?.device_id || device.deviceId || '';
563
- const sessionId = featPayload?.session_id || '';
595
+ const deviceId = featPayload?.deviceId || device.deviceId || '';
596
+ const sessionId = passphraseSessionId || featPayload?.sessionId || '';
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?.features?.device_id || device?.deviceId;
618
+ const deviceId = device?.deviceId || device?.features?.device_id;
586
619
  if (deviceId) {
587
620
  await (0, session_1.clearSessionFromKeychain)(deviceId);
588
621
  }
@@ -690,16 +723,18 @@ globalOpts) {
690
723
  // ── Step 2: Get features if searchDevices didn't populate them ──
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
- let deviceId = device.features?.device_id || device.deviceId || '';
726
+ let deviceId = device.features?.deviceId || device.deviceId || '';
727
+ let deviceType = (0, hd_core_1.getDeviceType)(device.features);
694
728
  let unlocked = device.features?.unlocked;
695
- let passphraseProtection = device.features?.passphrase_protection;
729
+ let passphraseProtection = device.features?.passphraseProtection;
696
730
  if (!deviceId || unlocked == null || passphraseProtection == null) {
697
731
  try {
698
732
  const featResult = await sdk.getFeatures(connectId);
699
733
  if (featResult?.success && featResult.payload) {
700
- deviceId = featResult.payload.device_id || deviceId;
734
+ deviceId = featResult.payload.deviceId || deviceId;
735
+ deviceType = (0, hd_core_1.getDeviceType)(featResult.payload) || deviceType;
701
736
  unlocked = featResult.payload.unlocked;
702
- passphraseProtection = featResult.payload.passphrase_protection;
737
+ passphraseProtection = featResult.payload.passphraseProtection;
703
738
  }
704
739
  }
705
740
  catch {
@@ -715,15 +750,15 @@ globalOpts) {
715
750
  if (wasLocked) {
716
751
  process.stderr.write('[onekey-hw] Device is locked. Unlocking (PIN required)...\n');
717
752
  const { payload: feat } = await unlockWithRetry(sdk, connectId);
718
- deviceId = feat.device_id || deviceId;
753
+ deviceId = feat.deviceId || deviceId;
719
754
  unlocked = feat.unlocked;
720
- passphraseProtection = feat.passphrase_protection;
755
+ passphraseProtection = feat.passphraseProtection;
721
756
  }
722
757
  if (!globalOpts.deviceId && deviceId) {
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?.sessionId : 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
@@ -1,4 +1,5 @@
1
1
  module.exports = {
2
2
  preset: '../../jest.config.js',
3
3
  testEnvironment: 'node',
4
+ modulePathIgnorePatterns: ['node_modules', '<rootDir>/dist'],
4
5
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hardware-cli",
3
- "version": "1.1.28",
3
+ "version": "1.2.0-alpha.1",
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.1.28",
34
- "@onekeyfe/hd-core": "1.1.28",
35
- "@onekeyfe/hd-shared": "1.1.28",
36
- "@onekeyfe/hd-transport-usb": "1.1.28",
33
+ "@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.1",
34
+ "@onekeyfe/hd-core": "1.2.0-alpha.1",
35
+ "@onekeyfe/hd-shared": "1.2.0-alpha.1",
36
+ "@onekeyfe/hd-transport-usb": "1.2.0-alpha.1",
37
37
  "commander": "^12.0.0"
38
38
  },
39
- "gitHead": "9cfd4f7f00a2b7317325161d666a7b0173345995"
39
+ "gitHead": "4f4aae3a47be7bd54b4db4a10c400056784e01bd"
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
@@ -63,8 +100,8 @@ program
63
100
  const features = await sdk.getFeatures(device.connectId);
64
101
  if (features?.success && features.payload) {
65
102
  device.features = features.payload;
66
- device.name = features.payload.label || features.payload.ble_name || device.name;
67
- const devType = features.payload.onekey_device_type?.toLowerCase();
103
+ device.name = features.payload.label || features.payload.bleName || device.name;
104
+ const devType = features.payload.deviceType?.toLowerCase();
68
105
  if (devType) {
69
106
  device.deviceType = devType as IDeviceType;
70
107
  }
@@ -687,7 +724,16 @@ sessionCmd
687
724
  outputResult(globalOpts, psResult);
688
725
  return;
689
726
  }
690
- const passphraseState = psResult.payload;
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 || '', {
@@ -711,8 +757,8 @@ sessionCmd
711
757
  skipPassphraseCheck: true,
712
758
  });
713
759
  const featPayload = featResult?.success ? featResult.payload : undefined;
714
- const deviceId = featPayload?.device_id || device.deviceId || '';
715
- const sessionId = featPayload?.session_id || '';
760
+ const deviceId = featPayload?.deviceId || device.deviceId || '';
761
+ const sessionId = passphraseSessionId || featPayload?.sessionId || '';
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?.features?.device_id || device?.deviceId;
788
+ const deviceId = device?.deviceId || device?.features?.device_id;
743
789
  if (deviceId) {
744
790
  await clearSessionFromKeychain(deviceId);
745
791
  }
@@ -868,9 +914,10 @@ async function prepareSession(
868
914
  connectId?: string;
869
915
  deviceId?: string;
870
916
  features?: {
871
- device_id?: string;
872
- session_id?: string;
873
- passphrase_protection?: boolean | null;
917
+ deviceId?: string | null;
918
+ deviceType?: string;
919
+ sessionId?: string | null;
920
+ passphraseProtection?: boolean | null;
874
921
  unlocked?: boolean | null;
875
922
  };
876
923
  };
@@ -882,17 +929,19 @@ async function prepareSession(
882
929
  // ── Step 2: Get features if searchDevices didn't populate them ──
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
- let deviceId = device.features?.device_id || device.deviceId || '';
932
+ let deviceId = device.features?.deviceId || device.deviceId || '';
933
+ let deviceType = getDeviceType(device.features as Features | undefined);
886
934
  let unlocked = device.features?.unlocked;
887
- let passphraseProtection = device.features?.passphrase_protection;
935
+ let passphraseProtection = device.features?.passphraseProtection;
888
936
 
889
937
  if (!deviceId || unlocked == null || passphraseProtection == null) {
890
938
  try {
891
939
  const featResult = await sdk.getFeatures(connectId);
892
940
  if (featResult?.success && featResult.payload) {
893
- deviceId = featResult.payload.device_id || deviceId;
941
+ deviceId = featResult.payload.deviceId || deviceId;
942
+ deviceType = getDeviceType(featResult.payload) || deviceType;
894
943
  unlocked = featResult.payload.unlocked;
895
- passphraseProtection = featResult.payload.passphrase_protection;
944
+ passphraseProtection = featResult.payload.passphraseProtection;
896
945
  }
897
946
  } catch {
898
947
  /* non-fatal — Step 3 will surface a clear error if device is gone */
@@ -908,9 +957,9 @@ async function prepareSession(
908
957
  if (wasLocked) {
909
958
  process.stderr.write('[onekey-hw] Device is locked. Unlocking (PIN required)...\n');
910
959
  const { payload: feat } = await unlockWithRetry(sdk, connectId);
911
- deviceId = feat.device_id || deviceId;
960
+ deviceId = feat.deviceId || deviceId;
912
961
  unlocked = feat.unlocked;
913
- passphraseProtection = feat.passphrase_protection;
962
+ passphraseProtection = feat.passphraseProtection;
914
963
  }
915
964
 
916
965
  if (!globalOpts.deviceId && deviceId) {
@@ -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 = psResult.payload;
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 = featAfter?.success ? featAfter.payload?.session_id : undefined;
1011
+ const sessionId =
1012
+ passphraseSessionId || (featAfter?.success ? featAfter.payload?.sessionId : undefined);
958
1013
  if (sessionId) {
959
1014
  await saveSessionToKeychain(deviceId, passphraseState, sessionId);
960
1015
  await preloadSessionFromKeychain(deviceId);