@candledottv/cli 0.12.0 → 0.13.0

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.
Files changed (3) hide show
  1. package/README.md +42 -32
  2. package/dist/index.js +4200 -1179
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @candledottv/cli
2
2
 
3
- The Candle CLI (current version 0.12.0): authorize a device from your browser, keep your own keys
3
+ The Candle CLI (current version 0.13.0): authorize a device from your browser, keep your own keys
4
4
  in an encrypted vault on this machine, hand an agent a TEE wallet it can trade, and manage API
5
5
  keys, wallets, and setup health from the terminal. Zero runtime dependencies; the whole thing is
6
6
  one self-contained `dist/index.js` that runs under plain Node.
@@ -122,10 +122,11 @@ emergency procedure, rebinding, trusted wallets and API key access levels are al
122
122
  | `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. |
123
123
  | `candle swap status <id> [--kind trade\|swap\|launch] [--wait]` | Read an operation without resending it; `--wait` follows a bridge until it ends. |
124
124
  | `candle transfer --to <address\|wallet name\|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`). 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. |
125
- | `candle launch --name <name> --symbol <symbol> --image <path>\|--image-url <url> --wallet <tee>\|embedded [--banner <file\|URL>] [--buy <amount>] [--quote-asset <asset>] [--dex-version v3\|v4] [--mode <mode>] [--curve-v <V> --curve-g <G>] [--creator-fee-bps 0\|100\|200] [--pool-fee 25\|50\|100] [--pool-open legacy\|curve_price] [--exp-pool-shape floor\|full_range] [--dry-run]` | Create a token from a TEE wallet. The image is `--image-url` (an `https://` URL) or `--image <path>` (a PNG, JPEG, GIF or WebP file on this machine, at most 10MB), never both; `--image` uploads the file before the confirm prompt, which makes it public and permanent, and launches with the URL that comes back. `--banner <file|URL>` adds a wide banner from a local file or an https URL. Local banners use `kind=banner`, retain their original shape (wider than 1.5:1), and become public and permanent before confirmation; the result reports `bannerUrl`. Without `--buy` it makes no first buy. `--buy <amount>` adds one from the same wallet, in whole units of the quote asset, reserved against the key's spend window before signing: as its own leg in one Jito bundle with the launch on Solana, as a last leg on Hood. It needs the server's `TEE_LAUNCH_BUYS_ENABLED`, which is off by default; while it is off Candle refuses the buy and nothing is built. Needs `launch:write`, `allowLaunch` turned on for the wallet by the account owner, and the Pro or Max plan. `--wallet embedded --buy <amount>` launches from the account's embedded wallet instead, on Solana, as an atomic launch: Candle's dry run first (nothing built or recorded), the quote to confirm, then one build and one `/launch/atomic/submit`, with Candle signing both legs into one Jito bundle. It needs Pro or Max, `launch:write` and `swap:write`, and does not depend on `TEE_LAUNCH_BUYS_ENABLED`. Without a first buy, every plan can launch from the embedded wallet with the MCP tool `candle_launch_token` or the SDK's `launch()`. The wallet decides the chain: a Hood TEE wallet launches on Hood and needs `--dex-version`. `--quote-asset` is sol, usdc or cndl on Solana, eth or usdg on Hood. `--mode` picks the curve: `open` or `exclusive`, `test-open` or `test-exclusive` where the server has `ENABLE_TEST_CURVES` on, or on Solana with sol or cndl `exp-a`, `exp-b`, `exp-c` and `exp-custom`, which takes `--curve-v <V>` and `--curve-g <G>` in whole units of the quote asset where the server has `EXP_CUSTOM_CURVES` on. `--creator-fee-bps 100` or `200` adds an extra creator fee on an `exp-` mode. On an `exp-` curve the first buy is at most 0.5 SOL (2,000,000 CNDL), or 10% of the threshold when that is lower. Solana pool choices: `--pool-fee 25|50|100` (bps; add `--pool-fee-from <bps> --pool-fee-minutes <min>` for an anti-snipe fall to that rate, at most 2500 bps over 30 minutes), `--pool-open legacy|curve_price` (preset tiers) and `--exp-pool-shape full_range` (exp- curves). For Solana preset tiers, omitting `--pool-open` defaults to `curve_price` (opens at the curve's last price and burns the remaining base) when `stakerAllocationBps` plus the team allocation fit the tier's limit (`graduation.maxStakerCarveBps` in the dry run); otherwise it falls back to `legacy` without refusal. Use `--pool-open legacy` to opt out. Explicit `curve_price` is refused above the limit. Experimental curves and Hood are unchanged. `--dry-run` prints Candle's preview of the launch (the curve's terms, the first buy's share, the fees, how the pool opens at graduation, the dev-buy ceiling) and builds, signs and records nothing; with `--image` the upload still happens. |
125
+ | `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] [--dry-run] [--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, `allowLaunch`, the bound key and verified signing authority. A TEE first buy needs `TEE_LAUNCH_BUYS_ENABLED` (off by default); 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. |
126
126
  | `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. |
