Previously used httpx's implicit default (5 seconds). Explicit timeout makes behavior clear and gives more time for slow responses.
43 lines
1.3 KiB
Python
43 lines
1.3 KiB
Python
"""Bitfinex price fetcher for BTC/EUR pair."""
|
|
|
|
from datetime import UTC, datetime
|
|
|
|
import httpx
|
|
|
|
BITFINEX_TICKER_URL = "https://api-pub.bitfinex.com/v2/ticker/tBTCEUR"
|
|
LAST_PRICE_INDEX = 6
|
|
REQUEST_TIMEOUT_SECONDS = 30.0
|
|
|
|
# Constants for price history records
|
|
SOURCE_BITFINEX = "bitfinex"
|
|
PAIR_BTC_EUR = "BTC/EUR"
|
|
|
|
|
|
async def fetch_btc_eur_price() -> tuple[float, datetime]:
|
|
"""
|
|
Fetch the current BTC/EUR price from Bitfinex.
|
|
|
|
Returns:
|
|
Tuple of (price, timestamp) where timestamp is the current UTC time.
|
|
|
|
Raises:
|
|
httpx.HTTPStatusError: If the API returns a non-2xx status code.
|
|
httpx.RequestError: If a network error occurs (including timeout).
|
|
ValueError: If the response format is unexpected.
|
|
"""
|
|
async with httpx.AsyncClient(timeout=REQUEST_TIMEOUT_SECONDS) as client:
|
|
response = await client.get(BITFINEX_TICKER_URL)
|
|
response.raise_for_status()
|
|
|
|
data = response.json()
|
|
|
|
# Bitfinex ticker response is an array:
|
|
# [BID, BID_SIZE, ASK, ASK_SIZE, DAILY_CHANGE, DAILY_CHANGE_RELATIVE,
|
|
# LAST_PRICE, VOLUME, HIGH, LOW]
|
|
if not isinstance(data, list) or len(data) <= LAST_PRICE_INDEX:
|
|
raise ValueError(f"Unexpected response format: {data}")
|
|
|
|
price = float(data[LAST_PRICE_INDEX])
|
|
timestamp = datetime.now(UTC)
|
|
|
|
return price, timestamp
|