hyperliquid-prime 0.1.0
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/LICENSE +21 -0
- package/README.md +426 -0
- package/dist/cli/context.d.ts +12 -0
- package/dist/cli/context.d.ts.map +1 -0
- package/dist/cli/context.js +27 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +5 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output.d.ts +7 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +29 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/program.d.ts +3 -0
- package/dist/cli/program.d.ts.map +1 -0
- package/dist/cli/program.js +232 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/collateral/manager.d.ts +45 -0
- package/dist/collateral/manager.d.ts.map +1 -0
- package/dist/collateral/manager.js +252 -0
- package/dist/collateral/manager.js.map +1 -0
- package/dist/collateral/types.d.ts +26 -0
- package/dist/collateral/types.d.ts.map +1 -0
- package/dist/collateral/types.js +2 -0
- package/dist/collateral/types.js.map +1 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -0
- package/dist/execution/executor.d.ts +30 -0
- package/dist/execution/executor.d.ts.map +1 -0
- package/dist/execution/executor.js +291 -0
- package/dist/execution/executor.js.map +1 -0
- package/dist/execution/monitor.d.ts +26 -0
- package/dist/execution/monitor.d.ts.map +1 -0
- package/dist/execution/monitor.js +50 -0
- package/dist/execution/monitor.js.map +1 -0
- package/dist/execution/types.d.ts +26 -0
- package/dist/execution/types.d.ts.map +1 -0
- package/dist/execution/types.js +2 -0
- package/dist/execution/types.js.map +1 -0
- package/dist/index.d.ts +87 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +249 -0
- package/dist/index.js.map +1 -0
- package/dist/logging/logger.d.ts +7 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +10 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/market/aggregator.d.ts +28 -0
- package/dist/market/aggregator.d.ts.map +1 -0
- package/dist/market/aggregator.js +166 -0
- package/dist/market/aggregator.js.map +1 -0
- package/dist/market/book.d.ts +22 -0
- package/dist/market/book.d.ts.map +1 -0
- package/dist/market/book.js +34 -0
- package/dist/market/book.js.map +1 -0
- package/dist/market/registry.d.ts +19 -0
- package/dist/market/registry.d.ts.map +1 -0
- package/dist/market/registry.js +127 -0
- package/dist/market/registry.js.map +1 -0
- package/dist/market/types.d.ts +53 -0
- package/dist/market/types.d.ts.map +1 -0
- package/dist/market/types.js +2 -0
- package/dist/market/types.js.map +1 -0
- package/dist/position/manager.d.ts +21 -0
- package/dist/position/manager.d.ts.map +1 -0
- package/dist/position/manager.js +63 -0
- package/dist/position/manager.js.map +1 -0
- package/dist/position/risk.d.ts +7 -0
- package/dist/position/risk.d.ts.map +1 -0
- package/dist/position/risk.js +23 -0
- package/dist/position/risk.js.map +1 -0
- package/dist/position/types.d.ts +28 -0
- package/dist/position/types.d.ts.map +1 -0
- package/dist/position/types.js +2 -0
- package/dist/position/types.js.map +1 -0
- package/dist/provider/nktkas.d.ts +63 -0
- package/dist/provider/nktkas.d.ts.map +1 -0
- package/dist/provider/nktkas.js +277 -0
- package/dist/provider/nktkas.js.map +1 -0
- package/dist/provider/provider.d.ts +42 -0
- package/dist/provider/provider.d.ts.map +1 -0
- package/dist/provider/provider.js +2 -0
- package/dist/provider/provider.js.map +1 -0
- package/dist/provider/types.d.ts +214 -0
- package/dist/provider/types.d.ts.map +1 -0
- package/dist/provider/types.js +4 -0
- package/dist/provider/types.js.map +1 -0
- package/dist/router/router.d.ts +30 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +256 -0
- package/dist/router/router.js.map +1 -0
- package/dist/router/scorer.d.ts +18 -0
- package/dist/router/scorer.d.ts.map +1 -0
- package/dist/router/scorer.js +43 -0
- package/dist/router/scorer.js.map +1 -0
- package/dist/router/simulator.d.ts +11 -0
- package/dist/router/simulator.d.ts.map +1 -0
- package/dist/router/simulator.js +44 -0
- package/dist/router/simulator.js.map +1 -0
- package/dist/router/splitter.d.ts +26 -0
- package/dist/router/splitter.d.ts.map +1 -0
- package/dist/router/splitter.js +119 -0
- package/dist/router/splitter.js.map +1 -0
- package/dist/router/types.d.ts +69 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.js +4 -0
- package/dist/router/types.js.map +1 -0
- package/dist/utils/errors.d.ts +28 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +55 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/math.d.ts +24 -0
- package/dist/utils/math.d.ts.map +1 -0
- package/dist/utils/math.js +43 -0
- package/dist/utils/math.js.map +1 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mehran Hydary
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
# Hyperliquid Prime
|
|
2
|
+
|
|
3
|
+
A TypeScript SDK that acts as a **prime broker layer** on top of Hyperliquid's perp markets — both native (ETH, BTC) and HIP-3 deployer markets (xyz's TSLA, Hyena's ETH). When multiple venues list the same asset with different collateral types (USDC, USDH, USDT0), Hyperliquid Prime automatically discovers all markets, compares liquidity/funding/cost, and routes to the best execution — presenting a single unified trading interface.
|
|
4
|
+
|
|
5
|
+
## The Problem
|
|
6
|
+
|
|
7
|
+
Hyperliquid has native perpetual markets (ETH, BTC, SOL) and HIP-3, which allows anyone to deploy additional perp markets. This means ETH can be traded on both the native HL market *and* third-party deployers like Hyena — each with different liquidity depth and funding rates. Similarly, TSLA exists across multiple HIP-3 venues (xyz, flx, km, cash) with different collateral types. Traders are left manually comparing across fragmented markets.
|
|
8
|
+
|
|
9
|
+
## What Hyperliquid Prime Does
|
|
10
|
+
|
|
11
|
+
- **Discovers** all perp markets per asset (native + HIP-3) and groups them
|
|
12
|
+
- **Aggregates** orderbooks across collateral types into a unified view
|
|
13
|
+
- **Routes** orders to the single best market based on price impact, funding rate, and collateral match
|
|
14
|
+
- **Splits** large orders across multiple markets for better fills when a single venue lacks depth
|
|
15
|
+
- **Swaps collateral** automatically (e.g., USDC → USDH) when the best liquidity lives on a non-USDC market
|
|
16
|
+
- **Executes** via an explicit quote-then-execute flow
|
|
17
|
+
- **Tracks** positions across all markets in a unified view
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install hyperliquid-prime
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### SDK Usage (TypeScript)
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { HyperliquidPrime } from 'hyperliquid-prime'
|
|
31
|
+
|
|
32
|
+
// --- Read-only (no wallet needed) ---
|
|
33
|
+
const hp = new HyperliquidPrime({ testnet: true })
|
|
34
|
+
await hp.connect()
|
|
35
|
+
|
|
36
|
+
// What markets exist for ETH? (native HL + HIP-3 deployers)
|
|
37
|
+
const ethMarkets = hp.getMarkets('ETH')
|
|
38
|
+
// [
|
|
39
|
+
// { coin: "ETH", dexName: "__native__", collateral: "USDC", isNative: true },
|
|
40
|
+
// { coin: "hyena:ETH", dexName: "hyena", collateral: "USDC", isNative: false },
|
|
41
|
+
// ]
|
|
42
|
+
|
|
43
|
+
// HIP-3-only assets also work
|
|
44
|
+
const tslaMarkets = hp.getMarkets('TSLA')
|
|
45
|
+
// [
|
|
46
|
+
// { coin: "xyz:TSLA", dexName: "xyz", collateral: "USDC", isNative: false },
|
|
47
|
+
// { coin: "flx:TSLA", dexName: "flx", collateral: "USDH", isNative: false },
|
|
48
|
+
// { coin: "km:TSLA", dexName: "km", collateral: "USDH", isNative: false },
|
|
49
|
+
// { coin: "cash:TSLA", dexName: "cash", collateral: "USDT0", isNative: false },
|
|
50
|
+
// ]
|
|
51
|
+
|
|
52
|
+
// Where's the best execution for a 50 TSLA long?
|
|
53
|
+
const quote = await hp.quote('TSLA', 'buy', 50)
|
|
54
|
+
console.log(quote.selectedMarket.coin) // "xyz:TSLA"
|
|
55
|
+
console.log(quote.estimatedAvgPrice) // 431.56
|
|
56
|
+
console.log(quote.estimatedPriceImpact) // 0.8 (bps)
|
|
57
|
+
console.log(quote.alternativesConsidered) // All markets with scores
|
|
58
|
+
|
|
59
|
+
// Aggregated orderbook across all TSLA markets
|
|
60
|
+
const book = await hp.getAggregatedBook('TSLA')
|
|
61
|
+
|
|
62
|
+
// Funding rate comparison
|
|
63
|
+
const funding = await hp.getFundingComparison('TSLA')
|
|
64
|
+
|
|
65
|
+
await hp.disconnect()
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Trading
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
const hp = new HyperliquidPrime({
|
|
72
|
+
privateKey: '0x...',
|
|
73
|
+
testnet: true,
|
|
74
|
+
})
|
|
75
|
+
await hp.connect()
|
|
76
|
+
|
|
77
|
+
// Two-step: quote then execute (recommended)
|
|
78
|
+
const quote = await hp.quote('TSLA', 'buy', 50)
|
|
79
|
+
// Review the quote...
|
|
80
|
+
const receipt = await hp.execute(quote.plan)
|
|
81
|
+
console.log(receipt.success) // true
|
|
82
|
+
console.log(receipt.filledSize) // "50"
|
|
83
|
+
console.log(receipt.avgPrice) // "431.50"
|
|
84
|
+
console.log(receipt.market.coin) // "xyz:TSLA"
|
|
85
|
+
|
|
86
|
+
// One-step convenience
|
|
87
|
+
const receipt2 = await hp.long('TSLA', 50)
|
|
88
|
+
const receipt3 = await hp.short('TSLA', 25)
|
|
89
|
+
|
|
90
|
+
// --- Split orders across multiple markets for better fills ---
|
|
91
|
+
const splitQuote = await hp.quoteSplit('TSLA', 'buy', 200)
|
|
92
|
+
console.log(splitQuote.allocations)
|
|
93
|
+
// [
|
|
94
|
+
// { market: xyz:TSLA, size: 120, proportion: 0.6 },
|
|
95
|
+
// { market: flx:TSLA, size: 50, proportion: 0.25 },
|
|
96
|
+
// { market: km:TSLA, size: 30, proportion: 0.15 },
|
|
97
|
+
// ]
|
|
98
|
+
console.log(splitQuote.collateralPlan.swapsNeeded) // false (resolved at executeSplit time)
|
|
99
|
+
|
|
100
|
+
const splitReceipt = await hp.executeSplit(splitQuote.splitPlan)
|
|
101
|
+
console.log(splitReceipt.totalFilledSize) // "200"
|
|
102
|
+
console.log(splitReceipt.aggregateAvgPrice) // "431.42"
|
|
103
|
+
|
|
104
|
+
// One-step split convenience
|
|
105
|
+
const splitReceipt2 = await hp.longSplit('TSLA', 200)
|
|
106
|
+
const splitReceipt3 = await hp.shortSplit('TSLA', 100)
|
|
107
|
+
|
|
108
|
+
// Unified position view across all perp markets
|
|
109
|
+
const positions = await hp.getGroupedPositions()
|
|
110
|
+
const tslaPositions = positions.get('TSLA')
|
|
111
|
+
// Shows all TSLA positions across all markets in one group
|
|
112
|
+
|
|
113
|
+
// Account balance
|
|
114
|
+
const balance = await hp.getBalance()
|
|
115
|
+
|
|
116
|
+
await hp.disconnect()
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### CLI
|
|
120
|
+
|
|
121
|
+
The `hp` CLI provides the same functionality from the terminal:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# Show all perp markets for an asset (native + HIP-3)
|
|
125
|
+
hp markets ETH
|
|
126
|
+
hp markets TSLA
|
|
127
|
+
hp markets TSLA --json
|
|
128
|
+
|
|
129
|
+
# Aggregated orderbook
|
|
130
|
+
hp book TSLA
|
|
131
|
+
hp book TSLA --depth 10
|
|
132
|
+
|
|
133
|
+
# Compare funding rates across markets
|
|
134
|
+
hp funding TSLA
|
|
135
|
+
|
|
136
|
+
# Get a routing quote (does not execute)
|
|
137
|
+
hp quote TSLA buy 50
|
|
138
|
+
|
|
139
|
+
# Execute trades via best market
|
|
140
|
+
HP_PRIVATE_KEY=0x... hp long TSLA 50
|
|
141
|
+
HP_PRIVATE_KEY=0x... hp short TSLA 25
|
|
142
|
+
|
|
143
|
+
# View positions and balance
|
|
144
|
+
HP_PRIVATE_KEY=0x... hp positions
|
|
145
|
+
HP_PRIVATE_KEY=0x... hp balance
|
|
146
|
+
|
|
147
|
+
# Use testnet
|
|
148
|
+
hp markets TSLA --testnet
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
For CLI secrets, use `HP_PRIVATE_KEY` (or `--key-env <NAME>`) instead of `--key` whenever possible.
|
|
152
|
+
|
|
153
|
+
## How Routing Works
|
|
154
|
+
|
|
155
|
+
### Single-Market Routing
|
|
156
|
+
|
|
157
|
+
When you call `hp.quote("TSLA", "buy", 50)`, the router:
|
|
158
|
+
|
|
159
|
+
1. **Fetches** the orderbook for every TSLA market (xyz, flx, km, cash)
|
|
160
|
+
2. **Simulates** walking each book to estimate average fill price and price impact at the requested size
|
|
161
|
+
3. **Scores** each market using three factors:
|
|
162
|
+
- **Price impact** (dominant) — cost in basis points to fill
|
|
163
|
+
- **Funding rate** (secondary) — prefers favorable funding direction
|
|
164
|
+
- **Collateral match** (penalty) — penalizes markets by the estimated cost to swap into their collateral (e.g., ~50 bps for USDC → USDH)
|
|
165
|
+
4. **Selects** the lowest-score market and builds an execution plan with IOC limit order + slippage
|
|
166
|
+
|
|
167
|
+
The result is a `Quote` object containing the selected market, estimated cost, and a ready-to-execute `ExecutionPlan`. You review it, then call `execute(plan)` to place the order.
|
|
168
|
+
|
|
169
|
+
### Split Routing (Multi-Market)
|
|
170
|
+
|
|
171
|
+
When you call `hp.quoteSplit("TSLA", "buy", 200)`, the router:
|
|
172
|
+
|
|
173
|
+
1. **Aggregates** all orderbooks into a single merged book with source tracking
|
|
174
|
+
2. **Walks** the merged book greedily — always consuming the cheapest liquidity first, regardless of venue
|
|
175
|
+
3. **Distributes** fills proportionally across sources at each price level
|
|
176
|
+
4. **Builds** a `SplitExecutionPlan` with one leg per market
|
|
177
|
+
5. **Defers collateral estimation** to `executeSplit()` so balances and swap costs are resolved from live account state at execution time
|
|
178
|
+
|
|
179
|
+
On execution, the system automatically:
|
|
180
|
+
- Enables **DEX abstraction** (Hyperliquid's unified account mode)
|
|
181
|
+
- **Transfers** USDC from perp to spot if needed
|
|
182
|
+
- **Swaps** USDC → target tokens (e.g., USDH) via spot market
|
|
183
|
+
- **Places all leg orders** in a single atomic `batchOrders` call
|
|
184
|
+
|
|
185
|
+
If only one market has competitive liquidity, 100% routes there — equivalent to single-market behavior.
|
|
186
|
+
|
|
187
|
+
## Configuration
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
interface HyperliquidPrimeConfig {
|
|
191
|
+
privateKey?: `0x${string}` // Required for trading, optional for read-only
|
|
192
|
+
walletAddress?: string // Derived from privateKey if not provided
|
|
193
|
+
testnet?: boolean // Default: false
|
|
194
|
+
defaultSlippage?: number // Default: 0.01 (1%)
|
|
195
|
+
logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'silent'
|
|
196
|
+
prettyLogs?: boolean // Default: false
|
|
197
|
+
builder?: BuilderConfig | null // Builder fee config (see below)
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Builder Fee
|
|
202
|
+
|
|
203
|
+
Hyperliquid Prime includes a small builder fee (1 basis point = 0.01%) on all orders placed through the SDK's execution methods. This uses Hyperliquid's native [builder fee](https://hyperliquid.gitbook.io/hyperliquid-docs) mechanism.
|
|
204
|
+
|
|
205
|
+
The fee is automatically approved on the trader's first order (one-time on-chain action per wallet).
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
// Default: 1 bps fee (no config needed)
|
|
209
|
+
const hp = new HyperliquidPrime({ privateKey: '0x...' })
|
|
210
|
+
|
|
211
|
+
// Custom builder address and fee
|
|
212
|
+
const hp = new HyperliquidPrime({
|
|
213
|
+
privateKey: '0x...',
|
|
214
|
+
builder: { address: '0xYourAddress', feeBps: 2 }, // 2 bps
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
// Disable builder fee entirely
|
|
218
|
+
const hp = new HyperliquidPrime({
|
|
219
|
+
privateKey: '0x...',
|
|
220
|
+
builder: null,
|
|
221
|
+
})
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
The builder fee only applies to orders placed through `execute()`, `executeSplit()`, and their convenience wrappers (`long`, `short`, `longSplit`, `shortSplit`). Raw provider calls via `hp.api` are never affected.
|
|
225
|
+
|
|
226
|
+
CLI flag to disable:
|
|
227
|
+
```bash
|
|
228
|
+
HP_PRIVATE_KEY=0x... hp long TSLA 50 --no-builder-fee
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## API Reference
|
|
232
|
+
|
|
233
|
+
### Read-Only Methods
|
|
234
|
+
|
|
235
|
+
| Method | Description |
|
|
236
|
+
| -------------------------------- | -------------------------------------------- |
|
|
237
|
+
| `getMarkets(asset)` | All perp markets for an asset (native + HIP-3) |
|
|
238
|
+
| `getAggregatedMarkets()` | Asset groups with multiple markets |
|
|
239
|
+
| `getAggregatedBook(asset)` | Merged orderbook across all markets |
|
|
240
|
+
| `getFundingComparison(asset)` | Funding rates compared across markets |
|
|
241
|
+
| `quote(asset, side, size)` | Routing quote for single best market |
|
|
242
|
+
| `quoteSplit(asset, side, size)` | Split quote across multiple markets |
|
|
243
|
+
|
|
244
|
+
### Trading Methods (wallet required)
|
|
245
|
+
|
|
246
|
+
| Method | Description |
|
|
247
|
+
| ------------------------- | ------------------------------------------------- |
|
|
248
|
+
| `execute(plan)` | Execute a single-market quote |
|
|
249
|
+
| `executeSplit(plan)` | Execute a split quote (handles collateral swaps) |
|
|
250
|
+
| `long(asset, size)` | Quote + execute a long on best market |
|
|
251
|
+
| `short(asset, size)` | Quote + execute a short on best market |
|
|
252
|
+
| `longSplit(asset, size)` | Split quote + execute a long across markets |
|
|
253
|
+
| `shortSplit(asset, size)` | Split quote + execute a short across markets |
|
|
254
|
+
| `close(asset)` | Close all positions for an asset |
|
|
255
|
+
|
|
256
|
+
### Position & Balance
|
|
257
|
+
|
|
258
|
+
| Method | Description |
|
|
259
|
+
| ----------------------- | ---------------------------------- |
|
|
260
|
+
| `getPositions()` | All positions with market metadata |
|
|
261
|
+
| `getGroupedPositions()` | Positions grouped by base asset |
|
|
262
|
+
| `getBalance()` | Account margin summary |
|
|
263
|
+
|
|
264
|
+
### Escape Hatches
|
|
265
|
+
|
|
266
|
+
| Property | Description |
|
|
267
|
+
| ------------ | --------------------------------------------------- |
|
|
268
|
+
| `hp.api` | Direct access to the `HLProvider` for raw API calls |
|
|
269
|
+
| `hp.markets` | Direct access to the `MarketRegistry` |
|
|
270
|
+
|
|
271
|
+
## Architecture
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
hyperliquid-prime/
|
|
275
|
+
├── src/
|
|
276
|
+
│ ├── index.ts # HyperliquidPrime class — public API surface
|
|
277
|
+
│ ├── config.ts # Configuration types
|
|
278
|
+
│ ├── provider/ # Wraps @nktkas/hyperliquid
|
|
279
|
+
│ │ ├── provider.ts # HLProvider interface
|
|
280
|
+
│ │ ├── nktkas.ts # Implementation
|
|
281
|
+
│ │ └── types.ts # Normalized types
|
|
282
|
+
│ ├── market/ # Perp market discovery (native + HIP-3)
|
|
283
|
+
│ │ ├── registry.ts # Discovers & indexes all perp markets per asset
|
|
284
|
+
│ │ ├── book.ts # Book normalization helpers
|
|
285
|
+
│ │ ├── aggregator.ts # Merges books across collateral types
|
|
286
|
+
│ │ └── types.ts # PerpMarket, MarketGroup, AggregatedBook
|
|
287
|
+
│ ├── router/ # Smart order routing
|
|
288
|
+
│ │ ├── router.ts # Scores markets, picks best one (or splits across many)
|
|
289
|
+
│ │ ├── simulator.ts # Walks books, estimates fill cost
|
|
290
|
+
│ │ ├── scorer.ts # Ranks by impact + funding + collateral swap cost
|
|
291
|
+
│ │ ├── splitter.ts # Optimizes order splits across aggregated book
|
|
292
|
+
│ │ └── types.ts # Quote, SplitQuote, ExecutionPlan, MarketScore
|
|
293
|
+
│ ├── execution/ # Order lifecycle
|
|
294
|
+
│ │ ├── executor.ts # Places orders via provider (single + batch)
|
|
295
|
+
│ │ ├── monitor.ts # Tracks order status via WebSocket
|
|
296
|
+
│ │ └── types.ts # ExecutionReceipt, SplitExecutionReceipt
|
|
297
|
+
│ ├── collateral/ # Collateral management for cross-market trading
|
|
298
|
+
│ │ ├── manager.ts # Estimates swap costs, executes USDC→token swaps
|
|
299
|
+
│ │ └── types.ts # CollateralPlan, CollateralRequirement
|
|
300
|
+
│ ├── position/ # Position tracking
|
|
301
|
+
│ │ ├── manager.ts # Read-only position tracking
|
|
302
|
+
│ │ ├── risk.ts # Per-position risk math
|
|
303
|
+
│ │ └── types.ts # LogicalPosition, RiskProfile
|
|
304
|
+
│ ├── cli/ # CLI commands
|
|
305
|
+
│ │ ├── index.ts # Entry point
|
|
306
|
+
│ │ ├── program.ts # Commander setup + all commands
|
|
307
|
+
│ │ ├── context.ts # Builds HyperliquidPrime from CLI flags
|
|
308
|
+
│ │ └── output.ts # JSON / table formatting
|
|
309
|
+
│ ├── logging/ # Structured logging (pino)
|
|
310
|
+
│ └── utils/ # Math helpers, error types
|
|
311
|
+
└── test/
|
|
312
|
+
├── fixtures/ # Deterministic test data
|
|
313
|
+
├── unit/ # Unit tests (mock provider)
|
|
314
|
+
└── integration/ # Testnet integration tests
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The provider interface (`HLProvider`) is the only module that imports `@nktkas/hyperliquid` directly. Swapping to a different SDK or going direct is a one-file change.
|
|
318
|
+
|
|
319
|
+
## OpenClaw Skill (AI-Assisted Trading)
|
|
320
|
+
|
|
321
|
+
Hyperliquid Prime includes an [OpenClaw](https://openclaw.ai) skill for AI-assisted trading via natural language.
|
|
322
|
+
|
|
323
|
+
### Installation
|
|
324
|
+
|
|
325
|
+
Install the skill via ClawHub:
|
|
326
|
+
```bash
|
|
327
|
+
clawhub install mehranhydary/hl-prime
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Or manually clone to your OpenClaw skills directory:
|
|
331
|
+
```bash
|
|
332
|
+
cd ~/.openclaw/skills
|
|
333
|
+
git clone https://github.com/mehranhydary/hl-prime.git hyperliquid-prime
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### What You Can Ask
|
|
337
|
+
|
|
338
|
+
Once the skill is installed, you can trade via conversational commands:
|
|
339
|
+
|
|
340
|
+
```
|
|
341
|
+
"What's the best market to buy 50 TSLA on Hyperliquid?"
|
|
342
|
+
"Show me all markets for GOLD"
|
|
343
|
+
"Compare funding rates across ETH markets"
|
|
344
|
+
"Get me a quote to short 100 NVDA"
|
|
345
|
+
"Execute that TSLA trade"
|
|
346
|
+
"Split 200 TSLA across all markets for better fills"
|
|
347
|
+
"Show my positions across all markets"
|
|
348
|
+
"Which market has the best price impact for buying 10 BTC?"
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### How It Works
|
|
352
|
+
|
|
353
|
+
The OpenClaw skill provides:
|
|
354
|
+
- **Natural language market discovery** — "Find all markets for AAPL"
|
|
355
|
+
- **Intelligent routing guidance** — AI explains which market is best and why
|
|
356
|
+
- **Split order optimization** — "Split 200 TSLA across venues for lowest cost"
|
|
357
|
+
- **Quote explanations** — "The xyz:TSLA market has lowest price impact (0.8 bps) and favorable funding"
|
|
358
|
+
- **Automatic collateral handling** — Swaps USDC to USDH/USDT0 when needed for best execution
|
|
359
|
+
- **Aggregated data access** — View combined orderbooks and funding comparisons conversationally
|
|
360
|
+
- **Position summaries** — "Show my TSLA exposure across all collateral types"
|
|
361
|
+
|
|
362
|
+
### Configuration
|
|
363
|
+
|
|
364
|
+
The skill works with your existing Hyperliquid Prime installation. No additional config needed — it uses the SDK directly.
|
|
365
|
+
|
|
366
|
+
For trading (not read-only), ensure your OpenClaw agent has access to your wallet or private key configuration.
|
|
367
|
+
|
|
368
|
+
### Example Session
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
You: Find the best market for buying 100 UNI
|
|
372
|
+
Agent: Found 4 markets for UNI. Analyzing...
|
|
373
|
+
|
|
374
|
+
Best route: xyz:UNI
|
|
375
|
+
- Price impact: 1.2 bps (lowest)
|
|
376
|
+
- Funding: -0.01% (you earn funding)
|
|
377
|
+
- Collateral: USDC (you hold USDC)
|
|
378
|
+
|
|
379
|
+
Alternative: cash:UNI
|
|
380
|
+
- Price impact: 2.8 bps
|
|
381
|
+
- Funding: +0.03%
|
|
382
|
+
- Collateral: USDT0
|
|
383
|
+
|
|
384
|
+
Recommendation: Route through xyz:UNI for lowest cost.
|
|
385
|
+
|
|
386
|
+
You: Execute it
|
|
387
|
+
Agent: Executed 100 UNI long on xyz:UNI
|
|
388
|
+
Filled: 100 UNI at avg price $12.34
|
|
389
|
+
Market: xyz:UNI
|
|
390
|
+
Status: success
|
|
391
|
+
|
|
392
|
+
You: Split 500 TSLA across all markets
|
|
393
|
+
Agent: Analyzing liquidity across 4 TSLA markets...
|
|
394
|
+
|
|
395
|
+
Split plan:
|
|
396
|
+
- xyz:TSLA → 300 (60%) — USDC, 0.9 bps impact
|
|
397
|
+
- flx:TSLA → 120 (24%) — USDH, 1.4 bps impact
|
|
398
|
+
- km:TSLA → 80 (16%) — USDH, 2.1 bps impact
|
|
399
|
+
|
|
400
|
+
Collateral: will be estimated at execution time from live balances (and swapped if needed)
|
|
401
|
+
Aggregate avg price: $431.42 (vs $432.10 single-market)
|
|
402
|
+
|
|
403
|
+
You: Execute the split
|
|
404
|
+
Agent: Executed 3-leg split order for 500 TSLA
|
|
405
|
+
Total filled: 500 TSLA at avg $431.42
|
|
406
|
+
Legs: xyz:TSLA (300), flx:TSLA (120), km:TSLA (80)
|
|
407
|
+
Collateral swaps: USDC → USDH completed
|
|
408
|
+
Status: success
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
See [openclaw/SKILL.md](./openclaw/SKILL.md) for full skill documentation.
|
|
412
|
+
|
|
413
|
+
## Development
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
npm install
|
|
417
|
+
npm run build # Compile TypeScript
|
|
418
|
+
npm test # Run unit tests
|
|
419
|
+
npm run test:watch # Watch mode
|
|
420
|
+
npm run typecheck # Type check without emitting
|
|
421
|
+
npm run hp -- markets TSLA --testnet # Run CLI in dev mode
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## License
|
|
425
|
+
|
|
426
|
+
MIT
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { HyperliquidPrime } from "../index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build a HyperliquidPrime client from CLI options.
|
|
4
|
+
*/
|
|
5
|
+
export declare function createContext(opts: {
|
|
6
|
+
testnet?: boolean;
|
|
7
|
+
key?: string;
|
|
8
|
+
keyEnv?: string;
|
|
9
|
+
logLevel?: string;
|
|
10
|
+
builderFee?: boolean;
|
|
11
|
+
}): Promise<HyperliquidPrime>;
|
|
12
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/cli/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C;;GAEG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA6B5B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { HyperliquidPrime } from "../index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build a HyperliquidPrime client from CLI options.
|
|
4
|
+
*/
|
|
5
|
+
export async function createContext(opts) {
|
|
6
|
+
const keyEnv = opts.keyEnv ?? "HP_PRIVATE_KEY";
|
|
7
|
+
const keyFromCli = opts.key?.trim();
|
|
8
|
+
const keyFromEnv = process.env[keyEnv]?.trim();
|
|
9
|
+
const resolvedKey = keyFromCli || keyFromEnv;
|
|
10
|
+
if (keyFromCli) {
|
|
11
|
+
console.error("Warning: --key exposes secrets in shell history/process listings. Prefer environment variables.");
|
|
12
|
+
}
|
|
13
|
+
if (resolvedKey && !/^0x[0-9a-fA-F]{64}$/.test(resolvedKey)) {
|
|
14
|
+
throw new Error(`Invalid private key format. Expected a 0x-prefixed 64-hex string (source: ${keyFromCli ? "--key" : keyEnv})`);
|
|
15
|
+
}
|
|
16
|
+
const config = {
|
|
17
|
+
testnet: opts.testnet ?? false,
|
|
18
|
+
privateKey: resolvedKey,
|
|
19
|
+
logLevel: opts.logLevel ?? "warn",
|
|
20
|
+
prettyLogs: true,
|
|
21
|
+
builder: opts.builderFee === false ? null : undefined,
|
|
22
|
+
};
|
|
23
|
+
const hp = new HyperliquidPrime(config);
|
|
24
|
+
await hp.connect();
|
|
25
|
+
return hp;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/cli/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAMnC;IACC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,gBAAgB,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IACpC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;IAC/C,MAAM,WAAW,GAAG,UAAU,IAAI,UAAU,CAAC;IAE7C,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,iGAAiG,CAClG,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CACb,6EAA6E,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,CAC9G,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAA2B;QACrC,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,KAAK;QAC9B,UAAU,EAAE,WAAwC;QACpD,QAAQ,EAAG,IAAI,CAAC,QAA+C,IAAI,MAAM;QACzE,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;KACtD,CAAC;IAEF,MAAM,EAAE,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC;IACnB,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;AAChC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output formatting for CLI commands.
|
|
3
|
+
*/
|
|
4
|
+
export declare function formatJson(data: unknown): string;
|
|
5
|
+
export declare function formatTable(headers: string[], rows: string[][]): string;
|
|
6
|
+
export declare function output(data: unknown, json: boolean): void;
|
|
7
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/cli/output.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAEhD;AAED,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,EAAE,MAAM,EAAE,EAAE,GACf,MAAM,CAgBR;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAQzD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output formatting for CLI commands.
|
|
3
|
+
*/
|
|
4
|
+
export function formatJson(data) {
|
|
5
|
+
return JSON.stringify(data, null, 2);
|
|
6
|
+
}
|
|
7
|
+
export function formatTable(headers, rows) {
|
|
8
|
+
const colWidths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? "").length)));
|
|
9
|
+
const sep = colWidths.map((w) => "-".repeat(w)).join("-+-");
|
|
10
|
+
const headerLine = headers
|
|
11
|
+
.map((h, i) => h.padEnd(colWidths[i]))
|
|
12
|
+
.join(" | ");
|
|
13
|
+
const dataLines = rows
|
|
14
|
+
.map((r) => r.map((c, i) => (c ?? "").padEnd(colWidths[i])).join(" | "))
|
|
15
|
+
.join("\n");
|
|
16
|
+
return `${headerLine}\n${sep}\n${dataLines}`;
|
|
17
|
+
}
|
|
18
|
+
export function output(data, json) {
|
|
19
|
+
if (json) {
|
|
20
|
+
console.log(formatJson(data));
|
|
21
|
+
}
|
|
22
|
+
else if (typeof data === "string") {
|
|
23
|
+
console.log(data);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
console.log(formatJson(data));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/cli/output.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,OAAiB,EACjB,IAAgB;IAEhB,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACrC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAC5D,CAAC;IAEF,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,OAAO;SACvB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;SACrC,IAAI,CAAC,KAAK,CAAC,CAAC;IACf,MAAM,SAAS,GAAG,IAAI;SACnB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACT,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAC5D;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,GAAG,UAAU,KAAK,GAAG,KAAK,SAAS,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAa,EAAE,IAAa;IACjD,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAChC,CAAC;SAAM,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAChC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoDpC,wBAAgB,aAAa,IAAI,OAAO,CAiPvC"}
|