Skip to content

Commit 583a96d

Browse files
committed
Version 0.13.0
1 parent b7b70f7 commit 583a96d

File tree

7 files changed

+435
-11
lines changed

7 files changed

+435
-11
lines changed

examples/basic_recover_user.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from hyperliquid.utils.signing import (
2+
TOKEN_DELEGATE_TYPES,
3+
recover_agent_or_user_from_l1_action,
4+
recover_user_from_user_signed_action,
5+
)
6+
7+
8+
def main():
9+
example_l1_signed_action = {
10+
"signature": {
11+
"r": "0xd088ceb979ab7616f21fd7dabee04342235bd3af6d82a6d153b503c34c73bc93",
12+
"s": "0x425d8467a69f4d0ff6d9ddfb360ef6152c8165cdd20329e03b0a8f19890d73e",
13+
"v": 27,
14+
},
15+
"vaultAddress": "0xc64cc00b46101bd40aa1c3121195e85c0b0918d8",
16+
"action": {"type": "cancel", "cancels": [{"a": 87, "o": 28800768235}]},
17+
"nonce": 1745532560074,
18+
}
19+
agent_or_user = recover_agent_or_user_from_l1_action(
20+
example_l1_signed_action["action"],
21+
example_l1_signed_action["signature"],
22+
example_l1_signed_action["vaultAddress"],
23+
example_l1_signed_action["nonce"],
24+
None,
25+
False,
26+
)
27+
print("recovered l1 action agent or user:", agent_or_user)
28+
29+
example_user_signed_action = {
30+
"signature": {
31+
"r": "0xa00406eb38821b8918743fab856c103132261e8d990852a8ee25e6f2e88891b",
32+
"s": "0x34cf47cfbf09173bcb851bcfdce3ad83dd64ed791ab32bfe9606d25e7c608859",
33+
"v": 27,
34+
},
35+
"action": {
36+
"type": "tokenDelegate",
37+
"signatureChainId": "0xa4b1",
38+
"hyperliquidChain": "Mainnet",
39+
"validator": "0x5ac99df645f3414876c816caa18b2d234024b487",
40+
"wei": 100163871320,
41+
"isUndelegate": True,
42+
"nonce": 1744932112279,
43+
},
44+
"isFrontend": True,
45+
"nonce": 1744932112279,
46+
}
47+
48+
user = recover_user_from_user_signed_action(
49+
example_user_signed_action["action"],
50+
example_user_signed_action["signature"],
51+
TOKEN_DELEGATE_TYPES,
52+
"HyperliquidTransaction:TokenDelegate",
53+
True,
54+
)
55+
print("recovered user-signed action user:", user)
56+
57+
58+
if __name__ == "__main__":
59+
main()

examples/c_signer.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Example script to run CSigner actions
2+
# See https://github.com/hyperliquid-dex/node?tab=readme-ov-file#begin-validating for spec
3+
#
4+
# IMPORTANT: Replace any arguments for the exchange calls below to match your deployment requirements.
5+
6+
import example_utils
7+
8+
from hyperliquid.utils import constants
9+
10+
# Change to one of "Jail" or "Unjail"
11+
ACTION = ""
12+
13+
14+
def main():
15+
address, info, exchange = example_utils.setup(constants.TESTNET_API_URL, skip_ws=True)
16+
17+
if ACTION == "Jail":
18+
jail_result = exchange.c_signer_jail_self()
19+
print("jail result", jail_result)
20+
elif ACTION == "Unjail":
21+
unjail_result = exchange.c_signer_unjail_self()
22+
print("unjail result", unjail_result)
23+
else:
24+
raise ValueError("Invalid action specified")
25+
26+
27+
if __name__ == "__main__":
28+
main()

