124 lines
4.2 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from typing import List, Optional
import logging
from app.database import get_db
from app.schemas.assets import (
AssetResponse, SingleAssetResponse, AssetHistoryResponse,
AssetMarketsResponse, ErrorResponse
)
from app.services.coincap_client import CoinCapClient
router = APIRouter(prefix="/assets", tags=["Assets"])
logger = logging.getLogger(__name__)
# Initialize client
client = CoinCapClient()
@router.get(
"",
response_model=AssetResponse,
summary="Get list of assets",
description="Retrieve a list of assets with optional filters"
)
async def get_assets(
search: Optional[str] = None,
ids: Optional[str] = None,
limit: Optional[int] = Query(100, ge=1, le=2000),
offset: Optional[int] = Query(0, ge=0),
db: Session = Depends(get_db)
):
try:
response = await client.get_assets(search=search, ids=ids, limit=limit, offset=offset)
return response
except Exception as e:
logger.error(f"Error fetching assets: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get(
"/{slug}",
response_model=SingleAssetResponse,
responses={404: {"model": ErrorResponse}},
summary="Get a specific asset",
description="Retrieve details for a specific asset by its slug"
)
async def get_asset(slug: str, db: Session = Depends(get_db)):
try:
response = await client.get_asset(slug)
if not response.get("data"):
raise HTTPException(status_code=404, detail=f"{slug} not found")
return response
except HTTPException:
raise
except Exception as e:
logger.error(f"Error fetching asset {slug}: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get(
"/{slug}/markets",
response_model=AssetMarketsResponse,
responses={404: {"model": ErrorResponse}},
summary="Get markets for an asset",
description="Retrieve markets for a specific asset"
)
async def get_asset_markets(
slug: str,
limit: Optional[int] = Query(100, ge=1, le=2000),
offset: Optional[int] = Query(0, ge=0),
db: Session = Depends(get_db)
):
try:
response = await client.get_asset_markets(slug, limit=limit, offset=offset)
if not response.get("data") and isinstance(response.get("data"), list):
raise HTTPException(status_code=404, detail=f"{slug} not found")
return response
except HTTPException:
raise
except Exception as e:
logger.error(f"Error fetching markets for asset {slug}: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get(
"/{slug}/history",
response_model=AssetHistoryResponse,
responses={404: {"model": ErrorResponse}},
summary="Get historical data for an asset",
description="Retrieve historical price data for a specific asset"
)
async def get_asset_history(
slug: str,
interval: str = Query(..., description="Time interval (m1, m5, m15, m30, h1, h2, h6, h12, d1)"),
start: Optional[int] = None,
end: Optional[int] = None,
db: Session = Depends(get_db)
):
# Validate interval
valid_intervals = ["m1", "m5", "m15", "m30", "h1", "h2", "h6", "h12", "d1"]
if interval not in valid_intervals:
raise HTTPException(
status_code=400,
detail=f"Invalid interval. Must be one of: {', '.join(valid_intervals)}"
)
# Validate start and end
if (start is None and end is not None) or (start is not None and end is None):
raise HTTPException(
status_code=400,
detail="Both start and end must be provided together or neither should be provided"
)
try:
response = await client.get_asset_history(
slug, interval=interval, start=start, end=end
)
if not response.get("data") and isinstance(response.get("data"), list):
raise HTTPException(status_code=404, detail=f"{slug} not found")
return response
except HTTPException:
raise
except Exception as e:
logger.error(f"Error fetching history for asset {slug}: {e}")
raise HTTPException(status_code=500, detail=str(e))