Agent skill
gdex-perp-trading
HyperLiquid perpetual futures — open/close positions, set leverage, place market and limit orders with TP/SL, and manage open orders
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/gdex-perp-trading
SKILL.md
GDEX: Perpetual Futures Trading (HyperLiquid)
Trade perpetual futures on HyperLiquid through GDEX managed-custody. Supports long/short positions, configurable leverage, take-profit/stop-loss, and market/limit orders.
When to Use
- Opening or closing perp positions
- Setting leverage for an asset
- Placing HL orders (market/limit) with TP/SL
- Querying positions, mark prices, or account state
- Canceling orders
Prerequisites
@gdexsdk/gdex-skillinstalled- Authenticated via
loginWithApiKey()— see gdex-authentication - USDC deposited to HyperLiquid — see gdex-perp-funding
Open a Position
import { GdexSkill, GDEX_API_KEY_PRIMARY } from '@gdexsdk/gdex-skill';
const skill = new GdexSkill();
skill.loginWithApiKey(GDEX_API_KEY_PRIMARY);
const pos = await skill.openPerpPosition({
coin: 'BTC', // asset symbol
side: 'long', // 'long' or 'short'
sizeUsd: '1000', // collateral in USD
leverage: 10, // 1–50× (default: 5)
takeProfitPrice: '110000', // optional TP
stopLossPrice: '95000', // optional SL
marginMode: 'cross', // 'cross' or 'isolated' (default: 'cross')
});
Close a Position
// Close 100% (default)
await skill.closePerpPosition({ coin: 'BTC' });
// Partial close
await skill.closePerpPosition({ coin: 'ETH', closePercent: 50 });
Set / Update Leverage
WARNING: The
hlUpdateLeverage//v1/hl/update_leverageendpoint is not implemented on the backend (returns 404). Leverage is set automatically when the backend executes orders — it callssetMaxLeverage()internally before each trade. You can control effective leverage through position sizing relative to your account balance.
// Simple (may not work — backend endpoint not implemented)
await skill.setPerpLeverage({ coin: 'BTC', leverage: 20 });
// Via HL managed-custody (ENDPOINT NOT IMPLEMENTED — returns 404)
// await skill.hlUpdateLeverage({
// coin: 'BTC',
// leverage: 40,
// isCross: true,
// apiKey,
// walletAddress, // control address, not managed
// sessionPrivateKey,
// });
// ✅ Leverage is set automatically by the backend before each order.
// Control effective leverage via position sizing:
// 10 USDC balance, 0.001 BTC @ $67k = ~$67 notional → ~6.7x effective leverage
Query Positions & Account State
// Get open positions
const positions = await skill.getPerpPositions({
walletAddress: '0xYourAddress',
coin: 'BTC', // optional filter
});
// Each: { coin, side, size, entryPrice, markPrice, leverage, unrealizedPnl, liquidationPrice }
// Full account state
const state = await skill.getHlAccountState({ walletAddress: '0xYourAddress' });
// { accountValue, totalNtlPos, totalRawUsd, totalMarginUsed, withdrawable, positions[] }
// Mark price for an asset
const price = await skill.getHlMarkPrice({ coin: 'BTC' });
Place Orders (HL Managed-Custody)
Market Order with TP/SL
await skill.hlCreateOrder({
coin: 'ETH',
isLong: true,
price: '0', // '0' for market orders
size: '0.5', // position size
reduceOnly: false,
isMarket: true,
tpPrice: '4000', // take-profit (optional)
slPrice: '3200', // stop-loss (optional)
apiKey,
walletAddress,
sessionPrivateKey,
});
Simple Order (no TP/SL)
await skill.hlPlaceOrder({
coin: 'SOL',
isLong: false, // short
price: '180', // limit price
size: '10',
reduceOnly: false,
apiKey,
walletAddress,
sessionPrivateKey,
});
Cancel Orders
// Cancel specific order
await skill.hlCancelOrder({
coin: 'BTC',
orderId: '12345',
apiKey,
walletAddress,
sessionPrivateKey,
});
// Cancel all orders
await skill.hlCancelAllOrders({
apiKey,
walletAddress,
sessionPrivateKey,
});
Close All Positions
WARNING: The
hlCloseAll//v1/hl/close_all_positionsendpoint is unreliable — it frequently returnsTIMEOUTor JSON parse errors from the backend. Use a reduce-only order instead (see below).
// ❌ Unreliable — may timeout
await skill.hlCloseAll({
apiKey,
walletAddress, // MUST be control address, not managed address
sessionPrivateKey,
});
// ✅ Reliable — close via reduce-only sell order
// To close a LONG position, place a SHORT reduce-only order for the exact size:
const btcPrice = await skill.getHlMarkPrice('BTC');
await skill.hlCreateOrder({
coin: 'BTC',
isLong: false, // opposite of your position
price: Math.round(btcPrice * 0.97).toString(), // 3% below mid for market sell
size: '0.001', // exact position size
reduceOnly: true, // close only, don't open new position
isMarket: true,
tpPrice: '0',
slPrice: '0',
apiKey,
walletAddress, // MUST be control address
sessionPrivateKey,
});
HL ABI Schemas (Critical)
HL operations use a different crypto pipeline than spot trades. Getting any detail wrong produces 400 Unauthorized (code 103).
| Action | ABI Types | Fields |
|---|---|---|
hl_deposit |
['uint64', 'address', 'uint256', 'string'] |
[chainId, tokenAddress, amount, nonce] |
hl_withdraw |
['string', 'string'] |
[amount, nonce] |
hl_create_order |
['string', 'bool', 'string', 'string', 'bool', 'string', 'string', 'string', 'bool'] |
[coin, isLong, price, size, reduceOnly, nonce, tpPrice, slPrice, isMarket] |
hl_place_order |
['string', 'bool', 'string', 'string', 'bool', 'string'] |
[coin, isLong, price, size, reduceOnly, nonce] |
hl_close_all |
['string'] |
[nonce] |
hl_cancel_order |
['string', 'string', 'string'] |
[nonce, coin, orderId] |
hl_cancel_all_orders |
['string'] |
[nonce] |
hl_update_leverage |
['string', 'uint32', 'bool', 'string'] |
[coin, leverage, isCross, nonce] |
CRITICAL: hl_deposit chainId is uint64, NOT uint256. This is the #1 cause of Unauthorized errors. The backend re-encodes with uint64 for signature verification — if you encode with uint256, the hex differs and you get code 103.
HL Managed-Custody Credentials
All HL write operations require HlManagedCredentials:
interface HlManagedCredentials {
apiKey: string; // GDEX API key for AES encryption
walletAddress: string; // CONTROL wallet address (from sign-in), NOT managed address
sessionPrivateKey: string; // Session key from sign-in flow
}
Default HL Assets
BTC, ETH, SOL, DOGE, AVAX, APE, APT, ARB, ATOM, BCH, BLUR, BNB, COMP, CRV, DOT, EOS, FIL, FTM, HBAR, ICP, IMX, INJ, JUP, KPEPE, LDO, LINK, LTC, MATIC, MKR, NEAR, OP, ORDI, PEPE, PYTH, RNDR, RUNE, SEI, SHIB, SNX, STX, SUI, TIA, TON, TRX, UNI, WIF, WLD, XRP
Critical: walletAddress Must Be Control Address
The #1 cause of 400 Unauthorized (code 103) on HL operations is passing the wrong walletAddress.
- During sign-in, the session key is registered against your control wallet address (e.g.,
0x53D0...2eD). - The backend returns a managed address (e.g.,
0x9967...0f) that holds the actual funds. - All HL write operations sign the message as
{action}-{walletAddress}-{data}, and the backend verifies the signature against the session key registered for that address. - If you pass the managed address, the signature verification fails → code 103.
// ❌ WRONG — causes 400 Unauthorized (code 103)
const creds = { apiKey, walletAddress: managedAddress, sessionPrivateKey };
// ✅ CORRECT — use the control wallet address from sign-in
const creds = { apiKey, walletAddress: controlAddress, sessionPrivateKey };
Related Skills
- gdex-authentication — Auth setup required for all HL operations
- gdex-perp-funding — Deposit/withdraw USDC to HyperLiquid
- gdex-portfolio — View positions and P&L
Autonomous Agent Notes (Live-Tested)
Endpoints That Don't Work
| Endpoint | Status | What to Do |
|---|---|---|
hlCloseAll / /v1/hl/close_all_positions |
Returns TIMEOUT or 400 | Place a reduce-only hlCreateOrder for the exact position size |
hlUpdateLeverage / /v1/hl/update_leverage |
Returns 404 | The backend sets leverage automatically per order. Control effective leverage via position sizing. |
getGbotUsdcBalance |
Returns 404 | Use getHlAccountState() or clearinghouse state to check balance |
Close Position Reliably (Live-Tested)
// Get current positions
const state = await skill.getHlAccountState({ walletAddress: controlAddress });
const positions = state?.assetPositions || [];
for (const p of positions) {
const pos = p.position;
if (Number(pos.szi) !== 0) {
const markPrice = Number(pos.entryPx); // or fetch via getHlMarkPrice
await skill.hlCreateOrder({
coin: pos.coin,
isLong: Number(pos.szi) < 0, // opposite direction
price: '0', // market
size: Math.abs(Number(pos.szi)).toString(),
reduceOnly: true,
isMarket: true,
tpPrice: '0',
slPrice: '0',
apiKey,
walletAddress: controlAddress, // MUST be control address
sessionPrivateKey,
});
}
}
HL Deposit Minimum
- Minimum deposit: 10 USDC (10000000 in smallest unit)
- Managed wallet must hold
amount × 1.01(1% fee buffer) - Delivery takes ~10 minutes after Arbitrum tx confirms
Position Sizing Notes
Since leverage cannot be set via API:
- Effective leverage = position notional value / account equity
- To get 5x leverage on $100 account: open a $500 position
- The backend may auto-set leverage to 50x cross — your risk is determined by position size relative to margin
Critical Checks Before Opening a Position
- Verify USDC is deposited on HL (use
getHlAccountState()) - Use control wallet address (not managed) for all write operations
- Generate a fresh nonce for every order
- For market orders: set
price: '0'andisMarket: true tpPriceandslPricecan be'0'to skip TP/SL
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?