127
127
  | `candle pnl [--profile <name>]` | P&L: realized net, fees, unrealized and total, then open positions, the same figures the console shows. Without `--profile`, the account's books (every profile, the web app and the CLI, one ledger; needs the Read scope), with a By agent table (each key, then Manual, then the account total). With `--profile <name>`, that profile's key's share of the same P&L: realized on its sales and the open positions that belong to it, with a row per wallet that sums to the total. Each wallet is its own average-cost pool, and a recorded move between the account's wallets carries its cost. Both show a Solana block, a Hood block, then the combined figure, the closed positions as money made, minus money lost, plus partial sells, and a `CHAIN` column (and `WALLET`, where the API names it) on positions. Unpriced positions are never valued at zero; dust (worth under one cent) is marked and still counted. A bridge between Solana and Hood is not a trade, and bridge and Relay costs are not netted. DAMM v2 LP positions are included: realized (withdrawals against the cost basis at the add, plus claimed fees), unrealized (open positions at their share of the pool plus unclaimed fees, against that basis) and vs holding (what the deposited tokens would be worth held); `Total` stays the console's token figure and `Total with LP` covers tokens and LP. |
128
128
  | `candle portfolio [<filter>] [--chain solana\|hood] [--rpc-url <url>] [--evm-rpc-url <url>] [--no-perps]` | Vault, TEE and embedded wallets on Solana and Hood in one table with chain, amount, price and value, subtotals per group and per chain, and a total. Solana vault and external balances are read over your own Solana RPC; Candle is sent only the mints, for prices. EVM vault keys are read over your own Hood RPC (`--evm-rpc-url`, else `CANDLE_EVM_RPC_URL`, else the built-in Hood RPC) for ETH and USDG only, priced by asset, never by address; an RPC on another chain is refused. An unpriced Hood token shows why (`no-market-row`, `stale-mark`, ...). `--chain` shows one chain. Each TEE wallet's DAMM v2 LP positions follow the tokens, valued by Candle at the same marks, and count in the total; one whose pool could not be read is shown as not read and the total says it is partial. A Hyperliquid section follows (each EVM TEE wallet's account, read from Hyperliquid directly, never in the total); `--no-perps` skips it. |
129
+ | `candle token clusters <mint> [--chain solana\|hood]` | Optional third-party Solana cluster estimates, with fetched time and a linked-wallet caveat. Unavailable analysis prints a reason and exits 0; `--json` emits the availability union. No key. |
129
130
  | `candle plans` | The plans the API serves (`GET /api/v1/agent/plans`): each plan's monthly price, agent trade fee, Hyperliquid perps builder fee, the limits a new key gets, and one row per capability (buying and selling tokens not launched on Candle, self-launch, atomic launch, linked wallets, perps, limit orders). Every number is the server's; the CLI bundles none. Needs no key and sends none. `--json` is the server's body. Your own plan is `candle doctor`'s Plan row. |
130
131
  | `candle lp pools\|add\|positions\|remove\|claim` | Meteora DAMM v2 liquidity from a TEE wallet through its bound key (`lp:write`, opt-in). `pools <token>` lists pools with liquidity, fee, volume and an estimated yield; `add <pool> --amount <n> <token> --wallet <tee>` opens or grows a position at the pool's ratio after showing both tokens' Token-2022 warnings; `positions` lists every position across your TEE wallets; `remove <position> --percent <n>` withdraws (100% also claims fees and closes the position); `claim <position>` claims fees and rewards. No Candle fee. A `tee sweep` closes open positions itself; see TEE wallets. |
131
132
  | `candle perps setup\|deposit\|open\|close\|cancel\|orders\|positions\|leverage` | Hyperliquid perpetuals from the EVM TEE wallet bound to the key (`perps:write`, opt-in). `setup` approves Candle's builder fee (0.1%, none on Max) once; `deposit <amount> <SOL\|USDC\|ETH\|USDG>` moves funds onto the Hyperliquid account through Relay from the key's Solana or Hood TEE wallet (`swap:write`; `--to` names the EVM TEE wallet from Solana; `deposit status <id>` reads it; no withdrawal yet); `open <coin> <long\|short> <size>` trades at market, or as a limit with `--price`, with optional `--tp` and `--sl`; `close <coin>` closes reduce-only; `cancel <cloid>`; `leverage <coin> <x> [--isolated]`; `orders` and `positions` read live. Candle builds each action within the key's limits; the CLI recomputes its hash and checks the action type and Candle's builder before anything is signed, then submits the signed action to Hyperliquid itself. `CANDLE_HYPERLIQUID_BUILDER` deliberately replaces the release builder pin; its use is shown in the preview. |
