Skip to content

Commit 105a403

Browse files
committed
various fixes
1 parent 24b1f29 commit 105a403

File tree

3 files changed

+49
-43
lines changed

3 files changed

+49
-43
lines changed

apps/hip-3-pusher/src/pusher/kms_signer.py

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
import boto3
23
from cryptography.hazmat.primitives import serialization
34
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
@@ -9,40 +10,55 @@
910
from hyperliquid.utils.constants import TESTNET_API_URL, MAINNET_API_URL
1011
from hyperliquid.utils.signing import get_timestamp_ms, action_hash, construct_phantom_agent, l1_payload
1112
from loguru import logger
13+
from pathlib import Path
1214

1315
from pusher.config import Config
1416

1517
SECP256K1_N_HALF = SECP256K1_N // 2
1618

1719

20+
def _init_client():
21+
# AWS_DEFAULT_REGION, AWS_ACCESS_KEY_ID, and AWS_SECRET_ACCESS_KEY should be set as environment variables
22+
return boto3.client(
23+
"kms",
24+
# can specify an endpoint for e.g. LocalStack
25+
# endpoint_url="http://localhost:4566"
26+
)
27+
28+
1829
class KMSSigner:
1930
def __init__(self, config: Config):
20-
use_testnet = config.hyperliquid.use_testnet
21-
url = TESTNET_API_URL if use_testnet else MAINNET_API_URL
31+
self.use_testnet = config.hyperliquid.use_testnet
32+
url = TESTNET_API_URL if self.use_testnet else MAINNET_API_URL
2233
self.oracle_publisher_exchange: Exchange = Exchange(wallet=None, base_url=url)
23-
self.client = self._init_client(config)
2434

35+
# AWS client and public key load
36+
self.client = _init_client()
37+
self._load_public_key(config.kms.key_path)
38+
39+
def _load_public_key(self, key_path: str):
2540
# Fetch public key once so we can derive address and check recovery id
26-
key_path = config.kms.key_path
27-
self.key_id = open(key_path, "r").read().strip()
28-
self.pubkey_der = self.client.get_public_key(KeyId=self.key_id)["PublicKey"]
41+
self.key_id = Path(key_path).read_text().strip()
42+
pubkey_der = self.client.get_public_key(KeyId=self.key_id)["PublicKey"]
43+
self.pubkey = serialization.load_der_public_key(pubkey_der)
44+
self._construct_pubkey_address_and_bytes()
45+
46+
def _construct_pubkey_address_and_bytes(self):
2947
# Construct eth address to log
30-
pub = serialization.load_der_public_key(self.pubkey_der)
31-
numbers = pub.public_numbers()
48+
numbers = self.pubkey.public_numbers()
3249
x = numbers.x.to_bytes(32, "big")
3350
y = numbers.y.to_bytes(32, "big")
3451
uncompressed = b"\x04" + x + y
35-
self.public_key_bytes = uncompressed
3652
self.address = "0x" + keccak(uncompressed[1:])[-20:].hex()
37-
logger.info("KMSSigner address: {}", self.address)
53+
logger.info("public key loaded from KMS: {}", self.address)
3854

39-
def _init_client(self, config):
40-
# AWS_REGION, AWS_ACCESS_KEY_ID, and AWS_SECRET_ACCESS_KEY should be set as environment variables
41-
return boto3.client(
42-
"kms",
43-
# can specify an endpoint for e.g. LocalStack
44-
# endpoint_url="http://localhost:4566"
55+
# Parse KMS public key into uncompressed secp256k1 bytes
56+
pubkey_bytes = self.pubkey.public_bytes(
57+
serialization.Encoding.X962,
58+
serialization.PublicFormat.UncompressedPoint,
4559
)
60+
# Strip leading 0x04 (uncompressed point indicator)
61+
self.raw_pubkey_bytes = pubkey_bytes[1:]
4662

4763
def set_oracle(self, dex, oracle_pxs, all_mark_pxs, external_perp_pxs):
4864
timestamp = get_timestamp_ms()
@@ -59,14 +75,14 @@ def set_oracle(self, dex, oracle_pxs, all_mark_pxs, external_perp_pxs):
5975
},
6076
}
6177
signature = self.sign_l1_action(
62-
action,
63-
timestamp,
64-
self.oracle_publisher_exchange.base_url == MAINNET_API_URL,
78+
action=action,
79+
nonce=timestamp,
80+
is_mainnet= self.use_testnet,
6581
)
6682
return self.oracle_publisher_exchange._post_action(
67-
action,
68-
signature,
69-
timestamp,
83+
action=action,
84+
signature=signature,
85+
nonce=timestamp,
7086
)
7187

