|
|
@@ -21,22 +21,21 @@ class Publisher:
|
|
|
"""
|
|
|
def __init__(self, config: Config, price_state: PriceState, metrics: Metrics):
|
|
|
self.publish_interval = float(config.hyperliquid.publish_interval)
|
|
|
- self.kms_signer = None
|
|
|
- self.enable_kms = False
|
|
|
self.use_testnet = config.hyperliquid.use_testnet
|
|
|
+ self.push_urls = [TESTNET_API_URL if self.use_testnet else MAINNET_API_URL] + config.hyperliquid.backup_push_urls
|
|
|
|
|
|
- if config.kms.enable_kms:
|
|
|
- self.enable_kms = True
|
|
|
- oracle_account = None
|
|
|
- self.kms_signer = KMSSigner(config)
|
|
|
- else:
|
|
|
- oracle_pusher_key_path = config.hyperliquid.oracle_pusher_key_path
|
|
|
- oracle_pusher_key = Path(oracle_pusher_key_path).read_text().strip()
|
|
|
+ self.kms_signer = None
|
|
|
+ self.enable_kms = False
|
|
|
+ oracle_account = None
|
|
|
+ if not config.kms.enable_kms:
|
|
|
+ oracle_pusher_key = Path(config.hyperliquid.oracle_pusher_key_path).read_text().strip()
|
|
|
oracle_account: LocalAccount = Account.from_key(oracle_pusher_key)
|
|
|
logger.info("oracle pusher local pubkey: {}", oracle_account.address)
|
|
|
+ self.publisher_exchanges = [Exchange(wallet=oracle_account, base_url=url) for url in self.push_urls]
|
|
|
+ if config.kms.enable_kms:
|
|
|
+ self.enable_kms = True
|
|
|
+ self.kms_signer = KMSSigner(config, self.publisher_exchanges)
|
|
|
|
|
|
- url = TESTNET_API_URL if self.use_testnet else MAINNET_API_URL
|
|
|
- self.oracle_publisher_exchange: Exchange = Exchange(wallet=oracle_account, base_url=url)
|
|
|
self.market_name = config.hyperliquid.market_name
|
|
|
self.market_symbol = config.hyperliquid.market_symbol
|
|
|
self.enable_publish = config.hyperliquid.enable_publish
|
|
|
@@ -72,6 +71,7 @@ class Publisher:
|
|
|
# TODO: "Each update can change oraclePx and markPx by at most 1%."
|
|
|
# TODO: "The markPx cannot be updated such that open interest would be 10x the open interest cap."
|
|
|
|
|
|
+ push_response = None
|
|
|
if self.enable_publish:
|
|
|
if self.enable_kms:
|
|
|
push_response = self.kms_signer.set_oracle(
|
|
|
@@ -81,18 +81,38 @@ class Publisher:
|
|
|
external_perp_pxs=external_perp_pxs,
|
|
|
)
|
|
|
else:
|
|
|
- push_response = self.oracle_publisher_exchange.perp_deploy_set_oracle(
|
|
|
- dex=self.market_name,
|
|
|
+ push_response = self._send_update(
|
|
|
oracle_pxs=oracle_pxs,
|
|
|
all_mark_pxs=mark_pxs,
|
|
|
external_perp_pxs=external_perp_pxs,
|
|
|
)
|
|
|
|
|
|
- # TODO: Look at specific error responses and log/alert accordingly
|
|
|
- logger.debug("publish: push response: {} {}", push_response, type(push_response))
|
|
|
- status = push_response.get("status", "")
|
|
|
- if status == "ok":
|
|
|
- self.metrics.successful_push_counter.add(1, self.metrics_labels)
|
|
|
- elif status == "err":
|
|
|
- self.metrics.failed_push_counter.add(1, self.metrics_labels)
|
|
|
- logger.error("publish: publish error: {}", push_response)
|
|
|
+ self._handle_response(push_response)
|
|
|
+
|
|
|
+ def _send_update(self, oracle_pxs, all_mark_pxs, external_perp_pxs):
|
|
|
+ for exchange in self.publisher_exchanges:
|
|
|
+ try:
|
|
|
+ return exchange.perp_deploy_set_oracle(
|
|
|
+ dex=self.market_name,
|
|
|
+ oracle_pxs=oracle_pxs,
|
|
|
+ all_mark_pxs=all_mark_pxs,
|
|
|
+ external_perp_pxs=external_perp_pxs,
|
|
|
+ )
|
|
|
+ except Exception as e:
|
|
|
+ logger.exception("perp_deploy_set_oracle exception for endpoint: {} error: {}", exchange.base_url, e)
|
|
|
+
|
|
|
+ return None
|
|
|
+
|
|
|
+ def _handle_response(self, response):
|
|
|
+ if response is None:
|
|
|
+ logger.error("Push API call failed")
|
|
|
+ self.metrics.failed_push_counter.add(1, self.metrics_labels)
|
|
|
+ return
|
|
|
+
|
|
|
+ logger.debug("publish: push response: {} {}", response, type(response))
|
|
|
+ status = response.get("status")
|
|
|
+ if status == "ok":
|
|
|
+ self.metrics.successful_push_counter.add(1, self.metrics_labels)
|
|
|
+ elif status == "err":
|
|
|
+ self.metrics.failed_push_counter.add(1, self.metrics_labels)
|
|
|
+ logger.error("publish: publish error: {}", response)
|