from pydantic import BaseModel, EmailStr, field_validator from typing import Optional, List, Any, Dict from datetime import datetime class UserCreate(BaseModel): email: EmailStr password: str class UserResponse(BaseModel): id: str email: str created_at: datetime updated_at: datetime class Config: from_attributes = True class Token(BaseModel): access_token: str token_type: str class UserSettings(BaseModel): email: EmailStr class UserSettingsUpdate(BaseModel): email: Optional[EmailStr] = None password: Optional[str] = None class BotCreate(BaseModel): name: str description: Optional[str] = None strategy_config: Optional[dict] = {} llm_config: Optional[dict] = {} class BotUpdate(BaseModel): name: Optional[str] = None description: Optional[str] = None strategy_config: Optional[dict] = None llm_config: Optional[dict] = None status: Optional[str] = None class BotResponse(BaseModel): id: str user_id: str name: str description: Optional[str] strategy_config: dict llm_config: dict status: str created_at: datetime updated_at: datetime class Config: from_attributes = True class BacktestCreate(BaseModel): token: str chain: str timeframe: str start_date: str end_date: str @field_validator("chain") @classmethod def chain_must_be_bsc(cls, v: str) -> str: if v != "bsc": raise ValueError("Phase 1 only supports BSC (bnb chain)") return v class BacktestResponse(BaseModel): id: str bot_id: str started_at: datetime ended_at: Optional[datetime] status: str config: dict result: Optional[dict] class Config: from_attributes = True class SimulationCreate(BaseModel): token: str chain: str duration_seconds: int = 3600 check_interval: int = 60 auto_execute: bool = False @field_validator("chain") @classmethod def chain_must_be_bsc(cls, v: str) -> str: if v != "bsc": raise ValueError("Phase 1 only supports BSC (bnb chain)") return v class SimulationResponse(BaseModel): id: str bot_id: str started_at: datetime status: str config: dict signals: Optional[List[dict]] class Config: from_attributes = True class BotConversationCreate(BaseModel): role: str content: str class BotConversationResponse(BaseModel): id: str bot_id: str role: str content: str created_at: datetime class Config: from_attributes = True class BotChatRequest(BaseModel): message: str strategy_config: Optional[bool] = False class BotChatResponse(BaseModel): response: str strategy_config: Optional[dict] = None success: bool = False class SignalResponse(BaseModel): id: str bot_id: str run_id: str signal_type: str token: str price: float confidence: Optional[float] reasoning: Optional[str] executed: bool created_at: datetime class Config: from_attributes = True class AveTokenSearchResponse(BaseModel): tokens: List[dict] upsell_message: Optional[str] = None class AveBatchPricesRequest(BaseModel): token_ids: List[str] class AveBatchPricesResponse(BaseModel): prices: Dict[str, dict] upsell_message: Optional[str] = None class AveTokenDetailsResponse(BaseModel): token: Optional[dict] = None upsell_message: Optional[str] = None class AveKlinesRequest(BaseModel): token_id: str interval: str = "1h" limit: int = 100 start_time: Optional[int] = None end_time: Optional[int] = None class AveKlinesResponse(BaseModel): klines: List[dict] upsell_message: Optional[str] = None class AveTrendingTokensResponse(BaseModel): tokens: List[dict] upsell_message: Optional[str] = None class AveTokenRiskResponse(BaseModel): risk: Optional[dict] = None upsell_message: Optional[str] = None class AveChainQuoteRequest(BaseModel): chain: str from_token: str to_token: str amount: str slippage: float = 0.5 class AveChainQuoteResponse(BaseModel): quote: Optional[dict] = None upsell_message: Optional[str] = None class AveChainSwapRequest(BaseModel): chain: str from_token: str to_token: str amount: str slippage: float = 0.5 wallet_address: Optional[str] = None class AveChainSwapResponse(BaseModel): swap: Optional[dict] = None upsell_message: Optional[str] = None