ToDo:
1. Aggiungere un aggregator per i dati recuperati dai provider. 2. Lavorare effettivamente all'issue Done: 1. creati test per i provider 2. creato market_providers_api_demo.py per mostrare i dati recuperati dalle api dei providers 3. aggiornato i provider 4. creato il provider binance sia pubblico che con chiave 5. creato error_handler.py per gestire decoratori e utilità: retry automatico, gestione timeout...
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import os
|
||||
import requests
|
||||
from app.markets.base import ProductInfo, BaseWrapper, Price
|
||||
from typing import Optional, Dict, Any
|
||||
from .base import ProductInfo, BaseWrapper, Price
|
||||
from .error_handler import retry_on_failure, handle_api_errors, MarketAPIError
|
||||
|
||||
BASE_URL = "https://min-api.cryptocompare.com"
|
||||
|
||||
@@ -10,7 +12,7 @@ class CryptoCompareWrapper(BaseWrapper):
|
||||
La documentazione delle API è disponibile qui: https://developers.coindesk.com/documentation/legacy/Price/SingleSymbolPriceEndpoint
|
||||
!!ATTENZIONE!! sembra essere una API legacy e potrebbe essere deprecata in futuro.
|
||||
"""
|
||||
def __init__(self, api_key:str = None, currency:str='USD'):
|
||||
def __init__(self, api_key: Optional[str] = None, currency: str = 'USD'):
|
||||
if api_key is None:
|
||||
api_key = os.getenv("CRYPTOCOMPARE_API_KEY")
|
||||
assert api_key is not None, "API key is required"
|
||||
@@ -18,7 +20,7 @@ class CryptoCompareWrapper(BaseWrapper):
|
||||
self.api_key = api_key
|
||||
self.currency = currency
|
||||
|
||||
def __request(self, endpoint: str, params: dict = None) -> dict:
|
||||
def __request(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
||||
if params is None:
|
||||
params = {}
|
||||
params['api_key'] = self.api_key
|
||||
@@ -26,6 +28,8 @@ class CryptoCompareWrapper(BaseWrapper):
|
||||
response = requests.get(f"{BASE_URL}{endpoint}", params=params)
|
||||
return response.json()
|
||||
|
||||
@retry_on_failure(max_retries=3, delay=1.0)
|
||||
@handle_api_errors
|
||||
def get_product(self, asset_id: str) -> ProductInfo:
|
||||
response = self.__request("/data/pricemultifull", params = {
|
||||
"fsyms": asset_id,
|
||||
@@ -34,6 +38,8 @@ class CryptoCompareWrapper(BaseWrapper):
|
||||
data = response.get('RAW', {}).get(asset_id, {}).get(self.currency, {})
|
||||
return ProductInfo.from_cryptocompare(data)
|
||||
|
||||
@retry_on_failure(max_retries=3, delay=1.0)
|
||||
@handle_api_errors
|
||||
def get_products(self, asset_ids: list[str]) -> list[ProductInfo]:
|
||||
response = self.__request("/data/pricemultifull", params = {
|
||||
"fsyms": ",".join(asset_ids),
|
||||
@@ -46,10 +52,37 @@ class CryptoCompareWrapper(BaseWrapper):
|
||||
assets.append(ProductInfo.from_cryptocompare(asset_data))
|
||||
return assets
|
||||
|
||||
@retry_on_failure(max_retries=3, delay=1.0)
|
||||
@handle_api_errors
|
||||
def get_all_products(self) -> list[ProductInfo]:
|
||||
raise NotImplementedError("CryptoCompare does not support fetching all assets")
|
||||
"""
|
||||
Workaround per CryptoCompare: utilizza una lista predefinita di asset popolari
|
||||
poiché l'API non fornisce un endpoint per recuperare tutti i prodotti.
|
||||
"""
|
||||
# Lista di asset popolari supportati da CryptoCompare
|
||||
popular_assets = [
|
||||
"BTC", "ETH", "ADA", "DOT", "LINK", "LTC", "XRP", "BCH", "BNB", "SOL",
|
||||
"MATIC", "AVAX", "ATOM", "UNI", "DOGE", "SHIB", "TRX", "ETC", "FIL", "XLM"
|
||||
]
|
||||
|
||||
try:
|
||||
# Utilizza get_products per recuperare i dati di tutti gli asset popolari
|
||||
return self.get_products(popular_assets)
|
||||
except Exception as e:
|
||||
# Fallback: prova con un set ridotto di asset principali
|
||||
main_assets = ["BTC", "ETH", "ADA", "DOT", "LINK"]
|
||||
try:
|
||||
return self.get_products(main_assets)
|
||||
except Exception as fallback_error:
|
||||
# Se anche il fallback fallisce, solleva l'errore originale con informazioni aggiuntive
|
||||
raise NotImplementedError(
|
||||
f"CryptoCompare get_all_products() workaround failed. "
|
||||
f"Original error: {str(e)}, Fallback error: {str(fallback_error)}"
|
||||
)
|
||||
|
||||
def get_historical_prices(self, asset_id: str, day_back: int = 10) -> list[dict]:
|
||||
@retry_on_failure(max_retries=3, delay=1.0)
|
||||
@handle_api_errors
|
||||
def get_historical_prices(self, asset_id: str = "BTC", day_back: int = 10) -> list[Price]:
|
||||
assert day_back <= 30, "day_back should be less than or equal to 30"
|
||||
response = self.__request("/data/v2/histohour", params = {
|
||||
"fsym": asset_id,
|
||||
|
||||
Reference in New Issue
Block a user