File size: 5,257 Bytes
5f67151 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
#!/usr/bin/env python3
"""
Whale Tracking Router
GET /api/whales/transactions, GET /api/whales/activity
"""
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import JSONResponse
from typing import Optional, List, Dict, Any
from datetime import datetime, timezone, timedelta
import logging
from backend.services.provider_fallback_manager import fallback_manager
from backend.services.data_resolver import get_data_resolver
from backend.services.persistence_service import PersistenceService
from database.db_manager import db_manager
logger = logging.getLogger(__name__)
router = APIRouter(
prefix="/api/whales",
tags=["Whale Tracking"]
)
persistence_service = PersistenceService()
def create_response(data: Any, source: str, attempted: List[str] = None) -> Dict[str, Any]:
"""Create standardized response"""
return {
"data": data,
"meta": {
"source": source,
"generated_at": datetime.now(timezone.utc).isoformat(),
"cache_ttl": 60,
"attempted": attempted or [source]
}
}
@router.get("/transactions")
async def get_whale_transactions(
limit: int = Query(50, description="Number of transactions"),
chain: Optional[str] = Query(None, description="Blockchain (ethereum, bsc, tron)"),
min_amount_usd: Optional[float] = Query(100000, description="Minimum amount in USD")
):
"""Get whale transactions"""
attempted = []
# Try database first
try:
transactions = await persistence_service.get_whale_transactions(
limit=limit,
chain=chain,
min_amount=min_amount_usd
)
if transactions:
attempted.append("database")
return create_response(transactions, "database", attempted)
except Exception as e:
logger.warning(f"Database query failed: {e}")
attempted.append("database")
# Try HF Space
try:
resolver = await get_data_resolver()
whale_data = await resolver.resolve_whale_transactions(limit=limit, chain=chain)
if whale_data:
attempted.append("hf")
# Save to database
await persistence_service.save_whale_transactions(whale_data)
return create_response(whale_data, "hf", attempted)
except Exception as e:
logger.warning(f"HF Space unavailable: {e}")
attempted.append("hf")
# Fallback to external APIs
try:
result = await fallback_manager.fetch_with_fallback(
endpoint="/whale/transactions",
params={"limit": limit, "chain": chain or "ethereum"},
transform_func=lambda x: x if isinstance(x, list) else []
)
attempted.extend(result.attempted)
if result.success and result.data:
# Filter by min_amount
filtered = [
tx for tx in result.data
if tx.get("amount_usd", 0) >= min_amount_usd
]
await persistence_service.save_whale_transactions(filtered)
return create_response(filtered[:limit], result.source, attempted)
except Exception as e:
logger.error(f"External APIs failed: {e}")
attempted.append("external_apis")
# Return empty with attempted sources
return create_response([], "none", attempted)
@router.get("/activity")
async def get_whale_activity(
hours: int = Query(24, description="Hours to look back")
):
"""Get whale activity statistics"""
attempted = []
# Try database
try:
since = datetime.now(timezone.utc) - timedelta(hours=hours)
activity = await persistence_service.get_whale_activity_stats(since)
if activity:
attempted.append("database")
return create_response(activity, "database", attempted)
except Exception as e:
logger.warning(f"Database query failed: {e}")
attempted.append("database")
# Try HF Space
try:
resolver = await get_data_resolver()
activity = await resolver.resolve_whale_activity(hours=hours)
if activity:
attempted.append("hf")
return create_response(activity, "hf", attempted)
except Exception as e:
logger.warning(f"HF Space unavailable: {e}")
attempted.append("hf")
# Fallback to external
try:
result = await fallback_manager.fetch_with_fallback(
endpoint="/whale/stats",
params={"hours": hours},
transform_func=lambda x: x if isinstance(x, dict) else {}
)
attempted.extend(result.attempted)
if result.success:
return create_response(result.data, result.source, attempted)
except Exception as e:
logger.error(f"External APIs failed: {e}")
attempted.append("external_apis")
# Return default stats
default_stats = {
"total_transactions": 0,
"total_volume_usd": 0,
"top_chains": [],
"period_hours": hours
}
return create_response(default_stats, "default", attempted)
|