hyperliquid 0.4.0 → 0.4.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +6 -507
- data/docs/API.md +95 -0
- data/docs/CONFIGURATION.md +53 -0
- data/docs/DEVELOPMENT.md +54 -0
- data/docs/ERRORS.md +38 -0
- data/docs/EXAMPLES.md +342 -0
- data/lib/hyperliquid/version.rb +1 -1
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 184e215d2d80056cb19bd6a20b273134d9997979d160d154318c5e155cdf02bb
|
|
4
|
+
data.tar.gz: 1f2bd8b08ef2e99e3732bd7775eeb70fe00ad7c2f4210312d07d237d28e670ed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1b8645b6f40ae9163343fbc6d7d5c814417643469d75ac320073546243d601055c26f92e1ecb272baf9d839dc4b983b19d56be01cc2bcf4709de9f0e6bf81116
|
|
7
|
+
data.tar.gz: 462b64553e8ee0939bf0284b0647ec602f9be2f3b2389144e64188813cf52d1bca1daf3feb233eab1167fb1337bda7028208acc38398e55a6279e2593ab26181
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
## [Ruby Hyperliquid SDK Changelog]
|
|
2
2
|
|
|
3
|
+
## [0.4.1] - 2025-01-28
|
|
4
|
+
|
|
5
|
+
- Reorganize documentation for improved readability
|
|
6
|
+
- Streamline README with basic setup and links to detailed docs
|
|
7
|
+
- Add `docs/API.md` with complete method reference
|
|
8
|
+
- Add `docs/EXAMPLES.md` with Info and Exchange code examples
|
|
9
|
+
- Add `docs/CONFIGURATION.md` with SDK options and retry settings
|
|
10
|
+
- Add `docs/ERRORS.md` with error handling guide
|
|
11
|
+
- Add `docs/DEVELOPMENT.md` with setup and testing instructions
|
|
12
|
+
|
|
3
13
|
## [0.4.0] - 2025-01-27
|
|
4
14
|
|
|
5
15
|
- Add Exchange API for authenticated write operations (trading)
|
data/README.md
CHANGED
|
@@ -46,514 +46,13 @@ trading_sdk = Hyperliquid.new(
|
|
|
46
46
|
exchange = trading_sdk.exchange
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
###
|
|
49
|
+
### Documentation
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
- `frontend_open_orders(user, dex: nil)` - Retrieve a user's open orders with additional frontend info
|
|
57
|
-
- `user_fills(user)` - Retrieve a user's fills
|
|
58
|
-
- `user_fills_by_time(user, start_time, end_time = nil)` - Retrieve a user's fills by time (optional end time)
|
|
59
|
-
- `user_rate_limit(user)` - Query user rate limits
|
|
60
|
-
- `order_status(user, oid)` - Query order status by order id (oid)
|
|
61
|
-
- `order_status_by_cloid(user, cloid)` - Query order status by client order id (cloid)
|
|
62
|
-
- `l2_book(coin)` - L2 book snapshot (Perpetuals and Spot)
|
|
63
|
-
- `candles_snapshot(coin, interval, start_time, end_time)` - Candle snapshot (Perpetuals and Spot)
|
|
64
|
-
- `max_builder_fee(user, builder)` - Check builder fee approval
|
|
65
|
-
- `historical_orders(user, start_time = nil, end_time = nil)` - Retrieve a user's historical orders
|
|
66
|
-
- `user_twap_slice_fills(user, start_time = nil, end_time = nil)` - Retrieve a user's TWAP slice fills
|
|
67
|
-
- `user_subaccounts(user)` - Retrieve a user's subaccounts
|
|
68
|
-
- `vault_details(vault_address, user = nil)` - Retrieve details for a vault
|
|
69
|
-
- `user_vault_equities(user)` - Retrieve a user's vault deposits
|
|
70
|
-
- `user_role(user)` - Query a user's role
|
|
71
|
-
- `portfolio(user)` - Query a user's portfolio
|
|
72
|
-
- `referral(user)` - Query a user's referral information
|
|
73
|
-
- `user_fees(user)` - Query a user's fees and fee schedule
|
|
74
|
-
- `delegations(user)` - Query a user's staking delegations
|
|
75
|
-
- `delegator_summary(user)` - Query a user's staking summary
|
|
76
|
-
- `delegator_history(user)` - Query a user's staking history
|
|
77
|
-
- `delegator_rewards(user)` - Query a user's staking rewards
|
|
78
|
-
|
|
79
|
-
##### Perpetuals Methods
|
|
80
|
-
- `perp_dexs()` - Retrieve all perpetual DEXs
|
|
81
|
-
- `meta(dex: nil)` - Get asset metadata (optionally for a specific perp DEX)
|
|
82
|
-
- `meta_and_asset_ctxs()` - Get extended asset metadata
|
|
83
|
-
- `user_state(user, dex: nil)` - Retrieve user's perpetuals account summary (optionally for a specific perp DEX)
|
|
84
|
-
- `predicted_fundings()` - Retrieve predicted funding rates across venues
|
|
85
|
-
- `perps_at_open_interest_cap()` - Query perps at open interest caps
|
|
86
|
-
- `perp_deploy_auction_status()` - Retrieve Perp Deploy Auction status
|
|
87
|
-
- `active_asset_data(user, coin)` - Retrieve a user's active asset data for a coin
|
|
88
|
-
- `perp_dex_limits(dex)` - Retrieve builder-deployed perp market limits for a DEX
|
|
89
|
-
- `user_funding(user, start_time, end_time = nil)` - Retrieve a user's funding history (optional end time)
|
|
90
|
-
- `user_non_funding_ledger_updates(user, start_time, end_time = nil)` - Retrieve a user's non-funding ledger updates. Non-funding ledger updates include deposits, transfers, and withdrawals. (optional end time)
|
|
91
|
-
- `funding_history(coin, start_time, end_time = nil)` - Retrieve historical funding rates (optional end time)
|
|
92
|
-
|
|
93
|
-
##### Spot Methods
|
|
94
|
-
- `spot_meta()` - Retrieve spot metadata (tokens and universe)
|
|
95
|
-
- `spot_meta_and_asset_ctxs()` - Retrieve spot metadata and asset contexts
|
|
96
|
-
- `spot_balances(user)` - Retrieve a user's spot token balances
|
|
97
|
-
- `spot_deploy_state(user)` - Retrieve Spot Deploy Auction information
|
|
98
|
-
- `spot_pair_deploy_auction_status()` - Retrieve Spot Pair Deploy Auction status
|
|
99
|
-
- `token_details(token_id)` - Retrieve information about a token by tokenId
|
|
100
|
-
|
|
101
|
-
#### Examples: Info
|
|
102
|
-
|
|
103
|
-
```ruby
|
|
104
|
-
# Retrieve mids for all coins
|
|
105
|
-
mids = sdk.info.all_mids
|
|
106
|
-
# => { "BTC" => "50000", "ETH" => "3000", ... }
|
|
107
|
-
|
|
108
|
-
user_address = "0x..."
|
|
109
|
-
|
|
110
|
-
# Retrieve a user's open orders
|
|
111
|
-
orders = sdk.info.open_orders(user_address)
|
|
112
|
-
# => [{ "coin" => "BTC", "sz" => "0.1", "px" => "50000", "side" => "A" }]
|
|
113
|
-
|
|
114
|
-
# Retrieve a user's open orders with additional frontend info
|
|
115
|
-
frontend_orders = sdk.info.frontend_open_orders(user_address)
|
|
116
|
-
# => [{ "coin" => "BTC", "isTrigger" => false, ... }]
|
|
117
|
-
|
|
118
|
-
# Retrieve a user's fills
|
|
119
|
-
fills = sdk.info.user_fills(user_address)
|
|
120
|
-
# => [{ "coin" => "BTC", "sz" => "0.1", "px" => "50000", "side" => "A", "time" => 1234567890 }]
|
|
121
|
-
|
|
122
|
-
# Retrieve a user's fills by time
|
|
123
|
-
start_time_ms = 1_700_000_000_000
|
|
124
|
-
end_time_ms = start_time_ms + 86_400_000
|
|
125
|
-
fills_by_time = sdk.info.user_fills_by_time(user_address, start_time_ms, end_time_ms)
|
|
126
|
-
# => [{ "coin" => "ETH", "px" => "3000", "time" => start_time_ms }, ...]
|
|
127
|
-
|
|
128
|
-
# Query user rate limits
|
|
129
|
-
rate_limit = sdk.info.user_rate_limit(user_address)
|
|
130
|
-
# => { "nRequestsUsed" => 100, "nRequestsCap" => 10000 }
|
|
131
|
-
|
|
132
|
-
# Query order status by oid
|
|
133
|
-
order_id = 12345
|
|
134
|
-
status_by_oid = sdk.info.order_status(user_address, order_id)
|
|
135
|
-
# => { "status" => "filled", ... }
|
|
136
|
-
|
|
137
|
-
# Query order status by cloid
|
|
138
|
-
cloid = "client-order-id-123"
|
|
139
|
-
status_by_cloid = sdk.info.order_status_by_cloid(user_address, cloid)
|
|
140
|
-
# => { "status" => "cancelled", ... }
|
|
141
|
-
|
|
142
|
-
# L2 order book snapshot
|
|
143
|
-
book = sdk.info.l2_book("BTC")
|
|
144
|
-
# => { "coin" => "BTC", "levels" => [[asks], [bids]], "time" => ... }
|
|
145
|
-
|
|
146
|
-
# Candle snapshot
|
|
147
|
-
candles = sdk.info.candles_snapshot("BTC", "1h", start_time_ms, end_time_ms)
|
|
148
|
-
# => [{ "t" => ..., "o" => "50000", "h" => "51000", "l" => "49000", "c" => "50500", "v" => "100" }]
|
|
149
|
-
|
|
150
|
-
# Check builder fee approval
|
|
151
|
-
builder_address = "0x..."
|
|
152
|
-
fee_approval = sdk.info.max_builder_fee(user_address, builder_address)
|
|
153
|
-
# => { "approved" => true, ... }
|
|
154
|
-
|
|
155
|
-
# Retrieve a user's historical orders
|
|
156
|
-
hist_orders = sdk.info.historical_orders(user_address)
|
|
157
|
-
# => [{ "oid" => 123, "coin" => "BTC", ... }]
|
|
158
|
-
hist_orders_ranged = sdk.info.historical_orders(user_address, start_time_ms, end_time_ms)
|
|
159
|
-
# => []
|
|
160
|
-
|
|
161
|
-
# Retrieve a user's TWAP slice fills
|
|
162
|
-
twap_fills = sdk.info.user_twap_slice_fills(user_address)
|
|
163
|
-
# => [{ "sliceId" => 1, "coin" => "ETH", "sz" => "1.0" }, ...]
|
|
164
|
-
twap_fills_ranged = sdk.info.user_twap_slice_fills(user_address, start_time_ms, end_time_ms)
|
|
165
|
-
# => []
|
|
166
|
-
|
|
167
|
-
# Retrieve a user's subaccounts
|
|
168
|
-
subaccounts = sdk.info.user_subaccounts(user_address)
|
|
169
|
-
# => ["0x1111...", ...]
|
|
170
|
-
|
|
171
|
-
# Retrieve details for a vault
|
|
172
|
-
vault_addr = "0x..."
|
|
173
|
-
vault = sdk.info.vault_details(vault_addr)
|
|
174
|
-
# => { "vaultAddress" => vault_addr, ... }
|
|
175
|
-
vault_with_user = sdk.info.vault_details(vault_addr, user_address)
|
|
176
|
-
# => { "vaultAddress" => vault_addr, "user" => user_address, ... }
|
|
177
|
-
|
|
178
|
-
# Retrieve a user's vault deposits
|
|
179
|
-
vault_deposits = sdk.info.user_vault_equities(user_address)
|
|
180
|
-
# => [{ "vaultAddress" => "0x...", "equity" => "123.45" }, ...]
|
|
181
|
-
|
|
182
|
-
# Query a user's role
|
|
183
|
-
role = sdk.info.user_role(user_address)
|
|
184
|
-
# => { "role" => "tradingUser" }
|
|
185
|
-
|
|
186
|
-
# Query a user's portfolio
|
|
187
|
-
portfolio = sdk.info.portfolio(user_address)
|
|
188
|
-
# => [["day", { "pnlHistory" => [...], "vlm" => "0.0" }], ...]
|
|
189
|
-
|
|
190
|
-
# Query a user's referral information
|
|
191
|
-
referral = sdk.info.referral(user_address)
|
|
192
|
-
# => { "referredBy" => { "referrer" => "0x..." }, ... }
|
|
193
|
-
|
|
194
|
-
# Query a user's fees
|
|
195
|
-
fees = sdk.info.user_fees(user_address)
|
|
196
|
-
# => { "userAddRate" => "0.0001", "feeSchedule" => { ... } }
|
|
197
|
-
|
|
198
|
-
# Query a user's staking delegations
|
|
199
|
-
delegations = sdk.info.delegations(user_address)
|
|
200
|
-
# => [{ "validator" => "0x...", "amount" => "100.0" }, ...]
|
|
201
|
-
|
|
202
|
-
# Query a user's staking summary
|
|
203
|
-
summary = sdk.info.delegator_summary(user_address)
|
|
204
|
-
# => { "delegated" => "12060.16529862", ... }
|
|
205
|
-
|
|
206
|
-
# Query a user's staking history
|
|
207
|
-
history = sdk.info.delegator_history(user_address)
|
|
208
|
-
# => [{ "time" => 1_736_726_400_073, "delta" => { ... } }, ...]
|
|
209
|
-
|
|
210
|
-
# Query a user's staking rewards
|
|
211
|
-
rewards = sdk.info.delegator_rewards(user_address)
|
|
212
|
-
# => [{ "time" => 1_736_726_400_073, "source" => "delegation", "totalAmount" => "0.123" }, ...]
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
Note: `l2_book` and `candles_snapshot` work for both Perpetuals and Spot. For spot, use `"{BASE}/USDC"` when available (e.g., `"PURR/USDC"`). Otherwise, use the index alias `"@{index}"` from `spot_meta["universe"]`.
|
|
216
|
-
|
|
217
|
-
##### Examples: Perpetuals
|
|
218
|
-
|
|
219
|
-
```ruby
|
|
220
|
-
# Retrieve all perpetual DEXs
|
|
221
|
-
perp_dexs = sdk.info.perp_dexs
|
|
222
|
-
# => [nil, { "name" => "test", "full_name" => "test dex", ... }]
|
|
223
|
-
|
|
224
|
-
# Retrieve perpetuals metadata (optionally for a specific perp dex)
|
|
225
|
-
meta = sdk.info.meta
|
|
226
|
-
# => { "universe" => [...] }
|
|
227
|
-
meta = sdk.info.meta(dex: "perp-dex-name")
|
|
228
|
-
# => { "universe" => [...] }
|
|
229
|
-
|
|
230
|
-
# Retrieve perpetuals asset contexts (includes mark price, current funding, open interest, etc.)
|
|
231
|
-
meta_ctxs = sdk.info.meta_and_asset_ctxs
|
|
232
|
-
# => { "universe" => [...], "assetCtxs" => [...] }
|
|
233
|
-
|
|
234
|
-
# Retrieve user's perpetuals account summary (optionally for a specific perp dex)
|
|
235
|
-
state = sdk.info.user_state(user_address)
|
|
236
|
-
# => { "assetPositions" => [...], "marginSummary" => {...} }
|
|
237
|
-
state = sdk.info.user_state(user_address, dex: "perp-dex-name")
|
|
238
|
-
# => { "assetPositions" => [...], "marginSummary" => {...} }
|
|
239
|
-
|
|
240
|
-
# Retrieve a user's funding history or non-funding ledger updates (optional end_time)
|
|
241
|
-
funding = sdk.info.user_funding(user_address, start_time)
|
|
242
|
-
# => [{ "delta" => { "type" => "funding", ... }, "time" => ... }]
|
|
243
|
-
funding = sdk.info.user_funding(user_address, start_time, end_time)
|
|
244
|
-
# => [{ "delta" => { "type" => "funding", ... }, "time" => ... }]
|
|
245
|
-
|
|
246
|
-
# Retrieve historical funding rates
|
|
247
|
-
hist = sdk.info.funding_history("ETH", start_time)
|
|
248
|
-
# => [{ "coin" => "ETH", "fundingRate" => "...", "time" => ... }]
|
|
249
|
-
|
|
250
|
-
# Retrieve predicted funding rates for different venues
|
|
251
|
-
pred = sdk.info.predicted_fundings
|
|
252
|
-
# => [["AVAX", [["HlPerp", { "fundingRate" => "0.0000125", "nextFundingTime" => ... }], ...]], ...]
|
|
253
|
-
|
|
254
|
-
# Query perps at open interest caps
|
|
255
|
-
oi_capped = sdk.info.perps_at_open_interest_cap
|
|
256
|
-
# => ["BADGER", "CANTO", ...]
|
|
257
|
-
|
|
258
|
-
# Retrieve information about the Perp Deploy Auction
|
|
259
|
-
auction = sdk.info.perp_deploy_auction_status
|
|
260
|
-
# => { "startTimeSeconds" => ..., "durationSeconds" => ..., "startGas" => "500.0", ... }
|
|
261
|
-
|
|
262
|
-
# Retrieve User's Active Asset Data
|
|
263
|
-
aad = sdk.info.active_asset_data(user_address, "APT")
|
|
264
|
-
# => { "user" => user_address, "coin" => "APT", "leverage" => { "type" => "cross", "value" => 3 }, ... }
|
|
265
|
-
|
|
266
|
-
# Retrieve Builder-Deployed Perp Market Limits
|
|
267
|
-
limits = sdk.info.perp_dex_limits("builder-dex")
|
|
268
|
-
# => { "totalOiCap" => "10000000.0", "oiSzCapPerPerp" => "...", ... }
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
##### Examples: Spot
|
|
272
|
-
|
|
273
|
-
```ruby
|
|
274
|
-
# Retrieve spot metadata
|
|
275
|
-
spot_meta = sdk.info.spot_meta
|
|
276
|
-
# => { "tokens" => [...], "universe" => [...] }
|
|
277
|
-
|
|
278
|
-
# Retrieve spot asset contexts
|
|
279
|
-
spot_meta_ctxs = sdk.info.spot_meta_and_asset_ctxs
|
|
280
|
-
# => [ { "tokens" => [...], "universe" => [...] }, [ { "midPx" => "...", ... } ] ]
|
|
281
|
-
|
|
282
|
-
# Retrieve a user's token balances
|
|
283
|
-
balances = sdk.info.spot_balances(user_address)
|
|
284
|
-
# => { "balances" => [{ "coin" => "USDC", "token" => 0, "total" => "..." }, ...] }
|
|
285
|
-
|
|
286
|
-
# Retrieve information about the Spot Deploy Auction
|
|
287
|
-
deploy_state = sdk.info.spot_deploy_state(user_address)
|
|
288
|
-
# => { "states" => [...], "gasAuction" => { ... } }
|
|
289
|
-
|
|
290
|
-
# Retrieve information about the Spot Pair Deploy Auction
|
|
291
|
-
pair_status = sdk.info.spot_pair_deploy_auction_status
|
|
292
|
-
# => { "startTimeSeconds" => ..., "durationSeconds" => ..., "startGas" => "...", ... }
|
|
293
|
-
|
|
294
|
-
# Retrieve information about a token by onchain id in 34-character hexadecimal format
|
|
295
|
-
details = sdk.info.token_details("0x00000000000000000000000000000000")
|
|
296
|
-
# => { "name" => "TEST", "maxSupply" => "...", "midPx" => "...", ... }
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
#### Exchange Methods (Trading)
|
|
300
|
-
|
|
301
|
-
**Note:** Exchange methods require initializing the SDK with a `private_key`.
|
|
302
|
-
|
|
303
|
-
- `order(coin:, is_buy:, size:, limit_px:, ...)` - Place a single limit order
|
|
304
|
-
- `bulk_orders(orders:, grouping:, ...)` - Place multiple orders in a batch
|
|
305
|
-
- `market_order(coin:, is_buy:, size:, slippage:, ...)` - Place a market order with slippage
|
|
306
|
-
- `cancel(coin:, oid:, ...)` - Cancel an order by order ID
|
|
307
|
-
- `cancel_by_cloid(coin:, cloid:, ...)` - Cancel an order by client order ID
|
|
308
|
-
- `bulk_cancel(cancels:, ...)` - Cancel multiple orders by order ID
|
|
309
|
-
- `bulk_cancel_by_cloid(cancels:, ...)` - Cancel multiple orders by client order ID
|
|
310
|
-
- `address` - Get the wallet address associated with the private key
|
|
311
|
-
|
|
312
|
-
All exchange methods support an optional `vault_address:` parameter for vault trading.
|
|
313
|
-
|
|
314
|
-
##### Examples: Exchange (Trading)
|
|
315
|
-
|
|
316
|
-
```ruby
|
|
317
|
-
# Initialize SDK with private key for trading
|
|
318
|
-
sdk = Hyperliquid.new(
|
|
319
|
-
testnet: true,
|
|
320
|
-
private_key: ENV['HYPERLIQUID_PRIVATE_KEY']
|
|
321
|
-
)
|
|
322
|
-
|
|
323
|
-
# Get wallet address
|
|
324
|
-
address = sdk.exchange.address
|
|
325
|
-
# => "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
|
|
326
|
-
|
|
327
|
-
# Place a limit buy order
|
|
328
|
-
result = sdk.exchange.order(
|
|
329
|
-
coin: 'BTC',
|
|
330
|
-
is_buy: true,
|
|
331
|
-
size: '0.01',
|
|
332
|
-
limit_px: '95000',
|
|
333
|
-
order_type: { limit: { tif: 'Gtc' } } # Good-til-canceled (default)
|
|
334
|
-
)
|
|
335
|
-
# => { "status" => "ok", "response" => { "type" => "order", "data" => { "statuses" => [...] } } }
|
|
336
|
-
|
|
337
|
-
# Place a limit sell order with client order ID
|
|
338
|
-
cloid = Hyperliquid::Cloid.from_int(123) # Or Cloid.random
|
|
339
|
-
result = sdk.exchange.order(
|
|
340
|
-
coin: 'ETH',
|
|
341
|
-
is_buy: false,
|
|
342
|
-
size: '0.5',
|
|
343
|
-
limit_px: '3500',
|
|
344
|
-
cloid: cloid
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
# Place a market order (IoC with slippage)
|
|
348
|
-
result = sdk.exchange.market_order(
|
|
349
|
-
coin: 'BTC',
|
|
350
|
-
is_buy: true,
|
|
351
|
-
size: '0.01',
|
|
352
|
-
slippage: 0.03 # 3% slippage tolerance (default: 5%)
|
|
353
|
-
)
|
|
354
|
-
|
|
355
|
-
# Place multiple orders at once
|
|
356
|
-
orders = [
|
|
357
|
-
{ coin: 'BTC', is_buy: true, size: '0.01', limit_px: '94000' },
|
|
358
|
-
{ coin: 'BTC', is_buy: false, size: '0.01', limit_px: '96000' }
|
|
359
|
-
]
|
|
360
|
-
result = sdk.exchange.bulk_orders(orders: orders)
|
|
361
|
-
|
|
362
|
-
# Cancel an order by order ID
|
|
363
|
-
oid = result.dig('response', 'data', 'statuses', 0, 'resting', 'oid')
|
|
364
|
-
sdk.exchange.cancel(coin: 'BTC', oid: oid)
|
|
365
|
-
|
|
366
|
-
# Cancel an order by client order ID
|
|
367
|
-
sdk.exchange.cancel_by_cloid(coin: 'ETH', cloid: cloid)
|
|
368
|
-
|
|
369
|
-
# Cancel multiple orders by order ID
|
|
370
|
-
cancels = [
|
|
371
|
-
{ coin: 'BTC', oid: 12345 },
|
|
372
|
-
{ coin: 'ETH', oid: 12346 }
|
|
373
|
-
]
|
|
374
|
-
sdk.exchange.bulk_cancel(cancels: cancels)
|
|
375
|
-
|
|
376
|
-
# Cancel multiple orders by client order ID
|
|
377
|
-
cloid_cancels = [
|
|
378
|
-
{ coin: 'BTC', cloid: Hyperliquid::Cloid.from_int(1) },
|
|
379
|
-
{ coin: 'ETH', cloid: Hyperliquid::Cloid.from_int(2) }
|
|
380
|
-
]
|
|
381
|
-
sdk.exchange.bulk_cancel_by_cloid(cancels: cloid_cancels)
|
|
382
|
-
|
|
383
|
-
# Vault trading (trade on behalf of a vault)
|
|
384
|
-
vault_address = '0x...'
|
|
385
|
-
sdk.exchange.order(
|
|
386
|
-
coin: 'BTC',
|
|
387
|
-
is_buy: true,
|
|
388
|
-
size: '1.0',
|
|
389
|
-
limit_px: '95000',
|
|
390
|
-
vault_address: vault_address
|
|
391
|
-
)
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
**Order Types:**
|
|
395
|
-
- `{ limit: { tif: 'Gtc' } }` - Good-til-canceled (default)
|
|
396
|
-
- `{ limit: { tif: 'Ioc' } }` - Immediate-or-cancel
|
|
397
|
-
- `{ limit: { tif: 'Alo' } }` - Add-liquidity-only (post-only)
|
|
398
|
-
|
|
399
|
-
**Trigger Orders (Stop Loss / Take Profit):**
|
|
400
|
-
```ruby
|
|
401
|
-
# Stop loss: Sell when price drops to trigger level
|
|
402
|
-
sdk.exchange.order(
|
|
403
|
-
coin: 'BTC',
|
|
404
|
-
is_buy: false,
|
|
405
|
-
size: '0.1',
|
|
406
|
-
limit_px: '89900',
|
|
407
|
-
order_type: {
|
|
408
|
-
trigger: {
|
|
409
|
-
trigger_px: 90_000,
|
|
410
|
-
is_market: true, # Execute as market order when triggered
|
|
411
|
-
tpsl: 'sl' # Stop loss
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
)
|
|
415
|
-
|
|
416
|
-
# Take profit: Sell when price rises to trigger level
|
|
417
|
-
sdk.exchange.order(
|
|
418
|
-
coin: 'BTC',
|
|
419
|
-
is_buy: false,
|
|
420
|
-
size: '0.1',
|
|
421
|
-
limit_px: '100100',
|
|
422
|
-
order_type: {
|
|
423
|
-
trigger: {
|
|
424
|
-
trigger_px: 100_000,
|
|
425
|
-
is_market: false, # Execute as limit order when triggered
|
|
426
|
-
tpsl: 'tp' # Take profit
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
)
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
**Client Order IDs (Cloid):**
|
|
433
|
-
```ruby
|
|
434
|
-
# Create from integer (zero-padded to 16 bytes)
|
|
435
|
-
cloid = Hyperliquid::Cloid.from_int(42)
|
|
436
|
-
# => "0x0000000000000000000000000000002a"
|
|
437
|
-
|
|
438
|
-
# Create from hex string
|
|
439
|
-
cloid = Hyperliquid::Cloid.from_str('0x1234567890abcdef1234567890abcdef')
|
|
440
|
-
|
|
441
|
-
# Create from UUID
|
|
442
|
-
cloid = Hyperliquid::Cloid.from_uuid('550e8400-e29b-41d4-a716-446655440000')
|
|
443
|
-
|
|
444
|
-
# Generate random
|
|
445
|
-
cloid = Hyperliquid::Cloid.random
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
### Configuration
|
|
449
|
-
|
|
450
|
-
```ruby
|
|
451
|
-
# Custom timeout (default: 30 seconds)
|
|
452
|
-
sdk = Hyperliquid.new(timeout: 60)
|
|
453
|
-
|
|
454
|
-
# Enable retry logic for handling transient failures (default: disabled)
|
|
455
|
-
sdk = Hyperliquid.new(retry_enabled: true)
|
|
456
|
-
|
|
457
|
-
# Enable trading with a private key
|
|
458
|
-
sdk = Hyperliquid.new(private_key: ENV['HYPERLIQUID_PRIVATE_KEY'])
|
|
459
|
-
|
|
460
|
-
# Set global order expiration (orders expire after this timestamp)
|
|
461
|
-
expires_at_ms = (Time.now.to_f * 1000).to_i + 30_000 # 30 seconds from now
|
|
462
|
-
sdk = Hyperliquid.new(
|
|
463
|
-
private_key: ENV['HYPERLIQUID_PRIVATE_KEY'],
|
|
464
|
-
expires_after: expires_at_ms
|
|
465
|
-
)
|
|
466
|
-
|
|
467
|
-
# Combine multiple configuration options
|
|
468
|
-
sdk = Hyperliquid.new(
|
|
469
|
-
testnet: true,
|
|
470
|
-
timeout: 60,
|
|
471
|
-
retry_enabled: true,
|
|
472
|
-
private_key: ENV['HYPERLIQUID_PRIVATE_KEY'],
|
|
473
|
-
expires_after: expires_at_ms
|
|
474
|
-
)
|
|
475
|
-
|
|
476
|
-
# Check which environment you're using
|
|
477
|
-
sdk.testnet? # => false
|
|
478
|
-
sdk.base_url # => "https://api.hyperliquid.xyz"
|
|
479
|
-
|
|
480
|
-
# Check if exchange is available (private_key was provided)
|
|
481
|
-
sdk.exchange # => nil if no private_key, Hyperliquid::Exchange instance otherwise
|
|
482
|
-
```
|
|
483
|
-
|
|
484
|
-
#### Retry Configuration
|
|
485
|
-
|
|
486
|
-
By default, retry logic is **disabled** for predictable API behavior. When enabled, the SDK will automatically retry requests that fail due to:
|
|
487
|
-
|
|
488
|
-
- Network connectivity issues (connection failed, timeouts)
|
|
489
|
-
- Server errors (5xx status codes)
|
|
490
|
-
- Rate limiting (429 status codes)
|
|
491
|
-
|
|
492
|
-
**Retry Settings:**
|
|
493
|
-
- Maximum retries: 2
|
|
494
|
-
- Base interval: 0.5 seconds
|
|
495
|
-
- Backoff factor: 2x (exponential backoff)
|
|
496
|
-
- Randomness: ±50% to prevent thundering herd
|
|
497
|
-
|
|
498
|
-
**Note:** Retries are disabled by default to avoid unexpected delays in time-sensitive trading applications. Enable only when you want automatic handling of transient failures.
|
|
499
|
-
|
|
500
|
-
### Error Handling
|
|
501
|
-
|
|
502
|
-
The SDK provides comprehensive error handling:
|
|
503
|
-
|
|
504
|
-
```ruby
|
|
505
|
-
begin
|
|
506
|
-
orders = sdk.info.open_orders(user_address)
|
|
507
|
-
rescue Hyperliquid::AuthenticationError
|
|
508
|
-
# Handle authentication issues
|
|
509
|
-
rescue Hyperliquid::RateLimitError
|
|
510
|
-
# Handle rate limiting
|
|
511
|
-
rescue Hyperliquid::ServerError
|
|
512
|
-
# Handle server errors
|
|
513
|
-
rescue Hyperliquid::NetworkError
|
|
514
|
-
# Handle network connectivity issues
|
|
515
|
-
rescue Hyperliquid::Error => e
|
|
516
|
-
# Handle any other Hyperliquid API errors
|
|
517
|
-
puts "Error: #{e.message}"
|
|
518
|
-
puts "Status: #{e.status_code}" if e.status_code
|
|
519
|
-
puts "Response: #{e.response_body}" if e.response_body
|
|
520
|
-
end
|
|
521
|
-
```
|
|
522
|
-
|
|
523
|
-
Available error classes:
|
|
524
|
-
- `Hyperliquid::Error` - Base error class
|
|
525
|
-
- `Hyperliquid::ClientError` - 4xx errors
|
|
526
|
-
- `Hyperliquid::ServerError` - 5xx errors
|
|
527
|
-
- `Hyperliquid::AuthenticationError` - 401 errors
|
|
528
|
-
- `Hyperliquid::BadRequestError` - 400 errors
|
|
529
|
-
- `Hyperliquid::NotFoundError` - 404 errors
|
|
530
|
-
- `Hyperliquid::RateLimitError` - 429 errors
|
|
531
|
-
- `Hyperliquid::NetworkError` - Connection issues
|
|
532
|
-
- `Hyperliquid::TimeoutError` - Request timeouts
|
|
533
|
-
|
|
534
|
-
## Development
|
|
535
|
-
|
|
536
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
537
|
-
|
|
538
|
-
Run the example:
|
|
539
|
-
```bash
|
|
540
|
-
ruby example.rb
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
Run tests:
|
|
544
|
-
```bash
|
|
545
|
-
rake spec
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
Run tests and linting together:
|
|
549
|
-
```bash
|
|
550
|
-
rake
|
|
551
|
-
```
|
|
552
|
-
|
|
553
|
-
Run linting:
|
|
554
|
-
```bash
|
|
555
|
-
rake rubocop
|
|
556
|
-
```
|
|
51
|
+
- [API Reference](docs/API.md) - Complete list of available methods
|
|
52
|
+
- [Examples](docs/EXAMPLES.md) - Code examples for Info and Exchange APIs
|
|
53
|
+
- [Configuration](docs/CONFIGURATION.md) - SDK configuration options
|
|
54
|
+
- [Error Handling](docs/ERRORS.md) - Error types and handling
|
|
55
|
+
- [Development](docs/DEVELOPMENT.md) - Contributing and running tests
|
|
557
56
|
|
|
558
57
|
## Roadmap
|
|
559
58
|
|
data/docs/API.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
## Info Methods
|
|
4
|
+
|
|
5
|
+
Read-only methods for querying market data and user information.
|
|
6
|
+
|
|
7
|
+
### General Info
|
|
8
|
+
|
|
9
|
+
- `all_mids()` - Retrieve mids for all coins
|
|
10
|
+
- `open_orders(user)` - Retrieve a user's open orders
|
|
11
|
+
- `frontend_open_orders(user, dex: nil)` - Retrieve a user's open orders with additional frontend info
|
|
12
|
+
- `user_fills(user)` - Retrieve a user's fills
|
|
13
|
+
- `user_fills_by_time(user, start_time, end_time = nil)` - Retrieve a user's fills by time (optional end time)
|
|
14
|
+
- `user_rate_limit(user)` - Query user rate limits
|
|
15
|
+
- `order_status(user, oid)` - Query order status by order id (oid)
|
|
16
|
+
- `order_status_by_cloid(user, cloid)` - Query order status by client order id (cloid)
|
|
17
|
+
- `l2_book(coin)` - L2 book snapshot (Perpetuals and Spot)
|
|
18
|
+
- `candles_snapshot(coin, interval, start_time, end_time)` - Candle snapshot (Perpetuals and Spot)
|
|
19
|
+
- `max_builder_fee(user, builder)` - Check builder fee approval
|
|
20
|
+
- `historical_orders(user, start_time = nil, end_time = nil)` - Retrieve a user's historical orders
|
|
21
|
+
- `user_twap_slice_fills(user, start_time = nil, end_time = nil)` - Retrieve a user's TWAP slice fills
|
|
22
|
+
- `user_subaccounts(user)` - Retrieve a user's subaccounts
|
|
23
|
+
- `vault_details(vault_address, user = nil)` - Retrieve details for a vault
|
|
24
|
+
- `user_vault_equities(user)` - Retrieve a user's vault deposits
|
|
25
|
+
- `user_role(user)` - Query a user's role
|
|
26
|
+
- `portfolio(user)` - Query a user's portfolio
|
|
27
|
+
- `referral(user)` - Query a user's referral information
|
|
28
|
+
- `user_fees(user)` - Query a user's fees and fee schedule
|
|
29
|
+
- `delegations(user)` - Query a user's staking delegations
|
|
30
|
+
- `delegator_summary(user)` - Query a user's staking summary
|
|
31
|
+
- `delegator_history(user)` - Query a user's staking history
|
|
32
|
+
- `delegator_rewards(user)` - Query a user's staking rewards
|
|
33
|
+
|
|
34
|
+
### Perpetuals Methods
|
|
35
|
+
|
|
36
|
+
- `perp_dexs()` - Retrieve all perpetual DEXs
|
|
37
|
+
- `meta(dex: nil)` - Get asset metadata (optionally for a specific perp DEX)
|
|
38
|
+
- `meta_and_asset_ctxs()` - Get extended asset metadata
|
|
39
|
+
- `user_state(user, dex: nil)` - Retrieve user's perpetuals account summary (optionally for a specific perp DEX)
|
|
40
|
+
- `predicted_fundings()` - Retrieve predicted funding rates across venues
|
|
41
|
+
- `perps_at_open_interest_cap()` - Query perps at open interest caps
|
|
42
|
+
- `perp_deploy_auction_status()` - Retrieve Perp Deploy Auction status
|
|
43
|
+
- `active_asset_data(user, coin)` - Retrieve a user's active asset data for a coin
|
|
44
|
+
- `perp_dex_limits(dex)` - Retrieve builder-deployed perp market limits for a DEX
|
|
45
|
+
- `user_funding(user, start_time, end_time = nil)` - Retrieve a user's funding history (optional end time)
|
|
46
|
+
- `user_non_funding_ledger_updates(user, start_time, end_time = nil)` - Retrieve a user's non-funding ledger updates. Non-funding ledger updates include deposits, transfers, and withdrawals. (optional end time)
|
|
47
|
+
- `funding_history(coin, start_time, end_time = nil)` - Retrieve historical funding rates (optional end time)
|
|
48
|
+
|
|
49
|
+
### Spot Methods
|
|
50
|
+
|
|
51
|
+
- `spot_meta()` - Retrieve spot metadata (tokens and universe)
|
|
52
|
+
- `spot_meta_and_asset_ctxs()` - Retrieve spot metadata and asset contexts
|
|
53
|
+
- `spot_balances(user)` - Retrieve a user's spot token balances
|
|
54
|
+
- `spot_deploy_state(user)` - Retrieve Spot Deploy Auction information
|
|
55
|
+
- `spot_pair_deploy_auction_status()` - Retrieve Spot Pair Deploy Auction status
|
|
56
|
+
- `token_details(token_id)` - Retrieve information about a token by tokenId
|
|
57
|
+
|
|
58
|
+
## Exchange Methods (Trading)
|
|
59
|
+
|
|
60
|
+
**Note:** Exchange methods require initializing the SDK with a `private_key`.
|
|
61
|
+
|
|
62
|
+
- `order(coin:, is_buy:, size:, limit_px:, ...)` - Place a single limit order
|
|
63
|
+
- `bulk_orders(orders:, grouping:, ...)` - Place multiple orders in a batch
|
|
64
|
+
- `market_order(coin:, is_buy:, size:, slippage:, ...)` - Place a market order with slippage
|
|
65
|
+
- `cancel(coin:, oid:, ...)` - Cancel an order by order ID
|
|
66
|
+
- `cancel_by_cloid(coin:, cloid:, ...)` - Cancel an order by client order ID
|
|
67
|
+
- `bulk_cancel(cancels:, ...)` - Cancel multiple orders by order ID
|
|
68
|
+
- `bulk_cancel_by_cloid(cancels:, ...)` - Cancel multiple orders by client order ID
|
|
69
|
+
- `address` - Get the wallet address associated with the private key
|
|
70
|
+
|
|
71
|
+
All exchange methods support an optional `vault_address:` parameter for vault trading.
|
|
72
|
+
|
|
73
|
+
### Order Types
|
|
74
|
+
|
|
75
|
+
- `{ limit: { tif: 'Gtc' } }` - Good-til-canceled (default)
|
|
76
|
+
- `{ limit: { tif: 'Ioc' } }` - Immediate-or-cancel
|
|
77
|
+
- `{ limit: { tif: 'Alo' } }` - Add-liquidity-only (post-only)
|
|
78
|
+
|
|
79
|
+
### Trigger Orders (Stop Loss / Take Profit)
|
|
80
|
+
|
|
81
|
+
Trigger orders execute when a price threshold is reached:
|
|
82
|
+
|
|
83
|
+
- `tpsl: 'sl'` - Stop loss
|
|
84
|
+
- `tpsl: 'tp'` - Take profit
|
|
85
|
+
- `is_market: true/false` - Execute as market or limit order when triggered
|
|
86
|
+
|
|
87
|
+
### Client Order IDs (Cloid)
|
|
88
|
+
|
|
89
|
+
Client order IDs must be 16 bytes in hex format (`0x` + 32 hex characters).
|
|
90
|
+
|
|
91
|
+
Factory methods:
|
|
92
|
+
- `Hyperliquid::Cloid.from_int(n)` - Create from integer (zero-padded)
|
|
93
|
+
- `Hyperliquid::Cloid.from_str(s)` - Create from hex string
|
|
94
|
+
- `Hyperliquid::Cloid.from_uuid(uuid)` - Create from UUID
|
|
95
|
+
- `Hyperliquid::Cloid.random` - Generate random
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
## Basic Options
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
# Custom timeout (default: 30 seconds)
|
|
7
|
+
sdk = Hyperliquid.new(timeout: 60)
|
|
8
|
+
|
|
9
|
+
# Enable retry logic for handling transient failures (default: disabled)
|
|
10
|
+
sdk = Hyperliquid.new(retry_enabled: true)
|
|
11
|
+
|
|
12
|
+
# Enable trading with a private key
|
|
13
|
+
sdk = Hyperliquid.new(private_key: ENV['HYPERLIQUID_PRIVATE_KEY'])
|
|
14
|
+
|
|
15
|
+
# Set global order expiration (orders expire after this timestamp)
|
|
16
|
+
expires_at_ms = (Time.now.to_f * 1000).to_i + 30_000 # 30 seconds from now
|
|
17
|
+
sdk = Hyperliquid.new(
|
|
18
|
+
private_key: ENV['HYPERLIQUID_PRIVATE_KEY'],
|
|
19
|
+
expires_after: expires_at_ms
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Combine multiple configuration options
|
|
23
|
+
sdk = Hyperliquid.new(
|
|
24
|
+
testnet: true,
|
|
25
|
+
timeout: 60,
|
|
26
|
+
retry_enabled: true,
|
|
27
|
+
private_key: ENV['HYPERLIQUID_PRIVATE_KEY'],
|
|
28
|
+
expires_after: expires_at_ms
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Check which environment you're using
|
|
32
|
+
sdk.testnet? # => false
|
|
33
|
+
sdk.base_url # => "https://api.hyperliquid.xyz"
|
|
34
|
+
|
|
35
|
+
# Check if exchange is available (private_key was provided)
|
|
36
|
+
sdk.exchange # => nil if no private_key, Hyperliquid::Exchange instance otherwise
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Retry Configuration
|
|
40
|
+
|
|
41
|
+
By default, retry logic is **disabled** for predictable API behavior. When enabled, the SDK will automatically retry requests that fail due to:
|
|
42
|
+
|
|
43
|
+
- Network connectivity issues (connection failed, timeouts)
|
|
44
|
+
- Server errors (5xx status codes)
|
|
45
|
+
- Rate limiting (429 status codes)
|
|
46
|
+
|
|
47
|
+
**Retry Settings:**
|
|
48
|
+
- Maximum retries: 2
|
|
49
|
+
- Base interval: 0.5 seconds
|
|
50
|
+
- Backoff factor: 2x (exponential backoff)
|
|
51
|
+
- Randomness: ±50% to prevent thundering herd
|
|
52
|
+
|
|
53
|
+
**Note:** Retries are disabled by default to avoid unexpected delays in time-sensitive trading applications. Enable only when you want automatic handling of transient failures.
|
data/docs/DEVELOPMENT.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Development
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
After checking out the repo, run `bin/setup` to install dependencies.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bin/setup
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Running Tests
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Run all tests
|
|
15
|
+
rake spec
|
|
16
|
+
|
|
17
|
+
# Run tests and linting together (default)
|
|
18
|
+
rake
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Linting
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
rake rubocop
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Interactive Console
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bin/console
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
This opens an interactive prompt with the SDK loaded for experimentation.
|
|
34
|
+
|
|
35
|
+
## Example Script
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
ruby example.rb
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Integration Testing (Testnet)
|
|
42
|
+
|
|
43
|
+
For real trading tests on testnet:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Get testnet funds from: https://app.hyperliquid-testnet.xyz
|
|
47
|
+
HYPERLIQUID_PRIVATE_KEY=0x... ruby test_integration.rb
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The integration test executes real trades on testnet:
|
|
51
|
+
1. Spot market roundtrip (buy/sell PURR/USDC)
|
|
52
|
+
2. Spot limit order (place and cancel)
|
|
53
|
+
3. Perp market roundtrip (long/close BTC)
|
|
54
|
+
4. Perp limit order (place short, cancel)
|
data/docs/ERRORS.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Error Handling
|
|
2
|
+
|
|
3
|
+
The SDK provides comprehensive error handling with typed exceptions.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
begin
|
|
9
|
+
orders = sdk.info.open_orders(user_address)
|
|
10
|
+
rescue Hyperliquid::AuthenticationError
|
|
11
|
+
# Handle authentication issues
|
|
12
|
+
rescue Hyperliquid::RateLimitError
|
|
13
|
+
# Handle rate limiting
|
|
14
|
+
rescue Hyperliquid::ServerError
|
|
15
|
+
# Handle server errors
|
|
16
|
+
rescue Hyperliquid::NetworkError
|
|
17
|
+
# Handle network connectivity issues
|
|
18
|
+
rescue Hyperliquid::Error => e
|
|
19
|
+
# Handle any other Hyperliquid API errors
|
|
20
|
+
puts "Error: #{e.message}"
|
|
21
|
+
puts "Status: #{e.status_code}" if e.status_code
|
|
22
|
+
puts "Response: #{e.response_body}" if e.response_body
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Error Classes
|
|
27
|
+
|
|
28
|
+
| Error Class | Description |
|
|
29
|
+
|-------------|-------------|
|
|
30
|
+
| `Hyperliquid::Error` | Base error class |
|
|
31
|
+
| `Hyperliquid::ClientError` | 4xx errors |
|
|
32
|
+
| `Hyperliquid::ServerError` | 5xx errors |
|
|
33
|
+
| `Hyperliquid::AuthenticationError` | 401 errors |
|
|
34
|
+
| `Hyperliquid::BadRequestError` | 400 errors |
|
|
35
|
+
| `Hyperliquid::NotFoundError` | 404 errors |
|
|
36
|
+
| `Hyperliquid::RateLimitError` | 429 errors |
|
|
37
|
+
| `Hyperliquid::NetworkError` | Connection issues |
|
|
38
|
+
| `Hyperliquid::TimeoutError` | Request timeouts |
|
data/docs/EXAMPLES.md
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
## Info API
|
|
4
|
+
|
|
5
|
+
### General Info
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
# Retrieve mids for all coins
|
|
9
|
+
mids = sdk.info.all_mids
|
|
10
|
+
# => { "BTC" => "50000", "ETH" => "3000", ... }
|
|
11
|
+
|
|
12
|
+
user_address = "0x..."
|
|
13
|
+
|
|
14
|
+
# Retrieve a user's open orders
|
|
15
|
+
orders = sdk.info.open_orders(user_address)
|
|
16
|
+
# => [{ "coin" => "BTC", "sz" => "0.1", "px" => "50000", "side" => "A" }]
|
|
17
|
+
|
|
18
|
+
# Retrieve a user's open orders with additional frontend info
|
|
19
|
+
frontend_orders = sdk.info.frontend_open_orders(user_address)
|
|
20
|
+
# => [{ "coin" => "BTC", "isTrigger" => false, ... }]
|
|
21
|
+
|
|
22
|
+
# Retrieve a user's fills
|
|
23
|
+
fills = sdk.info.user_fills(user_address)
|
|
24
|
+
# => [{ "coin" => "BTC", "sz" => "0.1", "px" => "50000", "side" => "A", "time" => 1234567890 }]
|
|
25
|
+
|
|
26
|
+
# Retrieve a user's fills by time
|
|
27
|
+
start_time_ms = 1_700_000_000_000
|
|
28
|
+
end_time_ms = start_time_ms + 86_400_000
|
|
29
|
+
fills_by_time = sdk.info.user_fills_by_time(user_address, start_time_ms, end_time_ms)
|
|
30
|
+
# => [{ "coin" => "ETH", "px" => "3000", "time" => start_time_ms }, ...]
|
|
31
|
+
|
|
32
|
+
# Query user rate limits
|
|
33
|
+
rate_limit = sdk.info.user_rate_limit(user_address)
|
|
34
|
+
# => { "nRequestsUsed" => 100, "nRequestsCap" => 10000 }
|
|
35
|
+
|
|
36
|
+
# Query order status by oid
|
|
37
|
+
order_id = 12345
|
|
38
|
+
status_by_oid = sdk.info.order_status(user_address, order_id)
|
|
39
|
+
# => { "status" => "filled", ... }
|
|
40
|
+
|
|
41
|
+
# Query order status by cloid
|
|
42
|
+
cloid = "client-order-id-123"
|
|
43
|
+
status_by_cloid = sdk.info.order_status_by_cloid(user_address, cloid)
|
|
44
|
+
# => { "status" => "cancelled", ... }
|
|
45
|
+
|
|
46
|
+
# L2 order book snapshot
|
|
47
|
+
book = sdk.info.l2_book("BTC")
|
|
48
|
+
# => { "coin" => "BTC", "levels" => [[asks], [bids]], "time" => ... }
|
|
49
|
+
|
|
50
|
+
# Candle snapshot
|
|
51
|
+
candles = sdk.info.candles_snapshot("BTC", "1h", start_time_ms, end_time_ms)
|
|
52
|
+
# => [{ "t" => ..., "o" => "50000", "h" => "51000", "l" => "49000", "c" => "50500", "v" => "100" }]
|
|
53
|
+
|
|
54
|
+
# Check builder fee approval
|
|
55
|
+
builder_address = "0x..."
|
|
56
|
+
fee_approval = sdk.info.max_builder_fee(user_address, builder_address)
|
|
57
|
+
# => { "approved" => true, ... }
|
|
58
|
+
|
|
59
|
+
# Retrieve a user's historical orders
|
|
60
|
+
hist_orders = sdk.info.historical_orders(user_address)
|
|
61
|
+
# => [{ "oid" => 123, "coin" => "BTC", ... }]
|
|
62
|
+
hist_orders_ranged = sdk.info.historical_orders(user_address, start_time_ms, end_time_ms)
|
|
63
|
+
# => []
|
|
64
|
+
|
|
65
|
+
# Retrieve a user's TWAP slice fills
|
|
66
|
+
twap_fills = sdk.info.user_twap_slice_fills(user_address)
|
|
67
|
+
# => [{ "sliceId" => 1, "coin" => "ETH", "sz" => "1.0" }, ...]
|
|
68
|
+
twap_fills_ranged = sdk.info.user_twap_slice_fills(user_address, start_time_ms, end_time_ms)
|
|
69
|
+
# => []
|
|
70
|
+
|
|
71
|
+
# Retrieve a user's subaccounts
|
|
72
|
+
subaccounts = sdk.info.user_subaccounts(user_address)
|
|
73
|
+
# => ["0x1111...", ...]
|
|
74
|
+
|
|
75
|
+
# Retrieve details for a vault
|
|
76
|
+
vault_addr = "0x..."
|
|
77
|
+
vault = sdk.info.vault_details(vault_addr)
|
|
78
|
+
# => { "vaultAddress" => vault_addr, ... }
|
|
79
|
+
vault_with_user = sdk.info.vault_details(vault_addr, user_address)
|
|
80
|
+
# => { "vaultAddress" => vault_addr, "user" => user_address, ... }
|
|
81
|
+
|
|
82
|
+
# Retrieve a user's vault deposits
|
|
83
|
+
vault_deposits = sdk.info.user_vault_equities(user_address)
|
|
84
|
+
# => [{ "vaultAddress" => "0x...", "equity" => "123.45" }, ...]
|
|
85
|
+
|
|
86
|
+
# Query a user's role
|
|
87
|
+
role = sdk.info.user_role(user_address)
|
|
88
|
+
# => { "role" => "tradingUser" }
|
|
89
|
+
|
|
90
|
+
# Query a user's portfolio
|
|
91
|
+
portfolio = sdk.info.portfolio(user_address)
|
|
92
|
+
# => [["day", { "pnlHistory" => [...], "vlm" => "0.0" }], ...]
|
|
93
|
+
|
|
94
|
+
# Query a user's referral information
|
|
95
|
+
referral = sdk.info.referral(user_address)
|
|
96
|
+
# => { "referredBy" => { "referrer" => "0x..." }, ... }
|
|
97
|
+
|
|
98
|
+
# Query a user's fees
|
|
99
|
+
fees = sdk.info.user_fees(user_address)
|
|
100
|
+
# => { "userAddRate" => "0.0001", "feeSchedule" => { ... } }
|
|
101
|
+
|
|
102
|
+
# Query a user's staking delegations
|
|
103
|
+
delegations = sdk.info.delegations(user_address)
|
|
104
|
+
# => [{ "validator" => "0x...", "amount" => "100.0" }, ...]
|
|
105
|
+
|
|
106
|
+
# Query a user's staking summary
|
|
107
|
+
summary = sdk.info.delegator_summary(user_address)
|
|
108
|
+
# => { "delegated" => "12060.16529862", ... }
|
|
109
|
+
|
|
110
|
+
# Query a user's staking history
|
|
111
|
+
history = sdk.info.delegator_history(user_address)
|
|
112
|
+
# => [{ "time" => 1_736_726_400_073, "delta" => { ... } }, ...]
|
|
113
|
+
|
|
114
|
+
# Query a user's staking rewards
|
|
115
|
+
rewards = sdk.info.delegator_rewards(user_address)
|
|
116
|
+
# => [{ "time" => 1_736_726_400_073, "source" => "delegation", "totalAmount" => "0.123" }, ...]
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Note:** `l2_book` and `candles_snapshot` work for both Perpetuals and Spot. For spot, use `"{BASE}/USDC"` when available (e.g., `"PURR/USDC"`). Otherwise, use the index alias `"@{index}"` from `spot_meta["universe"]`.
|
|
120
|
+
|
|
121
|
+
### Perpetuals
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
# Retrieve all perpetual DEXs
|
|
125
|
+
perp_dexs = sdk.info.perp_dexs
|
|
126
|
+
# => [nil, { "name" => "test", "full_name" => "test dex", ... }]
|
|
127
|
+
|
|
128
|
+
# Retrieve perpetuals metadata (optionally for a specific perp dex)
|
|
129
|
+
meta = sdk.info.meta
|
|
130
|
+
# => { "universe" => [...] }
|
|
131
|
+
meta = sdk.info.meta(dex: "perp-dex-name")
|
|
132
|
+
# => { "universe" => [...] }
|
|
133
|
+
|
|
134
|
+
# Retrieve perpetuals asset contexts (includes mark price, current funding, open interest, etc.)
|
|
135
|
+
meta_ctxs = sdk.info.meta_and_asset_ctxs
|
|
136
|
+
# => { "universe" => [...], "assetCtxs" => [...] }
|
|
137
|
+
|
|
138
|
+
# Retrieve user's perpetuals account summary (optionally for a specific perp dex)
|
|
139
|
+
state = sdk.info.user_state(user_address)
|
|
140
|
+
# => { "assetPositions" => [...], "marginSummary" => {...} }
|
|
141
|
+
state = sdk.info.user_state(user_address, dex: "perp-dex-name")
|
|
142
|
+
# => { "assetPositions" => [...], "marginSummary" => {...} }
|
|
143
|
+
|
|
144
|
+
# Retrieve a user's funding history or non-funding ledger updates (optional end_time)
|
|
145
|
+
funding = sdk.info.user_funding(user_address, start_time)
|
|
146
|
+
# => [{ "delta" => { "type" => "funding", ... }, "time" => ... }]
|
|
147
|
+
funding = sdk.info.user_funding(user_address, start_time, end_time)
|
|
148
|
+
# => [{ "delta" => { "type" => "funding", ... }, "time" => ... }]
|
|
149
|
+
|
|
150
|
+
# Retrieve historical funding rates
|
|
151
|
+
hist = sdk.info.funding_history("ETH", start_time)
|
|
152
|
+
# => [{ "coin" => "ETH", "fundingRate" => "...", "time" => ... }]
|
|
153
|
+
|
|
154
|
+
# Retrieve predicted funding rates for different venues
|
|
155
|
+
pred = sdk.info.predicted_fundings
|
|
156
|
+
# => [["AVAX", [["HlPerp", { "fundingRate" => "0.0000125", "nextFundingTime" => ... }], ...]], ...]
|
|
157
|
+
|
|
158
|
+
# Query perps at open interest caps
|
|
159
|
+
oi_capped = sdk.info.perps_at_open_interest_cap
|
|
160
|
+
# => ["BADGER", "CANTO", ...]
|
|
161
|
+
|
|
162
|
+
# Retrieve information about the Perp Deploy Auction
|
|
163
|
+
auction = sdk.info.perp_deploy_auction_status
|
|
164
|
+
# => { "startTimeSeconds" => ..., "durationSeconds" => ..., "startGas" => "500.0", ... }
|
|
165
|
+
|
|
166
|
+
# Retrieve User's Active Asset Data
|
|
167
|
+
aad = sdk.info.active_asset_data(user_address, "APT")
|
|
168
|
+
# => { "user" => user_address, "coin" => "APT", "leverage" => { "type" => "cross", "value" => 3 }, ... }
|
|
169
|
+
|
|
170
|
+
# Retrieve Builder-Deployed Perp Market Limits
|
|
171
|
+
limits = sdk.info.perp_dex_limits("builder-dex")
|
|
172
|
+
# => { "totalOiCap" => "10000000.0", "oiSzCapPerPerp" => "...", ... }
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Spot
|
|
176
|
+
|
|
177
|
+
```ruby
|
|
178
|
+
# Retrieve spot metadata
|
|
179
|
+
spot_meta = sdk.info.spot_meta
|
|
180
|
+
# => { "tokens" => [...], "universe" => [...] }
|
|
181
|
+
|
|
182
|
+
# Retrieve spot asset contexts
|
|
183
|
+
spot_meta_ctxs = sdk.info.spot_meta_and_asset_ctxs
|
|
184
|
+
# => [ { "tokens" => [...], "universe" => [...] }, [ { "midPx" => "...", ... } ] ]
|
|
185
|
+
|
|
186
|
+
# Retrieve a user's token balances
|
|
187
|
+
balances = sdk.info.spot_balances(user_address)
|
|
188
|
+
# => { "balances" => [{ "coin" => "USDC", "token" => 0, "total" => "..." }, ...] }
|
|
189
|
+
|
|
190
|
+
# Retrieve information about the Spot Deploy Auction
|
|
191
|
+
deploy_state = sdk.info.spot_deploy_state(user_address)
|
|
192
|
+
# => { "states" => [...], "gasAuction" => { ... } }
|
|
193
|
+
|
|
194
|
+
# Retrieve information about the Spot Pair Deploy Auction
|
|
195
|
+
pair_status = sdk.info.spot_pair_deploy_auction_status
|
|
196
|
+
# => { "startTimeSeconds" => ..., "durationSeconds" => ..., "startGas" => "...", ... }
|
|
197
|
+
|
|
198
|
+
# Retrieve information about a token by onchain id in 34-character hexadecimal format
|
|
199
|
+
details = sdk.info.token_details("0x00000000000000000000000000000000")
|
|
200
|
+
# => { "name" => "TEST", "maxSupply" => "...", "midPx" => "...", ... }
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Exchange API (Trading)
|
|
204
|
+
|
|
205
|
+
### Basic Orders
|
|
206
|
+
|
|
207
|
+
```ruby
|
|
208
|
+
# Initialize SDK with private key for trading
|
|
209
|
+
sdk = Hyperliquid.new(
|
|
210
|
+
testnet: true,
|
|
211
|
+
private_key: ENV['HYPERLIQUID_PRIVATE_KEY']
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# Get wallet address
|
|
215
|
+
address = sdk.exchange.address
|
|
216
|
+
# => "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
|
|
217
|
+
|
|
218
|
+
# Place a limit buy order
|
|
219
|
+
result = sdk.exchange.order(
|
|
220
|
+
coin: 'BTC',
|
|
221
|
+
is_buy: true,
|
|
222
|
+
size: '0.01',
|
|
223
|
+
limit_px: '95000',
|
|
224
|
+
order_type: { limit: { tif: 'Gtc' } } # Good-til-canceled (default)
|
|
225
|
+
)
|
|
226
|
+
# => { "status" => "ok", "response" => { "type" => "order", "data" => { "statuses" => [...] } } }
|
|
227
|
+
|
|
228
|
+
# Place a limit sell order with client order ID
|
|
229
|
+
cloid = Hyperliquid::Cloid.from_int(123) # Or Cloid.random
|
|
230
|
+
result = sdk.exchange.order(
|
|
231
|
+
coin: 'ETH',
|
|
232
|
+
is_buy: false,
|
|
233
|
+
size: '0.5',
|
|
234
|
+
limit_px: '3500',
|
|
235
|
+
cloid: cloid
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
# Place a market order (IoC with slippage)
|
|
239
|
+
result = sdk.exchange.market_order(
|
|
240
|
+
coin: 'BTC',
|
|
241
|
+
is_buy: true,
|
|
242
|
+
size: '0.01',
|
|
243
|
+
slippage: 0.03 # 3% slippage tolerance (default: 5%)
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# Place multiple orders at once
|
|
247
|
+
orders = [
|
|
248
|
+
{ coin: 'BTC', is_buy: true, size: '0.01', limit_px: '94000' },
|
|
249
|
+
{ coin: 'BTC', is_buy: false, size: '0.01', limit_px: '96000' }
|
|
250
|
+
]
|
|
251
|
+
result = sdk.exchange.bulk_orders(orders: orders)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Canceling Orders
|
|
255
|
+
|
|
256
|
+
```ruby
|
|
257
|
+
# Cancel an order by order ID
|
|
258
|
+
oid = result.dig('response', 'data', 'statuses', 0, 'resting', 'oid')
|
|
259
|
+
sdk.exchange.cancel(coin: 'BTC', oid: oid)
|
|
260
|
+
|
|
261
|
+
# Cancel an order by client order ID
|
|
262
|
+
sdk.exchange.cancel_by_cloid(coin: 'ETH', cloid: cloid)
|
|
263
|
+
|
|
264
|
+
# Cancel multiple orders by order ID
|
|
265
|
+
cancels = [
|
|
266
|
+
{ coin: 'BTC', oid: 12345 },
|
|
267
|
+
{ coin: 'ETH', oid: 12346 }
|
|
268
|
+
]
|
|
269
|
+
sdk.exchange.bulk_cancel(cancels: cancels)
|
|
270
|
+
|
|
271
|
+
# Cancel multiple orders by client order ID
|
|
272
|
+
cloid_cancels = [
|
|
273
|
+
{ coin: 'BTC', cloid: Hyperliquid::Cloid.from_int(1) },
|
|
274
|
+
{ coin: 'ETH', cloid: Hyperliquid::Cloid.from_int(2) }
|
|
275
|
+
]
|
|
276
|
+
sdk.exchange.bulk_cancel_by_cloid(cancels: cloid_cancels)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Vault Trading
|
|
280
|
+
|
|
281
|
+
```ruby
|
|
282
|
+
# Vault trading (trade on behalf of a vault)
|
|
283
|
+
vault_address = '0x...'
|
|
284
|
+
sdk.exchange.order(
|
|
285
|
+
coin: 'BTC',
|
|
286
|
+
is_buy: true,
|
|
287
|
+
size: '1.0',
|
|
288
|
+
limit_px: '95000',
|
|
289
|
+
vault_address: vault_address
|
|
290
|
+
)
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Trigger Orders (Stop Loss / Take Profit)
|
|
294
|
+
|
|
295
|
+
```ruby
|
|
296
|
+
# Stop loss: Sell when price drops to trigger level
|
|
297
|
+
sdk.exchange.order(
|
|
298
|
+
coin: 'BTC',
|
|
299
|
+
is_buy: false,
|
|
300
|
+
size: '0.1',
|
|
301
|
+
limit_px: '89900',
|
|
302
|
+
order_type: {
|
|
303
|
+
trigger: {
|
|
304
|
+
trigger_px: 90_000,
|
|
305
|
+
is_market: true, # Execute as market order when triggered
|
|
306
|
+
tpsl: 'sl' # Stop loss
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
# Take profit: Sell when price rises to trigger level
|
|
312
|
+
sdk.exchange.order(
|
|
313
|
+
coin: 'BTC',
|
|
314
|
+
is_buy: false,
|
|
315
|
+
size: '0.1',
|
|
316
|
+
limit_px: '100100',
|
|
317
|
+
order_type: {
|
|
318
|
+
trigger: {
|
|
319
|
+
trigger_px: 100_000,
|
|
320
|
+
is_market: false, # Execute as limit order when triggered
|
|
321
|
+
tpsl: 'tp' # Take profit
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Client Order IDs (Cloid)
|
|
328
|
+
|
|
329
|
+
```ruby
|
|
330
|
+
# Create from integer (zero-padded to 16 bytes)
|
|
331
|
+
cloid = Hyperliquid::Cloid.from_int(42)
|
|
332
|
+
# => "0x0000000000000000000000000000002a"
|
|
333
|
+
|
|
334
|
+
# Create from hex string
|
|
335
|
+
cloid = Hyperliquid::Cloid.from_str('0x1234567890abcdef1234567890abcdef')
|
|
336
|
+
|
|
337
|
+
# Create from UUID
|
|
338
|
+
cloid = Hyperliquid::Cloid.from_uuid('550e8400-e29b-41d4-a716-446655440000')
|
|
339
|
+
|
|
340
|
+
# Generate random
|
|
341
|
+
cloid = Hyperliquid::Cloid.random
|
|
342
|
+
```
|
data/lib/hyperliquid/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hyperliquid
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- carter2099
|
|
@@ -82,6 +82,11 @@ files:
|
|
|
82
82
|
- LICENSE.txt
|
|
83
83
|
- README.md
|
|
84
84
|
- Rakefile
|
|
85
|
+
- docs/API.md
|
|
86
|
+
- docs/CONFIGURATION.md
|
|
87
|
+
- docs/DEVELOPMENT.md
|
|
88
|
+
- docs/ERRORS.md
|
|
89
|
+
- docs/EXAMPLES.md
|
|
85
90
|
- example.rb
|
|
86
91
|
- lib/hyperliquid.rb
|
|
87
92
|
- lib/hyperliquid/client.rb
|