Portfolio & Market
Originally one merge task (below, historical); the two are now separate pages β
Portfolio (/portfolio, β
done) and Market (/market, π‘ in progress, Hyperliquid
trading). This doc covers both.
Portfolio (/portfolio) β β
Done (2026-06-30)
Merged Investment Summary (/summary) and Portfolio (/dashboard) into one page with
DB-backed persistence (Cloud SQL Postgres + Prisma; holdings keyed by user, survive refresh).
Details in ../history/2026-06-30-rabbit-history.md.
Market (/market) β π‘ In progress β Hyperliquid orderbook + trading
Canonical advanced implementation detail: Hyperliquid advanced market and trading β network-safe workspace, WebSocket lifecycle, typed data model, direct-signing and agent-wallet phases, validation rules, recovery behavior, tests, release gates. Use that page for new implementation work; this section is the decision log.
Status:
- β
Done (2026-07-07) β orderbook (ETC perp, REST 5s poll) + index cards on
/market. - β
Done (2026-07-21/22) β
TradePanel.tsx: MetaMask connect, one-time agent-wallet approval, perp + spot order placement/cancel, leverage control, via@nktkas/hyperliquidagainst HL testnet. Covers both direct wallet signing and the agent-wallet flow (see phases below). - β¬ To do β WebSocket book (replace 5s REST poll) β market picker (ETC/BTC/ETHβ¦).
Latest product decision (2026-07-20, β applied): default market is now ETH perp (was ETC). Build a simple Hyperliquid-backed HTS, prove direct MetaMask trading on testnet, then release a guarded mainnet direct-trading mode.
Design: server route proxies the Hyperliquid REST snapshot; render a compact L2 book above
the index cards. Public API β no key. lib/hyperliquid.ts + fetchL2Book; public
app/api/orderbook (?coin=); app/market/OrderBook.tsx polls every 5s (asks/spread/bids,
depth 8). Price formatter uses 5 significant figures (HL's rule) so sub-dollar ticks don't
collapse. middleware.ts: /api/indices + /api/orderbook in PUBLIC_PATHS so the public
/market page works logged-out.
Trading β auth model & phases (2026-07-07 research)
Hyperliquid auth is pure EIP-712 signatures β no API key, no registration; the account exists once funded.
- Funding: USDC on Arbitrum (+ a little ETH for gas) via the Hyperliquid bridge. Testnet
first:
HL_API_URL=https://api.hyperliquid-testnet.xyz, mock USDC from the testnet faucet (app.hyperliquid-testnet.xyz β may require a funded mainnet account as anti-spam; send a few USDC on Arbitrum first if rejected). - Signing model β decided (jay): (a) first, (b) later:
(a) direct wallet signing β MetaMask popup on every order, no key stored anywhere.
(b) agent (API) wallet β one-time
approveAgentsignature, then an app-held agent key signs orders popup-free (trade-only, cannot withdraw; 1 unnamed + up to 3 named agents/account). - Client-side only β browser β HL API directly (CORS-allowed, no server proxy, so no order
flow touches the app server). HL's action signing is msgpack-hash β phantom-agent β EIP-712 β
use a maintained SDK (
@nktkas/hyperliquid, works with ethers v6 signers), don't hand-roll. - Networks split so the public book stays real: display uses
HL_API_URL(server, mainnet); trading uses client-sideNEXT_PUBLIC_HL_TRADE_API=https://api.hyperliquid-testnet.xyz(public URL, not a secret) β TradePanel labeled "TESTNET" while set so. - Order rules: price β€ 5 significant figures Β· size rounded to the asset's
szDecimalsΒ· order value β₯ ~$10. - Account/funding: MetaMask account = HL-TEST. Fund via the Hyperliquid testnet faucet specifically (not Alchemy/Sepolia ETH faucets β HL testnet is its own chain, trades mock USDC).
- Agent-key storage: browser localStorage vs server-encrypted (like the AI-chat keys in ai-chat.md) β localStorage chosen to avoid custody.
July 21 request (jay): trade Hyperliquid perps on /market on testnet with a test account
that already holds mock USDC (account in .env or similar) β placed above the ETH Perp info
section; basic default inputs/buttons where no UI was specified. Delivered via TradePanel.tsx
(see "Done" above).