Uh oh!
There was an error while loading. Please reload this page.
feat: acp trade (swap + Hyperliquid) with copy polish - #34
Conversation
A single `acp trade` command for token swaps (same-chain and cross-chain via
the trading-agent server's BondingV5 / LiFi routing) and Hyperliquid (deposit,
spot, perp, withdraw). Routes by the params you pass: Hyperliquid is chain 1337,
so the chains decide the venue; `--side long|short` is a perp. Auto-balances the
HL perp/spot wallets so `deposit → trade` just works. Signing stays client-side
via the keystore signer; HL orders are EIP-712 actions.
Adds @nktkas/hyperliquid and bumps @virtuals-protocol/acp-node-v2 to ^0.1.2
(required for the provider signTypedData / sendTransaction APIs the trade flow
uses). Requires Node >=20.19 (engines) for the HL SDK. Documents the command in
README.md and SKILL.md.
Addresses review:
- spot market orders look up mids by `@{pairIndex}` (PURR special-cased), not
the pair name, which returned no mid.
- detectIntent gates perp on --side long|short so a stray --token can't
pre-empt chain-based spot routing.
- declare engines.node >=20.19.0 to match @nktkas/hyperliquid.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Hyperliquid lists leveraged perp markets beyond crypto (equities, currencies, commodities); the acp trade --side flags are identical across asset classes. Surface this in the SKILL.md frontmatter + trading section and the README perps section so agents know they can open stock/FX/commodity positions, not just crypto. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…trade` (#30) Adds a Treasures Finance route to `acp trade` — `--ticker` triggers a new "treasures-stock" intent and runs ownership-proof → quote → per-leg EIP-712 sign → submit → poll-status in one command. New `src/lib/treasures/client.ts` wraps the public Treasures API over `fetch` with HTTPS enforcement and TREASURES_API_URL / IS_TESTNET host selection. Also hardens the flow per review: - poll status once more after the final sleep so a late fill isn't misreported as TIMEOUT - non-zero exit code on terminal partial_failed / all_failed - validate --slippage-bps as a non-negative integer instead of sending null
A stock symbol is now named with --token everywhere; the companion flag picks the venue: --side -> HL perp, --amount-usdc/--amount-shares -> Treasures tokenized stock (spot). Drops the separate --ticker flag so an agent picks the asset once and the mode second, matching the CLI's params-decide-the-venue model. https://claude.ai/code/session_01C56LaYyFW7iRxtdY5tY3uA
Move the Treasures tokenized-stock flow out of the CLI and into the trading-agent planner. The CLI is now a thin signer: it POSTs a plan with a `treasures` block and drives the same /trade/plan + /trade/next loop as a swap, signing whatever the server asks via the new `sign` action. - runTradeLoop: handle `sign` actions (signTypedData / signMessage → post signature back). - runTreasuresStock: build a plan + run the loop; delete the ~150 lines of direct quote/sign/submit/poll and the now-dead lib/treasures/client.ts. - detectIntent: route a funded buy (--token ticker + --token-in/--chain-in/ --amount-in, no --token-out/--chain-out) to Treasures, so the server can bridge any chain's funds to USDC@eth before buying. - scripts/: tsx harnesses for the sign branch + detectIntent routing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rebasing the trade feature onto main surfaced two integration fixes: - package-lock.json: regenerate to include @nktkas/hyperliquid (the lock was taken from main during conflict resolution and lacked it). - getAgentApi: drop the walletAddress arg — main simplified getClient to (unauthenticated?: boolean), so passing a string no longer typechecks. The param was always ignored (resolveToken uses the config owner wallet). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add chain ID legend to --help (1 ETH, 42161 ARB, 8453 Base, 1337 HL) - Lead command description with cross-chain support - Clarify --chain-in/--chain-out flag descriptions with named chains - Clarify --amount-in is spend amount, not receive amount - Add --size/--leverage note in perp routing table - ensureHlFunds: actionable error with deposit command + leverage tip - --size error: explicitly say 'token units, not USD', show --leverage example - Progress labels: human-readable (Opening long / Buying / Selling vs Market long/buy/sell) - Spot validation: plain English instead of internal jargon
Fix/trade copywriting
- chains: parseChainArg() accepts named chain aliases (hyperliquid/hl, base, arb, eth, optimism, …) alongside numeric ids, case-insensitive. trade normalizes --chain-in/--chain-out up front so intent routing and the backend both get a clean id — `--chain-out hyperliquid` now works. - trade: new --dry-run flag previews any trade without signing/submitting. Swap/deposit/Treasures send dryRun to /trade/plan and render the server's new `preview` action; HL perp/spot/withdraw (signed client-side) compute and print their preview locally — size, notional, and margin at the effective leverage — without setting leverage, moving funds, or placing the order. - help: clarify --size is in token units (not USD); document aliases + --dry-run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removes two "two-ways-to-do-one-thing" footguns flagged in review: - Withdraw: collapse to one command. `acp trade withdraw-from-hl --amount <n>` is now the ONLY way to move USDC off Hyperliquid. Dropped the duplicate `--chain-in 1337 --chain-out <evm>` intent route and the ceremony it required (an explicit --chain-out whose only legal value was 42161 — HL's withdraw3 always settles to Arbitrum, so it was never a chain choice). --chain-in 1337 now means spot only; anything else points to the command. Adds --dry-run. - Slippage: one flag instead of two. `--slippage <pct>` (percent) now covers every route; removed `--slippage-bps` (the duplicate with a different unit that made `--slippage 300` mean wildly different things per route). Swaps/ Treasures convert pct→bps via slippageBpsFromPct; HL already used percent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…thdraw Backward-compat: existing callers/agents that move USDC off Hyperliquid via the chain-in/chain-out combo shouldn't break now that `withdraw-from-hl` is the canonical command. detectIntent routes `1337 → 42161` to the same withdrawal. HL's withdraw3 only ever settles to Arbitrum, so we honor 42161 and reject any other chain-out (with a message pointing at withdraw-from-hl) rather than silently sending to a chain HL can't reach. Docs/help updated to show the combo as an alias of withdraw-from-hl. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…dge onward) - Default: a bare HL withdraw (no --chain-out / --to-chain) settles to Arbitrum, where HL's withdraw3 always lands. - --chain-in 1337 --chain-out <evm> (or withdraw-from-hl --to-chain <id>) to a NON-Arbitrum chain now withdraws to Arbitrum first, waits for the funds to land (polls Arbitrum USDC balance, ~few min), then bridges the actual arrived amount onward via the normal swap/LiFi route. On settle-timeout it returns the exact follow-up bridge command — funds are never stranded without a next step. - detectIntent: chain-in 1337 with a non-USDC token-out still errors as a spot order missing --chain-out 1337, so a typo can't silently move funds off HL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`acp trade` with no flags previously dropped into a readline wizard. Drop it: the CLI is agent-first, and the wizard was a parallel input surface that could drift from the flag flows. With no intent in the flags, the command now errors with a pointer to `--help` instead. Removes runInteractive, the "interactive" intent, and the now-unused readline/prompt imports (the prompt lib stays — other commands use it). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The CLI is now a pure signer for Hyperliquid too. runPerp / runHlSpot / runWithdraw no longer touch the @nktkas ExchangeClient — they POST hl / hlSpot / hlWithdraw to /trade/plan and drive the existing runTradeLoop sign loop (the server builds each EIP-712 action; the CLI signs with the agent wallet). - Deletes the client-side execution: order placement, leverage, spot↔perp auto-balance (ensureHlFunds), the client withdraw-then-bridge, and the exitAfterOrder/placeHlOrder SDK-quirk workarounds. - lib/hl/client.ts shrinks to a read-only InfoClient for `trade status`; the ExchangeClient/signer wiring and order/price helpers are gone. - --dry-run, chain aliases, and the unified --slippage flag all keep working, now fully server-driven (the backend returns a `preview` action). Net −495 lines. `trade status` stays a client-side read (no signing). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…s intent The CLI no longer routes. `acp trade` collects whatever flags were passed into a flat body and POSTs to /trade/plan; the backend detects the venue and drives the sign loop. Deletes detectIntent + all per-venue run* functions (runSwap / runHlSpot / runPerp / runWithdraw / runTreasuresStock) and their helpers (isUsdcSymbol, validateTreasures*, parseSlippage, slippageBpsFromPct, parseChainArg usage). `withdraw-from-hl` stays as a thin alias that forwards the equivalent flat request; `status` stays a read-only HL query. Net big deletion; CLI is now a pure flag-forwarder + signer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`acp trade status` calls the new POST /trade/hl-status instead of reading HL directly. Deletes src/lib/hl/client.ts (the last HL SDK usage) and removes @nktkas/hyperliquid from package.json. The CLI now has zero Hyperliquid deps — all HL access (trade + status) goes through the backend. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
detectIntent was deleted (intent detection moved to the backend), so its harness no longer applies. tradeLoopSign.test.ts stays — runTradeLoop is still the CLI's sign loop and it passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sync package-lock.json after dropping the HL dependency, so `npm ci` no longer installs @nktkas/hyperliquid (or its transitive valibot). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…competent-raman-aac988
…policy, trim spot copy - Rename `acp trade status` to `acp trade hl-status`; clarify it's HL-account-only and that on-chain balances come from `acp wallet balance`. - add-signer: make the help/docs urge an explicit --policy (fallback is restricted, changing it later is manual); note unrestricted is for non-Virtuals contracts. - Remove concrete HL-spot how-to (examples + USDC-quoted note + table row); keep spot as a conceptual venue. Trim backend-plumbing prose to observable behavior. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 49a9b65. Configure here.
| } catch (err) { | ||
| outputError(json, err instanceof Error ? err : String(err)); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Documented trade picker missing
Medium Severity
README and SKILL state that running acp trade with no flags in a TTY opens an interactive picker for humans. The command action always calls runTrade with Commander options only; there is no TTY or empty-args branch and no use of the existing prompt helpers used elsewhere in the CLI.
Reviewed by Cursor Bugbot for commit 49a9b65. Configure here.
Uh oh!
There was an error while loading. Please reload this page.


Brings the unified
acp tradecommand (swaps + Hyperliquid deposit/spot/perp/withdraw, chain aliases, Treasures tokenized stocks,--dry-run) onto the latestmain, plus a round of agent-facing copy polish.This branch =
main+feat/trade-commandmerged in, with the documentation/UX edits below on top. Sincefeat/trade-commandhad no PR of its own, this lands it.Copy changes
acp trade status→acp trade hl-status. Renamed and clarified: it's the Hyperliquid account view only (HL perp positions, margin, HL spot balances). For on-chain token balances on any EVM chain, useacp wallet balance. Updated command, help text, examples, and comments.--policyrather than relying on therestrictedfallback (and note that changing it later is manual).unrestrictedis documented as the choice for transacting outside Virtuals-approved contracts. Applied to bothagent add-signerandagent create --signer.Mirrored across
README.mdandSKILL.md. Companion docs PR inwhitepaper-economyOS.🤖 Generated with Claude Code
Note
High Risk
New auto-signing trade flows move real funds across chains and Hyperliquid; incorrect routing or signer policy could cause unintended transactions despite HTTPS and backend-built calldata.
Overview
Adds
acp tradeas a unified trading surface: DEX swaps (same/cross-chain), Hyperliquid deposit/spot/perp/withdraw (chain 1337), Treasures tokenized stocks,--dry-run, plus subcommandshl-statusandwithdraw-from-hl. The CLI proxies/trade/planand/trade/next, runs arunTradeLoopthat signs/broadcastssendlegs and postssignresults (EIP-712 / personal) for Treasures; trade HTTP calls require HTTPS.createProviderAdaptergains extra mainnet viem chains for multi-chain legs;getApiContextandparseChainArgsupport trade routing.Docs / agent UX: Large README and SKILL sections for trade; skill description extended for trading.
acp trade statusis renamedhl-status(HL account only vswallet balance).add-signer/create --signerhelp and docs push an explicit--policy(not therestricteddefault) and clarifyunrestricted.Other: CLI entry registers trade + trading help blurb;
SLIPPAGE_TOO_LOW/INSUFFICIENT_GASerror codes;scripts/tradeLoopSign.test.tsfor the sign branch; Node>=20.19.0in package.json / lockfile.Reviewed by Cursor Bugbot for commit 49a9b65. Bugbot is set up for automated code reviews on this repo. Configure here.