hyperliquid 1.0.1 → 1.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -1
- data/AGENTS.md +83 -0
- data/CHANGELOG.md +26 -0
- data/CLAUDE.md +2 -197
- data/lib/hyperliquid/info.rb +77 -1
- data/lib/hyperliquid/version.rb +1 -1
- data/scripts/test_automated.rb +80 -0
- data/scripts/test_helpers.rb +10 -2
- metadata +7 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a9976736621e86406eb3de9e8e4827b59d1c96c86aac1efcff2ee700afa78429
|
|
4
|
+
data.tar.gz: 79c0a9f8587b1af017f02539e2c35b27e7311ba7e00328c0147db636483aed28
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 89e3b1c854bdb152494abc51ed5f7a3dcfe3c354226d7d92ed994ef8f99d9d5fabcf91d81ddedb18bf083bcc9f3cc4952578b2bfe1d95cc2d8c35b359eb392b1
|
|
7
|
+
data.tar.gz: c8fd08574cfa29c927bd5c848ca5bd578914bc82150af2ab0305c38ea84785b22f4f92bed0ca07e49f86f31c8dde089fd83c47e73c58678c807a0dacf5dc9b75
|
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.4.
|
|
1
|
+
3.4.8
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to AI coding agents working with this repository.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Ruby SDK (v1.0.1) for the Hyperliquid decentralized exchange API. Three API surfaces: **Info** (read-only market data), **Exchange** (authenticated trading), and **WebSocket** (real-time streaming). Built on Faraday for HTTP, the `eth` gem for EIP-712 signing, `msgpack` for action serialization, and `ws_lite` for WebSocket connections.
|
|
8
|
+
|
|
9
|
+
**Ruby**: >= 3.3.0 (CI tests 3.3, 3.4)
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bin/setup # install dependencies
|
|
15
|
+
rake # run tests + linting (CI default)
|
|
16
|
+
rake spec # tests only
|
|
17
|
+
rake rubocop # linting only
|
|
18
|
+
bundle exec rspec spec/hyperliquid/cloid_spec.rb # single file
|
|
19
|
+
bundle exec rspec spec/hyperliquid/cloid_spec.rb:62 # single test by line
|
|
20
|
+
bin/console # IRB with SDK loaded
|
|
21
|
+
ruby example.rb # example usage script
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Integration Tests (Testnet)
|
|
25
|
+
```bash
|
|
26
|
+
HYPERLIQUID_PRIVATE_KEY=0x... ruby scripts/test_all.rb # all
|
|
27
|
+
HYPERLIQUID_PRIVATE_KEY=0x... ruby scripts/test_08_usd_class_transfer.rb # single
|
|
28
|
+
```
|
|
29
|
+
Integration tests live in `scripts/` as standalone files. `test_integration.rb` at project root is a convenience wrapper.
|
|
30
|
+
|
|
31
|
+
## Architecture
|
|
32
|
+
|
|
33
|
+
### Request Flow
|
|
34
|
+
|
|
35
|
+
The SDK has three parallel API surfaces, all routed through `Hyperliquid::SDK` (`lib/hyperliquid.rb`):
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
Hyperliquid.new(...)
|
|
39
|
+
├── sdk.info → Info → Client → POST /info (always available)
|
|
40
|
+
├── sdk.exchange → Exchange → Client → POST /exchange (requires private_key)
|
|
41
|
+
└── sdk.ws → WS::Client → WSS /ws (real-time streaming)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Info path**: Method builds `{ type: 'someType' }` body → `Client` POSTs to `/info` → parsed JSON returned.
|
|
45
|
+
|
|
46
|
+
**Exchange path**: Method builds action payload → `Signer` generates EIP-712 signature over msgpack-encoded action → `Client` POSTs signed payload to `/exchange` → parsed JSON returned.
|
|
47
|
+
|
|
48
|
+
**WebSocket path**: `WS::Client` manages a persistent WSS connection with subscription tracking, automatic reconnection, ping keepalive (50s), and a bounded message queue (1024 max, drops oldest on overflow). Subscriptions are identified by a canonical key and dispatched via callbacks on a dedicated thread.
|
|
49
|
+
|
|
50
|
+
### Signing (Python SDK Parity)
|
|
51
|
+
|
|
52
|
+
The signing chain in `lib/hyperliquid/signing/` must exactly match the official Python SDK:
|
|
53
|
+
|
|
54
|
+
1. **Action hash**: `keccak256(msgpack(action) + nonce(8B big-endian) + vault_flag + [vault_addr] + [expires_flag + expires_after])`
|
|
55
|
+
2. **Phantom agent**: `{ source: 'a'|'b', connectionId: action_hash }` (a=mainnet, b=testnet)
|
|
56
|
+
3. **EIP-712 signature** over phantom agent with Exchange domain (chain ID 1337)
|
|
57
|
+
|
|
58
|
+
Any change to signing must maintain parity with the Python SDK or transactions will be rejected.
|
|
59
|
+
|
|
60
|
+
### Numeric Conversion
|
|
61
|
+
|
|
62
|
+
**float_to_wire** (in Exchange): Converts to string with 8 decimal precision, validates rounding tolerance (1e-12), normalizes trailing zeros. No scientific notation.
|
|
63
|
+
|
|
64
|
+
**Market order pricing** (_slippage_price): Apply slippage (default 5%) to mid price → round to 5 significant figures → round to `(6 for perp, 8 for spot) - szDecimals` decimal places.
|
|
65
|
+
|
|
66
|
+
**Spot vs Perp**: Assets with index >= 10,000 are spot (`SPOT_ASSET_THRESHOLD` in Exchange). This affects decimal place calculations.
|
|
67
|
+
|
|
68
|
+
### Testing
|
|
69
|
+
|
|
70
|
+
- **Unit tests** (`spec/`): RSpec + WebMock. WebMock resets between tests. Monkey-patching disabled. Test files mirror `lib/` structure.
|
|
71
|
+
- **Integration tests** (`scripts/`): Run against testnet with a real private key. Each script is self-contained.
|
|
72
|
+
|
|
73
|
+
### Code Style
|
|
74
|
+
|
|
75
|
+
RuboCop targets Ruby 3.3. Key relaxations: methods up to 50 lines, no class length limit (Info/Exchange are large by design), no block length limit in specs, no parameter list limit in Exchange. `scripts/`, `test_*.rb`, `local/`, and `vendor/` are excluded from linting.
|
|
76
|
+
|
|
77
|
+
### CI
|
|
78
|
+
|
|
79
|
+
GitHub Actions (`.github/workflows/main.yml`): runs `bundle exec rake` (tests + lint) on Ruby 3.3 and 3.4 for pushes to main and all PRs. Release workflow creates GitHub releases from CHANGELOG.md on version tags.
|
|
80
|
+
|
|
81
|
+
## Additional Docs
|
|
82
|
+
|
|
83
|
+
Detailed API reference, examples, WebSocket guide, configuration, and error handling in `docs/`.
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
## [Ruby Hyperliquid SDK Changelog]
|
|
2
2
|
|
|
3
|
+
## [1.1.0] - 2026-04-24
|
|
4
|
+
|
|
5
|
+
### New Info endpoints
|
|
6
|
+
|
|
7
|
+
- `Info#validator_summaries` — validator status/stake summaries
|
|
8
|
+
- `Info#exchange_status` — exchange-wide status
|
|
9
|
+
- `Info#max_market_order_ntls` — per-coin max market order notionals
|
|
10
|
+
- `Info#pre_transfer_check` — pre-flight checks for transfers
|
|
11
|
+
- `Info#vip?` — VIP status lookup
|
|
12
|
+
- `Info#liquidatable` — open positions flagged liquidatable
|
|
13
|
+
- `Info#recent_trades(coin)` — recent trades feed
|
|
14
|
+
- `Info#block_details(height)` — block detail lookup by height
|
|
15
|
+
- `Info#user_abstraction` — account abstraction state (unifiedAccount, portfolioMargin, dexAbstraction, etc.)
|
|
16
|
+
- `Info#vault_summaries` — vaults less than 2 hours old
|
|
17
|
+
- `Info#user_fills_by_time` now accepts `aggregate_by_time` and `reversed` kwargs (matches upstream Python/TS SDKs)
|
|
18
|
+
|
|
19
|
+
### Fixes
|
|
20
|
+
|
|
21
|
+
- Fix `TypeError` in `dump_status`/`check_result` when `response.data` is a String (e.g. `usdClassTransfer`, `approveBuilderFee` style actions)
|
|
22
|
+
|
|
23
|
+
## [1.0.2] - 2026-02-05
|
|
24
|
+
|
|
25
|
+
- Lower minimum Ruby requirement to 3.3 and align RuboCop target
|
|
26
|
+
- Expand CI matrix to Ruby 3.3, 3.4, and 4.0
|
|
27
|
+
- Bump `ws_lite` dependency to `~> 1.0.1`
|
|
28
|
+
|
|
3
29
|
## [1.0.1] - 2026-02-03
|
|
4
30
|
|
|
5
31
|
- Minor refactors to reduce method complexity
|
data/CLAUDE.md
CHANGED
|
@@ -2,200 +2,5 @@
|
|
|
2
2
|
|
|
3
3
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
This is a Ruby SDK for the Hyperliquid decentralized exchange API. The current version (0.4.0) supports both **read operations** (Info API) and **authenticated write operations** (Exchange API) for trading.
|
|
8
|
-
|
|
9
|
-
**Target Ruby Version**: 3.4.0+
|
|
10
|
-
|
|
11
|
-
## Development Commands
|
|
12
|
-
|
|
13
|
-
### Running Tests
|
|
14
|
-
```bash
|
|
15
|
-
# Run all tests
|
|
16
|
-
rake spec
|
|
17
|
-
|
|
18
|
-
# Run tests and linting together (default rake task)
|
|
19
|
-
rake
|
|
20
|
-
|
|
21
|
-
# Run a single test file
|
|
22
|
-
bundle exec rspec spec/hyperliquid/cloid_spec.rb
|
|
23
|
-
|
|
24
|
-
# Run a specific test by line number
|
|
25
|
-
bundle exec rspec spec/hyperliquid/cloid_spec.rb:62
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### Linting
|
|
29
|
-
```bash
|
|
30
|
-
# Run RuboCop linter
|
|
31
|
-
rake rubocop
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Interactive Console
|
|
35
|
-
```bash
|
|
36
|
-
# Open an interactive console with the SDK loaded
|
|
37
|
-
bin/console
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### Example Script
|
|
41
|
-
```bash
|
|
42
|
-
# Run the example usage script
|
|
43
|
-
ruby example.rb
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Integration Testing (Testnet)
|
|
47
|
-
```bash
|
|
48
|
-
# Run all integration tests (requires private key)
|
|
49
|
-
# Get testnet funds from: https://app.hyperliquid-testnet.xyz
|
|
50
|
-
HYPERLIQUID_PRIVATE_KEY=0x... ruby scripts/test_all.rb
|
|
51
|
-
|
|
52
|
-
# Run a single integration test
|
|
53
|
-
HYPERLIQUID_PRIVATE_KEY=0x... ruby scripts/test_08_usd_class_transfer.rb
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Integration tests live in `scripts/` as individual files. Each can be run standalone for debugging. `test_integration.rb` at the project root is a convenience wrapper that runs them all.
|
|
57
|
-
|
|
58
|
-
### Setup
|
|
59
|
-
```bash
|
|
60
|
-
# Install dependencies
|
|
61
|
-
bin/setup
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Architecture
|
|
65
|
-
|
|
66
|
-
### Core Components
|
|
67
|
-
|
|
68
|
-
**Hyperliquid::SDK** (`lib/hyperliquid.rb`)
|
|
69
|
-
- Main entry point created via `Hyperliquid.new(testnet:, timeout:, retry_enabled:, private_key:, expires_after:)`
|
|
70
|
-
- Manages environment selection (mainnet vs testnet)
|
|
71
|
-
- Exposes the `info` API client (always available)
|
|
72
|
-
- Exposes the `exchange` API client (when `private_key` provided)
|
|
73
|
-
|
|
74
|
-
**Hyperliquid::Client** (`lib/hyperliquid/client.rb`)
|
|
75
|
-
- Low-level HTTP client built on Faraday
|
|
76
|
-
- Handles all POST requests to the Hyperliquid API
|
|
77
|
-
- Manages retry logic (disabled by default, opt-in via `retry_enabled: true`)
|
|
78
|
-
- Converts HTTP errors into typed exceptions
|
|
79
|
-
|
|
80
|
-
**Hyperliquid::Info** (`lib/hyperliquid/info.rb`)
|
|
81
|
-
- High-level API client for all Info endpoints (read-only)
|
|
82
|
-
- Organized into three sections:
|
|
83
|
-
1. **General Info**: Market data, user orders, fills, rate limits, portfolios, referrals, fees, staking
|
|
84
|
-
2. **Perpetuals**: Perp DEXs, metadata, user state, funding rates, open interest
|
|
85
|
-
3. **Spot**: Spot tokens, balances, deploy auctions, token details
|
|
86
|
-
- All methods accept user wallet addresses and return parsed JSON responses
|
|
87
|
-
|
|
88
|
-
**Hyperliquid::Exchange** (`lib/hyperliquid/exchange.rb`)
|
|
89
|
-
- High-level API client for Exchange endpoints (authenticated write operations)
|
|
90
|
-
- Order placement: `order`, `bulk_orders`, `market_order`
|
|
91
|
-
- Order cancellation: `cancel`, `cancel_by_cloid`, `bulk_cancel`, `bulk_cancel_by_cloid`
|
|
92
|
-
- Supports trigger orders (stop loss / take profit)
|
|
93
|
-
- Supports vault trading via `vault_address` parameter
|
|
94
|
-
- Caches asset metadata for efficient lookups
|
|
95
|
-
|
|
96
|
-
**Hyperliquid::Signing::Signer** (`lib/hyperliquid/signing/signer.rb`)
|
|
97
|
-
- EIP-712 signature generation using phantom agent scheme
|
|
98
|
-
- Matches official Python SDK signing algorithm exactly
|
|
99
|
-
- Supports vault address and expiration in signature
|
|
100
|
-
|
|
101
|
-
**Hyperliquid::Signing::EIP712** (`lib/hyperliquid/signing/eip712.rb`)
|
|
102
|
-
- EIP-712 domain and type definitions
|
|
103
|
-
- L1 chain ID (1337) and source identifiers ('a' mainnet, 'b' testnet)
|
|
104
|
-
|
|
105
|
-
**Hyperliquid::Cloid** (`lib/hyperliquid/cloid.rb`)
|
|
106
|
-
- Type-safe client order ID class
|
|
107
|
-
- Validates 16-byte hex format (0x + 32 hex characters)
|
|
108
|
-
- Factory methods: `from_int`, `from_str`, `from_uuid`, `random`
|
|
109
|
-
|
|
110
|
-
**Hyperliquid::Constants** (`lib/hyperliquid/constants.rb`)
|
|
111
|
-
- API URLs for mainnet and testnet
|
|
112
|
-
- Endpoint paths (`/info`, `/exchange`)
|
|
113
|
-
- Default timeout values
|
|
114
|
-
|
|
115
|
-
**Hyperliquid::Errors** (`lib/hyperliquid/errors.rb`)
|
|
116
|
-
- Typed exception hierarchy for API errors
|
|
117
|
-
- Base class: `Hyperliquid::Error`
|
|
118
|
-
- Specific errors: `ClientError`, `ServerError`, `AuthenticationError`, `RateLimitError`, `BadRequestError`, `NotFoundError`, `TimeoutError`, `NetworkError`
|
|
119
|
-
|
|
120
|
-
### API Request Pattern
|
|
121
|
-
|
|
122
|
-
**Info API (read-only):**
|
|
123
|
-
1. SDK method called (e.g., `sdk.info.all_mids`)
|
|
124
|
-
2. Info class builds request body with `type` field (e.g., `{ type: 'allMids' }`)
|
|
125
|
-
3. Client POSTs JSON body to `/info` endpoint
|
|
126
|
-
4. Client parses response and handles errors
|
|
127
|
-
5. Parsed JSON returned to caller
|
|
128
|
-
|
|
129
|
-
**Exchange API (authenticated):**
|
|
130
|
-
1. SDK method called (e.g., `sdk.exchange.order(...)`)
|
|
131
|
-
2. Exchange class builds action payload with order/cancel details
|
|
132
|
-
3. Signer generates EIP-712 signature over msgpack-encoded action
|
|
133
|
-
4. Exchange POSTs signed payload to `/exchange` endpoint
|
|
134
|
-
5. Client parses response and handles errors
|
|
135
|
-
6. Parsed JSON returned to caller
|
|
136
|
-
|
|
137
|
-
### Testing
|
|
138
|
-
|
|
139
|
-
- Uses RSpec for testing
|
|
140
|
-
- WebMock for HTTP mocking
|
|
141
|
-
- Spec helper configures WebMock to reset between tests
|
|
142
|
-
- Test files mirror source structure in `spec/`
|
|
143
|
-
|
|
144
|
-
### Code Style
|
|
145
|
-
|
|
146
|
-
RuboCop configuration (`.rubocop.yml`):
|
|
147
|
-
- Targets Ruby 3.4.0+
|
|
148
|
-
- Allows longer methods (max 50 lines) for complex logic
|
|
149
|
-
- Disables class length checks (Info/Exchange classes implement many endpoints)
|
|
150
|
-
- Excludes block length checks for specs
|
|
151
|
-
- Enables NewCops by default
|
|
152
|
-
|
|
153
|
-
## Key Implementation Details
|
|
154
|
-
|
|
155
|
-
### Retry Logic
|
|
156
|
-
- **Disabled by default** for predictable behavior in time-sensitive trading
|
|
157
|
-
- When enabled: max 2 retries, 0.5s base interval, exponential backoff (2x), ±50% randomness
|
|
158
|
-
- Retries on: connection failures, timeouts, 429 (rate limit), 5xx errors
|
|
159
|
-
|
|
160
|
-
### API Endpoints
|
|
161
|
-
- Info requests POST to `/info` endpoint
|
|
162
|
-
- Exchange requests POST to `/exchange` endpoint
|
|
163
|
-
- Request body includes `type` field indicating the operation
|
|
164
|
-
|
|
165
|
-
### Time Parameters
|
|
166
|
-
- All timestamps are in **milliseconds** (not seconds)
|
|
167
|
-
- Methods with time ranges support optional `end_time` parameter
|
|
168
|
-
- `expires_after` is an absolute timestamp in milliseconds
|
|
169
|
-
|
|
170
|
-
### Signature Generation (Python SDK Parity)
|
|
171
|
-
The signing implementation matches the official Python SDK exactly:
|
|
172
|
-
- **Action hash**: `keccak256(msgpack(action) + nonce(8B BE) + vault_flag + [vault_addr] + [expires_flag + expires_after])`
|
|
173
|
-
- **Phantom agent**: `{ source: 'a'|'b', connectionId: action_hash }`
|
|
174
|
-
- **EIP-712 signature** over phantom agent with Exchange domain
|
|
175
|
-
|
|
176
|
-
### Float to Wire Format
|
|
177
|
-
Numeric values are converted to strings matching Python SDK `float_to_wire`:
|
|
178
|
-
- 8 decimal precision
|
|
179
|
-
- Rounding tolerance validation (1e-12)
|
|
180
|
-
- Trailing zero normalization (no scientific notation)
|
|
181
|
-
|
|
182
|
-
### Market Order Price Calculation
|
|
183
|
-
Market orders use Python SDK `_slippage_price` algorithm:
|
|
184
|
-
- Apply slippage to mid price
|
|
185
|
-
- Round to 5 significant figures
|
|
186
|
-
- Round to asset-specific decimal places: `(6 for perp, 8 for spot) - szDecimals`
|
|
187
|
-
|
|
188
|
-
### Client Order IDs (Cloid)
|
|
189
|
-
- Must be 16 bytes in hex format: `0x` + 32 hex characters
|
|
190
|
-
- Use `Hyperliquid::Cloid` class for type safety and validation
|
|
191
|
-
- Factory methods: `from_int(n)`, `from_str(s)`, `from_uuid(uuid)`, `random`
|
|
192
|
-
|
|
193
|
-
## Development Workflow
|
|
194
|
-
|
|
195
|
-
1. Make changes to library code in `lib/hyperliquid/`
|
|
196
|
-
2. Add/update tests in `spec/`
|
|
197
|
-
3. Run tests: `rake spec`
|
|
198
|
-
4. Run linter: `rake rubocop`
|
|
199
|
-
5. Test in console: `bin/console`
|
|
200
|
-
6. Run example script: `ruby example.rb`
|
|
201
|
-
|
|
5
|
+
AGENTS.md is the canonical source of truth; this file exists only as a Claude Code convenience entrypoint.
|
|
6
|
+
For comprehensive architecture documentation and implementation details, see **[AGENTS.md](./AGENTS.md)**.
|
data/lib/hyperliquid/info.rb
CHANGED
|
@@ -52,10 +52,15 @@ module Hyperliquid
|
|
|
52
52
|
# @param user [String] Wallet address
|
|
53
53
|
# @param start_time [Integer] Start timestamp in milliseconds
|
|
54
54
|
# @param end_time [Integer, nil] Optional end timestamp in milliseconds
|
|
55
|
+
# @param aggregate_by_time [Boolean, nil] If true, partial fills are aggregated when a
|
|
56
|
+
# crossing order fills multiple resting orders
|
|
57
|
+
# @param reversed [Boolean, nil] If true, fills are returned in reverse chronological order (newest first)
|
|
55
58
|
# @return [Array]
|
|
56
|
-
def user_fills_by_time(user, start_time, end_time = nil)
|
|
59
|
+
def user_fills_by_time(user, start_time, end_time = nil, aggregate_by_time: nil, reversed: nil)
|
|
57
60
|
body = { type: 'userFillsByTime', user: user, startTime: start_time }
|
|
58
61
|
body[:endTime] = end_time if end_time
|
|
62
|
+
body[:aggregateByTime] = aggregate_by_time unless aggregate_by_time.nil?
|
|
63
|
+
body[:reversed] = reversed unless reversed.nil?
|
|
59
64
|
@client.post(Constants::INFO_ENDPOINT, body)
|
|
60
65
|
end
|
|
61
66
|
|
|
@@ -89,6 +94,20 @@ module Hyperliquid
|
|
|
89
94
|
@client.post(Constants::INFO_ENDPOINT, { type: 'l2Book', coin: coin })
|
|
90
95
|
end
|
|
91
96
|
|
|
97
|
+
# Get recent trades for a coin
|
|
98
|
+
# @param coin [String] Asset symbol (e.g., "BTC")
|
|
99
|
+
# @return [Array] Recent trades with coin, side, px, sz, time, hash, tid, users (maker, taker)
|
|
100
|
+
def recent_trades(coin)
|
|
101
|
+
@client.post(Constants::INFO_ENDPOINT, { type: 'recentTrades', coin: coin })
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Get block details by block height
|
|
105
|
+
# @param height [Integer] Block height
|
|
106
|
+
# @return [Hash] Block details including blockTime, hash, height, numTxs, proposer, txs
|
|
107
|
+
def block_details(height)
|
|
108
|
+
@client.post(Constants::INFO_ENDPOINT, { type: 'blockDetails', height: height })
|
|
109
|
+
end
|
|
110
|
+
|
|
92
111
|
# Get candlestick data
|
|
93
112
|
# @param coin [String] Coin symbol
|
|
94
113
|
# @param interval [String] Time interval (e.g., "1m", "1h", "1d")
|
|
@@ -163,6 +182,13 @@ module Hyperliquid
|
|
|
163
182
|
@client.post(Constants::INFO_ENDPOINT, { type: 'userVaultEquities', user: user })
|
|
164
183
|
end
|
|
165
184
|
|
|
185
|
+
# Retrieve a list of vaults less than 2 hours old
|
|
186
|
+
# @return [Array] Recently created vaults with name, address, leader, tvl, isClosed,
|
|
187
|
+
# relationship, createTimeMillis
|
|
188
|
+
def vault_summaries
|
|
189
|
+
@client.post(Constants::INFO_ENDPOINT, { type: 'vaultSummaries' })
|
|
190
|
+
end
|
|
191
|
+
|
|
166
192
|
# Query a user's role
|
|
167
193
|
# @param user [String]
|
|
168
194
|
# @return [Hash]
|
|
@@ -240,6 +266,56 @@ module Hyperliquid
|
|
|
240
266
|
@client.post(Constants::INFO_ENDPOINT, { type: 'userDexAbstraction', user: user })
|
|
241
267
|
end
|
|
242
268
|
|
|
269
|
+
# Query a user's abstraction state
|
|
270
|
+
# @param user [String] Wallet address
|
|
271
|
+
# @return [String] Abstraction state (e.g., "unifiedAccount", "portfolioMargin", "disabled",
|
|
272
|
+
# "default", "dexAbstraction")
|
|
273
|
+
def user_abstraction(user)
|
|
274
|
+
@client.post(Constants::INFO_ENDPOINT, { type: 'userAbstraction', user: user })
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# Check user existence, activation fee, and sanctions status before a transfer
|
|
278
|
+
# @param user [String] Destination user address
|
|
279
|
+
# @param source [String] Source (funding) address
|
|
280
|
+
# @return [Hash] Keys: fee (String), isSanctioned (Boolean), userExists (Boolean),
|
|
281
|
+
# userHasSentTx (Boolean)
|
|
282
|
+
def pre_transfer_check(user, source)
|
|
283
|
+
@client.post(Constants::INFO_ENDPOINT, { type: 'preTransferCheck', user: user, source: source })
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# Check whether a user is a VIP
|
|
287
|
+
# @param user [String] Wallet address
|
|
288
|
+
# @return [Boolean, nil] True/false VIP status, or nil if the user is unknown
|
|
289
|
+
def vip?(user)
|
|
290
|
+
@client.post(Constants::INFO_ENDPOINT, { type: 'isVip', user: user })
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# Retrieve addresses of currently liquidatable users
|
|
294
|
+
# @return [Array] Array of liquidatable user entries
|
|
295
|
+
def liquidatable
|
|
296
|
+
@client.post(Constants::INFO_ENDPOINT, { type: 'liquidatable' })
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# Retrieve validator performance summaries
|
|
300
|
+
# @return [Array] Array of validator entries with validator, signer, name, description,
|
|
301
|
+
# nRecentBlocks, stake, isJailed, unjailableAfter, isActive, commission, and stats
|
|
302
|
+
# (day/week/month uptime fraction, predicted APR, and sample count)
|
|
303
|
+
def validator_summaries
|
|
304
|
+
@client.post(Constants::INFO_ENDPOINT, { type: 'validatorSummaries' })
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Retrieve exchange system status information
|
|
308
|
+
# @return [Hash] Keys: time (Integer, ms since epoch), specialStatuses (Object or nil)
|
|
309
|
+
def exchange_status
|
|
310
|
+
@client.post(Constants::INFO_ENDPOINT, { type: 'exchangeStatus' })
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
# Retrieve maximum market order notionals per asset
|
|
314
|
+
# @return [Array<Array>] Array of [notional (Numeric), symbol (String)] tuples
|
|
315
|
+
def max_market_order_ntls
|
|
316
|
+
@client.post(Constants::INFO_ENDPOINT, { type: 'maxMarketOrderNtls' })
|
|
317
|
+
end
|
|
318
|
+
|
|
243
319
|
# ============================
|
|
244
320
|
# Info: Perpetuals
|
|
245
321
|
# ============================
|
data/lib/hyperliquid/version.rb
CHANGED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Hyperliquid Ruby SDK - Automated Integration Test Runner
|
|
5
|
+
#
|
|
6
|
+
# Same as test_all.rb but excludes tests unsuitable for unattended runs:
|
|
7
|
+
# - test_09_sub_account_lifecycle.rb: requires $100k traded volume on testnet to create sub-accounts
|
|
8
|
+
# - test_12_staking.rb: requires HYPE token balance (locking issues)
|
|
9
|
+
#
|
|
10
|
+
# Usage:
|
|
11
|
+
# HYPERLIQUID_PRIVATE_KEY=0x... ruby scripts/test_automated.rb
|
|
12
|
+
|
|
13
|
+
SCRIPTS = [
|
|
14
|
+
'test_01_spot_market_roundtrip.rb',
|
|
15
|
+
'test_02_spot_limit_order.rb',
|
|
16
|
+
'test_03_perp_market_roundtrip.rb',
|
|
17
|
+
'test_04_perp_limit_order.rb',
|
|
18
|
+
'test_05_update_leverage.rb',
|
|
19
|
+
'test_06_modify_order.rb',
|
|
20
|
+
'test_07_market_close.rb',
|
|
21
|
+
'test_08_usd_class_transfer.rb',
|
|
22
|
+
'test_10_vault.rb',
|
|
23
|
+
'test_11_builder_fee.rb',
|
|
24
|
+
'test_13_ws_l2_book.rb',
|
|
25
|
+
'test_14_ws_candle.rb'
|
|
26
|
+
].freeze
|
|
27
|
+
|
|
28
|
+
def green(text)
|
|
29
|
+
"\e[32m#{text}\e[0m"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def red(text)
|
|
33
|
+
"\e[31m#{text}\e[0m"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
unless ENV['HYPERLIQUID_PRIVATE_KEY']
|
|
37
|
+
puts red('Error: Set HYPERLIQUID_PRIVATE_KEY environment variable')
|
|
38
|
+
puts 'Usage: HYPERLIQUID_PRIVATE_KEY=0x... ruby scripts/test_automated.rb'
|
|
39
|
+
exit 1
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
scripts_dir = __dir__
|
|
43
|
+
passed = []
|
|
44
|
+
failed = []
|
|
45
|
+
|
|
46
|
+
SCRIPTS.each do |script|
|
|
47
|
+
path = File.join(scripts_dir, script)
|
|
48
|
+
puts
|
|
49
|
+
puts '#' * 60
|
|
50
|
+
puts "# Running: #{script}"
|
|
51
|
+
puts '#' * 60
|
|
52
|
+
|
|
53
|
+
success = system(RbConfig.ruby, path)
|
|
54
|
+
|
|
55
|
+
if success
|
|
56
|
+
passed << script
|
|
57
|
+
else
|
|
58
|
+
failed << script
|
|
59
|
+
puts red("!!! #{script} exited with error !!!")
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
puts
|
|
64
|
+
puts '=' * 60
|
|
65
|
+
puts 'INTEGRATION TEST SUMMARY'
|
|
66
|
+
puts '=' * 60
|
|
67
|
+
puts
|
|
68
|
+
puts "Passed: #{passed.length}/#{SCRIPTS.length}"
|
|
69
|
+
passed.each { |s| puts green(" [PASS] #{s}") }
|
|
70
|
+
if failed.any?
|
|
71
|
+
puts
|
|
72
|
+
puts "Failed: #{failed.length}/#{SCRIPTS.length}"
|
|
73
|
+
failed.each { |s| puts red(" [FAIL] #{s}") }
|
|
74
|
+
end
|
|
75
|
+
puts
|
|
76
|
+
puts 'Check your testnet wallet for trade history:'
|
|
77
|
+
puts 'https://app.hyperliquid-testnet.xyz'
|
|
78
|
+
puts
|
|
79
|
+
|
|
80
|
+
exit(failed.empty? ? 0 : 1)
|
data/scripts/test_helpers.rb
CHANGED
|
@@ -49,7 +49,13 @@ end
|
|
|
49
49
|
def dump_status(result)
|
|
50
50
|
return unless result.is_a?(Hash)
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
response = result['response']
|
|
53
|
+
return unless response.is_a?(Hash)
|
|
54
|
+
|
|
55
|
+
data = response['data']
|
|
56
|
+
return unless data.is_a?(Hash)
|
|
57
|
+
|
|
58
|
+
status = data.dig('statuses', 0)
|
|
53
59
|
return unless status
|
|
54
60
|
|
|
55
61
|
puts " API status: #{status.inspect}"
|
|
@@ -60,7 +66,9 @@ def check_result(result, operation)
|
|
|
60
66
|
|
|
61
67
|
return false if api_error?(result)
|
|
62
68
|
|
|
63
|
-
|
|
69
|
+
response = result['response']
|
|
70
|
+
data = response.is_a?(Hash) ? response['data'] : nil
|
|
71
|
+
status = data.is_a?(Hash) ? data.dig('statuses', 0) : nil
|
|
64
72
|
|
|
65
73
|
if status.is_a?(Hash) && status['error']
|
|
66
74
|
$test_failed = true
|
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: 1.0
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- carter2099
|
|
@@ -71,14 +71,14 @@ dependencies:
|
|
|
71
71
|
requirements:
|
|
72
72
|
- - "~>"
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: 1.0.
|
|
74
|
+
version: 1.0.1
|
|
75
75
|
type: :runtime
|
|
76
76
|
prerelease: false
|
|
77
77
|
version_requirements: !ruby/object:Gem::Requirement
|
|
78
78
|
requirements:
|
|
79
79
|
- - "~>"
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
|
-
version: 1.0.
|
|
81
|
+
version: 1.0.1
|
|
82
82
|
description: A Ruby SDK for interacting with Hyperliquid's decentralized exchange
|
|
83
83
|
API
|
|
84
84
|
email:
|
|
@@ -90,6 +90,7 @@ files:
|
|
|
90
90
|
- ".rspec"
|
|
91
91
|
- ".rubocop.yml"
|
|
92
92
|
- ".ruby-version"
|
|
93
|
+
- AGENTS.md
|
|
93
94
|
- CHANGELOG.md
|
|
94
95
|
- CLAUDE.md
|
|
95
96
|
- CODE_OF_CONDUCT.md
|
|
@@ -130,6 +131,7 @@ files:
|
|
|
130
131
|
- scripts/test_13_ws_l2_book.rb
|
|
131
132
|
- scripts/test_14_ws_candle.rb
|
|
132
133
|
- scripts/test_all.rb
|
|
134
|
+
- scripts/test_automated.rb
|
|
133
135
|
- scripts/test_helpers.rb
|
|
134
136
|
- sig/hyperliquid.rbs
|
|
135
137
|
- test_integration.rb
|
|
@@ -148,14 +150,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
148
150
|
requirements:
|
|
149
151
|
- - ">="
|
|
150
152
|
- !ruby/object:Gem::Version
|
|
151
|
-
version: 3.
|
|
153
|
+
version: 3.3.0
|
|
152
154
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
155
|
requirements:
|
|
154
156
|
- - ">="
|
|
155
157
|
- !ruby/object:Gem::Version
|
|
156
158
|
version: '0'
|
|
157
159
|
requirements: []
|
|
158
|
-
rubygems_version: 3.6.
|
|
160
|
+
rubygems_version: 3.6.9
|
|
159
161
|
specification_version: 4
|
|
160
162
|
summary: Ruby SDK for Hyperliquid API
|
|
161
163
|
test_files: []
|