hyperliquid 1.0.0 → 1.0.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/.rubocop.yml +1 -0
- data/CHANGELOG.md +4 -0
- data/lib/hyperliquid/exchange.rb +40 -50
- data/lib/hyperliquid/info.rb +2 -1
- data/lib/hyperliquid/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1e1cb7c8ae1c1b83ab34eaba6f6bf9ce34b620ca1af4500912d62e54d75a95ab
|
|
4
|
+
data.tar.gz: 9d026ad803f2fe0d2983c3dd242ee5d901cf56677e7c32cf756b5da38eb39c68
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 99a8f5cf7847c9236f3b4b48cfb83734ecb6ae8b7679d8d5cc1aef003b1a510df3edefdf9f6481d7bdb4ff7d22546549247b9aa17771e95d58307eb93bdd0448
|
|
7
|
+
data.tar.gz: d649b243e0aab4ae25ffcd3c452878cce1be94dd86dde1aeb151b9478bba1c42fe534ec485f4ddd896e0f358b705d4b063180b26e23fcf7d09d42a9f71ffbc64
|
data/.rubocop.yml
CHANGED
|
@@ -5,6 +5,7 @@ AllCops:
|
|
|
5
5
|
Exclude:
|
|
6
6
|
- 'test_*.rb' # Exclude ad-hoc integration test scripts
|
|
7
7
|
- 'scripts/**/*' # Exclude integration test scripts
|
|
8
|
+
- 'local/**/*' # Exclude local test scripts
|
|
8
9
|
- 'vendor/**/*' # Exclude vendored gems (CI bundles here)
|
|
9
10
|
|
|
10
11
|
# Allow longer methods for complex logic
|
data/CHANGELOG.md
CHANGED
data/lib/hyperliquid/exchange.rb
CHANGED
|
@@ -355,34 +355,18 @@ module Hyperliquid
|
|
|
355
355
|
# @return [Hash] Order response
|
|
356
356
|
def market_close(coin:, size: nil, slippage: DEFAULT_SLIPPAGE, cloid: nil, vault_address: nil, builder: nil)
|
|
357
357
|
address = vault_address || @signer.address
|
|
358
|
-
|
|
359
|
-
state = dex_prefix ? @info.user_state(address, dex: dex_prefix) : @info.user_state(address)
|
|
360
|
-
|
|
361
|
-
position = state['assetPositions']&.find do |pos|
|
|
362
|
-
pos.dig('position', 'coin') == coin
|
|
363
|
-
end
|
|
358
|
+
position = find_position(coin, address)
|
|
364
359
|
raise ArgumentError, "No open position found for #{coin}" unless position
|
|
365
360
|
|
|
366
361
|
szi = position.dig('position', 'szi').to_f
|
|
367
362
|
is_buy = szi.negative?
|
|
368
363
|
close_size = size || szi.abs
|
|
369
|
-
|
|
370
|
-
mids = dex_prefix ? @info.all_mids(dex: dex_prefix) : @info.all_mids
|
|
371
|
-
mid = mids[coin]&.to_f
|
|
372
|
-
raise ArgumentError, "Unknown asset or no price available: #{coin}" unless mid&.positive?
|
|
373
|
-
|
|
374
|
-
slippage_price = calculate_slippage_price(coin, mid, is_buy, slippage)
|
|
364
|
+
slippage_price = calculate_slippage_price(coin, get_mid_price(coin), is_buy, slippage)
|
|
375
365
|
|
|
376
366
|
order(
|
|
377
|
-
coin: coin,
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
limit_px: slippage_price,
|
|
381
|
-
order_type: { limit: { tif: 'Ioc' } },
|
|
382
|
-
reduce_only: true,
|
|
383
|
-
cloid: cloid,
|
|
384
|
-
vault_address: vault_address,
|
|
385
|
-
builder: builder
|
|
367
|
+
coin: coin, is_buy: is_buy, size: close_size, limit_px: slippage_price,
|
|
368
|
+
order_type: { limit: { tif: 'Ioc' } }, reduce_only: true,
|
|
369
|
+
cloid: cloid, vault_address: vault_address, builder: builder
|
|
386
370
|
)
|
|
387
371
|
end
|
|
388
372
|
|
|
@@ -718,6 +702,23 @@ module Hyperliquid
|
|
|
718
702
|
(Time.now.to_f * 1000).to_i
|
|
719
703
|
end
|
|
720
704
|
|
|
705
|
+
# Find a position for a coin
|
|
706
|
+
def find_position(coin, address)
|
|
707
|
+
dex_prefix = extract_dex_prefix(coin)
|
|
708
|
+
state = dex_prefix ? @info.user_state(address, dex: dex_prefix) : @info.user_state(address)
|
|
709
|
+
state['assetPositions']&.find { |pos| pos.dig('position', 'coin') == coin }
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
# Get mid price for a coin
|
|
713
|
+
def get_mid_price(coin)
|
|
714
|
+
dex_prefix = extract_dex_prefix(coin)
|
|
715
|
+
mids = dex_prefix ? @info.all_mids(dex: dex_prefix) : @info.all_mids
|
|
716
|
+
mid = mids[coin]&.to_f
|
|
717
|
+
raise ArgumentError, "Unknown asset or no price available: #{coin}" unless mid&.positive?
|
|
718
|
+
|
|
719
|
+
mid
|
|
720
|
+
end
|
|
721
|
+
|
|
721
722
|
# Get asset index for a coin symbol
|
|
722
723
|
# @param coin [String] Asset symbol (supports HIP-3 prefixed names like "xyz:GOLD")
|
|
723
724
|
# @return [Integer] Asset index
|
|
@@ -766,30 +767,27 @@ module Hyperliquid
|
|
|
766
767
|
@asset_cache = { indices: {}, metadata: {} }
|
|
767
768
|
@loaded_dexes = Set.new
|
|
768
769
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
is_spot: false
|
|
777
|
-
}
|
|
770
|
+
load_perp_assets
|
|
771
|
+
load_spot_assets
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
def load_perp_assets
|
|
775
|
+
@info.meta['universe'].each_with_index do |asset, index|
|
|
776
|
+
cache_asset(asset['name'], index, asset['szDecimals'], is_spot: false)
|
|
778
777
|
end
|
|
778
|
+
end
|
|
779
779
|
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
name = pair['name']
|
|
784
|
-
spot_index = index + SPOT_ASSET_THRESHOLD
|
|
785
|
-
@asset_cache[:indices][name] = spot_index
|
|
786
|
-
@asset_cache[:metadata][name] = {
|
|
787
|
-
sz_decimals: pair['szDecimals'] || 0,
|
|
788
|
-
is_spot: true
|
|
789
|
-
}
|
|
780
|
+
def load_spot_assets
|
|
781
|
+
@info.spot_meta['universe'].each_with_index do |pair, index|
|
|
782
|
+
cache_asset(pair['name'], index + SPOT_ASSET_THRESHOLD, pair['szDecimals'] || 0, is_spot: true)
|
|
790
783
|
end
|
|
791
784
|
end
|
|
792
785
|
|
|
786
|
+
def cache_asset(name, index, sz_decimals, is_spot:, dex: nil)
|
|
787
|
+
@asset_cache[:indices][name] = index
|
|
788
|
+
@asset_cache[:metadata][name] = { sz_decimals: sz_decimals, is_spot: is_spot, dex: dex }.compact
|
|
789
|
+
end
|
|
790
|
+
|
|
793
791
|
# Load asset metadata for a HIP-3 dex
|
|
794
792
|
# HIP-3 asset IDs use formula: 100000 + perp_dex_index * 10000 + index_in_meta
|
|
795
793
|
# @param dex [String] Dex name (e.g., "xyz")
|
|
@@ -803,17 +801,9 @@ module Hyperliquid
|
|
|
803
801
|
perp_dex_index = perp_dexs.index { |d| d && d['name'] == dex }
|
|
804
802
|
return unless perp_dex_index
|
|
805
803
|
|
|
806
|
-
|
|
807
|
-
meta['universe']&.each_with_index do |asset, index|
|
|
808
|
-
name = asset['name']
|
|
809
|
-
# HIP-3 asset ID: 100000 + perp_dex_index * 10000 + index_in_meta
|
|
804
|
+
@info.meta(dex: dex)['universe']&.each_with_index do |asset, index|
|
|
810
805
|
hip3_asset_id = 100_000 + (perp_dex_index * 10_000) + index
|
|
811
|
-
|
|
812
|
-
@asset_cache[:metadata][name] = {
|
|
813
|
-
sz_decimals: asset['szDecimals'],
|
|
814
|
-
is_spot: false,
|
|
815
|
-
dex: dex
|
|
816
|
-
}
|
|
806
|
+
cache_asset(asset['name'], hip3_asset_id, asset['szDecimals'], is_spot: false, dex: dex)
|
|
817
807
|
end
|
|
818
808
|
end
|
|
819
809
|
|
data/lib/hyperliquid/info.rb
CHANGED
|
@@ -12,7 +12,8 @@ module Hyperliquid
|
|
|
12
12
|
# ============================
|
|
13
13
|
|
|
14
14
|
# Get all market mid prices
|
|
15
|
-
# @param dex [String, nil] Optional perp dex name (defaults to first perp dex;
|
|
15
|
+
# @param dex [String, nil] Optional perp dex name (defaults to first perp dex;
|
|
16
|
+
# spot mids only included with first perp dex)
|
|
16
17
|
# @return [Hash] Hash containing mid prices for all markets
|
|
17
18
|
def all_mids(dex: nil)
|
|
18
19
|
body = { type: 'allMids' }
|
data/lib/hyperliquid/version.rb
CHANGED