@onekeyfe/hardware-cli 1.2.0-alpha.27 → 1.2.0-alpha.29
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.d.ts +2 -2
- package/dist/cli.js +6 -15
- package/dist/sdk.d.ts +2 -2
- package/dist/sdk.js +2 -2
- package/dist/session.d.ts +2 -9
- package/dist/session.js +3 -22
- package/package.json +6 -6
- package/src/__tests__/wallet-session.test.ts +2 -9
- package/src/cli.ts +7 -22
- package/src/sdk.ts +2 -2
- package/src/session.ts +2 -24
package/dist/cli.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ export declare function getLegacyFirmwareConnectTimeout(transport: 'usb' | 'ble'
|
|
|
5
5
|
* Prepare passphrase session before SDK calls.
|
|
6
6
|
*
|
|
7
7
|
* 1. If --use-empty-passphrase or --passphrase-state provided → use as-is
|
|
8
|
-
* 2. Try keychain → preloadSessionCache → use cached session
|
|
9
|
-
* 3. Keychain miss → openWalletSession (triggers 1/2/3 prompt)
|
|
8
|
+
* 2. Try a legacy keychain entry → preloadSessionCache → use cached session
|
|
9
|
+
* 3. Keychain miss → openWalletSession (triggers 1/2/3 prompt)
|
|
10
10
|
*
|
|
11
11
|
* After this, globalOpts.passphraseState is set and getCommonParams will include it.
|
|
12
12
|
*/
|
package/dist/cli.js
CHANGED
|
@@ -622,7 +622,7 @@ program
|
|
|
622
622
|
const sessionCmd = program.command('session').description('Manage device passphrase session cache');
|
|
623
623
|
sessionCmd
|
|
624
624
|
.command('connect')
|
|
625
|
-
.description('Connect device and
|
|
625
|
+
.description('Connect device and select a hidden wallet for this invocation')
|
|
626
626
|
.action(() => runCommand({}, async ({ sdk, globalOpts }) => {
|
|
627
627
|
// 1. Search for device
|
|
628
628
|
const searchResult = await sdk.searchDevices();
|
|
@@ -657,23 +657,18 @@ sessionCmd
|
|
|
657
657
|
});
|
|
658
658
|
return;
|
|
659
659
|
}
|
|
660
|
-
const { deviceId, passphraseState
|
|
660
|
+
const { deviceId, passphraseState } = sessionResult.payload;
|
|
661
661
|
// 4. Get address to verify + extract deviceId
|
|
662
662
|
const addrResult = await sdk.evmGetAddress(connectId, deviceId, {
|
|
663
663
|
path: "m/44'/60'/0'/0/0",
|
|
664
664
|
showOnOneKey: false,
|
|
665
665
|
passphraseState,
|
|
666
666
|
});
|
|
667
|
-
// 5. Persist only the session id returned by the explicit wallet-session API.
|
|
668
|
-
if (sessionId) {
|
|
669
|
-
await (0, session_1.saveSessionToKeychain)(deviceId, passphraseState, sessionId);
|
|
670
|
-
}
|
|
671
667
|
outputResult(globalOpts, {
|
|
672
668
|
success: true,
|
|
673
669
|
payload: {
|
|
674
670
|
passphraseState,
|
|
675
671
|
deviceId,
|
|
676
|
-
...(sessionId ? { sessionId } : {}),
|
|
677
672
|
...(addrResult?.success ? { address: addrResult.payload.address } : {}),
|
|
678
673
|
},
|
|
679
674
|
});
|
|
@@ -761,8 +756,8 @@ async function unlockWithRetry(sdk, connectId, maxAttempts = 3) {
|
|
|
761
756
|
* Prepare passphrase session before SDK calls.
|
|
762
757
|
*
|
|
763
758
|
* 1. If --use-empty-passphrase or --passphrase-state provided → use as-is
|
|
764
|
-
* 2. Try keychain → preloadSessionCache → use cached session
|
|
765
|
-
* 3. Keychain miss → openWalletSession (triggers 1/2/3 prompt)
|
|
759
|
+
* 2. Try a legacy keychain entry → preloadSessionCache → use cached session
|
|
760
|
+
* 3. Keychain miss → openWalletSession (triggers 1/2/3 prompt)
|
|
766
761
|
*
|
|
767
762
|
* After this, globalOpts.passphraseState is set and getCommonParams will include it.
|
|
768
763
|
*/
|
|
@@ -835,7 +830,7 @@ globalOpts) {
|
|
|
835
830
|
if (passphraseProtection === false && deviceType !== hd_shared_1.EDeviceType.Pro2) {
|
|
836
831
|
return undefined;
|
|
837
832
|
}
|
|
838
|
-
// ── Step 5: Try keychain session reuse
|
|
833
|
+
// ── Step 5: Try legacy keychain session reuse ────────────────────
|
|
839
834
|
// Only attempt if device was already unlocked — locking invalidates
|
|
840
835
|
// all passphrase sessions, so cached session_id is useless after unlock.
|
|
841
836
|
if (!wasLocked && deviceId) {
|
|
@@ -853,13 +848,9 @@ globalOpts) {
|
|
|
853
848
|
if (sessionResult.payload.walletType !== 'hidden') {
|
|
854
849
|
return undefined;
|
|
855
850
|
}
|
|
856
|
-
const { deviceId: sessionDeviceId, passphraseState
|
|
851
|
+
const { deviceId: sessionDeviceId, passphraseState } = sessionResult.payload;
|
|
857
852
|
globalOpts.deviceId = sessionDeviceId;
|
|
858
853
|
globalOpts.passphraseState = passphraseState;
|
|
859
|
-
if (sessionId) {
|
|
860
|
-
await (0, session_1.saveSessionToKeychain)(sessionDeviceId, passphraseState, sessionId);
|
|
861
|
-
await (0, session_1.preloadSessionFromKeychain)(sessionDeviceId);
|
|
862
|
-
}
|
|
863
854
|
return passphraseState;
|
|
864
855
|
}
|
|
865
856
|
return undefined;
|
package/dist/sdk.d.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Passphrase flow aligns with app-monorepo CLI:
|
|
6
6
|
* - Standard wallet: --use-empty-passphrase, auto-respond
|
|
7
7
|
* - Hidden wallet: interactive 1/2/3 selection (standard / pinentry / on-device)
|
|
8
|
-
* -
|
|
9
|
-
*
|
|
8
|
+
* - Legacy session caching: existing OS keychain entries may still be preloaded,
|
|
9
|
+
* but public SDK responses never expose new device session ids
|
|
10
10
|
*/
|
|
11
11
|
import HardwareSDK from '@onekeyfe/hd-common-connect-sdk';
|
|
12
12
|
export interface SDKOptions {
|
package/dist/sdk.js
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* Passphrase flow aligns with app-monorepo CLI:
|
|
7
7
|
* - Standard wallet: --use-empty-passphrase, auto-respond
|
|
8
8
|
* - Hidden wallet: interactive 1/2/3 selection (standard / pinentry / on-device)
|
|
9
|
-
* -
|
|
10
|
-
*
|
|
9
|
+
* - Legacy session caching: existing OS keychain entries may still be preloaded,
|
|
10
|
+
* but public SDK responses never expose new device session ids
|
|
11
11
|
*/
|
|
12
12
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
13
|
if (k2 === undefined) k2 = k;
|
package/dist/session.d.ts
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Passphrase session management for hd-cli.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* Command: keychain → preloadSessionCache → SDK call (no passphrase prompt)
|
|
7
|
-
* Stale: error 112 → clear keychain → re-prompt → retry
|
|
8
|
-
* Logout: keychain delete
|
|
4
|
+
* Existing keychain entries remain readable for compatibility, but the public
|
|
5
|
+
* SDK no longer exposes new device session ids for persistence.
|
|
9
6
|
*/
|
|
10
7
|
/**
|
|
11
8
|
* Load passphraseState + sessionId from keychain and call preloadSessionCache.
|
|
12
9
|
* Non-fatal: returns the loaded passphraseState or undefined.
|
|
13
10
|
*/
|
|
14
11
|
export declare function preloadSessionFromKeychain(deviceId: string): Promise<string | undefined>;
|
|
15
|
-
/**
|
|
16
|
-
* Save passphraseState + sessionId to keychain for next CLI invocation.
|
|
17
|
-
*/
|
|
18
|
-
export declare function saveSessionToKeychain(deviceId: string, passphraseState: string, sessionId: string): Promise<void>;
|
|
19
12
|
/**
|
|
20
13
|
* Clear cached session from keychain.
|
|
21
14
|
*/
|
package/dist/session.js
CHANGED
|
@@ -2,14 +2,11 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Passphrase session management for hd-cli.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Command: keychain → preloadSessionCache → SDK call (no passphrase prompt)
|
|
8
|
-
* Stale: error 112 → clear keychain → re-prompt → retry
|
|
9
|
-
* Logout: keychain delete
|
|
5
|
+
* Existing keychain entries remain readable for compatibility, but the public
|
|
6
|
+
* SDK no longer exposes new device session ids for persistence.
|
|
10
7
|
*/
|
|
11
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.clearSessionFromKeychain = exports.
|
|
9
|
+
exports.clearSessionFromKeychain = exports.preloadSessionFromKeychain = void 0;
|
|
13
10
|
const hd_core_1 = require("@onekeyfe/hd-core");
|
|
14
11
|
const storage_1 = require("./storage");
|
|
15
12
|
// Keychain key format: scoped by deviceId for multi-device support
|
|
@@ -50,22 +47,6 @@ async function preloadSessionFromKeychain(deviceId) {
|
|
|
50
47
|
return undefined;
|
|
51
48
|
}
|
|
52
49
|
exports.preloadSessionFromKeychain = preloadSessionFromKeychain;
|
|
53
|
-
/**
|
|
54
|
-
* Save passphraseState + sessionId to keychain for next CLI invocation.
|
|
55
|
-
*/
|
|
56
|
-
async function saveSessionToKeychain(deviceId, passphraseState, sessionId) {
|
|
57
|
-
try {
|
|
58
|
-
const storage = getStorage();
|
|
59
|
-
await Promise.all([
|
|
60
|
-
storage.set(psKey(deviceId), Buffer.from(passphraseState, 'utf-8')),
|
|
61
|
-
storage.set(sidKey(deviceId), Buffer.from(sessionId, 'utf-8')),
|
|
62
|
-
]);
|
|
63
|
-
}
|
|
64
|
-
catch {
|
|
65
|
-
// Non-fatal — session still works in-memory for this invocation
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
exports.saveSessionToKeychain = saveSessionToKeychain;
|
|
69
50
|
/**
|
|
70
51
|
* Clear cached session from keychain.
|
|
71
52
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hardware-cli",
|
|
3
|
-
"version": "1.2.0-alpha.
|
|
3
|
+
"version": "1.2.0-alpha.29",
|
|
4
4
|
"description": "OneKey hardware wallet CLI for testing device communication",
|
|
5
5
|
"author": "OneKey",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"test": "jest"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.
|
|
35
|
-
"@onekeyfe/hd-core": "1.2.0-alpha.
|
|
36
|
-
"@onekeyfe/hd-shared": "1.2.0-alpha.
|
|
37
|
-
"@onekeyfe/hd-transport-usb": "1.2.0-alpha.
|
|
34
|
+
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.29",
|
|
35
|
+
"@onekeyfe/hd-core": "1.2.0-alpha.29",
|
|
36
|
+
"@onekeyfe/hd-shared": "1.2.0-alpha.29",
|
|
37
|
+
"@onekeyfe/hd-transport-usb": "1.2.0-alpha.29",
|
|
38
38
|
"@stoprocent/noble": "2.3.16",
|
|
39
39
|
"commander": "^12.0.0"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "4a4019e439cc472f89fd15ab47e84ef0ed43166a"
|
|
42
42
|
}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { prepareSession } from '../cli';
|
|
2
|
-
import { preloadSessionFromKeychain
|
|
2
|
+
import { preloadSessionFromKeychain } from '../session';
|
|
3
3
|
|
|
4
4
|
jest.mock('../session', () => ({
|
|
5
5
|
clearSessionFromKeychain: jest.fn(),
|
|
6
6
|
preloadSessionFromKeychain: jest.fn(),
|
|
7
|
-
saveSessionToKeychain: jest.fn(),
|
|
8
7
|
}));
|
|
9
8
|
|
|
10
9
|
describe('CLI wallet session', () => {
|
|
11
|
-
test('
|
|
10
|
+
test('uses the public wallet identity without persisting an internal session id', async () => {
|
|
12
11
|
const sdk = {
|
|
13
12
|
searchDevices: jest.fn().mockResolvedValue({
|
|
14
13
|
success: true,
|
|
@@ -34,7 +33,6 @@ describe('CLI wallet session', () => {
|
|
|
34
33
|
walletType: 'hidden',
|
|
35
34
|
deviceId: 'device-id',
|
|
36
35
|
passphraseState: 'wallet-state',
|
|
37
|
-
sessionId: 'wallet-session-id',
|
|
38
36
|
resumed: false,
|
|
39
37
|
},
|
|
40
38
|
}),
|
|
@@ -48,11 +46,6 @@ describe('CLI wallet session', () => {
|
|
|
48
46
|
mode: 'select-hidden',
|
|
49
47
|
});
|
|
50
48
|
expect(sdk.getFeatures).not.toHaveBeenCalled();
|
|
51
|
-
expect(saveSessionToKeychain).toHaveBeenCalledWith(
|
|
52
|
-
'device-id',
|
|
53
|
-
'wallet-state',
|
|
54
|
-
'wallet-session-id'
|
|
55
|
-
);
|
|
56
49
|
expect(globalOpts).toMatchObject({
|
|
57
50
|
connectId: 'pro2-connect-id',
|
|
58
51
|
deviceId: 'device-id',
|
package/src/cli.ts
CHANGED
|
@@ -14,11 +14,7 @@ import {
|
|
|
14
14
|
import { selectSearchDevice } from './deviceSelection';
|
|
15
15
|
import { getCanonicalDeviceState, getCompatibleFeatures } from './deviceStateCommands';
|
|
16
16
|
import { createSDK, disposeSDK } from './sdk';
|
|
17
|
-
import {
|
|
18
|
-
clearSessionFromKeychain,
|
|
19
|
-
preloadSessionFromKeychain,
|
|
20
|
-
saveSessionToKeychain,
|
|
21
|
-
} from './session';
|
|
17
|
+
import { clearSessionFromKeychain, preloadSessionFromKeychain } from './session';
|
|
22
18
|
|
|
23
19
|
import type {
|
|
24
20
|
DeviceStateScope,
|
|
@@ -800,7 +796,7 @@ const sessionCmd = program.command('session').description('Manage device passphr
|
|
|
800
796
|
|
|
801
797
|
sessionCmd
|
|
802
798
|
.command('connect')
|
|
803
|
-
.description('Connect device and
|
|
799
|
+
.description('Connect device and select a hidden wallet for this invocation')
|
|
804
800
|
.action(() =>
|
|
805
801
|
runCommand({}, async ({ sdk, globalOpts }) => {
|
|
806
802
|
// 1. Search for device
|
|
@@ -838,7 +834,7 @@ sessionCmd
|
|
|
838
834
|
});
|
|
839
835
|
return;
|
|
840
836
|
}
|
|
841
|
-
const { deviceId, passphraseState
|
|
837
|
+
const { deviceId, passphraseState } = sessionResult.payload;
|
|
842
838
|
|
|
843
839
|
// 4. Get address to verify + extract deviceId
|
|
844
840
|
const addrResult = await sdk.evmGetAddress(connectId, deviceId, {
|
|
@@ -847,17 +843,11 @@ sessionCmd
|
|
|
847
843
|
passphraseState,
|
|
848
844
|
});
|
|
849
845
|
|
|
850
|
-
// 5. Persist only the session id returned by the explicit wallet-session API.
|
|
851
|
-
if (sessionId) {
|
|
852
|
-
await saveSessionToKeychain(deviceId, passphraseState, sessionId);
|
|
853
|
-
}
|
|
854
|
-
|
|
855
846
|
outputResult(globalOpts, {
|
|
856
847
|
success: true,
|
|
857
848
|
payload: {
|
|
858
849
|
passphraseState,
|
|
859
850
|
deviceId,
|
|
860
|
-
...(sessionId ? { sessionId } : {}),
|
|
861
851
|
...(addrResult?.success ? { address: addrResult.payload.address } : {}),
|
|
862
852
|
},
|
|
863
853
|
});
|
|
@@ -966,8 +956,8 @@ async function unlockWithRetry(
|
|
|
966
956
|
* Prepare passphrase session before SDK calls.
|
|
967
957
|
*
|
|
968
958
|
* 1. If --use-empty-passphrase or --passphrase-state provided → use as-is
|
|
969
|
-
* 2. Try keychain → preloadSessionCache → use cached session
|
|
970
|
-
* 3. Keychain miss → openWalletSession (triggers 1/2/3 prompt)
|
|
959
|
+
* 2. Try a legacy keychain entry → preloadSessionCache → use cached session
|
|
960
|
+
* 3. Keychain miss → openWalletSession (triggers 1/2/3 prompt)
|
|
971
961
|
*
|
|
972
962
|
* After this, globalOpts.passphraseState is set and getCommonParams will include it.
|
|
973
963
|
*/
|
|
@@ -1080,7 +1070,7 @@ export async function prepareSession(
|
|
|
1080
1070
|
return undefined;
|
|
1081
1071
|
}
|
|
1082
1072
|
|
|
1083
|
-
// ── Step 5: Try keychain session reuse
|
|
1073
|
+
// ── Step 5: Try legacy keychain session reuse ────────────────────
|
|
1084
1074
|
// Only attempt if device was already unlocked — locking invalidates
|
|
1085
1075
|
// all passphrase sessions, so cached session_id is useless after unlock.
|
|
1086
1076
|
if (!wasLocked && deviceId) {
|
|
@@ -1100,15 +1090,10 @@ export async function prepareSession(
|
|
|
1100
1090
|
if (sessionResult.payload.walletType !== 'hidden') {
|
|
1101
1091
|
return undefined;
|
|
1102
1092
|
}
|
|
1103
|
-
const { deviceId: sessionDeviceId, passphraseState
|
|
1093
|
+
const { deviceId: sessionDeviceId, passphraseState } = sessionResult.payload;
|
|
1104
1094
|
globalOpts.deviceId = sessionDeviceId;
|
|
1105
1095
|
globalOpts.passphraseState = passphraseState;
|
|
1106
1096
|
|
|
1107
|
-
if (sessionId) {
|
|
1108
|
-
await saveSessionToKeychain(sessionDeviceId, passphraseState, sessionId);
|
|
1109
|
-
await preloadSessionFromKeychain(sessionDeviceId);
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
1097
|
return passphraseState;
|
|
1113
1098
|
}
|
|
1114
1099
|
return undefined;
|
package/src/sdk.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Passphrase flow aligns with app-monorepo CLI:
|
|
6
6
|
* - Standard wallet: --use-empty-passphrase, auto-respond
|
|
7
7
|
* - Hidden wallet: interactive 1/2/3 selection (standard / pinentry / on-device)
|
|
8
|
-
* -
|
|
9
|
-
*
|
|
8
|
+
* - Legacy session caching: existing OS keychain entries may still be preloaded,
|
|
9
|
+
* but public SDK responses never expose new device session ids
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import * as readline from 'node:readline';
|
package/src/session.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Passphrase session management for hd-cli.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* Command: keychain → preloadSessionCache → SDK call (no passphrase prompt)
|
|
7
|
-
* Stale: error 112 → clear keychain → re-prompt → retry
|
|
8
|
-
* Logout: keychain delete
|
|
4
|
+
* Existing keychain entries remain readable for compatibility, but the public
|
|
5
|
+
* SDK no longer exposes new device session ids for persistence.
|
|
9
6
|
*/
|
|
10
7
|
|
|
11
8
|
import { preloadSessionCache } from '@onekeyfe/hd-core';
|
|
@@ -55,25 +52,6 @@ export async function preloadSessionFromKeychain(deviceId: string): Promise<stri
|
|
|
55
52
|
return undefined;
|
|
56
53
|
}
|
|
57
54
|
|
|
58
|
-
/**
|
|
59
|
-
* Save passphraseState + sessionId to keychain for next CLI invocation.
|
|
60
|
-
*/
|
|
61
|
-
export async function saveSessionToKeychain(
|
|
62
|
-
deviceId: string,
|
|
63
|
-
passphraseState: string,
|
|
64
|
-
sessionId: string
|
|
65
|
-
): Promise<void> {
|
|
66
|
-
try {
|
|
67
|
-
const storage = getStorage();
|
|
68
|
-
await Promise.all([
|
|
69
|
-
storage.set(psKey(deviceId), Buffer.from(passphraseState, 'utf-8')),
|
|
70
|
-
storage.set(sidKey(deviceId), Buffer.from(sessionId, 'utf-8')),
|
|
71
|
-
]);
|
|
72
|
-
} catch {
|
|
73
|
-
// Non-fatal — session still works in-memory for this invocation
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
55
|
/**
|
|
78
56
|
* Clear cached session from keychain.
|
|
79
57
|
*/
|