hyperliquid 1.6.0 → 1.7.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/CHANGELOG.md +17 -0
- data/lib/hyperliquid/exchange.rb +137 -0
- data/lib/hyperliquid/info.rb +7 -0
- data/lib/hyperliquid/signing/eip712.rb +8 -0
- data/lib/hyperliquid/signing/multi_sig.rb +26 -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: fa1051cb2277e69795819ed2ae8564e89ac3e6b34139d9112a8273f0604d2fa1
|
|
4
|
+
data.tar.gz: 072416d6751fa766f0b4eeb5c416365ea96652b980301932d3ab32a549750b24
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 41059a1ef505d93e061fdd575f42ca340c6eb1e8100f14adf176c9512bd65ce4c1afdd1ddeeb831a1833bce63b9ca065f602681c673bba9b96f7a298130b05a0
|
|
7
|
+
data.tar.gz: 9cfb58786186bafc873dc9dd1747c2b87a645770fddc8d759ea3b5420e7367f1118de056de8e470dbe8bff06e44e55033ce063d839a3c81803fc418e3be68890
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
## [Ruby Hyperliquid SDK Changelog]
|
|
2
2
|
|
|
3
|
+
## [1.7.0] - 2026-06-11
|
|
4
|
+
|
|
5
|
+
### New Exchange actions
|
|
6
|
+
|
|
7
|
+
- `Exchange#authorize_aqav2_role(token:, role:)` — L1 action authorizing an AQAv2 role (e.g. `"treasury"`); supports `expires_after`.
|
|
8
|
+
- `Exchange#staking_link_disable_trading_user(trading_user:)` — user-signed action linking a staking account to a trading user (irreversible). Adds `STAKING_LINK_DISABLE_TRADING_USER_TYPES`.
|
|
9
|
+
- `Exchange#finalize_evm_contract(input:)` — L1 action linking a HyperCore spot token to a HyperEVM ERC-20 contract. Accepts a `Hash` (`{create: {nonce:}}`) or string variant (`"firstStorageSlot"` / `"customStorageSlot"`).
|
|
10
|
+
- HIP-4 `userOutcome` variants (L1 actions, not user-signed): `split_outcome(question:, outcome:, amount:)`, `merge_outcome(question:, amount:)`, `merge_question(question:, amount:)`, `negate_outcome(question:, outcome:, amount:)`. `merge_outcome` and `merge_question` accept `amount: nil` for the max-available case.
|
|
11
|
+
|
|
12
|
+
### New Info methods
|
|
13
|
+
|
|
14
|
+
- `Info#settled_outcome(outcome:)` — returns settled prediction-market outcome data.
|
|
15
|
+
|
|
16
|
+
### Fixes
|
|
17
|
+
|
|
18
|
+
- `Signing::MultiSig.payload_action` now normalizes `userSetAbstraction` long-form abstraction values (`"disabled"`, `"unifiedAccount"`, `"portfolioMargin"`) to their wire enum equivalents (`"i"`, `"u"`, `"p"`) in the L1 payload posted to `/exchange`, matching Python SDK 0.24.0. Pre-translated short codes pass through unchanged.
|
|
19
|
+
|
|
3
20
|
## [1.6.0] - 2026-05-26
|
|
4
21
|
|
|
5
22
|
### New Exchange actions
|
data/lib/hyperliquid/exchange.rb
CHANGED
|
@@ -1017,6 +1017,31 @@ module Hyperliquid
|
|
|
1017
1017
|
post_action(action, signature, nonce, nil)
|
|
1018
1018
|
end
|
|
1019
1019
|
|
|
1020
|
+
# Permanently disable a linked trading user, locking its funds
|
|
1021
|
+
# (`stakingLinkDisableTradingUser` user-signed action). Sent by the staking user.
|
|
1022
|
+
# After 1 year of locking, funds from the trading user are automatically transferred
|
|
1023
|
+
# to the staking user. **This action is irreversible.** The `trading_user` address is
|
|
1024
|
+
# lowercased to match the address-field convention used by other user-signed actions.
|
|
1025
|
+
# @param trading_user [String] Trading user address to disable
|
|
1026
|
+
# @return [Hash] Exchange response
|
|
1027
|
+
def staking_link_disable_trading_user(trading_user:)
|
|
1028
|
+
nonce = timestamp_ms
|
|
1029
|
+
trading_user_lower = trading_user.downcase
|
|
1030
|
+
action = {
|
|
1031
|
+
type: 'stakingLinkDisableTradingUser',
|
|
1032
|
+
signatureChainId: '0x66eee',
|
|
1033
|
+
hyperliquidChain: Signing::EIP712.hyperliquid_chain(testnet: @testnet),
|
|
1034
|
+
tradingUser: trading_user_lower,
|
|
1035
|
+
nonce: nonce
|
|
1036
|
+
}
|
|
1037
|
+
signature = @signer.sign_user_signed_action(
|
|
1038
|
+
{ tradingUser: trading_user_lower, nonce: nonce },
|
|
1039
|
+
'HyperliquidTransaction:StakingLinkDisableTradingUser',
|
|
1040
|
+
Signing::EIP712::STAKING_LINK_DISABLE_TRADING_USER_TYPES
|
|
1041
|
+
)
|
|
1042
|
+
post_action(action, signature, nonce, nil)
|
|
1043
|
+
end
|
|
1044
|
+
|
|
1020
1045
|
# Move assets between DEX instances on behalf of an agent's principal
|
|
1021
1046
|
# (`agentSendAsset` L1 action). Unlike `send_asset` (which is user-signed),
|
|
1022
1047
|
# this is signed by an agent and the destination must equal the agent's
|
|
@@ -1237,6 +1262,104 @@ module Hyperliquid
|
|
|
1237
1262
|
post_action(action, signature, nonce, nil)
|
|
1238
1263
|
end
|
|
1239
1264
|
|
|
1265
|
+
# HIP-4: split `amount` quote tokens into `amount` Yes and `amount` No shares
|
|
1266
|
+
# of an outcome (`userOutcome` L1 action, splitOutcome variant).
|
|
1267
|
+
# @param outcome [Integer] Outcome identifier
|
|
1268
|
+
# @param amount [String, Numeric] Amount of quote tokens to split (UnsignedDecimal, coerced via to_s)
|
|
1269
|
+
# @return [Hash] Exchange response
|
|
1270
|
+
def split_outcome(outcome:, amount:)
|
|
1271
|
+
nonce = timestamp_ms
|
|
1272
|
+
action = {
|
|
1273
|
+
type: 'userOutcome',
|
|
1274
|
+
splitOutcome: { outcome: outcome, amount: amount.to_s }
|
|
1275
|
+
}
|
|
1276
|
+
signature = @signer.sign_l1_action(
|
|
1277
|
+
action, nonce,
|
|
1278
|
+
expires_after: @expires_after
|
|
1279
|
+
)
|
|
1280
|
+
post_action(action, signature, nonce, nil)
|
|
1281
|
+
end
|
|
1282
|
+
|
|
1283
|
+
# HIP-4: merge `amount` Yes and `amount` No shares of an outcome back into
|
|
1284
|
+
# `amount` quote tokens (`userOutcome` L1 action, mergeOutcome variant).
|
|
1285
|
+
# Pass `amount: nil` to merge the maximum available.
|
|
1286
|
+
# @param outcome [Integer] Outcome identifier
|
|
1287
|
+
# @param amount [String, Numeric, nil] Amount of shares to merge; nil = maximum available
|
|
1288
|
+
# @return [Hash] Exchange response
|
|
1289
|
+
def merge_outcome(outcome:, amount: nil)
|
|
1290
|
+
nonce = timestamp_ms
|
|
1291
|
+
action = {
|
|
1292
|
+
type: 'userOutcome',
|
|
1293
|
+
mergeOutcome: { outcome: outcome, amount: amount&.to_s }
|
|
1294
|
+
}
|
|
1295
|
+
signature = @signer.sign_l1_action(
|
|
1296
|
+
action, nonce,
|
|
1297
|
+
expires_after: @expires_after
|
|
1298
|
+
)
|
|
1299
|
+
post_action(action, signature, nonce, nil)
|
|
1300
|
+
end
|
|
1301
|
+
|
|
1302
|
+
# HIP-4: merge `amount` Yes shares from every outcome of a question into
|
|
1303
|
+
# `amount` quote tokens (`userOutcome` L1 action, mergeQuestion variant).
|
|
1304
|
+
# Pass `amount: nil` to merge the maximum available.
|
|
1305
|
+
# @param question [Integer] Question identifier
|
|
1306
|
+
# @param amount [String, Numeric, nil] Amount of shares to merge; nil = maximum available
|
|
1307
|
+
# @return [Hash] Exchange response
|
|
1308
|
+
def merge_question(question:, amount: nil)
|
|
1309
|
+
nonce = timestamp_ms
|
|
1310
|
+
action = {
|
|
1311
|
+
type: 'userOutcome',
|
|
1312
|
+
mergeQuestion: { question: question, amount: amount&.to_s }
|
|
1313
|
+
}
|
|
1314
|
+
signature = @signer.sign_l1_action(
|
|
1315
|
+
action, nonce,
|
|
1316
|
+
expires_after: @expires_after
|
|
1317
|
+
)
|
|
1318
|
+
post_action(action, signature, nonce, nil)
|
|
1319
|
+
end
|
|
1320
|
+
|
|
1321
|
+
# HIP-4: convert `amount` No shares from one outcome of a question into
|
|
1322
|
+
# `amount` Yes shares of every other outcome associated with that question
|
|
1323
|
+
# (`userOutcome` L1 action, negateOutcome variant).
|
|
1324
|
+
# @param question [Integer] Question identifier
|
|
1325
|
+
# @param outcome [Integer] Outcome identifier whose No shares are being negated
|
|
1326
|
+
# @param amount [String, Numeric] Amount of No shares to negate (UnsignedDecimal, coerced via to_s)
|
|
1327
|
+
# @return [Hash] Exchange response
|
|
1328
|
+
def negate_outcome(question:, outcome:, amount:)
|
|
1329
|
+
nonce = timestamp_ms
|
|
1330
|
+
action = {
|
|
1331
|
+
type: 'userOutcome',
|
|
1332
|
+
negateOutcome: { question: question, outcome: outcome, amount: amount.to_s }
|
|
1333
|
+
}
|
|
1334
|
+
signature = @signer.sign_l1_action(
|
|
1335
|
+
action, nonce,
|
|
1336
|
+
expires_after: @expires_after
|
|
1337
|
+
)
|
|
1338
|
+
post_action(action, signature, nonce, nil)
|
|
1339
|
+
end
|
|
1340
|
+
|
|
1341
|
+
# Finalize the link between a HyperCore spot token and an ERC-20 contract on
|
|
1342
|
+
# HyperEVM (`finalizeEvmContract` L1 action). `input` selects the verification method
|
|
1343
|
+
# and is passed through verbatim — accepts a Hash `{ create: { nonce: <int> } }` for an
|
|
1344
|
+
# EOA-deployed contract, or one of the strings `"firstStorageSlot"` / `"customStorageSlot"`
|
|
1345
|
+
# for contracts that store the finalizer address in a known storage slot.
|
|
1346
|
+
# @param token [Integer] HyperCore spot token identifier to link
|
|
1347
|
+
# @param input [Hash, String] Verification method (see above)
|
|
1348
|
+
# @return [Hash] Exchange response
|
|
1349
|
+
def finalize_evm_contract(token:, input:)
|
|
1350
|
+
nonce = timestamp_ms
|
|
1351
|
+
action = {
|
|
1352
|
+
type: 'finalizeEvmContract',
|
|
1353
|
+
token: token,
|
|
1354
|
+
input: input
|
|
1355
|
+
}
|
|
1356
|
+
signature = @signer.sign_l1_action(
|
|
1357
|
+
action, nonce,
|
|
1358
|
+
expires_after: @expires_after
|
|
1359
|
+
)
|
|
1360
|
+
post_action(action, signature, nonce, nil)
|
|
1361
|
+
end
|
|
1362
|
+
|
|
1240
1363
|
# Opt in or out of spot dusting (`spotUser` L1 action).
|
|
1241
1364
|
# Spot dusting is the protocol's automatic conversion of small spot balances.
|
|
1242
1365
|
# Despite the generic action name, this method exclusively toggles that opt-out flag.
|
|
@@ -1252,6 +1375,20 @@ module Hyperliquid
|
|
|
1252
1375
|
post_action(action, signature, nonce, nil)
|
|
1253
1376
|
end
|
|
1254
1377
|
|
|
1378
|
+
# Authorize an AQAv2 role (`authorizeAqav2Role` L1 action).
|
|
1379
|
+
# @param token [Integer] Token identifier
|
|
1380
|
+
# @param role [String] Role to authorize ("technical" or "treasury")
|
|
1381
|
+
# @return [Hash] Exchange response
|
|
1382
|
+
def authorize_aqav2_role(token:, role:)
|
|
1383
|
+
nonce = timestamp_ms
|
|
1384
|
+
action = { type: 'authorizeAqav2Role', token: token.to_i, role: role }
|
|
1385
|
+
signature = @signer.sign_l1_action(
|
|
1386
|
+
action, nonce,
|
|
1387
|
+
expires_after: @expires_after
|
|
1388
|
+
)
|
|
1389
|
+
post_action(action, signature, nonce, nil)
|
|
1390
|
+
end
|
|
1391
|
+
|
|
1255
1392
|
# Clear the asset metadata cache
|
|
1256
1393
|
# Call this if metadata has been updated
|
|
1257
1394
|
def reload_metadata!
|
data/lib/hyperliquid/info.rb
CHANGED
|
@@ -515,6 +515,13 @@ module Hyperliquid
|
|
|
515
515
|
@client.post(Constants::INFO_ENDPOINT, { type: 'outcomeMeta' })
|
|
516
516
|
end
|
|
517
517
|
|
|
518
|
+
# Retrieve information about a settled outcome
|
|
519
|
+
# @param outcome [Integer] Outcome identifier
|
|
520
|
+
# @return [Hash, nil] Hash with spec, settleFraction, and details; or nil if not settled
|
|
521
|
+
def settled_outcome(outcome:)
|
|
522
|
+
@client.post(Constants::INFO_ENDPOINT, { type: 'settledOutcome', outcome: outcome.to_i })
|
|
523
|
+
end
|
|
524
|
+
|
|
518
525
|
# Retrieve a user's funding history
|
|
519
526
|
# @param user [String]
|
|
520
527
|
# @param start_time [Integer]
|
|
@@ -130,6 +130,14 @@ module Hyperliquid
|
|
|
130
130
|
]
|
|
131
131
|
}.freeze
|
|
132
132
|
|
|
133
|
+
STAKING_LINK_DISABLE_TRADING_USER_TYPES = {
|
|
134
|
+
'HyperliquidTransaction:StakingLinkDisableTradingUser': [
|
|
135
|
+
{ name: :hyperliquidChain, type: 'string' },
|
|
136
|
+
{ name: :tradingUser, type: 'address' },
|
|
137
|
+
{ name: :nonce, type: 'uint64' }
|
|
138
|
+
]
|
|
139
|
+
}.freeze
|
|
140
|
+
|
|
133
141
|
MULTI_SIG_TYPES = {
|
|
134
142
|
'HyperliquidTransaction:SendMultiSig': [
|
|
135
143
|
{ name: :hyperliquidChain, type: 'string' },
|
|
@@ -17,6 +17,16 @@ module Hyperliquid
|
|
|
17
17
|
module MultiSig
|
|
18
18
|
OUTER_PRIMARY_TYPE = 'HyperliquidTransaction:SendMultiSig'
|
|
19
19
|
|
|
20
|
+
# Wire-format normalization for userSetAbstraction inside multi_sig envelopes.
|
|
21
|
+
# Each co-signer's EIP-712 hash uses the human-readable abstraction string, but the
|
|
22
|
+
# L1 payload requires the single-char wire enum. Mirrors Python SDK 0.24.0's
|
|
23
|
+
# `_multi_sig_payload_action`.
|
|
24
|
+
USER_SET_ABSTRACTION_WIRE_VALUES = {
|
|
25
|
+
'disabled' => 'i',
|
|
26
|
+
'unifiedAccount' => 'u',
|
|
27
|
+
'portfolioMargin' => 'p'
|
|
28
|
+
}.freeze
|
|
29
|
+
|
|
20
30
|
# Build the outer multi-sig envelope (the action body posted to /exchange).
|
|
21
31
|
# @param inner_action [Hash] The wrapped action (any L1 or user-signed action body)
|
|
22
32
|
# @param multi_sig_user [String] Address of the multi-sig user (lowercased)
|
|
@@ -31,11 +41,26 @@ module Hyperliquid
|
|
|
31
41
|
payload: {
|
|
32
42
|
multiSigUser: multi_sig_user.downcase,
|
|
33
43
|
outerSigner: outer_signer.downcase,
|
|
34
|
-
action: inner_action
|
|
44
|
+
action: payload_action(inner_action)
|
|
35
45
|
}
|
|
36
46
|
}
|
|
37
47
|
end
|
|
38
48
|
|
|
49
|
+
# Normalize an inner action for the L1 payload. Currently only userSetAbstraction
|
|
50
|
+
# needs translation (long-form abstraction string → wire enum); all other actions
|
|
51
|
+
# pass through verbatim.
|
|
52
|
+
# @param inner_action [Hash] Inner action (symbol or string keys)
|
|
53
|
+
# @return [Hash] Possibly-normalized copy (or the original if no change needed)
|
|
54
|
+
def self.payload_action(inner_action)
|
|
55
|
+
return inner_action unless (inner_action[:type] || inner_action['type']) == 'userSetAbstraction'
|
|
56
|
+
|
|
57
|
+
key = inner_action.key?(:abstraction) ? :abstraction : 'abstraction'
|
|
58
|
+
abstraction = inner_action[key]
|
|
59
|
+
return inner_action unless USER_SET_ABSTRACTION_WIRE_VALUES.key?(abstraction)
|
|
60
|
+
|
|
61
|
+
inner_action.merge(key => USER_SET_ABSTRACTION_WIRE_VALUES[abstraction])
|
|
62
|
+
end
|
|
63
|
+
|
|
39
64
|
# Compute the multiSigActionHash that the submitter signs over.
|
|
40
65
|
# Mirrors Python's `sign_multi_sig_action`: action_hash(envelope - type, vault, nonce, expires).
|
|
41
66
|
# @param envelope [Hash] The multi-sig envelope (will have :type stripped before hashing)
|
data/lib/hyperliquid/version.rb
CHANGED