wallet-cli-usage
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesewallet-cli
wallet-cli
USB-based CLI for Ledger wallet flows. Networks: bitcoin, ethereum, solana (mainnet + testnets).
Install globally with a user-preferred package manager — , , , or . Run: .
npm i -g @ledgerhq/wallet-clipnpm add -g @ledgerhq/wallet-cliyarn global add @ledgerhq/wallet-clibun add -g @ledgerhq/wallet-cliwallet-cli [flags]Concepts & rationale: for why a command behaves the way it does, or to surface a safety rule that this skill states tersely (genuine check, receive-address verification, sessions, sandbox, device contention), read.references/business-logic.md
Session first: When invoked without a specific task, immediately run— do not ask the user what to do first. Show the result, then ask what to do next. If labels exist, skipsession view.account discover
Sandbox:,account discover,receive,send,genuine-check,swap execute,ring encrypt,ring decrypt,ring keysmust usering destroy— the first group is blocked by USB restrictions; the ring commands are blocked by OS keychain access restrictions.dangerouslyDisableSandbox: true
Device contention: Never run two device commands in parallel — they fail withor garbled APDU. Run sequentially.[object Object]
Device readiness: Before running a device command, briefly describe what you're about to do. The CLI prompts for device interaction itself — don't time out or kill the command. Exception:exits immediately (genuine-check, exit code 4) if any currency app is open — unlike the other device commands, it targets the dashboard and has no auto-launch path. Ensure the device is on the dashboard before running; if it exits, ask the user to back out to the dashboard and re-run.[✖] Wrong app. Open Ledger dashboard.
Ambiguous requests — ask, don't guess. If a required parameter is missing or unclear (no recipient for, no network forsend, an amount with no ticker), stop and ask. A wrong guess on a hardware wallet flow can mean irreversible fund loss.account discover
基于USB的Ledger钱包流程CLI。支持网络:bitcoin、ethereum、solana(主网 + 测试网)。
使用你偏好的包管理器全局安装 —— 、、 或 。运行方式:。
npm i -g @ledgerhq/wallet-clipnpm add -g @ledgerhq/wallet-cliyarn global add @ledgerhq/wallet-clibun add -g @ledgerhq/wallet-cliwallet-cli [flags]概念与设计逻辑: 若想了解命令行为的原因,或查看本技能简要提及的安全规则(正品校验、接收地址验证、会话、沙箱、设备争用),请阅读。references/business-logic.md
会话优先: 当调用时没有指定具体任务,立即运行—— 不要先询问用户要做什么。先展示结果,再询问下一步操作。如果已有账户标签,跳过session view。account discover
沙箱限制:、account discover、receive、send、genuine-check、swap execute、ring encrypt、ring decrypt、ring keys必须使用ring destroy—— 前一组命令受USB限制被沙箱拦截;ring系列命令受操作系统钥匙串访问限制被拦截。dangerouslyDisableSandbox: true
设备争用: 严禁并行运行两个设备相关命令 —— 否则会报错或出现APDU乱码。请按顺序执行。[object Object]
设备就绪检查: 运行设备命令前,请简要说明即将执行的操作。CLI会自行提示设备交互 —— 不要超时或终止命令。例外情况:如果打开了任何币种应用,会立即退出(报错genuine-check,退出码4)—— 与其他设备命令不同,该校验针对的是设备主界面,没有自动启动路径。运行前请确保设备处于主界面;如果命令退出,请让用户返回设备主界面后重新运行。[✖] Wrong app. Open Ledger dashboard.
请求不明确时 —— 询问,不要猜测。 如果缺少必填参数或参数不明确(没有收款方、send没有指定网络、金额没有币种代码),请停下来询问用户。硬件钱包流程中的错误猜测可能导致不可逆的资金损失。account discover
Intent map
意图映射
Map informal phrasings to commands. Account references use a session label (e.g. ).
ethereum-1| User says | Command |
|---|---|
| "show me my wallet", "what do I have", "let's get started", no specific task | |
| "find my accounts", "scan my wallet", "import my wallet", "set up Ethereum/Bitcoin" | |
| "where do I send funds to", "give me my address", "deposit address" | |
| "how much do I have", "balance", "what's my ETH balance" | |
| "what did I send", "transaction history", "recent activity" | |
| "send X to Y", "transfer", "pay", "withdraw to an exchange" | |
| "swap A to B", "convert", "trade ETH for BTC", "exchange" | |
| "where can I earn", "staking rates", "yield/APY", "best return on my ETH/SOL" | |
| "what am I staking", "my staking positions", "earn balance" | |
| "stake my SOL", "deposit into a vault", "earn yield on my USDC", "delegate" | |
| "unstake", "withdraw my stake", "redeem from vault", "stop earning" | |
| "is this Ledger real", "verify authenticity", "I bought this off eBay" | |
| "encrypt this file / these env vars / publish tokens", "GPG alternative", "secret manager", "decrypt anywhere with my Ledger" | |
| "what keys do I have on my ring", "list domains/projects I've encrypted under" | |
| "wipe my key ring", "destroy the ring", "tear down LKRP membership" | |
| "start over", "clear my session", "I switched devices" | |
将非正式表述映射到对应命令。账户引用使用会话标签(例如)。
ethereum-1| 用户说法 | 对应命令 |
|---|---|
| "给我看看我的钱包"、"我有什么资产"、"开始吧"、无具体任务 | |
| "查找我的账户"、"扫描我的钱包"、"导入我的钱包"、"设置以太坊/比特币" | |
| "我要把钱转到哪里"、"给我我的地址"、"充值地址" | |
| "我有多少钱"、"余额"、"我的ETH余额是多少" | |
| "我发送了什么"、"交易历史"、"近期活动" | |
| "把X转给Y"、"转账"、"付款"、"提现到交易所" | |
| "把A换成B"、"兑换"、"用ETH换BTC"、"交易" | |
| "我在哪里可以赚收益"、"质押利率"、"收益/年化收益率"、"我的ETH/SOL最佳收益" | |
| "我质押了什么"、"我的质押仓位"、"收益余额" | |
| "质押我的SOL"、"存入金库"、"用我的USDC赚收益"、"委托" | |
| "解除质押"、"提取我的质押"、"从金库赎回"、"停止赚收益" | |
| "这个Ledger是真的吗"、"验证真伪"、"我在eBay上买的这个" | |
| "加密这个文件/这些环境变量/发布令牌"、"GPG替代方案"、"密钥管理器"、"用我的Ledger在任何地方解密" | |
| "我的密钥环上有哪些密钥"、"列出我加密过的域名/项目" | |
| "清空我的密钥环"、"销毁密钥环"、"取消LKRP成员身份" | |
| "重新开始"、"清除我的会话"、"我换了设备" | |
Out of scope — say no, don't improvise
超出范围 —— 直接拒绝,不要临时发挥
If the user asks for any of the following, surface that wallet-cli does not support it yet rather than constructing a command:
- NFTs (mint, transfer, view).
- OpenPGP-compatible output or key-share / multi-recipient encryption (the commands encrypt with a per-user Ledger Key Ring, not a sharable key).
ring - ,
send,receive, oroperationson testnets and layer 2s (e.g. Base).swap execute - Custom chains not listed in the Networks line above.
如果用户询问以下任何内容,请说明wallet-cli暂不支持,不要自行构造命令:
- NFT(铸造、转账、查看)。
- OpenPGP兼容输出或密钥共享/多接收方加密(命令使用用户专属的Ledger Key Ring加密,而非可共享的密钥)。
ring - 测试网和二层网络(例如Base)上的、
send、receive或operations。swap execute - 上方支持网络列表中未列出的自定义链。
Session & labels
会话与标签
account discover<network>[-derivation][-env]-<n>ethereum-1bitcoin-native-1ethereum-sepolia-1All flags accept a session label (e.g. ). Run first to populate the session.
--accountethereum-1account discoveraccount discover<network>[-derivation][-env]-<n>ethereum-1bitcoin-native-1ethereum-sepolia-1所有参数都接受会话标签(例如)。请先运行来填充会话数据。
--accountethereum-1account discoverCommands
命令
| Command | Device | Sandbox | TTY† | Network |
|---|---|---|---|---|
| No | No | No | No |
| No | No | No | No |
| Yes | Required | No | Yes |
| Yes | Required | No | No |
| Yes* | Required | No | Yes |
| Yes | Required | No | Yes |
| No | No | No | Yes |
| No | No | No | Yes |
| No | No | No | Yes |
| Yes | Required | No | Yes |
| No | No | No | Yes |
| No | No | No | No |
| No | No | No | No |
| No | No | No | Yes |
| No | No | No | Yes |
| Yes* | Required | No | Yes |
| Yes* | Required | No | Yes |
| Yes | Required | Required‡ | Yes |
| No | Required | No | Yes |
| No | Required | No | Yes |
| No | Required | No | No |
| No | Required | Required‡‡ | Yes |
*, , and with need no device and no sandbox bypass.
sendearn depositearn withdraw--dry-run†TTY: whether the command requires an interactive terminal for user input.
‡ requires a password to protect the ring. must already be provided in the environment by the developer/user before the command runs — the agent never sets or injects it (see Non-TTY password injection).
ring initWALLET_PASS‡‡ prompts for typed confirmation (). Pipe it in non-interactive shells: . If a password was set, must already be present in the environment (provided by the developer, not the agent).
ring destroy"destroy"echo "destroy" | wallet-cli ring destroyWALLET_PASS| 命令 | 需设备 | 需绕过沙箱 | 需TTY† | 需指定网络 |
|---|---|---|---|---|
| 否 | 否 | 否 | 否 |
| 否 | 否 | 否 | 否 |
| 是 | 必须 | 否 | 是 |
| 是 | 必须 | 否 | 否 |
| 是* | 必须 | 否 | 是 |
| 是 | 必须 | 否 | 是 |
| 否 | 否 | 否 | 是 |
| 否 | 否 | 否 | 是 |
| 否 | 否 | 否 | 是 |
| 是 | 必须 | 否 | 是 |
| 否 | 否 | 否 | 是 |
| 否 | 否 | 否 | 否 |
| 否 | 否 | 否 | 否 |
| 否 | 否 | 否 | 是 |
| 否 | 否 | 否 | 是 |
| 是* | 必须 | 否 | 是 |
| 是* | 必须 | 否 | 是 |
| 是 | 必须 | 是‡ | 是 |
| 否 | 必须 | 否 | 是 |
| 否 | 必须 | 否 | 是 |
| 否 | 必须 | 否 | 否 |
| 否 | 必须 | 是‡‡ | 是 |
* 带参数的、和不需要设备,也不需要绕过沙箱。
--dry-runsendearn depositearn withdraw†TTY:命令是否需要交互式终端供用户输入。
‡‡会要求输入确认词()。在非交互式shell中可以通过管道传入:。如果设置了密码,环境变量中必须已存在(由开发者提供,而非Agent)。
ring destroy"destroy"echo "destroy" | wallet-cli ring destroyWALLET_PASSsession view / reset
session view / reset
bash
wallet-cli session view
wallet-cli session resetbash
wallet-cli session view
wallet-cli session resetaccount discover
account discover
bash
wallet-cli account discover ethereum
wallet-cli account discover bitcoin
wallet-cli account discover ethereum:sepoliaNetworks: (mainnet), , , , , .
bitcoinethereumsolanaethereum:sepoliabitcoin:testnetsolana:devnetbash
wallet-cli account discover ethereum
wallet-cli account discover bitcoin
wallet-cli account discover ethereum:sepolia支持网络:(主网)、、、、、。
bitcoinethereumsolanaethereum:sepoliabitcoin:testnetsolana:devnetreceive
receive
bash
wallet-cli receive ethereum-1
wallet-cli receive ethereum-1 --no-verify # skip device confirmationIf the on-screen address differs from the terminal address: do not share or use the address. Have the user disconnect the device and run before retrying. See § Receive-address verification for context.
genuine-checkreferences/business-logic.mdbash
wallet-cli receive ethereum-1
wallet-cli receive ethereum-1 --no-verify # 跳过设备确认如果设备屏幕上的地址与终端显示的地址不一致: 不要分享或使用该地址。请让用户断开设备连接,运行后再重试。相关说明请参见 § 接收地址验证。
genuine-checkreferences/business-logic.mdgenuine-check
genuine-check
bash
wallet-cli genuine-check
wallet-cli genuine-check --output json # only if a downstream caller needs to parse the resultPreconditions: device unlocked and on the dashboard (exit any open app); host has internet access (the secure channel reaches Ledger's backend — offline runs fail).
bash
wallet-cli genuine-check
wallet-cli genuine-check --output json # 仅当下游调用方需要解析结果时使用前置条件: 设备已解锁并处于主界面(退出所有打开的应用);主机有互联网连接(安全通道需要连接Ledger后端 —— 离线运行会失败)。
balances
balances
bash
wallet-cli balances ethereum-1
wallet-cli balances ethereum-1 --output jsonbash
wallet-cli balances ethereum-1
wallet-cli balances ethereum-1 --output jsonoperations
operations
bash
wallet-cli operations ethereum-1
wallet-cli operations ethereum-1 --limit 20 --cursor <cursor>Pagination: next cursor on stderr (human) or in JSON.
nextCursorbash
wallet-cli operations ethereum-1
wallet-cli operations ethereum-1 --limit 20 --cursor <cursor>分页:下一页游标会输出到stderr(人类可读格式)或JSON中的字段。
nextCursorsend
send
bash
wallet-cli send ethereum-1 --to 0xDEF... --amount '0.5 ETH'
wallet-cli send ethereum-1 --to 0xDEF... --amount '100 USDT' # ERC-20
wallet-cli send bitcoin-native-1 --to bc1q... --amount '0.001 BTC' --fee-per-byte 15 --rbf
wallet-cli send ethereum-1 --to 0xDEF... --amount '0.5 ETH' --dry-runTicker is mandatory in . No flag — ticker drives asset resolution.
--amount--tokenBitcoin flags: ,
--fee-per-byte <sats>--rbfSolana flags: , , ,
--mode send|stake.createAccount|stake.delegate|stake.undelegate|stake.withdraw--validator <addr>--stake-account <addr>--memo <text>bash
wallet-cli send ethereum-1 --to 0xDEF... --amount '0.5 ETH'
wallet-cli send ethereum-1 --to 0xDEF... --amount '100 USDT' # ERC-20
wallet-cli send bitcoin-native-1 --to bc1q... --amount '0.001 BTC' --fee-per-byte 15 --rbf
wallet-cli send ethereum-1 --to 0xDEF... --amount '0.5 ETH' --dry-run--amount--tokenBitcoin专属参数: 、
--fee-per-byte <sats>--rbfSolana专属参数: 、、、
--mode send|stake.createAccount|stake.delegate|stake.undelegate|stake.withdraw--validator <addr>--stake-account <addr>--memo <text>swap quote
swap quote
Fetches quotes in parallel from the built-in provider list (no device required; addresses are resolved from session accounts).
Currencies: / and / are Ledger currency IDs — native assets (e.g. , , ) or token IDs when the token’s parent chain is a supported native swap currency (same IDs the CLI allows for swap). They are not session account labels — use / for accounts.
--from-f--to-tethereumbitcoinsolana--from-account--to-accountDefault providers queried by and usable by : , , , , , , , , , , , . Some are CEX/aggregators run through the legacy Exchange-app pipeline; the DEX providers (, , , ) execute in the partner's embedded coin app — see swap execute — DEX providers.
swap quoteswap executechangellychangelly_v2ciccic_v2exoduslifinearintentsokxoneinchswapsxyzuniswapvelorauniswaponeinchveloraokxAccounts: and accept a session label only; the CLI resolves a fresh receive address from the account like .
--from-account--to-accountreceivebash
wallet-cli swap quote --from ethereum --to bitcoin --amount 0.1 --from-account ethereum-1 --to-account bitcoin-native-1
wallet-cli swap quote -f ethereum -t bitcoin --amount 0.1 --from-account ethereum-1 --to-account bitcoin-native-1 --output jsonRequired: , , , , .
--from--to--from-account--to-account--amount从内置提供商列表并行获取报价(不需要设备;地址从会话账户中解析)。
币种: / 和 / 是Ledger 币种ID —— 原生资产(例如、、)或代币ID(当代币的父链是支持的原生兑换币种时,与CLI允许的兑换ID相同)。它们不是会话账户标签 —— 账户请使用 / 参数。
--from-f--to-tethereumbitcoinsolana--from-account--to-accountswap quoteswap executechangellychangelly_v2ciccic_v2exoduslifinearintentsokxoneinchswapsxyzuniswapvelorauniswaponeinchveloraokx账户: 和 仅接受会话标签;CLI会像命令一样从账户解析一个新的接收地址。
--from-account--to-accountreceivebash
wallet-cli swap quote --from ethereum --to bitcoin --amount 0.1 --from-account ethereum-1 --to-account bitcoin-native-1
wallet-cli swap quote -f ethereum -t bitcoin --amount 0.1 --from-account ethereum-1 --to-account bitcoin-native-1 --output json必填参数:、、、、。
--from--to--from-account--to-account--amountswap execute
swap execute
Currencies: / and / are Ledger currency IDs (same as ): native assets or tokens on an allowed parent chain. They must match the asset of the source and of respectively.
--from-f--to-tswap quote--account--to-accountProviders: Valid values are , , , , , , , , , , , . Aliases: → , → . Use the provider id shown on the quote line you pick from .
--providerchangellychangelly_v2ciccic_v2exoduslifinearintentsokxoneinchswapsxyzuniswapvelorachangellychangelly_v21inchoneinchswap quoteDEX providers (, , , ): these run end-to-end in the partner's embedded coin app on the device (via the Device Intent Executor), not the legacy Exchange app. The flow re-fetches a quote for the chosen provider, then drives an on-device approval + swap sequence ( / / / broadcast), switching device apps as needed — confirm each and signing prompt on the device.
uniswaponeinchveloraokxsign-approvalsign-permit2sign-swapOpen <app>- EVM only. DEX execution requires an EVM source account (e.g. ); a non-EVM
ethereumfalls through to the legacy pipeline.--account - RFQ quotes are not supported in the CLI. If the picked quote resolves to an RFQ plan (/
rfq-order), the embedded flow is skipped and execution falls back to the legacy Exchange-app pipeline (you'll see aapproval-then-rfq-orderprogress line).falling back to legacy Exchange-app pipeline
All other providers (, , , , , , …) run the legacy Exchange-app pipeline (nonce → payload → complete exchange → sign/broadcast).
changellycicexodusnearintentsswapsxyzlifiFee strategy: accepts , (default), or . On the legacy pipeline it sets the refund-chain transaction fee.
--fee-strategyslowmediumfastbash
wallet-cli swap execute --from ethereum --to bitcoin --account ethereum-1 --to-account bitcoin-native-1 --provider changelly --amount 0.1
wallet-cli swap execute -f ethereum -t bitcoin --account ethereum-1 --to-account bitcoin-native-1 --provider changelly --amount 0.1 --fee-strategy fast
wallet-cli swap execute --from ethereum --to bitcoin --account ethereum-1 --to-account bitcoin-native-1 --provider changelly --amount 0.1 --output json币种: / 和 / 是Ledger 币种ID(与相同):允许的父链上的原生资产或代币。它们必须分别与源和的资产匹配。
--from-f--to-tswap quote--account--to-account提供商: 有效的值包括、、、、、、、、、、、。别名: → 、 → 。请使用你从结果中选择的报价行上的提供商ID。
--providerchangellychangelly_v2ciccic_v2exoduslifinearintentsokxoneinchswapsxyzuniswapvelorachangellychangelly_v21inchoneinchswap quoteDEX提供商(、、、): 这些提供商的兑换端到端运行在设备上的合作伙伴嵌入式币种应用中(通过设备意图执行器),而非旧版Exchange应用。该流程会为选定的提供商重新获取报价,然后驱动设备上的授权+兑换序列( / / / 广播),根据需要切换设备应用 —— 请在设备上确认每个和签名提示。
uniswaponeinchveloraokxsign-approvalsign-permit2sign-swapOpen <app>- 仅支持EVM。 DEX执行需要EVM源账户(例如);非EVM的
ethereum会回退到旧版流程。--account - CLI不支持RFQ报价。 如果选择的报价对应RFQ方案(/
rfq-order),会跳过嵌入式流程,执行回退到旧版Exchange应用流程(你会看到approval-then-rfq-order的进度提示行)。falling back to legacy Exchange-app pipeline
所有其他提供商(、、、、、等)运行旧版Exchange应用流程(nonce → payload → 完成兑换 → 签名/广播)。
changellycicexodusnearintentsswapsxyzlifi手续费策略: 接受 、(默认)或 。在旧版流程中,它设置退款链的交易手续费。
--fee-strategyslowmediumfastbash
wallet-cli swap execute --from ethereum --to bitcoin --account ethereum-1 --to-account bitcoin-native-1 --provider changelly --amount 0.1
wallet-cli swap execute -f ethereum -t bitcoin --account ethereum-1 --to-account bitcoin-native-1 --provider changelly --amount 0.1 --fee-strategy fast
wallet-cli swap execute --from ethereum --to bitcoin --account ethereum-1 --to-account bitcoin-native-1 --provider changelly --amount 0.1 --output jsonDEX (embedded coin app): EVM-only, source and destination on an EVM chain
DEX(嵌入式币种应用):仅支持EVM,源和目标都在EVM链上
wallet-cli swap execute --from ethereum --to ethereum/erc20/usd_tether__erc20_ --account ethereum-1 --to-account ethereum-1 --provider uniswap --amount 0.1
Required flags: `--from`, `--to`, `--account`, `--to-account`, `--provider`, `--amount`. Use a `--provider` value that matches the provider id on the quote line you pick from `swap quote`.wallet-cli swap execute --from ethereum --to ethereum/erc20/usd_tether__erc20_ --account ethereum-1 --to-account ethereum-1 --provider uniswap --amount 0.1
必填参数:`--from`、`--to`、`--account`、`--to-account`、`--provider`、`--amount`。请使用与你从`swap quote`结果中选择的报价行上的提供商ID匹配的`--provider`值。swap status
swap status
bash
wallet-cli swap status --swap-id <swapId> --provider changelly
wallet-cli swap status --swap-id <swapId> --provider changelly --output jsonRequired flags: ,
--swap-id--providerbash
wallet-cli swap status --swap-id <swapId> --provider changelly
wallet-cli swap status --swap-id <swapId> --provider changelly --output json必填参数:、
--swap-id--providerassets token / token-by-id
assets token / token-by-id
Resolve token metadata from the cryptoassets store. No device, no session.
bash
wallet-cli assets token ethereum 0xdac17f958d2ee523a2206206994597c13d831ec7
wallet-cli assets token-by-id ethereum/erc20/usd_tether__erc20_Use when you have the contract address; use when you have the id. Exits non-zero if not found.
tokentoken-by-idFor non-EVM chains pass .
--identifierThe printed here is the same id accepted by / and / .
idswap quote --from--toswap execute --from--to从加密资产库中解析代币元数据。不需要设备,不需要会话。
bash
wallet-cli assets token ethereum 0xdac17f958d2ee523a2206206994597c13d831ec7
wallet-cli assets token-by-id ethereum/erc20/usd_tether__erc20_如果你有合约地址,使用;如果你有ID,使用。如果未找到,命令以非零状态码退出。
tokentoken-by-id对于非EVM链,请传入参数。
--identifier这里输出的与 / 和 / 接受的ID是同一个。
idswap quote --from--toswap execute --from--toring — Ledger Key Ring (LKRP)
ring — Ledger Key Ring (LKRP)
Trustless, hardware-rooted encryption for files and text. The key ring is provisioned once on your Ledger via the Ledger Sync app; afterwards / run without the device — keys derive deterministically via HKDF-SHA256 from the LKRP-shared root and never leave AES-256-GCM. / still call the LKRP backend to restore the trustchain on each invocation, so network access is required. The ring is recoverable from your seed on any new machine.
encryptdecryptencryptdecryptbash
undefined无需信任的、硬件根保护的文件和文本加密。密钥环通过Ledger Sync应用在你的Ledger设备上一次性配置;之后/运行不需要设备 —— 密钥通过HKDF-SHA256从LKRP共享根密钥确定性派生,永远不会离开AES-256-GCM加密环境。/每次调用时仍会调用LKRP后端来恢复信任链,因此需要网络连接。密钥环可以在任何新机器上通过你的助记词恢复。
encryptdecryptencryptdecryptbash
undefinedOne-time provisioning (device required). Password comes from WALLET_PASS in the environment (see below); name the machine with --name.
一次性配置(需要设备)。密码来自环境变量中的WALLET_PASS(见下文);用--name为机器命名
wallet-cli ring init
wallet-cli ring init --name my-laptop
wallet-cli ring init
wallet-cli ring init --name my-laptop
File round-trip (no device after init):
文件加解密往返(初始化后不需要设备):
wallet-cli ring encrypt --key my-oss-project -i .publish-tokens -o .publish-tokens.enc
wallet-cli ring decrypt --key my-oss-project -i .publish-tokens.enc -o .publish-tokens
wallet-cli ring encrypt --key my-oss-project -i .publish-tokens -o .publish-tokens.enc
wallet-cli ring decrypt --key my-oss-project -i .publish-tokens.enc -o .publish-tokens
Text via stdin/stdout (clipboard pattern):
通过标准输入输出处理文本(剪贴板模式):
pbpaste | wallet-cli ring encrypt --key personal-notes | pbcopy
pbpaste | wallet-cli ring decrypt --key personal-notes | pbcopy
pbpaste | wallet-cli ring encrypt --key personal-notes | pbcopy
pbpaste | wallet-cli ring decrypt --key personal-notes | pbcopy
List the keys this machine has used; tear down the ring:
列出本机已使用的密钥;销毁密钥环:
wallet-cli ring keys
wallet-cli ring destroy
> **Always provision with a password.** The ring must be protected by a password. The user provides it via `WALLET_PASS` in the environment before running `ring init` (see [Non-TTY password injection](#ring--ledger-key-ring-lkrp)) — the agent never provisions a ring without one.
> **Decrypted output is sensitive.** `ring decrypt` emits secrets — never print them to the terminal, `cat` a decrypted file, or otherwise surface the decrypted contents, since they land in the agent transcript, logs, and scrollback. Pipe `decrypt` straight to its destination (a file via `-o`, another process, or the clipboard as shown above) or capture it into an env var; avoid `--output`/logging sinks that could echo it back.
`--key <name>` derives a per-name AES-256-GCM key; matching name at decrypt time is mandatory. Names are free-form (max 253 chars, no whitespace) — common patterns: project slugs (`my-oss-project`), env tags (`openClaw-prod`), notebooks (`personal-notes`).
**Non-TTY (CI / agentic) password injection:** the `ring` commands read the password from the `WALLET_PASS` env var when there is no TTY. **The password itself must be provisioned by the developer/user (exported in the environment or stored in the OS keychain) — the agent never chooses, types, or otherwise handles the secret value; it only references what the user has already provisioned.**
- **Never write the password literally** into a command (e.g. `WALLET_PASS=hunter2 wallet-cli …`, or via a flag). A literal leaks into shell history, `ps` output, CI logs, and — when an agent runs the command — the **agent transcript**. This applies to throwaway/test passwords too: make it a habit, because the same command shape is reused with a real secret.
- **Always inject via command substitution** so the secret never appears in the command text you type:
- macOS : `WALLET_PASS=$(security find-generic-password -a default -s ledger-wallet-cli -w) wallet-cli ring encrypt …`
- Linux : `WALLET_PASS=$(secret-tool lookup service ledger-wallet-cli account default) wallet-cli ring encrypt …`
- **Agents must not handle the secret at all.** Ask the user to store the password once in their OS keychain, then reference only the `$(…)` substitution. If a test or `ring init` needs a password, store a throwaway value in the keychain first (`security add-generic-password -a default -s ledger-wallet-cli -w`) and inject it the same way — never type the literal into a tool call.
- Even via substitution the value lives in the child process environment (readable via `ps eww` by the same user) — acceptable, but prefer the keychain form and avoid `--output json` sinks or logs that could echo it back.
**Rotation limitation:** the domain key derives from the ring's wallet-sync encryption key, which the LKRP protocol **rotates when a ring member is removed**. After a rotation, data encrypted before it can no longer be decrypted (decrypt fails with a "wrong key name, corrupted data, or the Ledger Key Ring rotated" error, and the CLI prints a `⚠ Ledger Key Ring rotated` warning). Re-encrypt the affected data under the new ring after a member is removed. `ring destroy` aborts (no changes) if you enter a wrong password, and also if `WALLET_PASS` is set but empty (a failed keychain lookup) — this is treated as a mistake, not a skip, so it never orphans the remote ring. To intentionally skip the remote teardown and wipe only local credentials, press Enter at the interactive password prompt.
---wallet-cli ring keys
wallet-cli ring destroy
> **务必配置密码。** 密钥环必须受密码保护。用户在运行`ring init`前通过环境变量`WALLET_PASS`提供密码(参见[非TTY密码注入](#ring--ledger-key-ring-lkrp))—— Agent绝不会在没有密码的情况下配置密钥环。
> **解密输出属于敏感信息。** `ring decrypt`会输出密钥 —— 绝不要将它们打印到终端、用`cat`查看解密文件或以其他方式暴露解密内容,因为这些内容会进入Agent对话记录、日志和滚动缓存。请将`decrypt`的输出直接管道传输到目的地(通过`-o`写入文件、传给另一个进程,或如上所示传到剪贴板),或存入环境变量;避免使用可能回显内容的`--output`或日志输出方式。
`--key <name>` 会派生一个对应名称的AES-256-GCM密钥;解密时必须使用相同的名称。名称是自由格式的(最多253个字符,无空格)—— 常见用法:项目标识(`my-oss-project`)、环境标签(`openClaw-prod`)、笔记(`personal-notes`)。
**非TTY(CI / Agent模式)密码注入:** 当没有TTY时,`ring`系列命令会从`WALLET_PASS`环境变量读取密码。**密码本身必须由开发者/用户配置(导出到环境变量或存储在操作系统钥匙串中)—— Agent绝不会选择、输入或以其他方式处理密钥值;它仅引用用户已配置的内容。**
- **绝不要在命令中直接写密码明文**(例如`WALLET_PASS=hunter2 wallet-cli …`,或通过参数传入)。明文会泄露到shell历史、`ps`输出、CI日志中,并且当Agent运行命令时,会泄露到**Agent对话记录**中。这也适用于临时/测试密码:养成习惯,因为相同的命令格式会在使用真实密钥时复用。
- **始终通过命令替换注入**,这样密钥永远不会出现在你输入的命令文本中:
- macOS : `WALLET_PASS=$(security find-generic-password -a default -s ledger-wallet-cli -w) wallet-cli ring encrypt …`
- Linux : `WALLET_PASS=$(secret-tool lookup service ledger-wallet-cli account default) wallet-cli ring encrypt …`
- **Agent绝不能处理密钥。** 请让用户将密码一次性存储在他们的操作系统钥匙串中,然后仅引用`$(…)`替换。如果测试或`ring init`需要密码,请先在钥匙串中存储一个临时值(`security add-generic-password -a default -s ledger-wallet-cli -w`),然后用同样的方式注入 —— 绝不要在工具调用中输入明文。
- 即使通过替换,密钥值仍存在于子进程环境中(同一用户可通过`ps eww`读取)—— 这是可接受的,但优先使用钥匙串方式,并避免使用可能回显内容的`--output json`或日志输出。
**轮换限制:** 域密钥派生密钥环的wallet-sync加密密钥,而LKRP协议会在**移除密钥环成员时轮换**该密钥。轮换后,之前加密的数据将无法解密(解密会失败并报错"wrong key name, corrupted data, or the Ledger Key Ring rotated",CLI会打印`⚠ Ledger Key Ring rotated`警告)。移除成员后,请使用新密钥环重新加密受影响的数据。`ring destroy`会中止(不做任何更改)如果输入错误的密码,或者`WALLET_PASS`已设置但为空(钥匙串查找失败)—— 这被视为错误操作而非跳过,因此绝不会导致远程密钥环成为孤儿。如果要故意跳过远程清理,仅擦除本地凭据,请在交互式密码提示时按Enter键。
---earn (staking & DeFi yield)
earn(质押与DeFi收益)
Earn covers two flows: Ethereum ERC-4626 DeFi vaults (deposit/redeem) and Solana native staking (delegate/undelegate). and are read-only (no device); and sign on the device.
yieldspositionsdepositwithdrawOnly ethereum & solana support/deposit. Other networks appear inwithdraw(informational) but cannot be deposited to via the CLI.earn yields
Earn包含两种流程:Ethereum ERC-4626 DeFi金库(存款/赎回)和Solana原生质押(委托/解除委托)。和是只读的(不需要设备);和需要在设备上签名。
yieldspositionsdepositwithdraw仅ethereum和solana支持/deposit。其他网络会出现在withdraw中(仅供参考),但无法通过CLI存入资金。earn yields
earn yields
earn yields
Lists yield opportunities (no device). Without it prints every network's headline rate. With or it also prints the concrete deposit targets, each ending with the exact value to pass to :
--network-n ethereum-n solana→ --product <id>earn deposit- ethereum → ERC-4626 vault ids (e.g. ).
1_0x7daeba3f217614e409f85d3014d33923a6b03630 - solana → validator vote accounts. The CLI surfaces the Ledger-operated validators ("Ledger by Figment", "Ledger by Bitwise") as the recommended targets; any other valid vote account also works as .
--product
bash
wallet-cli earn yields
wallet-cli earn yields -n solana
wallet-cli earn yields -n ethereum --output jsonThere is no separate "list validators / vaults" command — is how you discover a valid . In JSON, the value is the (ETH) or (SOL) field on each row.
earn yields -n <network>--productvaultIdvalidator列出收益机会(不需要设备)。不带参数时,它会打印每个网络的头条利率。使用或时,它还会打印具体的存款目标,每个目标的末尾是可传给的确切值:
--network-n ethereum-n solanaearn deposit→ --product <id>- ethereum → ERC-4626金库ID(例如)。
1_0x7daeba3f217614e409f85d3014d33923a6b03630 - solana → 验证者投票账户。CLI会列出Ledger运营的验证者("Ledger by Figment"、"Ledger by Bitwise")作为推荐目标;任何其他有效的投票账户也可以作为使用。
--product
bash
wallet-cli earn yields
wallet-cli earn yields -n solana
wallet-cli earn yields -n ethereum --output json没有单独的"列出验证者/金库"命令 —— 就是你查找有效的方式。在JSON格式中,该值是每行的(ETH)或(SOL)字段。
earn yields -n <network>--productvaultIdvalidatorearn positions
earn positions
Lists active earn positions for an account (no device). Account-based networks only (solana, ethereum).
bash
wallet-cli earn positions solana-1
wallet-cli earn positions solana-1 --fresh # request a background refresh--fresh(stale)Solana stake accounts: for Solana accounts the command also reads on-chain stake accounts and prints each one's , its (active / inactive / activating / deactivating), balance, and validator. This is where you get the value for . In JSON they're a top-level array alongside (each entry: , , , , ); the key is omitted entirely when there are none. Stake accounts show up here right after a deposit even if the backend snapshot is still empty. (Requires a chain sync; if it can't be reached the backend snapshot still prints, with a warning.)
→ --stake-account <address>state--stake-accountearn withdrawstakes[]positionsstakeAccountvalidatorstatestakeBalancewithdrawablestakes列出一个账户的活跃收益仓位(不需要设备)。仅支持基于账户的网络(solana、ethereum)。
bash
wallet-cli earn positions solana-1
wallet-cli earn positions solana-1 --fresh # 请求后台刷新--fresh(stale)Solana质押账户: 对于Solana账户,该命令还会读取链上质押账户,并打印每个账户的、(active / inactive / activating / deactivating)、余额和验证者。这就是你获取所需的值的地方。 在JSON格式中,它们是与并列的**顶层**数组(每个条目包含:、、、、);如果没有质押账户,键会被完全省略。即使后端快照仍然为空,质押账户在存款后也会立即显示在这里。(需要链同步;如果无法连接链,仍会打印后端快照,但附带警告。)
→ --stake-account <address>stateearn withdraw--stake-accountpositionsstakes[]stakeAccountvalidatorstatestakeBalancewithdrawablestakesearn deposit
earn deposit
Stakes (Solana) or deposits into a vault (Ethereum). Touches the device to sign — bypass the sandbox. comes from (see above). requires a ticker.
--productearn yields -n <network>--amountbash
undefined质押(Solana)或存入金库(Ethereum)。需要连接设备签名 —— 请绕过沙箱。来自(见上文)。需要包含币种代码。
--productearn yields -n <network>--amountbash
undefinedSolana: --product is a validator vote account
Solana:--product是验证者投票账户
wallet-cli earn deposit solana-1 --product 26pV97Ce83ZQ6Kz9XT4td8tdoUFPTng8Fb8gPyc53dJx --amount '1.5 SOL'
wallet-cli earn deposit solana-1 --product 26pV97Ce83ZQ6Kz9XT4td8tdoUFPTng8Fb8gPyc53dJx --amount '1.5 SOL'
Ethereum: --product is a vault id
Ethereum:--product是金库ID
wallet-cli earn deposit ethereum-1 --product 1_0x7daeba3f217614e409f85d3014d33923a6b03630 --amount '100 USDC'
wallet-cli earn deposit ethereum-1 --product 1_0x7daeba3f217614e409f85d3014d33923a6b03630 --amount '100 USDC'
Validate without signing (no device, no sandbox bypass)
仅验证不签名(不需要设备,无需绕过沙箱)
wallet-cli earn deposit solana-1 --product 26pV97… --amount '1.5 SOL' --dry-run
Solana `stake.createAccount` creates **and** delegates the stake account in one transaction. Ethereum deposits may run two transactions (ERC-20 `approve` then `deposit`).
**First-time ETH vault deposit — dry-run can't validate the deposit leg.** A first deposit into a vault you've never used is `approve` → `deposit`, and the deposit can only be built once a non-zero allowance exists on-chain. In `--dry-run` nothing is broadcast, so when an approve is still required the CLI validates the approve and **skips** the deposit build (status `not-simulated …`, overall `dry-run: approve validated; deposit needs an on-chain allowance to simulate`) rather than surfacing the backend's opaque 500. This is expected — **not** a balance error. The only way to validate the deposit leg is the real run (broadcast `approve`, wait for confirmation, then `deposit`). Treat a clean dry-run here as "approve is fine"; **confirm with the user before the live run** since it's an irreversible on-device signature. Once the allowance exists, a re-run of `--dry-run` will simulate the deposit normally.wallet-cli earn deposit solana-1 --product 26pV97… --amount '1.5 SOL' --dry-run
Solana的`stake.createAccount`会在一笔交易中创建**并**委托质押账户。Ethereum存款可能会运行两笔交易(ERC-20 `approve` 然后 `deposit`)。
**首次ETH金库存款 —— dry-run无法验证存款环节。** 首次存入你从未使用过的金库的流程是`approve` → `deposit`,而存款交易只有在链上存在非零授权时才能构建。在`--dry-run`模式下不会广播任何内容,因此当仍需要授权时,CLI会验证授权并**跳过**存款构建(状态为`not-simulated …`,整体结果为`dry-run: approve validated; deposit needs an on-chain allowance to simulate`),而不是返回后端不透明的500错误。这是预期行为 —— **不是**余额错误。验证存款环节的唯一方法是真实运行(广播`approve`,等待确认,然后`deposit`)。这里dry-run通过就意味着"授权没问题";**在真实运行前请与用户确认**,因为这是不可逆的设备上签名。一旦授权存在,重新运行`--dry-run`就会正常模拟存款。earn withdraw
earn withdraw
Unstakes (Solana) or redeems from a vault (Ethereum). Touches the device — bypass the sandbox.
- Ethereum: required;
--product <vault-id>optional. The amount is in the vault's asset units (e.g.--amount); if a ticker is given it must match the vault asset. Omit'50 USDC'for a full exit: the CLI sends--amountand the backend redeems the entire share balance, leaving no dust (don't compute the asset amount yourself for a full exit — the share→asset rate drifts).amount:"max" - Solana: (required). Two-phase: run once to
--stake-account <address>(deactivate), wait for the deactivation epoch boundary (~2–3 days), then re-run withundelegateto withdraw the now-inactive lamports back to the main account. coin-solana computes the withdrawable amount on-chain, so--finalizeis ignored on finalize.--amount
bash
undefined解除质押(Solana)或从金库赎回(Ethereum)。需要连接设备 —— 请绕过沙箱。
- Ethereum: 必填;
--product <vault-id>可选。金额以金库的资产单位计(例如--amount);如果提供了币种代码,必须与金库资产匹配。全额退出请省略'50 USDC': CLI会发送--amount,后端会赎回全部份额余额,不留零头(全额退出时不要自己计算资产金额 —— 份额兑资产的汇率会波动)。amount:"max" - Solana: 必填。分两阶段: 第一次运行执行
--stake-account <address>(解除委托/停用),等待停用周期边界(约2-3天),然后使用undelegate重新运行,将已停用的lamports提取回主账户。coin-solana会在链上计算可提取金额,因此finalize时会忽略--finalize参数。--amount
bash
undefinedEthereum vault redeem
Ethereum金库赎回
wallet-cli earn withdraw ethereum-1 --product 1_0x7daeba3f… --amount '50 USDC'
wallet-cli earn withdraw ethereum-1 --product 1_0x7daeba3f… --amount '50 USDC'
Solana phase 1: deactivate
Solana阶段1:解除委托
wallet-cli earn withdraw solana-1 --stake-account <stakeAccountAddr>
wallet-cli earn withdraw solana-1 --stake-account <stakeAccountAddr>
Solana phase 2 (after ~2–3 days): withdraw
Solana阶段2(约2-3天后):提取
wallet-cli earn withdraw solana-1 --stake-account <stakeAccountAddr> --finalize
Get the Solana `--stake-account` address from `earn positions <account>` (its `stakes[]` / `→ --stake-account` lines) — that's the stake account created by your earlier `earn deposit`.
---wallet-cli earn withdraw solana-1 --stake-account <stakeAccountAddr> --finalize
从`earn positions <account>`中获取Solana的`--stake-account`地址(其`stakes[]` / `→ --stake-account`行)—— 这是你之前通过`earn deposit`创建的质押账户。
---Common errors
常见错误
| Error | Cause | Fix |
|---|---|---|
| | Ask the user which asset they mean — do not guess. Then pass the ticker inline, e.g. |
| ticker not in account balances | Run |
| | Ask the user to exit the foreground app on the device (short-press both buttons on the app's main screen until |
| user rejected a sign request on device | The rejection was deliberate. Ask the user whether to retry or abort — do not auto-retry. If they retry, have them review amount, recipient, and fees on the device screen before approving. |
| user rejected the app-open prompt on device | Ask the user to confirm the app-open prompt on the device and re-run the command. |
| sandbox blocking USB, or device busy/locked | Surface to the user that the command needs |
| two device commands running in parallel (contention) | Run device-touching commands sequentially — never in parallel tool calls. |
| device powered off or unplugged | Ask the user to power on the device, unlock it, and connect via USB, then re-run the command. |
| device locked | Keep the command running — the CLI resumes automatically once unlocked. Ask the user to unlock the device with their PIN. |
| 错误信息 | 原因 | 解决方法 |
|---|---|---|
| | 询问用户指的是哪种资产 —— 不要猜测。然后将币种代码内联传入,例如 |
| 币种代码不在账户余额中 | 运行 |
| 打开了币种应用时调用了 | 请让用户退出设备上的前台应用(在应用主界面短按两个按钮,直到显示 |
| 用户在设备上拒绝了签名请求 | 拒绝是用户故意的。询问用户是重试还是中止 —— 不要自动重试。如果他们重试,请让他们在设备屏幕上确认金额、收款方和手续费后再批准。 |
| 用户在设备上拒绝了应用启动提示 | 请让用户在设备上确认应用启动提示,然后重新运行命令。 |
| 沙箱阻止了USB连接,或设备繁忙/已锁定 | 向用户说明该命令需要 |
| 两个设备命令并行运行(争用) | 按顺序运行涉及设备的命令 —— 绝不要在并行工具调用中运行。 |
| 设备关机或未连接 | 请让用户开机、解锁设备并通过USB连接,然后重新运行命令。 |
| 设备已锁定 | 保持命令运行 —— 设备解锁后CLI会自动恢复。请让用户用PIN码解锁设备。 |