@candledottv/cli 0.13.10 → 0.13.12
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 +10 -7
- package/dist/index.js +158 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ one self-contained `dist/index.js` that runs under plain Node.
|
|
|
7
7
|
|
|
8
8
|
The full custody guide is [CLI custody](https://docs.candle.tv/developers/cli-custody), and every
|
|
9
9
|
command and flag is in the [Candle CLI reference](https://docs.candle.tv/developers/cli).
|
|
10
|
+
Not sure this is the right tool? [How to choose: SDK, MCP or CLI](https://docs.candle.tv/developers/choose-a-surface).
|
|
10
11
|
|
|
11
12
|
`candle vault rename --pairs-from <file> [--dry-run]` renames 1–256 vault or external keys under
|
|
12
13
|
one unlock and one commit. Use `<label|address|id> <new-label>` lines or CSV columns `from,to`
|
|
@@ -84,7 +85,7 @@ emergency procedure, rebinding, trusted wallets and API key access levels are al
|
|
|
84
85
|
| Command | What it does |
|
|
85
86
|
| --- | --- |
|
|
86
87
|
| `candle setup [--no-browser]` | The onboarding wizard: authorizes this device (skipped when already authorized), prints the agent wallets as funding destinations plus the paste-into-your-agent brief, shows the skill/MCP install lines, runs the full doctor check (setup's exit code is doctor's), and links the web console. Safe to re-run. |
|
|
87
|
-
| `candle auth login [--api-url <url>] [--profile <name>] [--scopes <a,b,c>] [--label <name>] [--embedded-wallet deny\|allow] [--no-browser]` | Authorizes this device: prints the API host and
|
|
88
|
+
| `candle auth login [--api-url <url>] [--profile <name>] [--scopes <a,b,c>] [--label <name>] [--embedded-wallet deny\|allow] [--no-browser]` | Authorizes this device: prints the API host, a code and its expiry, opens (or prints) an approval URL, polls until approved, then stores the resulting device token and API key. A new profile needs `--api-url` or a prompt. `--label` names both the device and the key. `--embedded-wallet` defaults to deny. `transfer:bound` is refused here and granted afterwards with `keys access <prefix> --access withdraw`. |
|
|
88
89
|
| `candle auth status` | Shows which storage backend is in use, both credential prefixes, the config file path, and a live validity check for each credential. |
|
|
89
90
|
| `candle auth logout [--keep-key]` | Revokes the stored API key (skipped with `--keep-key`), clears local credentials and config, and prints the portal URL for revoking the device itself. |
|
|
90
91
|
| `candle keys list [--scopes]` | Lists this account's API keys: prefix, name, Read, Write or Withdraw access, environment, timestamps, and which device minted each one. `--scopes` adds the raw scopes, sorted. |
|
|
@@ -92,6 +93,8 @@ emergency procedure, rebinding, trusted wallets and API key access levels are al
|
|
|
92
93
|
| `candle keys access <prefix\|label\|self> (--access read\|write\|withdraw [--yes] \| --history)` | Changes an existing key's level in place (same key, wallets and caps). Widening needs the device token and the prefix typed back at a terminal; `--yes` skips the prompt when narrowing; `self` narrows the profile's own key and can never widen it. `--history` lists the key's changes and who made them. |
|
|
93
94
|
| `candle keys update <prefix\|label> --embedded-wallet allow\|deny [--yes]`, `candle keys self embedded-wallet deny` | Allow or deny a key the account's embedded wallet, with the device token (allowing needs the prefix typed back at a terminal). `self embedded-wallet deny` lets the profile's own key give it up with no prompt; a key can never allow itself. |
|
|
94
95
|
| `candle keys signer approve <code> --key <prefix\|label> [--reject]`, `candle keys signer move <prefix\|label> [--to-key <prefix\|label>]` | Key signers for bots on a different machine from the vault. `approve` accepts (or rejects) a key's signer request with the device token, after you type the full fingerprint the trading machine printed. `move`, on the machine holding a wallet's current signer, moves every wallet on the key onto its active signer; `--to-key` moves a revoked key's wallets to a live key. |
|
|
96
|
+
| `candle keys stop <prefix>` | Pause one key using the device token. Its requests are refused with `PROFILE_PAUSED` until resumed; the key and its local credential are kept. Repeating the command succeeds. |
|
|
97
|
+
| `candle keys resume <prefix>` | Resume a stopped key using the device token. Repeating the command succeeds. An API key cannot stop or resume itself; a revoked key cannot be resumed. |
|
|
95
98
|
| `candle keys revoke <prefix>` | Revokes an API key by prefix. Revoking the CLI's own stored key also clears it locally. |
|
|
96
99
|
| `candle keys wallets <prefix>`, `keys wallets set <prefix> --wallets <id,id>`, `keys wallets scope <prefix> --scope all\|selected` | Each key is an agent profile with its own wallet set: list it, replace it, or limit the profile to its assigned wallets. |
|
|
97
100
|
| `candle wallets` (alias `candle wallet`) | Shows the account's embedded (launch) wallets and any linked wallets, using the API key, with a `Signer` column saying whether this machine holds each linked wallet's signing key and a `Trusted` column saying whether it is yours (linked while signed in, or marked with `trust`). It links and revokes; it never generates or prints a key, which the vault now derives. |
|
|
@@ -101,7 +104,7 @@ emergency procedure, rebinding, trusted wallets and API key access levels are al
|
|
|
101
104
|
| `candle wallets close-empty [--wallet embedded\|<tee address\|label>] [--keep <mint>]... [--yes]` | Closes a wallet's empty token accounts and returns their rent to it, after a preview: the embedded wallet (`transfer:write`), or a Solana TEE wallet bound to the key (`swap:write`), whose close transactions Candle builds, this machine checks and the key signer approves. |
|
|
102
105
|
| `candle vault init\|status\|list\|new-key\|rename\|phrase show\|restore\|reconcile-exposure` | The encrypted local vault, `vault.enc` (Tier 1). `init` creates it with a passphrase factor and a 24-word recovery phrase (and no key), `new-key` derives a key inside it (`--count`, `--labels-from <file>` for many under one unlock), `list [filter] [--balances]` shows one line per key, `rename` changes a label only, `phrase show` displays the phrase on a terminal (never in `--json`, a log or a pipe), and `restore --phrase` rebuilds the derived keys on another machine with a new passphrase (`--count`, `--tee-count`, `--external-count`, `--evm-count` and `--evm-tee-count` for EVM keys and Hood TEE wallets, or a Solana gap scan with `--rpc-url`); a restored vault never allocates new keys. `reconcile-exposure` re-reads the account and adds exposure records, clearing nothing. No key ever leaves the vault to reach Candle. See [CLI custody](https://docs.candle.tv/developers/cli-custody). |
|
|
103
106
|
| `candle vault factor list\|add passphrase\|add security-key\|add touch-id\|add passkey\|remove` (or `vault enroll <kind>`), `vault backup --to <path>\|icloud`, `vault verify-backup <path>` | What can open the vault, and proving a copy of it works: `backup` verifies the copy in full before reporting (a copy is sealed, keeping only the passphrase and security-key envelopes, unless it goes to a recognised local disk or removable drive, so a cloud folder and any path the CLI cannot place are both sealed unless `--accept-shared-domain` is passed), and `verify-backup` re-checks an existing one against this vault's key and address set. `add security-key` enrolls a FIDO2 security key (CTAP2 `hmac-secret`, user-verified with the key's PIN or biometric) through the bundled `candle-fido2` helper (`--install-helper` fetches and verifies this release's helper first); one key is not a recoverable factor, two keys are a pair, an enrolled key can authorize adding another, and the passphrase stays the recovery floor. `add touch-id` and `add passkey` are refused with `VAULT_FACTOR_UNSUPPORTED_ON_PLATFORM` until the Apple-signed helper ships. Every vault command then takes `--factor <id\|passphrase\|security-key>` to say which envelope opens it and `--device <id>` to name the key when several are attached. |
|
|
104
|
-
| `candle vault transfer\|promote\|promote-batch\|fund\|demote\|export-key` | Moving value and authority. `transfer` and `fund` sign locally after showing the decoded transaction (`transfer` from a vault key or a promoted TEE wallet, which warns when an agent may be trading it and reports the finalized transfer to Candle's history; `fund` reaches a TEE wallet from its pinned vault key, or an external wallet, with no `--yes`; both verify once, at the unlock, which names the send, then show the destination grouped in fours and take a typed `confirm`); `promote --from <cold label>` derives a fresh TEE wallet pinned to that key (an EVM vault key becomes a Hood TEE wallet), `promote --in-place <label> --sweep-to <cold label>` promotes a key at its own address after a typed warning, `promote-batch --pairs-from <file>` does many in place under one unlock, `--to-key` binds the result to another of your keys, and `demote` (disable then sweep; `--emergency` sweeps even when the stop request fails) sends it back to its pinned vault; `export-key` is the one ceremony that writes a single private key to a file you name. |
|
|
107
|
+
| `candle vault transfer\|promote\|promote-batch\|fund\|demote\|export-key` | Moving value and authority. `transfer` and `fund` sign locally after showing the decoded transaction (`transfer` from a vault key or a promoted TEE wallet, which warns when an agent may be trading it and reports the finalized transfer to Candle's history; `fund` reaches a TEE wallet from its pinned vault key, or an external wallet, with no `--yes`; both verify once, at the unlock, which names the send, then show the destination grouped in fours and take a typed `confirm`); `promote --from <cold label>` derives a fresh TEE wallet pinned to that key (an EVM vault key becomes a Hood TEE wallet), `promote --in-place <label> --sweep-to <cold label>` promotes a key at its own address after a typed warning, `promote-batch --pairs-from <file>` does many in place under one unlock, `--to-key` binds the result to another of your keys, and `demote` (disable then sweep; `--emergency` sweeps even when the stop request fails) sends it back to its pinned vault; `export-key` is the one ceremony that writes a single private key to a file you name. `demote` takes several addresses, or `--all --empty` for every Solana TEE wallet with nothing left to sweep, under one unlock and one typed `confirm` (`--yes` skips it), with a result line per wallet and one `--json` document. |
|
|
105
108
|
| `candle external new\|list\|sweep` | External wallets for outside tools: keys on the vault's third branch (`m/44'/501'/n'/2'`), never delegated to Privy and never registered with Candle. `new` allocates one (and moves the vault to format version 3; refused in a restored vault), `list` shows them, and `sweep <external> --to <vault>` sends everything back to a named vault key, signed locally, confirmed by a typed `confirm` after the vault key's address is shown. See [Bring your own services](https://docs.candle.tv/developers/cli#bring-your-own-services). |
|
|
106
109
|
| `candle sign [--file <path>] --wallet <external>... [--broadcast] [--yes]`, `candle sign message --wallet <external> [--file <path>] [--yes]` | The generic signer: a base64 transaction any tool built, legacy or v0, decoded (lookup tables resolved) and simulated over your own RPC before it is displayed and signed with an external wallet only. A vault key, a TEE wallet or an unnamed signer is refused; a failing simulation is refused with no override; `--yes` skips the confirmation prompt and nothing else. `sign message` signs the exact bytes of a file or of stdin. |
|
|
107
110
|
| `candle secrets set\|list\|remove <name>` | Your own third-party API keys, in a keychain namespace separate from Candle's credentials (`tv.candle.cli.secrets`, or `secrets.enc` on the encrypted-file fallback). Typed on a hidden prompt, never sent to Candle, never printed after `set`; `list` shows names only. A plug-in receives one as `CANDLE_SECRET_<NAME>` only when named with `--secret`. |
|
|
@@ -116,8 +119,8 @@ emergency procedure, rebinding, trusted wallets and API key access levels are al
|
|
|
116
119
|
| `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. |
|
|
117
120
|
| `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. |
|
|
118
121
|
| `candle swap status <id> [--kind trade\|swap\|launch] [--wait]` | Read an operation without resending it; `--wait` follows a bridge until it ends. |
|
|
119
|
-
| `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. |
|
|
120
|
-
| `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] [--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, `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. `--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 and verified-active state, and the server's `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. |
|
|
122
|
+
| `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. |
|
|
123
|
+
| `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] [--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, `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. `--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 and verified-active state, and the server's `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. |
|
|
121
124
|
| `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. |
|
|
122
125
|
| `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. |
|
|
123
126
|
| `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. |
|
|
@@ -159,7 +162,7 @@ Every command accepts these global options:
|
|
|
159
162
|
| `--device <id>` | Vault commands: the security key to use, by id. |
|
|
160
163
|
| `--no-verify-account` | Skips the check that the stored key belongs to the profile's account. |
|
|
161
164
|
| `--full` | Prints ids in full where a table would shorten them (`9EAq…9Hd7`). |
|
|
162
|
-
| `--json` | Machine-readable output instead of a formatted table or summary, generally the underlying API response.
|
|
165
|
+
| `--json` | Machine-readable output instead of a formatted table or summary, generally the underlying API response. Two exceptions: `auth login`'s JSON result still omits the plaintext device token and API key, matching its human-readable summary, since login never displays either value in any mode; and its device-code progress (code, approval URL, expiry) is printed to stderr as one JSON object with `"stage":"device_code"`, keeping stdout a single parseable JSON value. |
|
|
163
166
|
| `--help`, `-h` | Prints usage. |
|
|
164
167
|
| `--version`, `-v` | Prints the CLI version. |
|
|
165
168
|
|
|
@@ -552,7 +555,7 @@ MIT, see [LICENSE](LICENSE). Third-party material, including the EFF long wordli
|
|
|
552
555
|
generated vault passphrases (CC BY 3.0 US), is listed in
|
|
553
556
|
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
554
557
|
|
|
555
|
-
### Immutable token updates
|
|
558
|
+
### Immutable token updates
|
|
556
559
|
|
|
557
560
|
`candle token update <address> --file ./update.txt --chain solana --idempotency-key <saved-key>`
|
|
558
561
|
posts 1–1000 characters with the account's `token-pages:write` key and fresh 0.5% eligibility.
|
|
@@ -563,7 +566,7 @@ soft-deletes a post owned by that key's account, including posts from its agents
|
|
|
563
566
|
Both commands support `--json` and default-off server refusals. Package release remains a separate
|
|
564
567
|
human-owned step.
|
|
565
568
|
|
|
566
|
-
### Token comments
|
|
569
|
+
### Token comments
|
|
567
570
|
|
|
568
571
|
`candle token comment <address> --file ./comment.txt --chain solana --idempotency-key <saved-key>`
|
|
569
572
|
posts 1–500 characters under the same `token-pages:write` key and fresh 0.5% eligibility as a
|
package/dist/index.js
CHANGED
|
@@ -3476,7 +3476,7 @@ var init_terminal_theme = __esm(() => {
|
|
|
3476
3476
|
});
|
|
3477
3477
|
|
|
3478
3478
|
// src/version.ts
|
|
3479
|
-
var CLI_VERSION = "0.13.
|
|
3479
|
+
var CLI_VERSION = "0.13.12";
|
|
3480
3480
|
|
|
3481
3481
|
// src/presentation.ts
|
|
3482
3482
|
function terminalStyle(deps, stream, machine = false) {
|
|
@@ -15771,7 +15771,9 @@ var init_trading = __esm(() => {
|
|
|
15771
15771
|
transaction: exports_external.string().min(1),
|
|
15772
15772
|
maxDebitLamports: exports_external.string().regex(/^\d+$/),
|
|
15773
15773
|
expiresAt: exports_external.number().finite(),
|
|
15774
|
-
fee: feeSchema.optional()
|
|
15774
|
+
fee: feeSchema.optional(),
|
|
15775
|
+
feeWallet: exports_external.string().optional(),
|
|
15776
|
+
feeWalletSource: exports_external.string().optional()
|
|
15775
15777
|
});
|
|
15776
15778
|
walletSchema = exports_external.object({
|
|
15777
15779
|
id: exports_external.string(),
|
|
@@ -38464,7 +38466,7 @@ var init_token_clusters = __esm(() => {
|
|
|
38464
38466
|
});
|
|
38465
38467
|
|
|
38466
38468
|
// ../mcp/src/version.ts
|
|
38467
|
-
var SERVER_VERSION = "0.10.
|
|
38469
|
+
var SERVER_VERSION = "0.10.29";
|
|
38468
38470
|
|
|
38469
38471
|
// ../mcp/src/update-notice.ts
|
|
38470
38472
|
function newer(a, b) {
|
|
@@ -39722,7 +39724,7 @@ var init_launch_definition = __esm(() => {
|
|
|
39722
39724
|
{
|
|
39723
39725
|
key: "feeWallet",
|
|
39724
39726
|
type: "string",
|
|
39725
|
-
help: "Solana only: the wallet this launch's curve and pool fees earn to, an on-curve wallet or a Squads v4 vault; defaults to the account wallet.",
|
|
39727
|
+
help: "Solana only: the wallet this launch's curve and pool fees earn to, an on-curve wallet or a Squads v4 vault; defaults to the wallet that launches the token (the account wallet on a server without LAUNCH_FEE_WALLET_FROM_LAUNCHER, except an embedded launch).",
|
|
39726
39728
|
chains: [
|
|
39727
39729
|
"solana"
|
|
39728
39730
|
],
|
|
@@ -44683,6 +44685,18 @@ function buildRequest(name, args, cfg) {
|
|
|
44683
44685
|
init: { method: "POST", headers: jsonHeaders(apiKey), body: JSON.stringify(body) }
|
|
44684
44686
|
};
|
|
44685
44687
|
}
|
|
44688
|
+
case "candle_atomic_launch_dry_run": {
|
|
44689
|
+
const apiKey = requireApiKey2(cfg);
|
|
44690
|
+
const { payer, chain: _chain, buyAmount: _buyAmount, ...rest } = args;
|
|
44691
|
+
return {
|
|
44692
|
+
url: `${base2}/api/v1/launch/atomic/dry-run`,
|
|
44693
|
+
init: {
|
|
44694
|
+
method: "POST",
|
|
44695
|
+
headers: jsonHeaders(apiKey),
|
|
44696
|
+
body: JSON.stringify({ ...rest, chain: "solana", payer: payer ?? { type: "main" } })
|
|
44697
|
+
}
|
|
44698
|
+
};
|
|
44699
|
+
}
|
|
44686
44700
|
case "candle_get_market": {
|
|
44687
44701
|
const { chain: chain2, mint } = args;
|
|
44688
44702
|
return {
|
|
@@ -45355,7 +45369,7 @@ MARKET_NOT_FOUND means Candle has no market for that token and this could not ru
|
|
|
45355
45369
|
}, async (args) => callAndRelay("candle_claim_staking_reward", args, getConfig(), doFetch));
|
|
45356
45370
|
register("candle_get_fees", {
|
|
45357
45371
|
title: "Read the creator fees this account's tokens can pay",
|
|
45358
|
-
description: "The tokens launched by the account's own wallets, with what each could pay now in creator fees " + "(raw units from direct chain reads) and `
|
|
45372
|
+
description: "The tokens launched by the account's own wallets, with what each could pay now in creator fees " + "(raw units from direct chain reads) and a `reason` saying who can claim: `claimable_by_key` on a " + "claimable Solana row, and otherwise why this key cannot (including `claimable_via_web_session` " + "and `fee_wallet_designated`, which name whose authority collects). Reads only; " + "moves nothing. It returns no earned or paid-out totals. An unreadable token is marked, never " + "shown as zero. Paged: pass `continueCursor` back as `cursor`.",
|
|
45359
45373
|
inputSchema: getFeesShape
|
|
45360
45374
|
}, async (args) => callAndRelay("candle_get_fees", args, getConfig(), doFetch));
|
|
45361
45375
|
register("candle_claim_fees", {
|
|
@@ -45468,6 +45482,12 @@ MARKET_NOT_FOUND means Candle has no market for that token and this could not ru
|
|
|
45468
45482
|
const result = await executeTrade(args, getConfig(), doFetch);
|
|
45469
45483
|
return { content: [{ type: "text", text: result.text }], ...result.isError ? { isError: true } : {} };
|
|
45470
45484
|
});
|
|
45485
|
+
register("candle_atomic_launch_dry_run", {
|
|
45486
|
+
title: "Dry-run an atomic Solana launch",
|
|
45487
|
+
description: "Check a Solana launch bundled with first buys and price each buy, without building anything. Runs the " + "same checks as the atomic build, in the same order (payers, Believer check, fee and spend limits, the " + "key's transaction cap), then returns the launch preview (curveTerms) and one fill per first buy: the " + "tokens it would receive and the floor the build would sign it at. Reads only; moves nothing, reserves " + "nothing, and the clientLaunchId stays unused. It does not check balances, the daily cap, or the " + "transaction's size, so the real launch can still refuse. Needs launch:write, swap:write and Pro or Max.",
|
|
45488
|
+
inputSchema: atomicLaunchDryRunShape,
|
|
45489
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
|
|
45490
|
+
}, async (args) => callAndRelay("candle_atomic_launch_dry_run", args, getConfig(), doFetch));
|
|
45471
45491
|
register("candle_launch_and_seed", {
|
|
45472
45492
|
title: "Launch a token and seed it",
|
|
45473
45493
|
description: "Launch a new token from the account's embedded wallet, with an optional dev-buy seed, then " + "return the fresh market state and token links in one result. On solana a seed makes this " + (options.headlessSeed === true ? "the seed is a separate first-buy transaction in the same Jito bundle as the launch, so " + "both land or neither does. That works on every plan, Free included, and needs no " + "swap:write. On hood the seed is " : "the atomic launch: the launch and the seed are two transactions Candle signs and sends as " + "one Jito bundle, so both land or neither does. That needs Pro or Max (TIER_REQUIRED " + "otherwise) and swap:write on the key, and the result carries bundleId. On hood the seed is ") + "a best-effort follow-up. A launch with no seed works on every plan, Free included. MOVES " + "REAL FUNDS unless dryRun; dry-run first, which spends nothing. Seeds above the platform " + "dev-buy ceiling are rejected (DEV_BUY_TOO_HIGH): at most 0.5 SOL / 500 USDC / 2,000,000 " + "CNDL, or on an exp- curve 10% of the threshold when that is lower; the server holds the " + "creator's own seed to the effective ceiling, so launch with the largest devBuy it allows " + "and top up with candle_trade. " + LAUNCH_SHARED_SENTENCES + (imageDir ? IMAGE_PATH_DISCLOSURE : ""),
|
|
@@ -45670,7 +45690,7 @@ async function registerEligibleProfileTool(server, env = process.env, doFetch =
|
|
|
45670
45690
|
}
|
|
45671
45691
|
return eligible;
|
|
45672
45692
|
}
|
|
45673
|
-
var VAMP_CANDIDATES_DESCRIPTION, localProfileTools, STAKING_DISCLOSURE = "No instant unstake. Read pool.withdrawalTimelockSeconds for the wait. Solana rewards accrue to the holding wallet. sCNDL in any eligible account wallet counts toward Pro and earns the account's Hood staking reward, except a wallet another account also claims, wallets past the 200-wallet cap, and an account with no EVM wallet. CNDL in a pending withdrawal counts toward nothing for Pro.", stakingWriteShape, TOOL_NAMES, LAB_TOOL_NAMES, PROFILE_EDIT_TOOL_NAMES, isProfileEditTool = (name) => PROFILE_EDIT_TOOL_NAMES.includes(name), OPERATION_NOT_FOUND_RULE, getMarketShape, TOKEN_EVENTS_LIMIT_MESSAGE = "limit must be a whole number from 1 to 1000", tokenEventsLimit, TOKEN_EVENTS_KIND_NOTE = "kept back from the request and applied to the returned page by this server, so a filtered page can be shorter than limit while older events of other kinds remain: page with nextCursor as before until it is null", tokenCardShape, tokenEventsShape, tokenForensicsShape, FEED_LIMIT_MESSAGE = "limit must be a whole number from 1 to 200", feedLimit, getFeedShape, reportActivityShape, getAgentProfileShape, listAgentsShape, createPostShape, deletePostShape, listAgentPostsShape, getAgentPositionsShape, getOperationShape, vampCandidatesShape, getFeesShape, claimFeesShape, resolveTokenShape, profileWalletsShape, profilePnlShape, profileTradesShape, setProfileWalletsShape, swapShape, tradeShape, tokenImageUrl, tokenBannerUrl, localImageShape, localLaunchTokenShape, localLaunchAndSeedShape, IMAGE_PATH_DISCLOSURE, transferShape, sweepShape, PROFILE_PNL_HYPERLIQUID;
|
|
45693
|
+
var VAMP_CANDIDATES_DESCRIPTION, localProfileTools, STAKING_DISCLOSURE = "No instant unstake. Read pool.withdrawalTimelockSeconds for the wait. Solana rewards accrue to the holding wallet. sCNDL in any eligible account wallet counts toward Pro and earns the account's Hood staking reward, except a wallet another account also claims, wallets past the 200-wallet cap, and an account with no EVM wallet. CNDL in a pending withdrawal counts toward nothing for Pro.", stakingWriteShape, TOOL_NAMES, LAB_TOOL_NAMES, PROFILE_EDIT_TOOL_NAMES, isProfileEditTool = (name) => PROFILE_EDIT_TOOL_NAMES.includes(name), OPERATION_NOT_FOUND_RULE, getMarketShape, TOKEN_EVENTS_LIMIT_MESSAGE = "limit must be a whole number from 1 to 1000", tokenEventsLimit, TOKEN_EVENTS_KIND_NOTE = "kept back from the request and applied to the returned page by this server, so a filtered page can be shorter than limit while older events of other kinds remain: page with nextCursor as before until it is null", tokenCardShape, tokenEventsShape, tokenForensicsShape, FEED_LIMIT_MESSAGE = "limit must be a whole number from 1 to 200", feedLimit, getFeedShape, reportActivityShape, getAgentProfileShape, listAgentsShape, createPostShape, deletePostShape, listAgentPostsShape, getAgentPositionsShape, getOperationShape, vampCandidatesShape, getFeesShape, atomicPayerShape, atomicLaunchDryRunShape, claimFeesShape, resolveTokenShape, profileWalletsShape, profilePnlShape, profileTradesShape, setProfileWalletsShape, swapShape, tradeShape, tokenImageUrl, tokenBannerUrl, localImageShape, localLaunchTokenShape, localLaunchAndSeedShape, IMAGE_PATH_DISCLOSURE, transferShape, sweepShape, PROFILE_PNL_HYPERLIQUID;
|
|
45674
45694
|
var init_tools = __esm(() => {
|
|
45675
45695
|
init_zod();
|
|
45676
45696
|
init_client2();
|
|
@@ -45735,6 +45755,7 @@ var init_tools = __esm(() => {
|
|
|
45735
45755
|
"candle_get_plans",
|
|
45736
45756
|
"candle_trade",
|
|
45737
45757
|
"candle_launch_and_seed",
|
|
45758
|
+
"candle_atomic_launch_dry_run",
|
|
45738
45759
|
"candle_swap",
|
|
45739
45760
|
"candle_transfer",
|
|
45740
45761
|
"candle_sweep",
|
|
@@ -45886,6 +45907,22 @@ var init_tools = __esm(() => {
|
|
|
45886
45907
|
cursor: exports_external.string().optional().describe("The previous page's continueCursor, verbatim"),
|
|
45887
45908
|
limit: exports_external.number().optional().describe("Tokens per page, 1 to 50 (default 20). Each one costs chain reads")
|
|
45888
45909
|
};
|
|
45910
|
+
atomicPayerShape = exports_external.union([
|
|
45911
|
+
exports_external.object({ type: exports_external.literal("main") }),
|
|
45912
|
+
exports_external.object({ type: exports_external.literal("linked"), linkedWalletId: exports_external.string().min(1) })
|
|
45913
|
+
]);
|
|
45914
|
+
atomicLaunchDryRunShape = (() => {
|
|
45915
|
+
const { buyAmount: _buyAmount, chain: _chain, ...launch } = launchTokenShape;
|
|
45916
|
+
return {
|
|
45917
|
+
...launch,
|
|
45918
|
+
clientLaunchId: exports_external.string().optional().describe("Not used by a dry run; send the id you will launch with"),
|
|
45919
|
+
payer: atomicPayerShape.optional().describe("Who pays for the launch: {type:'main'} (default) or {type:'linked', linkedWalletId}"),
|
|
45920
|
+
firstBuys: exports_external.array(exports_external.object({
|
|
45921
|
+
payer: atomicPayerShape,
|
|
45922
|
+
amountRaw: exports_external.string().regex(/^[1-9][0-9]*$/).describe("Quote-asset raw units")
|
|
45923
|
+
})).min(1).max(4).describe("One to four first buys, each priced on the curve this launch would deploy")
|
|
45924
|
+
};
|
|
45925
|
+
})();
|
|
45889
45926
|
claimFeesShape = {
|
|
45890
45927
|
mint: exports_external.string().describe("The launched token: a Solana mint or a Hood token address, as candle_get_fees lists it"),
|
|
45891
45928
|
dryRun: exports_external.boolean().optional().describe("Check and read only. Sends nothing and writes nothing. Use it first to see what would be claimed")
|
|
@@ -74853,6 +74890,9 @@ init_keys_embedded_wallet();
|
|
|
74853
74890
|
var DEVICE_CODE_PATH = "/api/v1/agent/device/code";
|
|
74854
74891
|
var DEVICE_TOKEN_PATH = "/api/v1/agent/device/token";
|
|
74855
74892
|
var MAX_CLIENT_NAME_LENGTH = 64;
|
|
74893
|
+
function expiresInWords(seconds) {
|
|
74894
|
+
return seconds % 60 === 0 ? `${seconds / 60}m` : `${seconds}s`;
|
|
74895
|
+
}
|
|
74856
74896
|
function loginApiUrlFault(value, env) {
|
|
74857
74897
|
let url;
|
|
74858
74898
|
try {
|
|
@@ -74975,11 +75015,14 @@ async function authLogin(args, ctx) {
|
|
|
74975
75015
|
const code = codeResult.body;
|
|
74976
75016
|
const progress = json ? deps.stderr : deps.stdout;
|
|
74977
75017
|
if (json) {
|
|
74978
|
-
progress.write(
|
|
74979
|
-
|
|
74980
|
-
|
|
74981
|
-
|
|
74982
|
-
|
|
75018
|
+
progress.write(`${JSON.stringify({
|
|
75019
|
+
stage: "device_code",
|
|
75020
|
+
apiUrl,
|
|
75021
|
+
userCode: code.userCode,
|
|
75022
|
+
verificationUri: code.verificationUri,
|
|
75023
|
+
verificationUriComplete: code.verificationUriComplete,
|
|
75024
|
+
expiresIn: code.expiresIn
|
|
75025
|
+
})}
|
|
74983
75026
|
`);
|
|
74984
75027
|
} else {
|
|
74985
75028
|
const style = terminalStyle(deps, "stdout");
|
|
@@ -74988,7 +75031,8 @@ async function authLogin(args, ctx) {
|
|
|
74988
75031
|
${fields([
|
|
74989
75032
|
["API", apiUrl],
|
|
74990
75033
|
["Device code", code.userCode],
|
|
74991
|
-
["Approve at", code.verificationUriComplete]
|
|
75034
|
+
["Approve at", code.verificationUriComplete],
|
|
75035
|
+
["Code expires in", expiresInWords(code.expiresIn)]
|
|
74992
75036
|
], style).join(`
|
|
74993
75037
|
`)}
|
|
74994
75038
|
|
|
@@ -76100,7 +76144,7 @@ var LAUNCH_DEFINITION = {
|
|
|
76100
76144
|
{
|
|
76101
76145
|
key: "feeWallet",
|
|
76102
76146
|
type: "string",
|
|
76103
|
-
help: "Solana only: the wallet this launch's curve and pool fees earn to, an on-curve wallet or a Squads v4 vault; defaults to the account wallet.",
|
|
76147
|
+
help: "Solana only: the wallet this launch's curve and pool fees earn to, an on-curve wallet or a Squads v4 vault; defaults to the wallet that launches the token (the account wallet on a server without LAUNCH_FEE_WALLET_FROM_LAUNCHER, except an embedded launch).",
|
|
76104
76148
|
chains: [
|
|
76105
76149
|
"solana"
|
|
76106
76150
|
],
|
|
@@ -76756,7 +76800,7 @@ var HELP = {
|
|
|
76756
76800
|
launch: {
|
|
76757
76801
|
group: "Trade",
|
|
76758
76802
|
summary: "Create a token on Solana or Hood, with an optional first buy",
|
|
76759
|
-
description: "Creates a token from the wallet you name, with an optional first buy. Embedded launches use /launch/headless on every plan, with the key's embedded-wallet allowance and launch:write; no swap:write is needed. A Solana first buy is a creator bundle, signed by Candle. A Hood first buy is best effort after creation. TEE launches use /launch/self and require Pro or Max, allowLaunch, a bound key and verified authority. TEE buys need TEE_LAUNCH_BUYS_ENABLED on the server; Solana buys also need AGENT_TRADING_ENABLED and Jito. Existing server gates and ceilings apply. The embedded path previews the launch before confirmation; --dry-run stops at the preview. No buy creates only the token. Local image and banner uploads happen before confirmation and are public and permanent even if the launch is declined. Reuse --client-trade-id for recovery. On Solana, --fee-wallet <address> sets the wallet the launch's curve and pool fees earn to, an on-curve wallet by itself or a Squads v4 vault with --fee-wallet-multisig <address> and --fee-wallet-multisig-vault-index <n>; without it the fees earn to the account wallet,
|
|
76803
|
+
description: "Creates a token from the wallet you name, with an optional first buy. Embedded launches use /launch/headless on every plan, with the key's embedded-wallet allowance and launch:write; no swap:write is needed. A Solana first buy is a creator bundle, signed by Candle. A Hood first buy is best effort after creation. TEE launches use /launch/self and require Pro or Max, allowLaunch, a bound key and verified authority. TEE buys need TEE_LAUNCH_BUYS_ENABLED on the server; Solana buys also need AGENT_TRADING_ENABLED and Jito. Existing server gates and ceilings apply. The embedded path previews the launch before confirmation; --dry-run stops at the preview. No buy creates only the token. Local image and banner uploads happen before confirmation and are public and permanent even if the launch is declined. Reuse --client-trade-id for recovery. On Solana, --fee-wallet <address> sets the wallet the launch's curve and pool fees earn to, an on-curve wallet by itself or a Squads v4 vault with --fee-wallet-multisig <address> and --fee-wallet-multisig-vault-index <n>; without it the fees earn to the wallet that launches the token where the server has LAUNCH_FEE_WALLET_FROM_LAUNCHER on (an embedded launch already earns to its embedded wallet), otherwise to the account wallet, and the preview, the confirm and --check all say which; a live launch also warns on stderr when it defaults, and --require-fee-wallet refuses the launch without one. --check answers first, before any of it: which launch path works on this key and server (embedded allowance, tier, allowLaunch, TEE_LAUNCH_BUYS_ENABLED) in one call, with nothing uploaded, built or sent; name a wallet with --wallet to narrow it, and it exits 1 when no path works. status reads one launch by its mint or clientLaunchId: build, signed, confirmed, trading, bonded, then migrated, with the market's lifecycle and migration fields. --wait follows it until the token is trading, the launch has failed, or ten minutes pass.",
|
|
76760
76804
|
usage: [LAUNCH_USAGE, "candle launch status <mint-or-client-launch-id> [--wait]"],
|
|
76761
76805
|
rows: [
|
|
76762
76806
|
{
|
|
@@ -77261,7 +77305,9 @@ var HELP = {
|
|
|
77261
77305
|
invocation: "self embedded-wallet deny",
|
|
77262
77306
|
description: "The profile's own key gives up the embedded wallet, with no prompt. A key can never allow itself: the owner does that with keys update"
|
|
77263
77307
|
},
|
|
77264
|
-
{ invocation: "
|
|
77308
|
+
{ invocation: "stop <prefix>", description: "Pause one key with the device token; reversible with keys resume" },
|
|
77309
|
+
{ invocation: "resume <prefix>", description: "Resume a stopped key with the device token" },
|
|
77310
|
+
{ invocation: "revoke <prefix>", description: "Revoke an API key permanently" },
|
|
77265
77311
|
{
|
|
77266
77312
|
invocation: "signer approve <code> --key <prefix|label> [--reject]",
|
|
77267
77313
|
description: "Approve (or reject) a key's signer request with the device token; type the full fingerprint the trading machine printed"
|
|
@@ -77296,7 +77342,9 @@ var HELP = {
|
|
|
77296
77342
|
"candle tee rebind --label-prefix dest- --to-key Ab3dEf9h",
|
|
77297
77343
|
"candle keys signer approve ABCD-EFGH --key tr-2",
|
|
77298
77344
|
"candle keys signer move tr-2",
|
|
77299
|
-
"candle keys revoke ck_live_ab12"
|
|
77345
|
+
"candle keys revoke ck_live_ab12",
|
|
77346
|
+
"candle keys stop ck_live_ab12",
|
|
77347
|
+
"candle keys resume ck_live_ab12"
|
|
77300
77348
|
],
|
|
77301
77349
|
env: ENV_API
|
|
77302
77350
|
},
|
|
@@ -78207,6 +78255,7 @@ var TOOL_CLASSES = {
|
|
|
78207
78255
|
candle_execution_status: READ,
|
|
78208
78256
|
candle_get_operation: READ,
|
|
78209
78257
|
candle_get_fees: READ,
|
|
78258
|
+
candle_atomic_launch_dry_run: READ,
|
|
78210
78259
|
candle_get_staking: READ,
|
|
78211
78260
|
candle_perps_markets: READ,
|
|
78212
78261
|
candle_perps_market: READ,
|
|
@@ -89775,6 +89824,8 @@ var REASON_WORDS = {
|
|
|
89775
89824
|
embedded_wallet_not_permitted: "this key may not use the embedded wallet",
|
|
89776
89825
|
not_recipient: "the fees go to someone else, or the token has no fee vault",
|
|
89777
89826
|
fee_wallet_designated: "the fees go to this launch's designated fee wallet, which claims them itself",
|
|
89827
|
+
claimable_by_key: "claimable by this key",
|
|
89828
|
+
claimable_via_web_session: "the fees go to this account's web wallet; a signed-in session claims them",
|
|
89778
89829
|
insufficient_gas: "the recipient wallet cannot cover the network fee"
|
|
89779
89830
|
};
|
|
89780
89831
|
function reasonText(reason, missing) {
|
|
@@ -89809,7 +89860,7 @@ async function feesList(args, ctx) {
|
|
|
89809
89860
|
notice(ctx.deps, "stdout", "note", "No launched tokens on this account.");
|
|
89810
89861
|
else {
|
|
89811
89862
|
const rows = page.map((row) => {
|
|
89812
|
-
const status = row.unreadable ? "could not be read" : row.claimable ?
|
|
89863
|
+
const status = row.unreadable ? "could not be read" : row.claimable ? `${row.reason === "claimable_by_key" ? "claimable by this key" : "claimable"}: ${amountsText(row.claimableAmounts, missing)}` : `not claimable: ${reasonText(row.reason, missing)}`;
|
|
89813
89864
|
return [
|
|
89814
89865
|
safeText(String(row.symbol ?? row.name ?? row.mint)),
|
|
89815
89866
|
safeText(String(row.chain)),
|
|
@@ -90388,6 +90439,63 @@ ${fields(rows, style).join(`
|
|
|
90388
90439
|
return 0;
|
|
90389
90440
|
}
|
|
90390
90441
|
|
|
90442
|
+
// src/commands/keys-stop.ts
|
|
90443
|
+
init_args();
|
|
90444
|
+
init_client();
|
|
90445
|
+
init_deps();
|
|
90446
|
+
init_presentation();
|
|
90447
|
+
init_profiles();
|
|
90448
|
+
init_key_output();
|
|
90449
|
+
init_keys();
|
|
90450
|
+
function keysStop(args, ctx) {
|
|
90451
|
+
return setKeyPaused(args, ctx, true);
|
|
90452
|
+
}
|
|
90453
|
+
function keysResume(args, ctx) {
|
|
90454
|
+
return setKeyPaused(args, ctx, false);
|
|
90455
|
+
}
|
|
90456
|
+
async function setKeyPaused(args, ctx, paused) {
|
|
90457
|
+
const { deps, apiUrl, json } = ctx;
|
|
90458
|
+
const parsed = parseArgs(args, {});
|
|
90459
|
+
if ("error" in parsed) {
|
|
90460
|
+
writeScreenUsageFailure(deps, parsed.error, json);
|
|
90461
|
+
return 2;
|
|
90462
|
+
}
|
|
90463
|
+
const prefix = parsed.positionals[0];
|
|
90464
|
+
if (!prefix?.trim() || parsed.positionals.length !== 1) {
|
|
90465
|
+
writeScreenUsageFailure(deps, `Usage: candle keys ${paused ? "stop" : "resume"} <prefix>`, json);
|
|
90466
|
+
return 2;
|
|
90467
|
+
}
|
|
90468
|
+
await printIdentity(ctx);
|
|
90469
|
+
const deviceToken = await resolveDeviceToken(deps, ctx.profile);
|
|
90470
|
+
if (!deviceToken) {
|
|
90471
|
+
writeScreenLocalFailure(deps, NO_DEVICE_TOKEN, json);
|
|
90472
|
+
return 1;
|
|
90473
|
+
}
|
|
90474
|
+
const result = await apiRequest(`/api/v1/agent/keys/${encodeURIComponent(prefix)}/stop`, {
|
|
90475
|
+
method: "POST",
|
|
90476
|
+
auth: "device",
|
|
90477
|
+
credentials: { deviceToken },
|
|
90478
|
+
apiUrl,
|
|
90479
|
+
fetch: deps.fetch,
|
|
90480
|
+
env: deps.env,
|
|
90481
|
+
body: { paused }
|
|
90482
|
+
});
|
|
90483
|
+
if (!result.ok) {
|
|
90484
|
+
writeScreenFailure(deps, result, { apiUrl, authType: "device" }, json);
|
|
90485
|
+
return 1;
|
|
90486
|
+
}
|
|
90487
|
+
if (json) {
|
|
90488
|
+
deps.stdout.write(`${JSON.stringify(result.body)}
|
|
90489
|
+
`);
|
|
90490
|
+
return 0;
|
|
90491
|
+
}
|
|
90492
|
+
const body = result.body;
|
|
90493
|
+
const state = body.paused ? "stopped" : "resumed";
|
|
90494
|
+
deps.stdout.write(`${success(`Key ${prefix} ${body.changed ? "" : "already "}${state}.`, terminalStyle(deps, "stdout"))}
|
|
90495
|
+
`);
|
|
90496
|
+
return 0;
|
|
90497
|
+
}
|
|
90498
|
+
|
|
90391
90499
|
// src/commands/keys-wallets.ts
|
|
90392
90500
|
init_args();
|
|
90393
90501
|
init_client();
|
|
@@ -91028,7 +91136,8 @@ function decodeAddress(value, flag) {
|
|
|
91028
91136
|
throw new Error(`${flag} takes a Solana address.`);
|
|
91029
91137
|
}
|
|
91030
91138
|
}
|
|
91031
|
-
|
|
91139
|
+
var fromLauncher = (echo) => echo?.feeWalletSource === "launching_wallet" && typeof echo.feeWallet === "string";
|
|
91140
|
+
function feeWalletLines(selection, echo, launcherDefault = false) {
|
|
91032
91141
|
if (selection)
|
|
91033
91142
|
return [
|
|
91034
91143
|
`Fee wallet: ${selection.feeWallet} (earns this launch's fees; set by --fee-wallet)`,
|
|
@@ -91036,14 +91145,20 @@ function feeWalletLines(selection, echo) {
|
|
|
91036
91145
|
`Fee wallet multisig: ${selection.feeWalletMultisig.address}, vault ${selection.feeWalletMultisig.vaultIndex} (the Squads v4 multisig behind the fee wallet)`
|
|
91037
91146
|
] : []
|
|
91038
91147
|
];
|
|
91148
|
+
if (fromLauncher(echo))
|
|
91149
|
+
return [
|
|
91150
|
+
`Fee wallet: ${echo.feeWallet} (defaults to the launching wallet; pass --fee-wallet <address> to change it)`
|
|
91151
|
+
];
|
|
91152
|
+
if (launcherDefault)
|
|
91153
|
+
return ["Fee wallet: defaults to the launching wallet (pass --fee-wallet <address> to change it)."];
|
|
91039
91154
|
return [
|
|
91040
|
-
echo ? `Fee wallet: ${echo} (defaults to the account wallet; pass --fee-wallet <address> to change it)` : "Fee wallet: defaults to the account wallet (pass --fee-wallet <address> to change it)."
|
|
91155
|
+
echo?.feeWallet ? `Fee wallet: ${echo.feeWallet} (defaults to the account wallet; pass --fee-wallet <address> to change it)` : "Fee wallet: defaults to the account wallet (pass --fee-wallet <address> to change it)."
|
|
91041
91156
|
];
|
|
91042
91157
|
}
|
|
91043
|
-
var FEE_WALLET_DEFAULT_WARNING = "No --fee-wallet given: this launch's curve and pool fees earn to the account wallet. Pass --fee-wallet <address> to send them to another wallet.";
|
|
91044
|
-
function feeWalletQuoteLine(selection) {
|
|
91158
|
+
var FEE_WALLET_DEFAULT_WARNING = "No --fee-wallet given: this launch's curve and pool fees earn to the launching wallet, or to the account wallet on a server that does not record the launching wallet; the confirmation names which. Pass --fee-wallet <address> to send them to another wallet.";
|
|
91159
|
+
function feeWalletQuoteLine(selection, echo) {
|
|
91045
91160
|
if (!selection)
|
|
91046
|
-
return "defaults to the account wallet";
|
|
91161
|
+
return fromLauncher(echo) ? `${echo.feeWallet} (the launching wallet, by default)` : "defaults to the account wallet";
|
|
91047
91162
|
return `${selection.feeWallet}${selection.feeWalletMultisig ? ` (Squads vault of ${selection.feeWalletMultisig.address}, vault ${selection.feeWalletMultisig.vaultIndex})` : ""}`;
|
|
91048
91163
|
}
|
|
91049
91164
|
|
|
@@ -91190,7 +91305,8 @@ var checkSchema = exports_external.object({
|
|
|
91190
91305
|
switches: exports_external.object({
|
|
91191
91306
|
headlessLaunch: exports_external.boolean(),
|
|
91192
91307
|
agentTrading: exports_external.boolean(),
|
|
91193
|
-
teeLaunchBuys: exports_external.boolean()
|
|
91308
|
+
teeLaunchBuys: exports_external.boolean(),
|
|
91309
|
+
feeWalletFromLauncher: exports_external.boolean().optional()
|
|
91194
91310
|
}),
|
|
91195
91311
|
embedded: exports_external.object({
|
|
91196
91312
|
solana: exports_external.object({ address: exports_external.string(), delegated: exports_external.boolean().optional() }).nullable().optional(),
|
|
@@ -91302,8 +91418,9 @@ async function launchCheck(ctx, key, walletFlag, requestedChain, feeWallet = und
|
|
|
91302
91418
|
const lines = [`Launch paths for key ${answer2.key.keyPrefix} (tier ${answer2.key.tier}):`];
|
|
91303
91419
|
if (requestedChain)
|
|
91304
91420
|
lines.push(`Requested launch chain: ${chainName(requestedChain)}.`);
|
|
91421
|
+
const launcherDefault = answer2.switches.feeWalletFromLauncher === true;
|
|
91305
91422
|
if (!requestedChain || requestedChain === "solana")
|
|
91306
|
-
lines.push(...feeWalletLines(feeWallet));
|
|
91423
|
+
lines.push(...feeWalletLines(feeWallet, undefined, launcherDefault));
|
|
91307
91424
|
if (walletFlag === undefined || embeddedOnly)
|
|
91308
91425
|
lines.push(...embeddedLines(answer2, requestedChain));
|
|
91309
91426
|
for (const row of shownWallets)
|
|
@@ -91317,7 +91434,7 @@ async function launchCheck(ctx, key, walletFlag, requestedChain, feeWallet = und
|
|
|
91317
91434
|
...requestedChain ? { requestedChain } : {},
|
|
91318
91435
|
key: answer2.key,
|
|
91319
91436
|
switches: answer2.switches,
|
|
91320
|
-
...feeWallet ? { feeWallet: { ...feeWallet, set: true } } : { feeWallet: { default: "account wallet", set: false } },
|
|
91437
|
+
...feeWallet ? { feeWallet: { ...feeWallet, set: true } } : { feeWallet: { default: launcherDefault ? "launching wallet" : "account wallet", set: false } },
|
|
91321
91438
|
...answer2.embedded ? { embedded: answer2.embedded } : {},
|
|
91322
91439
|
wallets: shownWallets.map((row) => ({
|
|
91323
91440
|
...row,
|
|
@@ -91664,7 +91781,7 @@ async function launch(args, ctx) {
|
|
|
91664
91781
|
fee: built.fee ?? { bps: 0, feeRaw: "0" },
|
|
91665
91782
|
minimumReceived: buy ? "not quoted (the first buy on the new curve)" : "0 tokens (no first buy)",
|
|
91666
91783
|
maxDebitLamports: built.maxDebitLamports,
|
|
91667
|
-
feeWallet: feeWalletQuoteLine(feeWallet),
|
|
91784
|
+
feeWallet: feeWalletQuoteLine(feeWallet, built),
|
|
91668
91785
|
tokenRisks: []
|
|
91669
91786
|
};
|
|
91670
91787
|
notice(ctx.deps, "stderr", "note", buyNotice(buy, "solana").trim());
|
|
@@ -91794,14 +91911,19 @@ var previewSchema = exports_external.object({
|
|
|
91794
91911
|
}).passthrough().optional(),
|
|
91795
91912
|
devBuyMax: exports_external.string().nullable().optional(),
|
|
91796
91913
|
feeWallet: exports_external.string().optional(),
|
|
91914
|
+
feeWalletSource: exports_external.string().optional(),
|
|
91797
91915
|
fills: exports_external.array(exports_external.object({ index: exports_external.number(), amountRaw: exports_external.string(), supplyPct: exports_external.number() }).passthrough()).optional()
|
|
91798
91916
|
}).passthrough();
|
|
91799
91917
|
var percent = (value) => `${Number(value.toFixed(4))}%`;
|
|
91918
|
+
function feeWalletEchoOf(answer2) {
|
|
91919
|
+
const parsed = exports_external.object({ feeWallet: exports_external.string().optional(), feeWalletSource: exports_external.string().optional() }).safeParse(answer2);
|
|
91920
|
+
return parsed.success ? parsed.data : undefined;
|
|
91921
|
+
}
|
|
91800
91922
|
function previewLines(answer2, chain2, feeWallet = undefined) {
|
|
91801
91923
|
const parsed = previewSchema.safeParse(answer2);
|
|
91802
91924
|
if (!parsed.success)
|
|
91803
91925
|
return "";
|
|
91804
|
-
const { resolved, curveTerms: terms, devBuyMax, feeWallet: echo, fills } = parsed.data;
|
|
91926
|
+
const { resolved, curveTerms: terms, devBuyMax, feeWallet: echo, feeWalletSource, fills } = parsed.data;
|
|
91805
91927
|
const quote = (resolved?.quoteAsset ?? LAUNCH_DEFINITION.defaultQuote[chain2]).toUpperCase();
|
|
91806
91928
|
const decimals = (chain2 === "hood" ? HOOD_BASES[quote] : BASES[quote])?.decimals;
|
|
91807
91929
|
const whole = (raw) => decimals === undefined ? `${raw} raw` : `${shortAmount(raw, decimals)} ${quote}`;
|
|
@@ -91820,7 +91942,7 @@ function previewLines(answer2, chain2, feeWallet = undefined) {
|
|
|
91820
91942
|
if (devBuyMax)
|
|
91821
91943
|
lines.push(`Dev-buy ceiling: ${whole(devBuyMax)}.`);
|
|
91822
91944
|
if (chain2 === "solana")
|
|
91823
|
-
lines.push(...feeWalletLines(feeWallet, echo));
|
|
91945
|
+
lines.push(...feeWalletLines(feeWallet, { feeWallet: echo, feeWalletSource }));
|
|
91824
91946
|
return lines.length ? `${lines.join(`
|
|
91825
91947
|
`)}
|
|
91826
91948
|
` : "";
|
|
@@ -91886,7 +92008,9 @@ var atomicLegSchema = exports_external.object({
|
|
|
91886
92008
|
var atomicBuildSchema = exports_external.object({
|
|
91887
92009
|
bundleId: exports_external.string().min(1),
|
|
91888
92010
|
legs: exports_external.array(atomicLegSchema),
|
|
91889
|
-
expiresAt: exports_external.number().finite()
|
|
92011
|
+
expiresAt: exports_external.number().finite(),
|
|
92012
|
+
feeWallet: exports_external.string().optional(),
|
|
92013
|
+
feeWalletSource: exports_external.string().optional()
|
|
91890
92014
|
});
|
|
91891
92015
|
var atomicOutcomeSchema = exports_external.discriminatedUnion("status", [
|
|
91892
92016
|
exports_external.object({ status: exports_external.literal("landed"), bundleId: exports_external.string(), mint: exports_external.string(), signatures: exports_external.array(exports_external.string()) }).passthrough(),
|
|
@@ -91930,7 +92054,7 @@ async function atomicLaunch(ctx, key, args) {
|
|
|
91930
92054
|
candleFee: reading.feeRaw > 0n ? `${decimalAmount(reading.feeRaw.toString(), decimals)} ${quoteAsset} (the tier fee on the first buy, in its leg)` : "none on this first buy",
|
|
91931
92055
|
minimumReceived: minOut !== undefined ? `${minOut} raw units of the new token (the first buy's floor)` : "not quoted",
|
|
91932
92056
|
maxLoss: quoteAsset === "SOL" ? sol : `${sol} and ${decimalAmount(reading.quoteRaw.toString(), decimals)} ${quoteAsset}`,
|
|
91933
|
-
feeWallet: feeWalletQuoteLine(feeWalletSelection(flags)),
|
|
92057
|
+
feeWallet: feeWalletQuoteLine(feeWalletSelection(flags), built),
|
|
91934
92058
|
tokenRisks: [],
|
|
91935
92059
|
bundleId: built.bundleId
|
|
91936
92060
|
};
|
|
@@ -92092,7 +92216,7 @@ async function embeddedLaunch(ctx, key, args) {
|
|
|
92092
92216
|
venue: "curve launch (signed by Candle)",
|
|
92093
92217
|
priceImpactPct: null,
|
|
92094
92218
|
minimumReceived: "0 tokens (no first buy)",
|
|
92095
|
-
...chain2 === "solana" ? { feeWallet: feeWalletQuoteLine(feeWalletSelection(flags)) } : {},
|
|
92219
|
+
...chain2 === "solana" ? { feeWallet: feeWalletQuoteLine(feeWalletSelection(flags), feeWalletEchoOf(answer2)) } : {},
|
|
92096
92220
|
tokenRisks: []
|
|
92097
92221
|
};
|
|
92098
92222
|
if (buy && chain2 === "solana") {
|
|
@@ -92867,6 +92991,7 @@ var MCP_TOOL_NAMES = [
|
|
|
92867
92991
|
"candle_execution_status",
|
|
92868
92992
|
"candle_get_operation",
|
|
92869
92993
|
"candle_get_fees",
|
|
92994
|
+
"candle_atomic_launch_dry_run",
|
|
92870
92995
|
"candle_claim_fees",
|
|
92871
92996
|
"candle_get_staking",
|
|
92872
92997
|
"candle_stake",
|
|
@@ -115054,6 +115179,8 @@ var COMMANDS = {
|
|
|
115054
115179
|
limit: keysLimit,
|
|
115055
115180
|
self: keysSelf,
|
|
115056
115181
|
revoke: keysRevoke,
|
|
115182
|
+
stop: keysStop,
|
|
115183
|
+
resume: keysResume,
|
|
115057
115184
|
wallets: keysWallets,
|
|
115058
115185
|
signer: keysSigner
|
|
115059
115186
|
}
|
package/package.json
CHANGED