from abc import ABC, abstractmethod from typing import Dict, List, Optional, Any from decimal import Decimal from app.services.solana import get_token_metadata class BaseDexService(ABC): """Base class for DEX price monitoring services""" def __init__(self, name: str): self.name = name @abstractmethod async def get_token_price(self, token_address: str, quote_token_address: Optional[str] = None) -> Dict[str, Any]: """ Get token price from the DEX Args: token_address: The address of the token to get price for quote_token_address: The address of the quote token (default USDC) Returns: Dict containing: price: The token price in quote token liquidity: Available liquidity for the token pair timestamp: When the price was fetched metadata: Additional DEX-specific data """ pass @abstractmethod async def get_token_prices(self, token_addresses: List[str], quote_token_address: Optional[str] = None) -> Dict[str, Dict[str, Any]]: """ Get prices for multiple tokens from the DEX Args: token_addresses: List of token addresses to get prices for quote_token_address: The address of the quote token (default USDC) Returns: Dict of token_address -> price_data """ pass def format_token_amount(self, token_address: str, amount: int) -> float: """Convert raw token amount to human-readable format""" token_metadata = get_token_metadata(token_address) decimals = token_metadata.get("decimals", 9) return float(Decimal(amount) / Decimal(10**decimals)) def parse_token_amount(self, token_address: str, amount: float) -> int: """Convert human-readable token amount to raw format""" token_metadata = get_token_metadata(token_address) decimals = token_metadata.get("decimals", 9) return int(Decimal(amount) * Decimal(10**decimals))