@candledottv/cli 0.13.18 → 0.13.20
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/README.md +33 -4
- package/dist/index.js +3046 -1492
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Single and batch rename require new labels of at most 64 characters, without edg
|
|
|
19
19
|
control characters or a leading `-`; names are never trimmed. Existing longer labels still
|
|
20
20
|
resolve as targets. A terminal is required. TEE wallets are refused by `vault rename`; use
|
|
21
21
|
`candle tee rename`. A retired TEE wallet (demoted and swept) is the exception: it renames here,
|
|
22
|
-
since Candle no longer holds it. `candle vault list` hides retired TEE wallets unless `--all
|
|
22
|
+
since Candle no longer holds it. `candle vault list` hides retired TEE wallets unless `--all`; `vault fund` and `vault transfer` refuse one as a destination (`TEE_WALLET_STOPPED`).
|
|
23
23
|
|
|
24
24
|
`candle tee rename <label|address|id> <new-label>` renames a TEE wallet on both sides: the label
|
|
25
25
|
Candle holds and, when the wallet's key is in this vault, the vault entry.
|
|
@@ -135,10 +135,12 @@ chosen words from your saved copy. Clear your terminal's scrollback too: the CLI
|
|
|
135
135
|
| `candle tee signer remove --key <prefix\|label>` | Removes this machine's key signer once it owns no wallets, and tells the server the signer is gone. Refuses while a wallet is still owned by it. Uses the device token, or the key's own API key. |
|
|
136
136
|
| `candle tee rebind <wallet...> --to-key <prefix\|label>`, `candle tee rebinds [wallet]` | Move TEE wallets to another key on the same account (owner only, preview then `confirm`; funds and the relay signer do not move), and list the rebind history, filtered to one wallet by its id, address or exact label. |
|
|
137
137
|
| `candle tee rename <label\|address\|id> <new-label>`, `candle tee rename --pairs-from <file> [--dry-run]` | Rename one TEE wallet, or 1–256 from a pairs file: the label Candle holds and the vault entry when there is one (owner only; one server call, all or nothing, then one vault commit). |
|
|
138
|
+
| `candle tee check <address\|id\|label>... [--label-prefix <p>] [--sign] [--max <n>] [--rpc-url <url>]` | Check, without spending, that each named TEE wallet can really trade: payable membership, wallet record parity against the swap's own listing, and this machine's signer. `--label-prefix` selects wallets by label, `--json` prints one object per run with each wallet's `checks` and a `summary`, and the exit code is 1 when any check fails. `--sign` also builds a tiny SOL/USDC quote, checks its spend, requests a relay signature, verifies it locally and simulates; it never broadcasts, is capped at `--max` wallets (default 10) and needs `swap:write` |
|
|
138
139
|
| `candle tee new\|enable` | `new` adds a key to an existing `tee-wallets.enc` and refuses when that store is absent (`vault new-key --chain solana`, then `vault promote --from <label> --to-key <prefix>`). `--factor` does not apply. `enable <address> --vault <address>` delegates an existing key with a pinned sweep vault. `vault import-legacy --tee` migrates an existing store. |
|
|
139
|
-
| `candle swap <from> <to> --amount <n>\|--percent <n> --wallet <tee> [--to <tee>] [--wait]` | Quote, confirm and swap through the TEE wallet's bound key; the first buy after a launch is this command, unless `candle launch --buy` made it. The assets decide the chain (ETH, USDG or a 0x token is Hood; SOL, USDC, CNDL or a mint is Solana). SOL or USDC to ETH or USDG, or back, is a bridge through Relay into this key's own TEE wallet on the other chain (`--to` names it when there are several); `--wait` follows it for up to ten minutes. With `--json`, stdout is exactly one JSON value for swaps, token trades, replays and `swap status`: `kind`, `status`, `clientTradeId`, `signature` (the primary transaction, or `null`), `signatures` (a list) and `raw` (the original response). Every human line is on stderr. The keys older versions printed stay beside them. |
|
|
140
|
+
| `candle swap <from> <to> --amount <n>\|--percent <n> --wallet <tee> [--to <tee>] [--wait] [--dry-run]` | Quote, confirm and swap through the TEE wallet's bound key; the first buy after a launch is this command, unless `candle launch --buy` made it. The assets decide the chain (ETH, USDG or a 0x token is Hood; SOL, USDC, CNDL or a mint is Solana). SOL or USDC to ETH or USDG, or back, is a bridge through Relay into this key's own TEE wallet on the other chain (`--to` names it when there are several); `--wait` follows it for up to ten minutes. With `--json`, stdout is exactly one JSON value for swaps, token trades, replays and `swap status`: `kind`, `status`, `clientTradeId`, `signature` (the primary transaction, or `null`), `signatures` (a list) and `raw` (the original response). Every human line is on stderr. The keys older versions printed stay beside them. `--dry-run` (Solana TEE payer only) checks the wallet, builds the quote and checks its spend, then stops: it never signs, sends, prompts or saves an operation, refuses `--yes`, `--percent` and `--client-trade-id`, and refuses embedded, Hood and bridge payers. With `--json` stdout is the per-check results and the quote. |
|
|
140
141
|
| `candle swap status <id> [--kind trade\|swap\|launch] [--wait]` | Read an operation without resending it; `--wait` follows a bridge until it ends. |
|
|
141
|
-
| `candle transfer --to <address\|wallet name\|allowlist label\|vault> --asset <SOL\|USDC\|CNDL\|ETH\|USDG>\|--mint <mint>\|--token <0x...> --amount <decimal\|max> [--wallet <tee>] [--rpc-url <url>] [--yes]` | Move funds out of a TEE wallet through its bound Withdraw key, to the wallet's own pinned vault (`--to vault`, any token, `max` allowed, one SOL transfer at most the server's backstop ceiling, 50 SOL by default) or to another of the account's wallets you linked while signed in or marked trusted (a base asset, counted against the key's caps, which must include a per-asset cap and a USD `--tx-limit`). Where the server has `TEE_WITHDRAWALS_ENABLED` on (it ships off), also to an address on the account's withdrawal allowlist, named by its label, id or address, with the same base-asset rule. The asset decides the chain: ETH, USDG or `--token` moves from a Hood TEE wallet. The destination and its kind are shown before you confirm; Candle builds, the relay signs, Candle broadcasts. |
|
|
142
|
+
| `candle transfer --to <address\|wallet name\|allowlist label\|vault> --asset <SOL\|USDC\|CNDL\|ETH\|USDG>\|--mint <mint>\|--token <0x...> --amount <decimal\|max> [--wallet <tee>] [--client-id <id>] [--rpc-url <url>] [--yes]` | Move funds out of a TEE wallet through its bound Withdraw key, to the wallet's own pinned vault (`--to vault`, any token, `max` allowed, one SOL transfer at most the server's backstop ceiling, 50 SOL by default) or to another of the account's wallets you linked while signed in or marked trusted (a base asset, counted against the key's caps, which must include a per-asset cap and a USD `--tx-limit`). Where the server has `TEE_WITHDRAWALS_ENABLED` on (it ships off), also to an address on the account's withdrawal allowlist, named by its label, id or address, with the same base-asset rule. The asset decides the chain: ETH, USDG or `--token` moves from a Hood TEE wallet. The destination and its kind are shown before you confirm; Candle builds, the relay signs, Candle broadcasts. `--client-id <id>` (1 to 128 of letters, digits, `.` `_` `:` `-`) names the transfer yourself: reusing an id for a transfer already built or sent is `IDEMPOTENCY_CONFLICT` naming that transfer, so a retry never sends twice. |
|
|
143
|
+
| `candle transfer status <transfer id\|client id> [--json]` | Where a transfer stands, by the id the build returned or the `--client-id` it was sent under: `built` (signable until `expiresAt`), `expired`, `submitted` with its `signature`, `unconfirmed` (may still land; check the chain or `candle activity` before using a new client id), or `failed`. Candle keeps the answer for 24 hours; an older transfer is in `candle activity`. An unknown id is `JOB_NOT_FOUND`. |
|
|
142
144
|
| `candle launch --name <name> --symbol <symbol> --image <path>\|--image-url <url> --wallet <tee>\|embedded [--banner <file\|URL>] [--description <text>] [--website <url>] [--x <url>] [--telegram <url>] [--discord <url>] [--buy <amount>] [--quote-asset <asset>] [--dex-version v3\|v4] [--mode <mode>] [--curve-v <V> --curve-g <G>] [--creator-fee-bps 0\|100\|200] [--staker-allocation-bps <bps>] [--visibility production\|test\|local\|hidden] [--pool-fee 25\|50\|100] [--pool-fee-from <bps> --pool-fee-minutes <min>] [--pool-open legacy\|curve_price] [--exp-pool-shape floor\|full_range] [--fee-wallet <address>\|--fee-wallet-multisig <address> [--fee-wallet-multisig-vault-index <n>]] [--require-fee-wallet] [--open-in <duration>] [--max-buy-per-wallet <amount> --cap-window <duration>] [--allowlist <path> --allowlist-window <duration>] [--dev-buy-max <amount>] [--dry-run] [--check] [--client-trade-id <id>] [--yes]` | Create a token from the named wallet, with an optional first buy. `--wallet embedded` (or `main`) uses `/launch/headless` on Solana or Hood, with or without `--buy`; every plan can use it with `launch:write` and the key's embedded-wallet allowance, without `swap:write`. It previews through `/launch/headless/dry-run`, shows the quote for confirmation, then sends one headless request. A Solana buy is a creator bundle signed by Candle, preserving `bundleId` in the result; a Hood buy is best effort after creation. The server's slippage floor applies; there is no separate CLI build-floor comparison. TEE wallets use `/launch/self` and need Pro or Max, `launch:write`, the bound key and verified signing authority; a server with `TEE_LAUNCH_BY_SCOPE_ENABLED` off also asks for the owner's `allowLaunch` (deprecated). A TEE first buy needs `TEE_LAUNCH_BUYS_ENABLED` (off by default), and with `TEE_LAUNCH_BY_SCOPE_ENABLED` on it also needs `swap:write` (a key without it gets `SCOPE_MISSING`); Solana creator buys also need `AGENT_TRADING_ENABLED` and a configured Jito engine. No gate or plan default changes. `--buy` is a decimal in whole quote units (SOL/USDC/CNDL on Solana, ETH on Hood; USDG has no first buy); zero or empty means no buy. A Hood launch needs `--dex-version v3\|v4`. `--description` and the four absolute http(s) socials flags travel with every preview/build: `--x` maps to `socials.twitter`. `--staker-allocation-bps` accepts 50–1000; `--visibility` is production, test, local or hidden (test keys need test or hidden). `--mode exp-custom` needs `--curve-v` and `--curve-g` in whole quote units; ranges and common help come from the shared launch definition and appear in `candle launch --help`. `--pool-fee` sets the Solana graduated pool fee (default 50 bps); `--pool-fee-from` and `--pool-fee-minutes` add a fall to that rate. Preset `--pool-open curve_price` opens at the curve's last price and burns the rest; omitted it applies when allocations fit `graduation.maxStakerCarveBps`, otherwise falls back to legacy. Exp `--exp-pool-shape` is floor or full_range. `--image-url` is https; `--image` uploads a local PNG/JPEG/GIF/WebP up to 10MB. `--banner` takes a wide local file or https URL. Uploads are public and permanent before confirmation, even on a dry run or decline. `--dry-run` stops at the preview without claiming the launch id. Reuse `--client-trade-id` for recovery, and always pass `--json` in scripts. `--check` answers which launch path works before any of it, in one call (`GET /api/v1/launch/preflight`): the key's tier and embedded-wallet allowance, each bound TEE wallet's allowLaunch (served `true` where the server has `TEE_LAUNCH_BY_SCOPE_ENABLED` on) and verified-active state, and the server's `TEE_LAUNCH_BY_SCOPE_ENABLED`, `TEE_LAUNCH_BUYS_ENABLED` and `AGENT_TRADING_ENABLED` switches. No name, symbol or image is needed, nothing is uploaded or sent, `--wallet <name>` narrows the answer to one wallet, and it exits 1 when no launch path works. On Solana, where the server has `CURVE_LAUNCH_RULES_ENABLED` on, launch rules are fixed at launch and enforced by the curve program: `--open-in` delays the open (until then only the launching wallet may buy, up to `--dev-buy-max`, which defaults to `--buy`), `--max-buy-per-wallet` with `--cap-window` caps what each wallet spends on the curve after the open, and `--allowlist <path>` (one address per line, or comma separated, at most 4,096) with `--allowlist-window` lets only the listed wallets buy. Durations are seconds or `90m`, `6h`, `2d` (the open at most 7 days away, each window at most 24 hours); amounts are whole quote units. The CLI checks each value before any request with the API's bounds, sends the request's nested `launchRules` in raw units, and the preview prints a Launch rules block from the API's answer. Nobody can change the rules after the launch. |
|
|
143
145
|
| `candle launch status <mint-or-client-launch-id> [--wait]` | One launch state, `build`, `signed`, `confirmed`, `trading`, `bonded` or `migrated`, for a mint or a `clientLaunchId`. Reads `GET /api/v1/launch/status/{id}` (`launch:read`) and reports the market's own `lifecycle` and `migration` fields. `--wait` follows it until the token is trading, the launch has failed, or ten minutes pass. Nothing is sent. |
|
|
144
146
|
| `candle image upload <path>` | Uploads a PNG, JPEG, GIF or WebP file, at most 10MB, and prints the `https://` URL Candle hosts it at, ready to be a launch's `imageUrl`. The type is read from the file's first bytes. The file becomes public and permanent. Needs `launch:write`; spends nothing and does not count against the launch cap. `--json` adds the content type and the size. |
|
|
@@ -168,6 +170,10 @@ chosen words from your saved copy. Clear your terminal's scrollback too: the CLI
|
|
|
168
170
|
|
|
169
171
|
`candle vault transfer <to> --amount max --asset SOL --from <label>` sends the source wallet’s SOL balance minus the exact quoted transaction fee. The plain system wallet is emptied, so its source rent reserve is zero. The balance and fee are refreshed after confirmation; a changed amount or fee is displayed and must be confirmed again (at most three confirmations). An unavailable or unstable fee quote, or a balance that cannot cover the fee and a positive send, refuses before signing. Nonce and program accounts cannot use this plain transfer shape. SPL and Token-2022 `max` send the source associated token account’s full raw balance (mint fees may reduce what arrives); SOL must still cover fees and any destination token account rent. Hood native `max` deducts the fee cap; ERC-20 `max` sends the whole token balance.
|
|
170
172
|
|
|
173
|
+
### Retrying a transfer safely
|
|
174
|
+
|
|
175
|
+
Pass `--client-id <id>` and a retry cannot send twice. The id rides the build as `clientTransferId`, and the receipt carries it back. If the first attempt died before you saw the result, run `candle transfer status <id>` (the transfer id or your client id): `submitted` shows the `signature`, `built` means nothing was sent yet, and `expired` means the build lapsed unsent. `unconfirmed` keeps the signature and the client id bound even after the build expires: it may still land, so check the chain or `candle activity` before doing anything else or using a new client id. `failed` means a definite revert or a refusal before broadcast. Running the same `candle transfer --client-id <id>` again while the earlier one is pending, built, sent or unconfirmed is refused with `IDEMPOTENCY_CONFLICT`, naming the transfer. Status is kept for 24 hours; older transfers are in `candle activity`.
|
|
176
|
+
|
|
171
177
|
`candle transfer --asset SOL --amount max` (including `--to vault` from a TEE wallet) sends the balance minus 10,000 lamports of fee headroom and the RPC-reported rent-exempt minimum for a zero-byte system account. It keeps the payer rent-exempt. If no positive amount remains, Candle refuses before signing with `TRANSFER_AMOUNT_UNAVAILABLE`; the message reports the spendable lamports, fee headroom and rent minimum. The returned `amountRaw` is the amount the transaction moves.
|
|
172
178
|
|
|
173
179
|
The documented `--access` values are `read`, `write` and `withdraw`. The older `read-write`, `transfer` and `read-write-transfer` values remain accepted as silent, permanent aliases.
|
|
@@ -228,6 +234,17 @@ table above) runs the same check against the trusted root compiled into the bina
|
|
|
228
234
|
call required. It is also what `install.sh` uses on a machine with neither. Full walkthrough, including the installer script's own signature and the
|
|
229
235
|
transparency log: [Verify a Candle release](https://docs.candle.tv/developers/verify-a-candle-release).
|
|
230
236
|
|
|
237
|
+
## Browser confirm for owner steps
|
|
238
|
+
|
|
239
|
+
Where the API has `OWNER_CONFIRM_ENABLED` on, an owner step made with the device token that widens what the account's keys can do also needs one approval in your browser, signed in as the account owner. The API answers `403 OWNER_CONFIRM_REQUIRED` and changes nothing; the CLI then:
|
|
240
|
+
|
|
241
|
+
1. Prints what you are approving (a summary the server built), `Open <url>` and `Code: XXXX-XXXX` on stderr, with "Only approve if you just ran this command." It opens the browser only with `--open`. Under `--json` it writes one line to stderr instead, `{"ok":false,"pending":true,"code":"OWNER_CONFIRM_REQUIRED","ownerConfirm":{"userCode","verificationUriComplete","expiresIn","step","summary"}}`, and keeps stdout for the final result.
|
|
242
|
+
2. Waits, polling every few seconds. The code expires 5 minutes after it was issued.
|
|
243
|
+
3. When you approve at `/dev/agent/confirm`, sends the identical request again and prints its result. Deny it and the command exits 1 with `Denied in the browser; nothing changed.`; let it expire and it exits 1 with `The confirmation expired; nothing changed. Run the command again.`
|
|
244
|
+
4. With `--no-wait` it prints the code and exits 7 without waiting. The command does not resume later: run it again without `--no-wait`, or make the change in the console.
|
|
245
|
+
|
|
246
|
+
One approval covers exactly one request, from this device, for this account. The steps that ask for it: `keys create` (every key, a read-only one included), `keys rotate`, `keys access` when it widens, `keys update --embedded-wallet allow`, `auth login --embedded-wallet allow` when it allows the new key the embedded wallet, `keys signer approve` (not `--reject`), `tee rebind` (not the preview), `wallets allow-launch`, `vault promote --to-key` (one approval per wallet), `keys limit` when it raises, clears or changes the window of a transaction limit, `perps thresholds set` and `clear` when they loosen, and `perps reduce-only off`. The Candle Harness shows the same summary, URL and code when its core mints a key. Narrowing steps never ask: revoking or stopping a key, narrowing access, `rotate --finish`, tightening a limit, `reduce-only on`. An older CLI prints the server's message, which carries the URL and code, but cannot finish the step: update the CLI before this is on. A signed-in console session never sees the confirm.
|
|
247
|
+
|
|
231
248
|
## The `--json` contract
|
|
232
249
|
|
|
233
250
|
For agents and scripts, `--json` guarantees: **stdout carries exactly one JSON value** -- the
|
|
@@ -261,7 +278,10 @@ A generated vault passphrase is shown once on the terminal and never inside a JS
|
|
|
261
278
|
`vault init` and `vault factor add passphrase` under `--json` take `--own-passphrase` (typed at a
|
|
262
279
|
hidden prompt, nothing shown) and refuse the generated form with exit `2`. Prompts themselves are
|
|
263
280
|
rendered on stderr, so a command that unlocks a vault on a terminal still leaves stdout as one
|
|
264
|
-
JSON value. A
|
|
281
|
+
JSON value. A vault command run without a terminal to prompt at — stdin and stdout for the
|
|
282
|
+
ceremony commands, stdin and stderr for the prompt itself — refuses with `VAULT_TERMINAL_REQUIRED`
|
|
283
|
+
before anything is asked; it is not an unlock failure, and no flag or environment variable
|
|
284
|
+
supplies a passphrase or PIN. A security key's PIN is read the same way, by the CLI on its own hidden prompt, and
|
|
265
285
|
reaches the `candle-fido2` helper only inside a request piped to it; the helper never reads the
|
|
266
286
|
terminal and the PIN never appears in any output.
|
|
267
287
|
|
|
@@ -634,3 +654,12 @@ for the complete contract.
|
|
|
634
654
|
During the verifier upgrade, rotation and finish may return retryable 503 with reason
|
|
635
655
|
`rotation_verifier_not_ready` before changing any credential. Keep the existing secret
|
|
636
656
|
and retry after the service is ready; the API does not silently shorten the grace guarantee.
|
|
657
|
+
|
|
658
|
+
## Uncertain Hood legs (BE-3072)
|
|
659
|
+
|
|
660
|
+
On Hood, when a leg's receipt is not confirmed, the CLI reports `LEG_UNCONFIRMED` (exit 3), keeps the
|
|
661
|
+
hash it computed from its own signed bytes, and tells you not to repeat the trade and to read
|
|
662
|
+
`candle swap status <id> --kind trade`. A revert exits 1 before the trade leg succeeded and 3 after.
|
|
663
|
+
`No leg landed` is no longer printed on an empty list: it was never negative evidence; the CLI says
|
|
664
|
+
`No leg is confirmed yet`. JSON output keeps `legEvidence`, `reconciliation`, `recoveryRequired`,
|
|
665
|
+
`safeAction` and `pollAfterMs` from the server. Status makes no signing or send calls.
|