examples/c_validator.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Example script to register a validator
2+
# See https://github.com/hyperliquid-dex/node?tab=readme-ov-file#join-network for spec
3+
#
4+
# IMPORTANT: Replace any arguments for the exchange calls below to match your deployment requirements.
5+
6+
import example_utils
7+
8+
from hyperliquid.utils import constants
9+
10+
# Change to one of "Register", "ChangeProfile", or "Unregister"
11+
ACTION = ""
12+
DUMMY_SIGNER = "0x0000000000000000000000000000000000000001"
13+
14+
15+
def main():
16+
address, info, exchange = example_utils.setup(constants.TESTNET_API_URL, skip_ws=True)
17+
18+
if ACTION == "Register":
19+
node_ip = "1.2.3.4"
20+
name = "..."
21+
description = "..."
22+
delegations_disabled = True
23+
commission_bps = 5
24+
signer = DUMMY_SIGNER
25+
unjailed = False
26+
initial_wei = 100000
27+
register_result = exchange.c_validator_register(
28+
node_ip,
29+
name,
30+
description,
31+
delegations_disabled,
32+
commission_bps,
33+
signer,
34+
unjailed,
35+
initial_wei,
36+
)
37+
print("register result", register_result)
38+
elif ACTION == "ChangeProfile":
39+
node_ip = None
40+
name = None
41+
description = None
42+
unjailed = False
43+
disable_delegations = None
44+
commission_bps = None
45+
signer = None
46+
change_profile_result = exchange.c_validator_change_profile(
47+
node_ip,
48+
name,
49+
description,
50+
unjailed,
51+
disable_delegations,
52+
commission_bps,
53+
signer,
54+
)
55+
print("change profile result", change_profile_result)
56+
elif ACTION == "Unregister":
57+
unregister_result = exchange.c_validator_unregister()
58+
print("unregister result", unregister_result)
59+
else:
60+
raise ValueError("Invalid action specified")
61+
62+
63+
if __name__ == "__main__":
64+
main()
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import argparse
2+
import json
3+
import os
4+
from collections import defaultdict
5+
6+
import lz4.frame
7+
8+
from hyperliquid.utils.signing import TOKEN_DELEGATE_TYPES, recover_user_from_user_signed_action
9+
10+
REPLICA_CMD_BATCH_SIZE = 10000
11+
12+
13+
def decompress_lz4(input_file, output_file):
14+
with open(input_file, "rb") as f_in:
15+
compressed_data = f_in.read()
16+
17+
decompressed_data = lz4.frame.decompress(compressed_data)
18+
19+
with open(output_file, "wb") as f_out:
20+
f_out.write(decompressed_data)
21+
22+
23+
def main():
24+
parser = argparse.ArgumentParser(description="parse token delegate actions from replica cmds")
25+
parser.add_argument("--data-dir", type=str, required=True)
26+
parser.add_argument("--start-height", type=int, required=True)
27+
parser.add_argument("--end-height", type=int, required=True)
28+
args = parser.parse_args()
29+
30+
data_dir = args.data_dir
31+
start_height = args.start_height
32+
end_height = args.end_height
33+
34+
if start_height % REPLICA_CMD_BATCH_SIZE == 0:
35+
raise Exception("start height is not aligned with replica cmd batch size")
36+
if end_height % REPLICA_CMD_BATCH_SIZE == 0:
37+
raise Exception("end height is not aligned with replica cmd batch size")
38+
39+
flns = []
40+
for height in range(start_height, end_height, REPLICA_CMD_BATCH_SIZE):
41+
lz4_fln = f"{data_dir}/{height}.lz4"
42+
if not os.path.exists(lz4_fln):
43+
raise Exception(
44+
f"replica cmds file at {height} not found - download missing block files(s) using 'aws s3 cp s3://hl-[testnet | mainnet]-replica-cmds/<block_object_path> --request-payer requester'"
45+
)
46+
fln = f"{data_dir}/{height}"
47+
decompress_lz4(lz4_fln, fln)
48+
flns.append(fln)
49+
50+
user_to_validator_to_amount: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
51+
52+
for fln in flns:
53+
f = open(fln)
54+
lines = f.readlines()
55+
for line in lines:
56+
if "tokenDelegate" not in line:
57+
continue
58+
data = json.loads(line)
59+
bundles = data["abci_block"]["signed_action_bundles"]
60+
for bundle in bundles:
61+
for signed_action in bundle[1]["signed_actions"]:
62+
action = signed_action["action"]
63+
if action["type"] != "tokenDelegate":
64+
continue
65+
validator = action["validator"]
66+
wei = action["wei"]
67+
is_delegate = not action["isUndelegate"]
68+
user = recover_user_from_user_signed_action(
69+
action,
70+
signed_action["signature"],
71+
TOKEN_DELEGATE_TYPES,
72+
"HyperliquidTransaction:TokenDelegate",
73+
True,
74+
)
75+
if not is_delegate:
76+
wei = -wei
77+
user_to_validator_to_amount[user][validator] += wei / 100_000_000 # native token wei decimals
78+
79+
print("user to validator to wei amount delegated", user_to_validator_to_amount)
80+
81+
82+
if __name__ == "__main__":
83+
main()

0 commit comments

Comments
 (0)