@@ -153,6 +154,7 @@ Every command accepts these global options:
153
154
  | `--factor <id\|kind>` | Vault commands: unlock with this envelope. |
154
155
  | `--device <id>` | Vault commands: the security key to use, by id. |
155
156
  | `--no-verify-account` | Skips the check that the stored key belongs to the profile's account. |
157
+ | `--full` | Prints ids in full where a table would shorten them (`9EAq…9Hd7`). |
156
158
  | `--json` | Machine-readable output instead of a formatted table or summary, generally the underlying API response. One exception: `auth login`'s JSON output still omits the plaintext device token and API key, matching its human-readable summary, since login never displays either value in any mode. |
157
159
  | `--help`, `-h` | Prints usage. |
158
160
  | `--version`, `-v` | Prints the CLI version. |
@@ -319,14 +321,15 @@ profile deletes its two stored credentials and nothing else; imported wallet sig
319
321
  wallet, not the profile. `candle wallets` marks, per linked wallet, whether this machine holds its
320
322
  signer (`stored`, `none`, or `stale` for a revoked wallet whose signer is still here).
321
323
 
322
- Every authenticated command prints `Profile: <name> Account: <account> at <api url>` before its
323
- own output (`--json` output is unchanged except `auth status`, `auth login` and `doctor`, which
324
- carry `profile` and `account`; `auth status` and `doctor` also carry `cachedAccount`, the account
325
- the profile recorded, whenever a profile is resolved; scripts get identity from
326
- `auth status --json`). The account is cached
324
+ Every authenticated command prints `Profile <name> · Account <account> · <api host>`, then a
325
+ blank line, before its own output. Plain mode, a pipe and CI use `-` in place of `·`. The
326
+ address is shortened (`FfU8…8pPD`; `--full` prints it whole) and an `https://` scheme is dropped. `--json` output is unchanged except `auth status`,
327
+ `auth login` and `doctor`, which carry `profile` and `account`; `auth status` and `doctor` also
328
+ carry `cachedAccount`, the account the profile recorded, whenever a profile is resolved; scripts
329
+ get identity from `auth status --json`. The account is cached
327
330
  at login from the API. Where the line is printed from that cache and `CANDLE_API_KEY` or
328
331
  `CANDLE_DEVICE_TOKEN` is overriding the stored credential, it reads
329
- `Account: unknown (CANDLE_API_KEY override)` rather than naming an account that credential was
332
+ `Account unknown (CANDLE_API_KEY override)` rather than naming an account that credential was
330
333
  never checked against; `auth status` and `setup` look the account up live and print what they
331
334
  get, and `auth status` and `doctor` name the account the profile recorded beside it when the two
332
335
  differ (not under an env credential override, where the live answer is not the profile's key's).
