home / skills / openclaw / skills / vincent-hyperliquid
This skill helps agents manage HyperLiquid wallets for perpetuals and spot trading securely, without exposing private keys.
npx playbooks add skill openclaw/skills --skill vincent-hyperliquidReview the files below or copy the command above to add this skill to your agents.
---
name: Vincent - HyperLiquid for agents
description: Use this skill to create a HyperLiquid perpetuals and spot wallet for your agent. Trade perps, manage spot balances, transfer USDC between sub-accounts, get prices, place orders — all without exposing private keys.
homepage: https://heyvincent.ai
source: https://github.com/HeyVincent-ai/Vincent
metadata:
clawdbot:
homepage: https://heyvincent.ai
requires:
config:
- ${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/credentials/agentwallet
- ./agentwallet
---
# Vincent - HyperLiquid for agents
Use this skill to create a HyperLiquid perpetuals and spot wallet for your agent. Trade perps, check spot balances, and transfer USDC between perps and spot sub-accounts. The generated EOA **is** the HyperLiquid account — fund it directly via the HL bridge and start trading immediately with no Safe deployment or collateral approval steps.
**The agent never sees the private key.** All operations are executed server-side. The agent receives a scoped API key that can only perform actions permitted by the wallet owner's policies.
All commands use the `@vincentai/cli` package. API keys are stored and resolved automatically.
## Security Model
**No environment variables are required.** The agent creates its own HyperLiquid wallet at runtime by calling the Vincent API, which returns a scoped API key. There is no pre-existing credential to configure.
**The generated EOA is a standalone HyperLiquid account.** Unlike Polymarket (which deploys a Gnosis Safe), the EOA private key IS the HyperLiquid account. Deposits go directly to this address via the HyperLiquid bridge from Arbitrum, or via `usdSend` from another HL account.
**The agent's API key is not a private key.** It is a scoped Bearer token enforced server-side. The Vincent server evaluates all policies before executing any trade. If a trade violates a policy, the server rejects it. If a trade requires human approval, the server holds it and notifies the wallet owner via Telegram.
**All API calls go exclusively to `heyvincent.ai`** over HTTPS/TLS. The service calls `api.hyperliquid.xyz` server-side on the agent's behalf.
**Key lifecycle:**
- **Creation**: Agent runs `secret create` — Vincent generates the EOA, stores the key, returns `keyId`, `walletAddress`, and `claimUrl`.
- **Claim**: Human operator uses the claim URL to take ownership and configure policies at `https://heyvincent.ai`.
- **Revocation**: Wallet owner revokes the agent's API key from the frontend at any time.
- **Re-linking**: Agent exchanges a one-time re-link token (generated by the owner) for a new key via `secret relink`.
## Quick Start
### 1. Check for Existing Keys
Before creating a new wallet, check if one already exists:
```bash
npx @vincentai/cli@latest secret list --type HYPERLIQUID_WALLET
```
If a key is returned, use its `id` as `--key-id` for all subsequent commands. If not, create one.
### 2. Create a HyperLiquid Wallet
```bash
npx @vincentai/cli@latest secret create --type HYPERLIQUID_WALLET --memo "My HL perp wallet"
```
Returns:
- `keyId` — use for all future commands
- `walletAddress` — the EOA address (this IS the HyperLiquid account)
- `claimUrl` — share with the user to take ownership
After creating, tell the user:
> "Here is your wallet claim URL: `<claimUrl>`. Use this to claim ownership, set spending policies, and monitor your agent's wallet activity at https://heyvincent.ai."
**Important:** The wallet is empty at creation. The user must deposit USDC before trading.
### 3. Get Balance
```bash
npx @vincentai/cli@latest hyperliquid balance --key-id <KEY_ID>
```
Returns:
- `walletAddress` — the EOA address
- `accountValue` — total perps account value in USD (cross-margin)
- `withdrawable` — USDC available to withdraw from the perps account
- `positions` — array of open perpetual positions
- `spotBalances` — array of spot token balances (each with `coin`, `token`, `hold`, `total`)
### 4. Transfer Between Perps and Spot
HyperLiquid has separate perps and spot sub-accounts. USDC must be in the correct sub-account before trading. Use `internal-transfer` to move USDC between them.
```bash
# Move 100 USDC from spot → perps (needed before perp trading)
npx @vincentai/cli@latest hyperliquid internal-transfer --key-id <KEY_ID> --amount 100 --to-perp true
# Move 50 USDC from perps → spot (needed before spot trading)
npx @vincentai/cli@latest hyperliquid internal-transfer --key-id <KEY_ID> --amount 50 --to-perp false
```
Parameters:
- `--amount`: USDC amount to transfer (string, numeric)
- `--to-perp`: `true` = spot→perps, `false` = perps→spot
**Response codes:**
- `200` — `status: "executed"` — transfer completed
- `202` — `status: "pending_approval"` (human approval required by policy)
- `403` — `status: "denied"` (rejected by policy)
### 5. Fund the Wallet
Deposit USDC to the EOA address via:
- **HyperLiquid bridge** from Arbitrum: visit `https://app.hyperliquid.xyz/portfolio` and bridge USDC to the EOA address
- **HL→HL transfer** (`usdSend`) from another HL account — instant
Minimum for a BTC perp trade: **$2 USDC** (covers $10 notional at 20x default leverage + taker fees).
### 6. Browse Markets
```bash
npx @vincentai/cli@latest hyperliquid markets --key-id <KEY_ID>
```
Returns a JSON object mapping coin names to mid prices (e.g. `{"BTC": "105234.5", "ETH": "3412.0", ...}`).
### 7. Get Order Book
```bash
npx @vincentai/cli@latest hyperliquid orderbook --key-id <KEY_ID> --coin BTC
```
Returns `levels` — a two-element array `[bids, asks]`. Each entry is `[price, size, numOrders]`. Use `levels[1][0][0]` for best ask, `levels[0][0][0]` for best bid.
### 8. Place a Trade
```bash
# Market buy (IoC — fills immediately or cancels)
npx @vincentai/cli@latest hyperliquid trade --key-id <KEY_ID> \
--coin BTC --is-buy true --sz 0.0001 \
--limit-px 106000 --order-type market
# Market sell to close (reduceOnly)
npx @vincentai/cli@latest hyperliquid trade --key-id <KEY_ID> \
--coin BTC --is-buy false --sz 0.0001 \
--limit-px 104000 --order-type market --reduce-only
# GTC limit buy
npx @vincentai/cli@latest hyperliquid trade --key-id <KEY_ID> \
--coin BTC --is-buy true --sz 0.0001 \
--limit-px 100000 --order-type limit
```
Parameters:
- `--coin`: Asset name (e.g. `BTC`, `ETH`, `SOL`)
- `--is-buy`: `true` for long, `false` for short/close
- `--sz`: Size in base currency (e.g. `0.0001` BTC)
- `--limit-px`: Price. For market orders, set slightly above ask (buy) or below bid (sell) to ensure fill. Recommended: `askPx * 1.005` for buys, `bidPx * 0.995` for sells.
- `--order-type`: `market` (IoC) or `limit` (GTC)
- `--reduce-only`: Pass when closing a position to prevent accidentally opening a new one in the opposite direction
**Minimum notional:** $10 (e.g. 0.0001 BTC at $100k/BTC). Default leverage is 20x cross-margin.
**Response codes:**
- `200` — `status: "executed"` with `orderId` (numeric) and `fillDetails`
- `202` — `status: "pending_approval"` (human approval required by policy)
- `403` — `status: "denied"` (rejected by policy)
### 9. View Open Orders
```bash
# All open orders
npx @vincentai/cli@latest hyperliquid open-orders --key-id <KEY_ID>
# Filter by coin
npx @vincentai/cli@latest hyperliquid open-orders --key-id <KEY_ID> --coin BTC
```
### 10. View Trade History
```bash
# All fills
npx @vincentai/cli@latest hyperliquid trades --key-id <KEY_ID>
# Filter by coin
npx @vincentai/cli@latest hyperliquid trades --key-id <KEY_ID> --coin ETH
```
### 11. Cancel Orders
```bash
# Cancel a specific order (requires coin and numeric order ID)
npx @vincentai/cli@latest hyperliquid cancel-order --key-id <KEY_ID> --coin BTC --oid <ORDER_ID>
# Cancel all open orders
npx @vincentai/cli@latest hyperliquid cancel-all --key-id <KEY_ID>
# Cancel all orders for a specific coin
npx @vincentai/cli@latest hyperliquid cancel-all --key-id <KEY_ID> --coin ETH
```
## Trading Engine: Stop-Loss, Take-Profit & Trailing Stop
The **Trading Engine** fully supports HyperLiquid. You can set automated stop-loss, take-profit, and trailing stop rules on any HL position. Rules execute automatically when price conditions are met — no LLM involved.
For HyperLiquid rules, use `--venue hyperliquid` and set `--market-id` / `--token-id` to the coin name (e.g. `BTC`, `ETH`, `SOL`). The `--trigger-price` is an absolute USD price (not 0–1 like Polymarket).
### Stop-Loss
```bash
npx @vincentai/cli@latest trading-engine create-rule --key-id <KEY_ID> \
--venue hyperliquid --market-id BTC --token-id BTC \
--rule-type STOP_LOSS --trigger-price 95000
```
Sells the position if BTC drops to $95,000.
### Take-Profit
```bash
npx @vincentai/cli@latest trading-engine create-rule --key-id <KEY_ID> \
--venue hyperliquid --market-id ETH --token-id ETH \
--rule-type TAKE_PROFIT --trigger-price 4500
```
Sells the position if ETH rises to $4,500.
### Trailing Stop
```bash
npx @vincentai/cli@latest trading-engine create-rule --key-id <KEY_ID> \
--venue hyperliquid --market-id SOL --token-id SOL \
--rule-type TRAILING_STOP --trigger-price 170 --trailing-percent 5
```
Stop price ratchets up as SOL rises. Sells if SOL drops 5% from its peak.
### Manage Rules
```bash
# List all rules
npx @vincentai/cli@latest trading-engine list-rules --key-id <KEY_ID>
# Update trigger price
npx @vincentai/cli@latest trading-engine update-rule --key-id <KEY_ID> --rule-id <RULE_ID> --trigger-price 98000
# Cancel a rule
npx @vincentai/cli@latest trading-engine delete-rule --key-id <KEY_ID> --rule-id <RULE_ID>
# View rule events
npx @vincentai/cli@latest trading-engine events --key-id <KEY_ID>
```
For full strategy docs (LLM-powered strategies, signal pipeline, drivers), see the **Trading Engine** skill.
## Policies (Server-Side Enforcement)
The wallet owner controls what the agent can do by setting policies at `https://heyvincent.ai`. All policies are enforced server-side before any trade executes.
| Policy | What it does |
| --------------------------- | ---------------------------------------------------------------- |
| **Spending limit (per tx)** | Max USD notional per trade |
| **Spending limit (daily)** | Max USD notional per rolling 24 hours |
| **Spending limit (weekly)** | Max USD notional per rolling 7 days |
| **Require approval** | Every trade needs human approval via Telegram |
| **Approval threshold** | Trades above a USD amount need human approval via Telegram |
If a trade is blocked, the API returns `status: "denied"` with the reason. If approval is needed, `status: "pending_approval"` is returned and the wallet owner receives a Telegram notification.
## Re-linking
If the agent loses its API key:
1. User generates a re-link token from `https://heyvincent.ai`
2. User gives the token to the agent
3. Agent runs:
```bash
npx @vincentai/cli@latest secret relink --token <TOKEN_FROM_USER>
```
Re-link tokens are one-time use and expire after 10 minutes.
## Workflow Example
```bash
# 1. Create wallet
npx @vincentai/cli@latest secret create --type HYPERLIQUID_WALLET --memo "HL wallet"
# → returns keyId, walletAddress, claimUrl
# 2. Tell user: "Fund <walletAddress> on HyperLiquid with USDC, then I can trade."
# 3. Check balance after funding (returns both perps and spot balances)
npx @vincentai/cli@latest hyperliquid balance --key-id <KEY_ID>
# → accountValue shows perps balance, spotBalances shows spot holdings
# 4. Transfer USDC between sub-accounts if needed
# Move 100 USDC from spot → perps before perp trading:
npx @vincentai/cli@latest hyperliquid internal-transfer --key-id <KEY_ID> --amount 100 --to-perp true
# Move 50 USDC from perps → spot before spot trading:
npx @vincentai/cli@latest hyperliquid internal-transfer --key-id <KEY_ID> --amount 50 --to-perp false
# 5. Get BTC mid price
npx @vincentai/cli@latest hyperliquid markets --key-id <KEY_ID>
# 6. Get order book to find best ask
npx @vincentai/cli@latest hyperliquid orderbook --key-id <KEY_ID> --coin BTC
# → levels[1][0][0] is best ask, e.g. "105200.0"
# 7. Open long — 0.5% above ask to ensure IoC fill
npx @vincentai/cli@latest hyperliquid trade --key-id <KEY_ID> \
--coin BTC --is-buy true --sz 0.0001 --limit-px 105726 --order-type market
# 8. Check fills
npx @vincentai/cli@latest hyperliquid trades --key-id <KEY_ID> --coin BTC
# 9. Close long — 0.5% below bid
npx @vincentai/cli@latest hyperliquid orderbook --key-id <KEY_ID> --coin BTC
npx @vincentai/cli@latest hyperliquid trade --key-id <KEY_ID> \
--coin BTC --is-buy false --sz 0.0001 --limit-px 104674 --order-type market --reduce-only
```
## Output Format
All CLI commands return JSON to stdout.
**balance:**
```json
{
"walletAddress": "0x...",
"accountValue": "105.23",
"withdrawable": "95.00",
"positions": [
{
"position": {
"coin": "BTC",
"szi": "0.0001",
"entryPx": "105200.0",
"positionValue": "10.52",
"unrealizedPnl": "0.05",
"liquidationPx": null,
"leverage": { "type": "cross", "value": 20 }
},
"type": "oneWay"
}
],
"spotBalances": [
{
"coin": "USDC",
"token": 0,
"hold": "0.0",
"total": "50.0"
}
]
}
```
**markets:**
```json
{
"BTC": "105234.5",
"ETH": "3412.0",
"SOL": "185.3"
}
```
**orderbook:**
```json
{
"coin": "BTC",
"levels": [
[["105200.0", "0.5", 3], ["105100.0", "1.2", 5]],
[["105300.0", "0.3", 2], ["105400.0", "0.8", 4]]
]
}
```
`levels[0]` = bids (descending), `levels[1]` = asks (ascending). Each entry is `[price, size, numOrders]`. Best bid: `levels[0][0][0]`, best ask: `levels[1][0][0]`.
**trade (executed):**
```json
{
"orderId": 12345678,
"status": "executed",
"transactionLogId": "clx...",
"walletAddress": "0x...",
"fillDetails": {
"totalSz": "0.0001",
"avgPx": "105250.0"
}
}
```
**trade (pending approval):**
```json
{
"status": "pending_approval",
"transactionLogId": "clx...",
"walletAddress": "0x...",
"reason": "Exceeds approval threshold"
}
```
**trade (denied):**
```json
{
"status": "denied",
"transactionLogId": "clx...",
"walletAddress": "0x...",
"reason": "Exceeds daily spending limit"
}
```
**internal-transfer (executed):**
```json
{
"status": "executed",
"transactionLogId": "clx..."
}
```
**internal-transfer (pending approval):**
```json
{
"status": "pending_approval",
"transactionLogId": "clx...",
"reason": "Exceeds approval threshold"
}
```
**internal-transfer (denied):**
```json
{
"status": "denied",
"transactionLogId": "clx...",
"reason": "Exceeds daily spending limit"
}
```
**open-orders:**
```json
{
"walletAddress": "0x...",
"openOrders": [
{
"coin": "BTC",
"side": "B",
"limitPx": "100000.0",
"sz": "0.0001",
"oid": 12345678,
"timestamp": 1700000000000,
"origSz": "0.0001"
}
]
}
```
`side`: `"B"` = buy/long, `"A"` = ask/sell.
**trades (fills):**
```json
{
"walletAddress": "0x...",
"fills": [
{
"coin": "BTC",
"px": "105200.0",
"sz": "0.0001",
"side": "B",
"time": 1700000000000,
"dir": "Open Long",
"closedPnl": "0",
"fee": "0.0105",
"oid": 12345678
}
]
}
```
**cancel-order / cancel-all:**
```json
{}
```
Empty object on success. Any non-zero exit code indicates failure.
## Error Handling
| Error | Cause | Resolution |
|-------|-------|------------|
| `401 Unauthorized` | Invalid or missing API key | Check key-id is correct; re-link if needed |
| `status: "denied"` | Trade blocked by server-side policy | User must adjust policies at heyvincent.ai |
| `status: "pending_approval"` | Trade exceeds approval threshold | Do not retry — wallet owner receives Telegram notification to approve/deny |
| `400 Bad Request` | Invalid parameters (e.g. non-numeric oid, bad coin) | Fix the parameter values |
| `429 Rate Limited` | Too many requests | Wait and retry with backoff |
| `500 TRADE_FAILED` | HyperLiquid rejected the order (e.g. insufficient margin, bad price) | Check account balance and order parameters |
| `Key not found` | API key was revoked or never created | Re-link with a new token from the wallet owner |
## Important Notes
- **No gas required.** HyperLiquid L1 is gasless — all perp trades settle natively.
- **Perps and spot sub-accounts.** The generated EOA has both a perps sub-account (cross-margin) and a spot sub-account. Use `internal-transfer` to move USDC between them. Deposits via the HL bridge land in the perps account by default.
- **Never try to access raw secret values.** The private key stays server-side.
- Always share the claim URL with the user after creating a wallet.
- For market orders, always set `limitPx` slightly outside the best price (`* 1.005` for buys, `* 0.995` for sells) to guarantee IoC fill at the current market price.
- If a trade returns `status: "pending_approval"`, do not retry — wait for the wallet owner to respond via Telegram.
This skill creates and manages a HyperLiquid perpetuals and spot wallet for an agent, enabling perp trading, spot balance management, internal USDC transfers, market data queries, and order placement without exposing private keys. The generated EOA is the HyperLiquid account and all operations are executed server-side via a scoped API key enforced by owner policies. It returns JSON outputs for every CLI action and supports automated trading rules (stop-loss, take-profit, trailing stop).
The agent uses the Vincent CLI to create a HyperLiquid wallet (EOA) at runtime; the private key is stored server-side and never shared with the agent. Commands call Vincent’s API which enforces owner policies and then makes HyperLiquid API calls on the agent’s behalf. Responses include balances, markets, order books, trades, and transfer statuses in JSON. Human approvals, revocation, and re-linking are supported through tokens and the owner dashboard at heyvincent.ai.
Does the agent ever get the wallet private key?
No. The private key remains server-side. The agent receives a scoped API key that can only perform actions allowed by owner policies.
How do I fund the generated wallet?
Deposit USDC to the returned EOA via the HyperLiquid bridge or use usdSend from another HL account. The wallet starts empty after creation.