mgbam commited on
Commit
476cee0
Β·
verified Β·
1 Parent(s): 30c8028

Update app/price_fetcher.py

Browse files
Files changed (1) hide show
  1. app/price_fetcher.py +59 -16
app/price_fetcher.py CHANGED
@@ -1,27 +1,70 @@
1
  """
2
- Background price cache using public CoinGecko
3
- (If you have Gemini keys, swap endpoints & add auth)
4
  """
5
- import httpx, logging, os
 
6
 
 
7
  COINGECKO_URL = (
8
  "https://api.coingecko.com/api/v3/simple/price"
9
  "?ids=bitcoin,ethereum,dogecoin&vs_currencies=usd"
10
  )
 
 
 
 
 
 
 
 
 
11
 
12
- CURRENT_PRICES = {"bitcoin": "‑‑", "ethereum": "‑‑", "dogecoin": "‑‑"}
13
 
14
  def fetch_prices() -> None:
 
 
 
 
15
  global CURRENT_PRICES
16
- try:
17
- resp = httpx.get(COINGECKO_URL, timeout=5)
18
- resp.raise_for_status()
19
- data = resp.json()
20
- CURRENT_PRICES = {
21
- "bitcoin": data["bitcoin"]["usd"],
22
- "ethereum": data["ethereum"]["usd"],
23
- "dogecoin": data["dogecoin"]["usd"],
24
- }
25
- logging.info("β›“ prices updated")
26
- except Exception as e:
27
- logging.warning(f"Price fetch failed: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  """
2
+ Background price cache with multi-API fallback and rate-limit handling
 
3
  """
4
+ import httpx
5
+ import logging
6
 
7
+ # Primary and secondary APIs for crypto prices
8
  COINGECKO_URL = (
9
  "https://api.coingecko.com/api/v3/simple/price"
10
  "?ids=bitcoin,ethereum,dogecoin&vs_currencies=usd"
11
  )
12
+ COINCAP_URL = (
13
+ "https://api.coincap.io/v2/assets?ids=bitcoin,ethereum,dogecoin"
14
+ )
15
+
16
+ # Shared price cache
17
+ CURRENT_PRICES = {"bitcoin": "--", "ethereum": "--", "dogecoin": "--"}
18
+
19
+ # How often to retry each API before falling back (seconds)
20
+ RETRY_DELAY = 5
21
 
 
22
 
23
  def fetch_prices() -> None:
24
+ """
25
+ Try CoinGecko first; on 429 or error, fall back to CoinCap.
26
+ Updates CURRENT_PRICES in-place.
27
+ """
28
  global CURRENT_PRICES
29
+ apis = [
30
+ ("CoinGecko", COINGECKO_URL),
31
+ ("CoinCap", COINCAP_URL)
32
+ ]
33
+
34
+ for name, url in apis:
35
+ try:
36
+ resp = httpx.get(url, timeout=10)
37
+ # Handle CoinCap JSON structure separately
38
+ if name == "CoinGecko":
39
+ resp.raise_for_status()
40
+ data = resp.json()
41
+ prices = {
42
+ "bitcoin": data["bitcoin"]["usd"],
43
+ "ethereum": data["ethereum"]["usd"],
44
+ "dogecoin": data["dogecoin"]["usd"]
45
+ }
46
+ else:
47
+ resp.raise_for_status()
48
+ data = resp.json().get("data", [])
49
+ prices = {item["id"]: float(item["priceUsd"]) for item in data}
50
+
51
+ CURRENT_PRICES.update(prices)
52
+ logging.info("βœ… [%s] prices updated: %s", name, prices)
53
+ return
54
+
55
+ except httpx.HTTPStatusError as e:
56
+ status = e.response.status_code
57
+ if status == 429:
58
+ logging.warning("⚠️ [%s] rate limit (429). Retrying fallback.", name)
59
+ else:
60
+ logging.warning("⚠️ [%s] HTTP error %s: %s", name, status, e)
61
+ except Exception as e:
62
+ logging.warning("⚠️ [%s] fetch error: %s", name, e)
63
+
64
+ # If we reach here, wait a bit before trying next API
65
+ try:
66
+ import time; time.sleep(RETRY_DELAY)
67
+ except Exception:
68
+ pass
69
+
70
+ logging.error("❌ All price APIs failed. Keeping previous prices: %s", CURRENT_PRICES)