@@ -456,11 +459,11 @@ has no price impact or token receipt and shows its maximum SOL debit. Without `-
456
459
  no first buy; use a separate swap for that buy. With `--buy <amount>` (whole units of the quote
457
460
  asset, as `--amount` is for a swap) the same wallet buys at launch: as its own leg in one Jito bundle with the launch on
458
461
  Solana, as a last leg after the curve and the fee on Hood. Candle reserves the buy against the
459
- key's spend window before anything is signed. `--buy` needs the server's
462
+ key's spend window before anything is signed. A TEE `--buy` needs the server's
460
463
  `TEE_LAUNCH_BUYS_ENABLED=1`, which is off by default; while it is off Candle refuses the buy
461
464
  (`VALIDATION_FAILED` on `buyAmount`) and nothing is built or signed.
462
465
 
463
- Swaps require `swap:write`. Launch requires `launch:write` **and** `allowLaunch` on the
466
+ Swaps require `swap:write`. A TEE launch requires `launch:write` **and** `allowLaunch` on the
464
467
  wallet, which is off by default. The account owner (not Candle, and not the agent) sets it with
465
468
  `candle wallets allow-launch <wallet>` and clears it with `candle wallets disallow-launch <wallet>`,
466
469
  over the device token from `candle auth login` (the same endpoint, `PUT /api/v1/agent/wallets/<id>/capabilities`,
@@ -488,28 +491,35 @@ read the existing `GET /api/v1/agent/keys/{prefix}/pnl`. The answer adds an opti
488
491
  `hyperliquid` section, and the CLI prints it under **Hyperliquid**. The existing read
489
492
  authentication applies; on an older API the section is simply absent. No additional signing, deposit or setup is needed for this read.
490
493
 
491
- The section reports main-exchange perp `realizedGrossUsd` (venue `closedPnl`), signed
492
- `fundingUsd` (received positive, paid negative), `feesUsd` (venue fees including builder fees;
493
- rebates are negative), and `realizedNetUsd = realizedGrossUsd + fundingUsd - feesUsd`.
494
- Builder fees are already included in the venue fee and are not subtracted again. These figures
495
- stay separate from spot and LP totals and exclude unrealized perps, deposits and withdrawals.
496
-
497
- Coverage is **currently bound EVM TEE wallets since the current TEE binding**,
498
- shown in `byWallet` with `startTime` in epoch milliseconds. That start is the latest rebind
499
- onto this key, or the wallet's creation time when it was bound then and never rebound. A
500
- rebound wallet does not bring its previous key's history. A wallet-set row is not required,
501
- and an older one cannot move the start earlier than the binding. Revoked and previous
502
- bindings, spot and HIP-3 fills are excluded. This is a binding-period read, not lifetime or
503
- order-level attribution.
504
-
505
- Reads use the venue client's two-second cache. `userFills` is capped at 2,000 recent rows;
506
- `userFunding` at 500 rows from `startTime`, and this response covers at most 20 bound
507
- wallets. `truncated` flags any reached history cap or remaining wallet page; `byWallet` names
508
- `fillsTruncated` and `fundingTruncated`. Funding and fills can cover different time spans when
509
- capped: a partial net must not be quoted as a lifetime figure. On upstream, wallet-discovery or
510
- malformed-data failure the section is `{ read: false, reason }`, without amounts; spot PnL still
511
- answers. An empty successful read is `{ read: true, ... }` with zero amounts. `--json` preserves
512
- the section and its coverage fields. Agent boards are outside this slice.
494
+ The section reports main-exchange perps for **every EVM TEE wallet bound to the key's profile,
495
+ per binding period** (`coverage: "profile"`; revoked, swept and rebound wallets included for the
496
+ time they were the profile's). `realizedGrossUsd` is the venue `closedPnl`, `fundingUsd` is
497
+ signed (received positive, paid negative), `feesUsd` is venue fees including builder fees
498
+ (rebates are negative), and `realizedNetUsd = realizedGrossUsd + fundingUsd - feesUsd`. Builder
499
+ fees are already included in the venue fee and are not subtracted again. `unrealizedUsd` is the
500
+ open positions' unrealized at each wallet's cutoff, `netUsd = realizedNetUsd + unrealizedUsd`
501
+ (both USD decimal strings), and `positions` lists the open positions, each with
502
+ `fundingNetUsd` positive when earned. Deposits and withdrawals are not P&L.
503
+
504
+ Facts and unrealized stop at the same cutoff per wallet. For a wallet still bound to the
505
+ profile, the cutoff is Hyperliquid's position time at this read: the fills and funding since the
506
+ wallet's last stored snapshot are read through that time and must reconcile with the positions
507
+ (each fill continues the previous position, the positions match, and every open hour has its
508
+ funding row). That wallet's `byWallet` entries say `reconciliation: "live"`, and the CLI prints
509
+ "(live, not yet settled)". A wallet whose binding to the profile ended before its last stored
510
+ snapshot is `settled`. `markedAt` is the oldest wallet cutoff, `completeThroughMs` the lowest
511
+ completeness watermark, and `perpsSnapshotId` identifies the cutoff vector. "Reconciled" is not
512
+ "complete": a round opened and closed between two fills Hyperliquid never returned cannot be
513
+ seen.
514
+
515
+ The net is **also counted in the total**: when `read` is true, `pnl.totalUsd` includes `netUsd`
516
+ and the answer's `perpsInTotal` is `true`; the CLI's `Total` line says it includes Hyperliquid.
517
+ When the section cannot be read or reconciled within the request's Hyperliquid budget, it is
518
+ `{ read: false, code, reason }` without amounts, `pnl.totalUsd` is the spot total,
519
+ `perpsInTotal` is `false`, and the CLI says the total excludes perps and why. Never a zero.
520
+ `historyPartial` (and `partialReasons`) flags history the stored record does not cover;
521
+ `truncated` repeats it for older CLIs. At most 20 wallets are read. `--json` preserves the
522
+ section and its coverage fields. Agent boards are outside this slice.
513
523
 
514
524
 
515
525
  ## CNDL staking