Skip to content

Commit

Permalink
feat: rework handle of ETH price
Browse files Browse the repository at this point in the history
  • Loading branch information
aimxhaisse committed Apr 15, 2024
1 parent d76b3d9 commit f4a038f
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 27 deletions.
50 changes: 24 additions & 26 deletions eth_validator_watcher/coinbase.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@
"""Contains the Coinbase class, which is responsible for fetching the ETH/USD"""
"""Helper to fetch the ETH/USD"""

from prometheus_client import Gauge
from cachetools import func
from pydantic import parse_obj_as
from requests import Session

from .models import CoinbaseTrade


URL = "https://api.pro.coinbase.com/products/ETH-USD/trades"
metric_eth_usd_gauge = Gauge("eth_usd", "ETH/USD conversion rate")


class Coinbase:
"""Coinbase abstraction."""

def __init__(self) -> None:
"""Coinbase"""
self.__http = Session()

def emit_eth_usd_conversion_rate(self) -> None:
"""Emit the ETH/USD conversion rate to Prometheus Gauge.
If any error, fails silently.
"""
try:
response = self.__http.get(URL, params=dict(limit=1))
trades_dict = response.json()
trades = parse_obj_as(list[CoinbaseTrade], trades_dict)
trade, *_ = trades
metric_eth_usd_gauge.set(trade.price)
except:
# This feature is totally optional, so if it fails, we just return 0
pass


@func.ttl_cache(ttl=600)
def get_current_eth_price() -> float:
"""Get the current ETH price in USD.
Returns:
--------
float
"""
try:
response = Session().get(URL, params=dict(limit=1))
trades_dict = response.json()
trades = parse_obj_as(list[CoinbaseTrade], trades_dict)
trade, *_ = trades
except:
# This feature is totally optional, so if it fails, we just
# return 0.0.
return 0.0

return trade.price
2 changes: 2 additions & 0 deletions eth_validator_watcher/entrypoint_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import typer
import time

from .coinbase import get_current_eth_price
from .beacon import Beacon
from .config import load_config, WatchedKeyConfig
from .metrics import get_prometheus_metrics
Expand Down Expand Up @@ -156,6 +157,7 @@ def _update_metrics(self, watched_validators: WatchedValidators, epoch: int, slo
"""
self._metrics.eth_epoch.set(epoch)
self._metrics.eth_slot.set(slot)
self._metrics.eth_current_price.set(get_current_eth_price())

# We iterate once on the validator set to optimize CPU as
# there is a log of entries here, this makes code here a bit
Expand Down
2 changes: 2 additions & 0 deletions eth_validator_watcher/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class PrometheusMetrics:
"""
eth_slot: Gauge
eth_epoch: Gauge
eth_current_price: Gauge

eth_validator_status_count: Gauge
eth_suboptimal_sources_rate: Gauge
Expand All @@ -39,6 +40,7 @@ def get_prometheus_metrics() -> PrometheusMetrics:
_metrics = PrometheusMetrics(
eth_slot=Gauge("eth_slot", "Current slot"),
eth_epoch=Gauge("eth_epoch", "Current epoch"),
eth_current_price=Gauge("eth_current_price", "Current price of ETH in USD"),
eth_validator_status_count=Gauge("eth_validator_status_count", "Validator status count", ['scope', 'status']),
eth_suboptimal_sources_rate=Gauge("eth_suboptimal_sources_rate", "Suboptimal sources rate", ['scope']),
eth_suboptimal_targets_rate=Gauge("eth_suboptimal_targets_rate", "Suboptimal targets rate", ['scope']),
Expand Down
13 changes: 12 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ tenacity = "^8.2.2"
pyyaml = "^6.0.1"
pydantic-yaml = "^1.2.0"
pydantic-settings = "^2.1.0"
cachetools = "^5.3.3"

[tool.poetry.group.dev.dependencies]
mypy = "^1.2.0"
Expand Down

0 comments on commit f4a038f

Please sign in to comment.