7288
def sign_l1_action(self, action, nonce, is_mainnet):
@@ -91,20 +107,12 @@ def sign_message(self, message_hash: bytes) -> dict:
91107
# Ethereum requires low-s form
92108
if s > SECP256K1_N_HALF:
93109
s = SECP256K1_N - s
94-
# Parse KMS public key into uncompressed secp256k1 bytes
95-
# TODO: Pull this into init
96-
pubkey = serialization.load_der_public_key(self.pubkey_der)
97-
pubkey_bytes = pubkey.public_bytes(
98-
serialization.Encoding.X962,
99-
serialization.PublicFormat.UncompressedPoint,
100-
)
101-
# Strip leading 0x04 (uncompressed point indicator)
102-
raw_pubkey_bytes = pubkey_bytes[1:]
110+
103111
# Try both recovery ids
104112
for v in (0, 1):
105113
sig_obj = Signature(vrs=(v, r, s))
106114
recovered_pub = sig_obj.recover_public_key_from_msg_hash(message_hash)
107-
if recovered_pub.to_bytes() == raw_pubkey_bytes:
115+
if recovered_pub.to_bytes() == self.raw_pubkey_bytes:
108116
return {
109117
"r": to_hex(r),
110118
"s": to_hex(s),

apps/hip-3-pusher/src/pusher/metrics.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ def __init__(self, config: Config):
1717
reader = PrometheusMetricReader()
1818
# Meter is responsible for creating and recording metrics
1919
set_meter_provider(MeterProvider(metric_readers=[reader]))
20-
# TODO: sync version number and add?
2120
self.meter = get_meter_provider().get_meter(METER_NAME)
22-
2321
self._init_metrics()
2422

2523
def _init_metrics(self):
@@ -35,5 +33,3 @@ def _init_metrics(self):
3533
name="hip_3_pusher_failed_push_count",
3634
description="Number of failed push attempts",
3735
)
38-
39-
# TODO: labels/attributes

apps/hip-3-pusher/src/pusher/publisher.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import asyncio
22
from loguru import logger
3+
from pathlib import Path
34

45
from eth_account import Account
56
from eth_account.signers.local import LocalAccount
@@ -30,7 +31,7 @@ def __init__(self, config: Config, price_state: PriceState, metrics: Metrics):
3031
self.kms_signer = KMSSigner(config)
3132
else:
3233
oracle_pusher_key_path = config.hyperliquid.oracle_pusher_key_path
33-
oracle_pusher_key = open(oracle_pusher_key_path, "r").read().strip()
34+
oracle_pusher_key = Path(oracle_pusher_key_path).read_text().strip()
3435
oracle_account: LocalAccount = Account.from_key(oracle_pusher_key)
3536
logger.info("oracle pusher local pubkey: {}", oracle_account.address)
3637

@@ -42,6 +43,7 @@ def __init__(self, config: Config, price_state: PriceState, metrics: Metrics):
4243

4344
self.price_state = price_state
4445
self.metrics = metrics
46+
self.metrics_labels = {"dex": self.market_name}
4547

4648
async def run(self):
4749
while True:
@@ -56,17 +58,17 @@ def publish(self):
5658
oracle_px = self.price_state.get_current_oracle_price()
5759
if not oracle_px:
5860
logger.error("No valid oracle price available")
59-
self.metrics.no_oracle_price_counter.add(1)
61+
self.metrics.no_oracle_price_counter.add(1, self.metrics_labels)
6062
return
6163
else:
6264
logger.debug("Current oracle price: {}", oracle_px)
6365
oracle_pxs[self.market_symbol] = oracle_px
6466

6567
mark_pxs = []
66-
#if self.price_state.hl_mark_price:
67-
# mark_pxs.append({self.market_symbol: self.price_state.hl_mark_price})
68-
6968
external_perp_pxs = {}
69+
if self.price_state.hl_mark_price:
70+
external_perp_pxs[self.market_symbol] = self.price_state.hl_mark_price.price
71+
7072
# TODO: "Each update can change oraclePx and markPx by at most 1%."
7173
# TODO: "The markPx cannot be updated such that open interest would be 10x the open interest cap."
7274

@@ -90,7 +92,7 @@ def publish(self):
9092
logger.debug("publish: push response: {} {}", push_response, type(push_response))
9193
status = push_response.get("status", "")
9294
if status == "ok":
93-
self.metrics.successful_push_counter.add(1)
95+
self.metrics.successful_push_counter.add(1, self.metrics_labels)
9496
elif status == "err":
95-
self.metrics.failed_push_counter.add(1)
97+
self.metrics.failed_push_counter.add(1, self.metrics_labels)
9698
logger.error("publish: publish error: {}", push_response)

0 commit comments

Comments
 (0)