update 03-28 11:38
This commit is contained in:
@@ -54,6 +54,7 @@ class OracleMonitor:
|
||||
}
|
||||
|
||||
def __init__(self, rpc_url: Optional[str] = None) -> None:
|
||||
from collections import deque
|
||||
self._rpc_url = rpc_url or "https://polygon.drpc.org"
|
||||
self._w3 = None
|
||||
self._contracts: dict[str, object] = {}
|
||||
@@ -61,10 +62,11 @@ class OracleMonitor:
|
||||
self._last_oracle_prices: dict[str, float] = {}
|
||||
self._last_oracle_timestamps: dict[str, float] = {}
|
||||
self._last_oracle_round_ids: dict[str, int] = {}
|
||||
self._update_intervals: dict[str, list[float]] = {
|
||||
"BTC": [], "ETH": [], "SOL": []
|
||||
self._update_intervals: dict[str, deque[float]] = {
|
||||
asset: deque(maxlen=100) for asset in self.FEEDS
|
||||
}
|
||||
self._initialized = False
|
||||
self._shutdown_event: Optional[asyncio.Event] = None
|
||||
|
||||
async def initialize(self) -> bool:
|
||||
"""Initialize web3 connection and contract instances."""
|
||||
@@ -106,7 +108,10 @@ class OracleMonitor:
|
||||
|
||||
try:
|
||||
contract = self._contracts[asset]
|
||||
result = contract.functions.latestRoundData().call()
|
||||
loop = asyncio.get_event_loop()
|
||||
result = await loop.run_in_executor(
|
||||
None, contract.functions.latestRoundData().call
|
||||
)
|
||||
|
||||
round_id, answer, started_at, updated_at, answered_in_round = result
|
||||
decimals = self._decimals.get(asset, 8)
|
||||
@@ -127,11 +132,7 @@ class OracleMonitor:
|
||||
prev_ts = self._last_oracle_timestamps.get(asset)
|
||||
if prev_ts is not None and timestamp > prev_ts:
|
||||
interval = timestamp - prev_ts
|
||||
intervals = self._update_intervals[asset]
|
||||
intervals.append(interval)
|
||||
# Keep last 100 intervals
|
||||
if len(intervals) > 100:
|
||||
intervals.pop(0)
|
||||
self._update_intervals[asset].append(interval)
|
||||
|
||||
self._last_oracle_prices[asset] = price
|
||||
self._last_oracle_timestamps[asset] = timestamp
|
||||
@@ -159,19 +160,33 @@ class OracleMonitor:
|
||||
return None
|
||||
return (cex_price - oracle_price) / oracle_price * 100
|
||||
|
||||
async def poll_loop(self, interval: float = 5.0) -> None:
|
||||
async def poll_loop(
|
||||
self, interval: float = 5.0, shutdown_event: Optional[asyncio.Event] = None
|
||||
) -> None:
|
||||
"""Continuously poll oracle prices."""
|
||||
if not self._initialized:
|
||||
log.warning("oracle_poll_not_initialized")
|
||||
return
|
||||
|
||||
while True:
|
||||
if shutdown_event is not None:
|
||||
self._shutdown_event = shutdown_event
|
||||
|
||||
while not (self._shutdown_event and self._shutdown_event.is_set()):
|
||||
for asset in self.FEEDS:
|
||||
try:
|
||||
await self.get_oracle_price(asset)
|
||||
except Exception:
|
||||
log.exception("oracle_poll_error", asset=asset)
|
||||
await asyncio.sleep(interval)
|
||||
try:
|
||||
if self._shutdown_event:
|
||||
await asyncio.wait_for(
|
||||
self._shutdown_event.wait(), timeout=interval
|
||||
)
|
||||
break
|
||||
else:
|
||||
await asyncio.sleep(interval)
|
||||
except asyncio.TimeoutError:
|
||||
pass
|
||||
|
||||
def get_stats(self) -> dict:
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user