@onekeyfe/hardware-cli 1.1.25-alpha.0 → 1.1.25-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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "onekey-hardware",
3
3
  "description": "OneKey hardware wallet CLI skills for Claude Code — device management, multi-chain signing, firmware updates",
4
- "version": "0.1.0",
4
+ "version": "1.1.25-alpha.1",
5
5
  "author": {
6
6
  "name": "OneKey",
7
7
  "email": "dev@onekey.so"
package/AGENTS.md ADDED
@@ -0,0 +1,40 @@
1
+ # OneKey Hardware Wallet — CLI Agent Skills
2
+
3
+ When working with the `onekey-hw` CLI, read the skill files before running commands.
4
+ Do NOT guess parameters or explore via `--help` — the skills document exact
5
+ command signatures, workflows, and security rules.
6
+
7
+ ## Skills
8
+
9
+ | Skill | Path | Use When |
10
+ |---|---|---|
11
+ | **Device** | `skills/device/SKILL.md` | Search devices (with features), lock, verify, wipe |
12
+ | **Signing** | `skills/signing/SKILL.md` | Get addresses, sign transactions/messages (27 chains) |
13
+ | **Firmware** | `skills/firmware/SKILL.md` | Check firmware versions (updates via OneKey App only) |
14
+ | **Security** | `skills/security/SKILL.md` | PIN, passphrase, device settings, factory reset |
15
+
16
+ ## Quick Start
17
+
18
+ ```bash
19
+ # Install globally
20
+ npm install -g @onekeyfe/hardware-cli
21
+
22
+ # Search for connected devices (auto-fetches device info)
23
+ onekey-hw search
24
+
25
+ # Get an Ethereum address
26
+ onekey-hw get-address --chain evm --use-empty-passphrase
27
+
28
+ # Sign a message
29
+ onekey-hw sign-message --chain evm --message "hello" --use-empty-passphrase
30
+ ```
31
+
32
+ ## Important
33
+
34
+ - All signing operations require **physical confirmation** on the hardware device
35
+ - Commands block while waiting for device interaction (PIN, button press)
36
+ - All output is structured JSON
37
+ - Uses direct USB (libusb) — no external daemon needed
38
+
39
+ Each skill file includes pre-flight checks, security rules, and parameter
40
+ conventions. Read the relevant skill for your task.
package/CLAUDE.md ADDED
@@ -0,0 +1,40 @@
1
+ # OneKey Hardware Wallet — CLI Agent Skills
2
+
3
+ When working with the `onekey-hw` CLI, read the skill files before running commands.
4
+ Do NOT guess parameters or explore via `--help` — the skills document exact
5
+ command signatures, workflows, and security rules.
6
+
7
+ ## Skills
8
+
9
+ | Skill | Path | Use When |
10
+ |---|---|---|
11
+ | **Device** | `skills/device/SKILL.md` | Search devices (with features), lock, verify, wipe |
12
+ | **Signing** | `skills/signing/SKILL.md` | Get addresses, sign transactions/messages (27 chains) |
13
+ | **Firmware** | `skills/firmware/SKILL.md` | Check firmware versions (updates via OneKey App only) |
14
+ | **Security** | `skills/security/SKILL.md` | PIN, passphrase, device settings, factory reset |
15
+
16
+ ## Quick Start
17
+
18
+ ```bash
19
+ # Install globally
20
+ npm install -g @onekeyfe/hardware-cli
21
+
22
+ # Search for connected devices (auto-fetches device info)
23
+ onekey-hw search
24
+
25
+ # Get an Ethereum address
26
+ onekey-hw get-address --chain evm --use-empty-passphrase
27
+
28
+ # Sign a message
29
+ onekey-hw sign-message --chain evm --message "hello" --use-empty-passphrase
30
+ ```
31
+
32
+ ## Important
33
+
34
+ - All signing operations require **physical confirmation** on the hardware device
35
+ - Commands block while waiting for device interaction (PIN, button press)
36
+ - All output is structured JSON
37
+ - Uses direct USB (libusb) — no external daemon needed
38
+
39
+ Each skill file includes pre-flight checks, security rules, and parameter
40
+ conventions. Read the relevant skill for your task.
package/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # @onekeyfe/hardware-cli
2
+
3
+ OneKey hardware wallet CLI for AI agent integration. Enables Claude Code and other AI agents to interact with OneKey hardware wallets — search devices, get addresses, sign transactions, manage firmware and security.
4
+
5
+ ## Install
6
+
7
+ ### Claude Code
8
+
9
+ ```bash
10
+ claude plugin marketplace add OneKeyHQ/hardware-js-sdk --sparse .claude-plugin packages/hd-cli
11
+ claude plugin install onekey-hardware@onekey-hardware-plugins
12
+ ```
13
+
14
+ The CLI is installed automatically on first use via the skill's pre-flight check.
15
+
16
+ ### Other AI Tools (Codex, Gemini, Cursor)
17
+
18
+ ```bash
19
+ npm install -g @onekeyfe/hardware-cli
20
+ ```
21
+
22
+ ### Development / Testing
23
+
24
+ ```bash
25
+ claude --plugin-dir /path/to/hardware-js-sdk/packages/hd-cli
26
+ ```
27
+
28
+ ## Commands
29
+
30
+ ### Device
31
+
32
+ | Command | Description | Needs PIN? |
33
+ |---------|-------------|:----------:|
34
+ | `onekey-hw search` | Search devices + auto-fetch features | No |
35
+ | `onekey-hw lock` | Lock the device | No |
36
+ | `onekey-hw device-verify` | Verify device is genuine | Yes |
37
+ | `onekey-hw device-settings` | Update label, language, etc. | Yes |
38
+ | `onekey-hw device-wipe` | Factory reset (IRREVERSIBLE) | Yes |
39
+
40
+ ### Address & Signing
41
+
42
+ | Command | Description | Needs PIN? |
43
+ |---------|-------------|:----------:|
44
+ | `onekey-hw get-address --chain <chain>` | Get address (27 chains) | Yes |
45
+ | `onekey-hw get-public-key --chain <chain>` | Get public key | Yes |
46
+ | `onekey-hw batch-get-address --bundle <json>` | Multi-chain batch | Yes |
47
+ | `onekey-hw sign-transaction --chain <chain> --tx <json>` | Sign transaction | Yes |
48
+ | `onekey-hw sign-message --chain <chain> --message <msg>` | Sign message | Yes |
49
+ | `onekey-hw sign-typed-data --data <json>` | Sign EIP-712 (EVM) | Yes |
50
+ | `onekey-hw sign-psbt --psbt <hex>` | Sign Bitcoin PSBT | Yes |
51
+ | `onekey-hw verify-message --chain <chain> ...` | Verify signed message | Yes |
52
+
53
+ ### Chain-Specific
54
+
55
+ | Command | Description |
56
+ |---------|-------------|
57
+ | `onekey-hw evm-sign-eip712` | EIP-712 by hash |
58
+ | `onekey-hw sol-sign-offchain` | Solana off-chain message |
59
+ | `onekey-hw nostr-encrypt` | Nostr NIP-04 encrypt |
60
+ | `onekey-hw nostr-decrypt` | Nostr NIP-04 decrypt |
61
+ | `onekey-hw nostr-sign-schnorr` | Nostr Schnorr signature |
62
+ | `onekey-hw lnurl-auth` | Lightning LNURL auth |
63
+ | `onekey-hw conflux-sign-cip23` | Conflux CIP-23 message |
64
+ | `onekey-hw aptos-sign-in` | Aptos sign-in |
65
+ | `onekey-hw ton-sign-proof` | TON Connect proof |
66
+
67
+ ### Firmware (Read-Only)
68
+
69
+ | Command | Description |
70
+ |---------|-------------|
71
+ | `onekey-hw firmware-check` | Check firmware updates |
72
+ | `onekey-hw firmware-check-all` | Check all components |
73
+ | `onekey-hw bootloader-check` | Check bootloader |
74
+
75
+ Firmware updates must be done via the [OneKey App](https://onekey.so/download) or [firmware.onekey.so](https://firmware.onekey.so/).
76
+
77
+ ### Security
78
+
79
+ | Command | Description |
80
+ |---------|-------------|
81
+ | `onekey-hw change-pin` | Change/set PIN |
82
+ | `onekey-hw passphrase-state` | Get passphrase state |
83
+ | `onekey-hw toggle-passphrase --enable <bool>` | Enable/disable passphrase |
84
+
85
+ ## Supported Chains
86
+
87
+ | Chain | `--chain` | Address | Sign TX | Sign Message |
88
+ |-------|-----------|:-------:|:-------:|:------------:|
89
+ | Ethereum / EVM | `evm` | ✅ | ✅ | ✅ |
90
+ | Bitcoin | `btc` | ✅ | ✅ | ✅ |
91
+ | Solana | `sol` | ✅ | ✅ | ✅ |
92
+ | Cosmos | `cosmos` | ✅ | ✅ | — |
93
+ | Cardano | `cardano` | ✅ | ✅ | ✅ |
94
+ | Polkadot | `polkadot` | ✅ | ✅ | — |
95
+ | Tron | `tron` | ✅ | ✅ | ✅ |
96
+ | Aptos | `aptos` | ✅ | ✅ | ✅ |
97
+ | Sui | `sui` | ✅ | ✅ | ✅ |
98
+ | Near | `near` | ✅ | ✅ | — |
99
+ | XRP | `xrp` | ✅ | ✅ | — |
100
+ | Stellar | `stellar` | ✅ | ✅ | — |
101
+ | TON | `ton` | ✅ | — | ✅ |
102
+ | Nostr | `nostr` | ✅ | — | ✅ |
103
+ | +13 more | | ✅ | ✅ | varies |
104
+
105
+ ## Transport
106
+
107
+ Uses `libusb` for direct USB communication. No external daemon needed.
108
+ Works on macOS, Linux, and Windows.
109
+
110
+ ## License
111
+
112
+ Apache-2.0
package/dist/cli.js CHANGED
@@ -9,11 +9,10 @@ const program = new commander_1.Command();
9
9
  program
10
10
  .name('onekey-hw')
11
11
  .description('OneKey hardware wallet CLI for AI agent integration')
12
- .version('1.1.25-alpha.0');
12
+ .version('1.1.25-alpha.1');
13
13
  // ============================================================
14
14
  // Global Options
15
15
  // ============================================================
16
- program.option('--json', 'Output in JSON format (for agent consumption)');
17
16
  program.option('--connect-id <id>', 'Device connection ID (USB: serial, iOS: uuid, Android: MAC)');
18
17
  program.option('--device-id <id>', 'Persistent device ID from getFeatures (changes when seed changes)');
19
18
  program.option('--passphrase-state <state>', 'Passphrase state for hidden wallet access');
@@ -24,25 +23,30 @@ program.option('--use-empty-passphrase', 'Use standard wallet (skip passphrase p
24
23
  program
25
24
  .command('search')
26
25
  .description('Search for connected OneKey hardware wallet devices')
27
- .option('--timeout <ms>', 'Search timeout in milliseconds', '10000')
28
- .action(async (opts) => {
29
- const sdk = await (0, sdk_1.createSDK)(program.opts());
30
- try {
31
- const result = await sdk.searchDevices();
32
- outputResult(program.opts(), result);
33
- }
34
- finally {
35
- sdk.dispose();
36
- }
37
- });
38
- program
39
- .command('status')
40
- .description('Get device features and current status')
41
26
  .action(async () => {
42
27
  const globalOpts = program.opts();
43
28
  const sdk = await (0, sdk_1.createSDK)(globalOpts);
44
29
  try {
45
- const result = await sdk.getFeatures(globalOpts.connectId);
30
+ const result = await sdk.searchDevices();
31
+ // Auto-fetch features for each discovered device (doesn't require PIN)
32
+ if (result?.success && Array.isArray(result.payload)) {
33
+ for (const device of result.payload) {
34
+ if (device.connectId) {
35
+ try {
36
+ const features = await sdk.getFeatures(device.connectId);
37
+ if (features?.success && features.payload) {
38
+ device.features = features.payload;
39
+ device.name = features.payload.label || features.payload.ble_name || device.name;
40
+ device.deviceType =
41
+ features.payload.onekey_device_type?.toLowerCase() || device.deviceType;
42
+ }
43
+ }
44
+ catch {
45
+ // Features fetch failed — device may need PIN, continue with basic info
46
+ }
47
+ }
48
+ }
49
+ }
46
50
  outputResult(globalOpts, result);
47
51
  }
48
52
  finally {
@@ -487,51 +491,27 @@ program
487
491
  });
488
492
  program
489
493
  .command('firmware-update')
490
- .description('Update device firmware')
491
- .option('--version <ver>', 'Target firmware version (e.g., "4.8.0")')
492
- .option('--platform <platform>', 'Platform: native | desktop | ext | web', 'desktop')
493
- .action(async (opts) => {
494
- const globalOpts = program.opts();
495
- const sdk = await (0, sdk_1.createSDK)(globalOpts);
496
- try {
497
- // firmwareUpdateV2 requires: connectId, deviceId, { updateType, platform, version? }
498
- const params = {
499
- updateType: 'firmware',
500
- platform: opts.platform,
501
- };
502
- if (opts.version) {
503
- params.version = parseVersion(opts.version);
504
- }
505
- // firmwareUpdateV2 signature: (connectId, params) — 2 args only
506
- const result = await sdk.firmwareUpdateV2(globalOpts.connectId, params);
507
- outputResult(globalOpts, result);
508
- }
509
- finally {
510
- sdk.dispose();
511
- }
494
+ .description('Firmware update is not supported via CLI')
495
+ .action(() => {
496
+ outputResult(program.opts(), {
497
+ success: false,
498
+ payload: {
499
+ error: 'Firmware update via CLI is not supported. Please use the OneKey App or https://firmware.onekey.so/ to update firmware.',
500
+ code: 'FIRMWARE_UPDATE_NOT_SUPPORTED',
501
+ },
502
+ });
512
503
  });
513
504
  program
514
505
  .command('firmware-update-ble')
515
- .description('Update BLE (Bluetooth) firmware')
516
- .option('--version <ver>', 'Target BLE firmware version')
517
- .option('--platform <platform>', 'Platform: native | desktop | ext | web', 'desktop')
518
- .action(async (opts) => {
519
- const globalOpts = program.opts();
520
- const sdk = await (0, sdk_1.createSDK)(globalOpts);
521
- try {
522
- const params = {
523
- updateType: 'ble',
524
- platform: opts.platform,
525
- };
526
- if (opts.version) {
527
- params.version = parseVersion(opts.version);
528
- }
529
- const result = await sdk.firmwareUpdateV2(globalOpts.connectId, params);
530
- outputResult(globalOpts, result);
531
- }
532
- finally {
533
- sdk.dispose();
534
- }
506
+ .description('BLE firmware update is not supported via CLI')
507
+ .action(() => {
508
+ outputResult(program.opts(), {
509
+ success: false,
510
+ payload: {
511
+ error: 'BLE firmware update via CLI is not supported. Please use the OneKey App or https://firmware.onekey.so/ to update firmware.',
512
+ code: 'FIRMWARE_UPDATE_NOT_SUPPORTED',
513
+ },
514
+ });
535
515
  });
536
516
  program
537
517
  .command('bootloader-check')
@@ -600,66 +580,6 @@ program
600
580
  sdk.dispose();
601
581
  }
602
582
  });
603
- program
604
- .command('device-backup')
605
- .description('Trigger recovery phrase backup on device')
606
- .action(async () => {
607
- const globalOpts = program.opts();
608
- const sdk = await (0, sdk_1.createSDK)(globalOpts);
609
- try {
610
- const result = await sdk.deviceBackup(globalOpts.connectId);
611
- outputResult(globalOpts, result);
612
- }
613
- finally {
614
- sdk.dispose();
615
- }
616
- });
617
- program
618
- .command('device-recovery')
619
- .description('Recover wallet from recovery phrase (entered on device)')
620
- .option('--word-count <count>', 'Recovery phrase length: 12, 18, or 24', '24')
621
- .option('--passphrase-protection <bool>', 'Enable passphrase after recovery', 'false')
622
- .option('--pin-protection <bool>', 'Set PIN after recovery', 'true')
623
- .option('--label <name>', 'Device label')
624
- .action(async (opts) => {
625
- const globalOpts = program.opts();
626
- const sdk = await (0, sdk_1.createSDK)(globalOpts);
627
- try {
628
- const result = await sdk.deviceRecovery(globalOpts.connectId, {
629
- wordCount: safeParseInt(opts.wordCount, '--word-count'),
630
- passphraseProtection: opts.passphraseProtection === 'true',
631
- pinProtection: opts.pinProtection === 'true',
632
- label: opts.label,
633
- });
634
- outputResult(globalOpts, result);
635
- }
636
- finally {
637
- sdk.dispose();
638
- }
639
- });
640
- program
641
- .command('device-reset')
642
- .description('Initialize device with a new wallet seed (DESTROYS current wallet)')
643
- .option('--word-count <count>', 'Seed phrase length: 12, 18, or 24', '24')
644
- .option('--passphrase-protection <bool>', 'Enable passphrase', 'false')
645
- .option('--pin-protection <bool>', 'Set PIN', 'true')
646
- .option('--label <name>', 'Device label')
647
- .action(async (opts) => {
648
- const globalOpts = program.opts();
649
- const sdk = await (0, sdk_1.createSDK)(globalOpts);
650
- try {
651
- const result = await sdk.deviceReset(globalOpts.connectId, {
652
- strength: wordCountToStrength(safeParseInt(opts.wordCount, '--word-count')),
653
- passphraseProtection: opts.passphraseProtection === 'true',
654
- pinProtection: opts.pinProtection === 'true',
655
- label: opts.label,
656
- });
657
- outputResult(globalOpts, result);
658
- }
659
- finally {
660
- sdk.dispose();
661
- }
662
- });
663
583
  program
664
584
  .command('device-wipe')
665
585
  .description('Factory reset — erase ALL data (IRREVERSIBLE)')
@@ -760,27 +680,15 @@ function getCommonParams(globalOpts) {
760
680
  useEmptyPassphrase: globalOpts.useEmptyPassphrase,
761
681
  };
762
682
  }
763
- function outputResult(globalOpts, result) {
683
+ function outputResult(_globalOpts, result) {
764
684
  // #10 FIX: Always use JSON.stringify to avoid [Object] truncation
765
685
  console.log(JSON.stringify(result, null, 2));
766
- // #11 FIX: Exit with code 1 on SDK failure
686
+ // Exit after output SDK event listeners keep the process alive otherwise
767
687
  if (result && typeof result === 'object' && 'success' in result && !result.success) {
768
- process.exitCode = 1;
688
+ process.exit(1);
769
689
  }
770
- }
771
- function wordCountToStrength(wordCount) {
772
- // #8 FIX: Validate word count is one of the allowed values
773
- if (![12, 18, 24].includes(wordCount)) {
774
- throw new Error(`Invalid word count: ${wordCount}. Must be 12, 18, or 24.`);
775
- }
776
- switch (wordCount) {
777
- case 12:
778
- return 128;
779
- case 18:
780
- return 192;
781
- case 24:
782
- default:
783
- return 256;
690
+ else {
691
+ process.exit(0);
784
692
  }
785
693
  }
786
694
  /**
@@ -811,14 +719,4 @@ function safeParseInt(input, label) {
811
719
  }
812
720
  return num;
813
721
  }
814
- /**
815
- * #15 FIX: Validate firmware version format
816
- */
817
- function parseVersion(input) {
818
- const parts = input.split('.').map(Number);
819
- if (parts.length < 2 || parts.length > 4 || parts.some(Number.isNaN)) {
820
- throw new Error(`Invalid version format: "${input}". Expected format: "4.8.0"`);
821
- }
822
- return parts;
823
- }
824
722
  program.parse();
package/dist/index.d.ts CHANGED
@@ -11,7 +11,6 @@ import { CoreApi } from '@onekeyfe/hd-core';
11
11
  * Reference: packages/core/src/core/index.ts (event registration pattern)
12
12
  */
13
13
  interface SDKOptions {
14
- json?: boolean;
15
14
  connectId?: string;
16
15
  passphraseState?: string;
17
16
  useEmptyPassphrase?: boolean;
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@
12
12
  * npx @onekeyfe/hardware-cli get-address --chain evm
13
13
  * npx @onekeyfe/hardware-cli sign-transaction --chain evm --tx '{...}'
14
14
  *
15
- * For AI agent integration, use --json flag for structured output.
15
+ * All output is structured JSON for AI agent consumption.
16
16
  *
17
17
  * IMPORTANT: All signing operations require physical confirmation on the
18
18
  * hardware device. The CLI handles PIN/Passphrase prompts via stdin for
package/dist/sdk.d.ts CHANGED
@@ -8,7 +8,6 @@
8
8
  * Reference: packages/core/src/core/index.ts (event registration pattern)
9
9
  */
10
10
  export interface SDKOptions {
11
- json?: boolean;
12
11
  connectId?: string;
13
12
  passphraseState?: string;
14
13
  useEmptyPassphrase?: boolean;
package/dist/sdk.js CHANGED
@@ -159,15 +159,17 @@ function registerEventHandlers(sdk, opts) {
159
159
  process.stderr.write('[onekey-hw] Please confirm the action on your device...\n');
160
160
  }
161
161
  });
162
- // Device connection events
162
+ // Device connection events — only show when device has a known name
163
163
  sdk.on(hd_core_1.DEVICE.CONNECT, (device) => {
164
- if (!opts.json) {
165
- process.stderr.write(`[onekey-hw] Device connected: ${device?.name || 'Unknown'}\n`);
164
+ const name = device?.label || device?.name;
165
+ if (name) {
166
+ process.stderr.write(`[onekey-hw] Device connected: ${name}\n`);
166
167
  }
167
168
  });
168
169
  sdk.on(hd_core_1.DEVICE.DISCONNECT, (device) => {
169
- if (!opts.json) {
170
- process.stderr.write(`[onekey-hw] Device disconnected: ${device?.name || 'Unknown'}\n`);
170
+ const name = device?.label || device?.name;
171
+ if (name) {
172
+ process.stderr.write(`[onekey-hw] Device disconnected: ${name}\n`);
171
173
  }
172
174
  });
173
175
  }