con un clic
ledger-wallet-cli
// Official Ledger wallet-cli — USB-based CLI for Ledger hardware wallet flows (account discover, receive, balances, operations, send) built on the Device Management Kit (DMK)
// Official Ledger wallet-cli — USB-based CLI for Ledger hardware wallet flows (account discover, receive, balances, operations, send) built on the Device Management Kit (DMK)
| name | ledger-wallet-cli |
| description | Official Ledger wallet-cli — USB-based CLI for Ledger hardware wallet flows (account discover, receive, balances, operations, send) built on the Device Management Kit (DMK) |
wallet-cli is an experimental USB-based CLI for Ledger wallet flows, built on the Device Management Kit (DMK). Supported networks: bitcoin, ethereum, base, solana (mainnet and testnets). On Ledger devices, Base uses the Ethereum app.
Device contention: Only one command can use the device at a time. Never run two device-required commands in parallel — they will conflict and fail with
[object Object]or a garbled APDU error. Run device commands sequentially.
Prerequisites: Ledger device connected via USB, with the relevant coin app open on device for commands that require it (Base requires opening the Ethereum app).
Run from repo root:
pnpm --silent wallet-cli start <command> [flags]
Sandbox: Commands that open the USB device (
account discover,receive,send) must be run withdangerouslyDisableSandbox: truein the Bash tool — the sandbox blocks USB access and causes aTimeout has occurrederror. Commands that don't need the device (balances,operations,send --dry-run) work fine in the sandbox.
| Command | Device required | Disable sandbox |
|---|---|---|
account discover | Yes | Yes |
receive | Yes (optional with --no-verify) | Yes |
send | Yes (unless --dry-run) | Yes (unless --dry-run) |
balances | No | No |
operations | No | No |
account discover outputs V1 descriptors:
account:1:<type>:<network>:<env>:<xpub_or_address>:<path>
Hardened segments use h (shell-safe). ' is also accepted for backward compatibility.
Examples:
account:1:utxo:bitcoin:main:xpub6BosfCn...:m/84h/0h/0h
account:1:address:ethereum:main:0x71C7656EC7ab88b098defB751B7401B5f6d8976F:m/44h/60h/0h/0/0
account:1:address:solana:main:7xCU4XQfL...:m/44h/501h/0h/0h
account:1:utxo:bitcoin:testnet:tpubD8Lg2g...:m/84h/1h/0h
All commands (balances, operations, receive, send) accept V1 descriptors as --account or first positional arg. Legacy V0 (js:2:bitcoin:xpub...:native_segwit:0) still accepted.
pnpm --silent wallet-cli start account discover bitcoin
pnpm --silent wallet-cli start account discover ethereum
pnpm --silent wallet-cli start account discover base
pnpm --silent wallet-cli start account discover ethereum:sepolia
pnpm --silent wallet-cli start account discover bitcoin --output json
Network forms: bitcoin (= mainnet), ethereum:mainnet (alias → main), base, ethereum:sepolia, bitcoin:testnet (env → testnet), solana:devnet (env → devnet).
Human output: one account per line with fresh address and V1 descriptor to copy.
JSON output: { "accounts": ["account:1:utxo:bitcoin:main:xpub...:m/84h/0h/0h", ...] }
pnpm --silent wallet-cli start receive account:1:utxo:bitcoin:main:xpub...:m/84h/0h/0h
pnpm --silent wallet-cli start receive account:1:address:ethereum:main:0xABC...:m/44h/60h/0h/0/0 --no-verify
Use --no-verify to skip device confirmation.
pnpm --silent wallet-cli start balances account:1:address:ethereum:main:0xABC...:m/44h/60h/0h/0/0
pnpm --silent wallet-cli start balances account:1:utxo:bitcoin:main:xpub...:m/84h/0h/0h --output json
Fetches native balance and token balances (ERC-20). JSON amounts are human-readable strings ("1.5 ETH", "100 USDT").
pnpm --silent wallet-cli start operations account:1:address:ethereum:main:0xABC...:m/44h/60h/0h/0/0
pnpm --silent wallet-cli start operations <descriptor> --limit 20 --cursor <cursor>
pnpm --silent wallet-cli start operations <descriptor> --output json
Lists transactions including internal operations (ETH contract call traces). Pagination: --limit <n> and --cursor <cursor>. Next cursor on stderr (human) or nextCursor in JSON.
JSON: value/fee are human-readable ticker strings. accountId is the V1 descriptor string.
--dry-run)# Native ETH
pnpm --silent wallet-cli start send account:1:address:ethereum:main:0xABC...:m/44h/60h/0h/0/0 \
--to 0xDEF... --amount '0.5 ETH'
# ERC-20 token — ticker resolves the token automatically
pnpm --silent wallet-cli start send account:1:address:ethereum:main:0xABC...:m/44h/60h/0h/0/0 \
--to 0xDEF... --amount '100 USDT'
# Bitcoin with custom fee
pnpm --silent wallet-cli start send account:1:utxo:bitcoin:main:xpub...:m/84h/0h/0h \
--to bc1q... --amount '0.001 BTC' --fee-per-byte 15 --rbf
# Dry run — no device needed
pnpm --silent wallet-cli start send account:1:address:ethereum:main:0xABC...:m/44h/60h/0h/0/0 \
--to 0xDEF... --amount '0.5 ETH' --dry-run
Ticker is mandatory in --amount (e.g. '0.5 ETH', '0.001 BTC'). It drives asset resolution — no --token flag.
--dry-run: prepares and validates without signing or broadcasting. No device opened.
| Flag | Description |
|---|---|
--amount '<value> <TICKER>' | Required. e.g. '0.001 BTC', '0.01 ETH', '0.4 USDT' |
--to <address> | Required. Recipient address |
--dry-run | Prepare and validate without signing or opening the device |
--output json | Machine-readable JSON output |
| Flag | Description |
|---|---|
--fee-per-byte <satoshis> | Custom fee per byte in satoshis |
--rbf | Enable Replace-By-Fee |
| Flag | Description |
|---|---|
--mode <mode> | send, stake.createAccount, stake.delegate, stake.undelegate, stake.withdraw (default: send) |
--validator <address> | Validator address (staking flows) |
--stake-account <address> | Stake account address (staking flows) |
--memo <text> | Memo/tag |
All commands: --output human (default) or --output json.
JSON envelope shape:
{
"status": "success",
"command": "balances",
"network": "ethereum:main",
"account": "account:1:address:ethereum:main:0xABC...:m/44h/60h/0h/0/0",
"timestamp": "2026-04-03T12:00:00.000Z",
"...": "command-specific fields"
}
Command-specific payloads:
account discover: { "accounts": ["account:1:...", ...] }balances: { "balances": [{ "asset": "ethereum", "amount": "1.5 ETH" }, ...] }operations: { "operations": [{ "accountId": "account:1:...", "value": "0.1 ETH", "fee": "...", ... }], "nextCursor": "..." }send: { "tx_hash": "0x...", "amount": "0.5 ETH", "fee": "0.0003 ETH" }send --dry-run: { "dry_run": true, "recipient": "0x...", "amount": "0.5 ETH", "fee": "0.0003 ETH" }Error envelope: { "status": "error", "message": "...", ... } — exit code non-zero.
| Error | Cause |
|---|---|
Amount must include a ticker, e.g. '0.5 ETH' or '0.001 BTC' | --amount given a bare number |
Ticker UNKN not found in account. Available: ETH, USDT, ... | Ticker not in account balances |
No currencyId mapping for network "x:y" | Unsupported network/env combination |
UnknownDeviceExchangeError | Device not connected or coin app not open |
[x] Transaction Cancelled: Rejected on device. No funds moved. | User rejected on device |
Add E2E tests for new coins or update existing Playwright tests for ledger-live-desktop. Use when the user wants to add send/receive e2e tests for a new cryptocurrency, update test configurations, or work with Speculos device simulator.
Create a pull request with proper description, changeset, and all required elements
Interactive setup wizard for running desktop E2E (Playwright + Speculos) tests locally
Interactive setup wizard for running mobile E2E (Detox) tests locally
Guided feature development with codebase understanding and architecture focus
When typecheck finds an error importing from a lib in the monorepo, rebuild the lib