
- Create project structure with FastAPI - Add database models for blocks, transactions, arbitrages, pools, and DEXes - Implement Solana RPC client for fetching blockchain data - Create arbitrage detection algorithm - Implement comprehensive API endpoints for analytics - Set up database migrations with Alembic - Add detailed project documentation generated with BackendIM... (backend.im) Co-Authored-By: Claude <noreply@anthropic.com>
188 lines
4.9 KiB
Python
188 lines
4.9 KiB
Python
from typing import Any, List, Optional, Dict
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app import crud
|
|
from app.api import deps
|
|
from app.schemas.pool import Pool, PoolWithDex, PoolList
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/", response_model=PoolList)
|
|
def read_pools(
|
|
db: Session = Depends(deps.get_db),
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
sort_by_tvl: bool = True
|
|
) -> Any:
|
|
"""
|
|
Retrieve pools with pagination.
|
|
"""
|
|
result = crud.pool.get_pools_with_dex(db, skip=skip, limit=limit)
|
|
|
|
pools_with_dex = []
|
|
for pool, dex in result:
|
|
pools_with_dex.append(PoolWithDex(
|
|
**pool.__dict__,
|
|
dex_name=dex.name,
|
|
dex_address=dex.address
|
|
))
|
|
|
|
total = crud.pool.get_count(db)
|
|
return {"pools": pools_with_dex, "total": total}
|
|
|
|
|
|
@router.get("/active", response_model=PoolList)
|
|
def read_most_active_pools(
|
|
db: Session = Depends(deps.get_db),
|
|
limit: int = Query(20, ge=1, le=100)
|
|
) -> Any:
|
|
"""
|
|
Get the most active pools by volume.
|
|
"""
|
|
pools = crud.pool.get_most_active_pools(db, limit=limit)
|
|
|
|
# Add DEX information
|
|
pools_with_dex = []
|
|
for p in pools:
|
|
dex = crud.dex.get(db, id=p.dex_id)
|
|
if dex:
|
|
pools_with_dex.append(PoolWithDex(
|
|
**p.__dict__,
|
|
dex_name=dex.name,
|
|
dex_address=dex.address
|
|
))
|
|
|
|
return {"pools": pools_with_dex, "total": len(pools_with_dex)}
|
|
|
|
|
|
@router.get("/{pool_id}", response_model=PoolWithDex)
|
|
def read_pool(
|
|
pool_id: int,
|
|
db: Session = Depends(deps.get_db),
|
|
) -> Any:
|
|
"""
|
|
Get a specific pool by id.
|
|
"""
|
|
pool = crud.pool.get(db, id=pool_id)
|
|
if not pool:
|
|
raise HTTPException(status_code=404, detail="Pool not found")
|
|
|
|
dex = crud.dex.get(db, id=pool.dex_id)
|
|
if not dex:
|
|
raise HTTPException(status_code=404, detail="DEX not found")
|
|
|
|
return PoolWithDex(
|
|
**pool.__dict__,
|
|
dex_name=dex.name,
|
|
dex_address=dex.address
|
|
)
|
|
|
|
|
|
@router.get("/address/{address}", response_model=PoolWithDex)
|
|
def read_pool_by_address(
|
|
address: str,
|
|
db: Session = Depends(deps.get_db),
|
|
) -> Any:
|
|
"""
|
|
Get a specific pool by address.
|
|
"""
|
|
pool = crud.pool.get_by_address(db, address=address)
|
|
if not pool:
|
|
raise HTTPException(status_code=404, detail="Pool not found")
|
|
|
|
dex = crud.dex.get(db, id=pool.dex_id)
|
|
if not dex:
|
|
raise HTTPException(status_code=404, detail="DEX not found")
|
|
|
|
return PoolWithDex(
|
|
**pool.__dict__,
|
|
dex_name=dex.name,
|
|
dex_address=dex.address
|
|
)
|
|
|
|
|
|
@router.get("/token/{token_address}", response_model=PoolList)
|
|
def read_pools_by_token(
|
|
token_address: str,
|
|
db: Session = Depends(deps.get_db),
|
|
skip: int = 0,
|
|
limit: int = 100
|
|
) -> Any:
|
|
"""
|
|
Get pools that contain a specific token.
|
|
"""
|
|
pools = crud.pool.get_by_token(db, token_address=token_address, skip=skip, limit=limit)
|
|
|
|
# Add DEX information
|
|
pools_with_dex = []
|
|
for p in pools:
|
|
dex = crud.dex.get(db, id=p.dex_id)
|
|
if dex:
|
|
pools_with_dex.append(PoolWithDex(
|
|
**p.__dict__,
|
|
dex_name=dex.name,
|
|
dex_address=dex.address
|
|
))
|
|
|
|
return {"pools": pools_with_dex, "total": len(pools_with_dex)}
|
|
|
|
|
|
@router.get("/pair", response_model=PoolList)
|
|
def read_pools_by_token_pair(
|
|
token_a: str = Query(...),
|
|
token_b: str = Query(...),
|
|
db: Session = Depends(deps.get_db),
|
|
skip: int = 0,
|
|
limit: int = 100
|
|
) -> Any:
|
|
"""
|
|
Get pools for a specific token pair.
|
|
"""
|
|
pools = crud.pool.get_by_token_pair(
|
|
db, token_a=token_a, token_b=token_b, skip=skip, limit=limit
|
|
)
|
|
|
|
# Add DEX information
|
|
pools_with_dex = []
|
|
for p in pools:
|
|
dex = crud.dex.get(db, id=p.dex_id)
|
|
if dex:
|
|
pools_with_dex.append(PoolWithDex(
|
|
**p.__dict__,
|
|
dex_name=dex.name,
|
|
dex_address=dex.address
|
|
))
|
|
|
|
return {"pools": pools_with_dex, "total": len(pools_with_dex)}
|
|
|
|
|
|
@router.get("/tvl-range", response_model=PoolList)
|
|
def read_pools_by_tvl(
|
|
min_tvl: float = Query(..., ge=0),
|
|
max_tvl: Optional[float] = Query(None, ge=0),
|
|
db: Session = Depends(deps.get_db),
|
|
skip: int = 0,
|
|
limit: int = 100
|
|
) -> Any:
|
|
"""
|
|
Get pools within a TVL range.
|
|
"""
|
|
pools = crud.pool.get_by_tvl_range(
|
|
db, min_tvl=min_tvl, max_tvl=max_tvl, skip=skip, limit=limit
|
|
)
|
|
|
|
# Add DEX information
|
|
pools_with_dex = []
|
|
for p in pools:
|
|
dex = crud.dex.get(db, id=p.dex_id)
|
|
if dex:
|
|
pools_with_dex.append(PoolWithDex(
|
|
**p.__dict__,
|
|
dex_name=dex.name,
|
|
dex_address=dex.address
|
|
))
|
|
|
|
return {"pools": pools_with_dex, "total": len(pools_with_dex)} |