from datetime import datetime from typing import List, Optional from pydantic import BaseModel, Field class TokenTransferBase(BaseModel): token_address: str from_address: str to_address: str amount: float program_id: str class TokenTransferCreate(TokenTransferBase): transaction_id: int class TokenTransfer(TokenTransferBase): id: int transaction_id: int timestamp: datetime class Config: from_attributes = True class ArbitrageEventBase(BaseModel): profit_token_address: str profit_amount: float profit_usd: Optional[float] = None path: str confidence_score: float = Field(..., ge=0.0, le=1.0) class ArbitrageEventCreate(ArbitrageEventBase): transaction_id: int class ArbitrageEvent(ArbitrageEventBase): id: int transaction_id: int detected_at: datetime class Config: from_attributes = True class TransactionBase(BaseModel): signature: str fee: int status: str raw_data: str class TransactionCreate(TransactionBase): block_id: int class Transaction(TransactionBase): id: int block_id: int timestamp: datetime token_transfers: List[TokenTransfer] = [] arbitrage_events: List[ArbitrageEvent] = [] class Config: from_attributes = True class BlockBase(BaseModel): slot: int blockhash: str parent_blockhash: str processed: bool = False class BlockCreate(BlockBase): pass class Block(BlockBase): id: int timestamp: datetime transactions: List[Transaction] = [] class Config: from_attributes = True class ArbitrageEventResponse(BaseModel): id: int transaction_signature: str profit_token_address: str profit_amount: float profit_usd: Optional[float] = None path: str confidence_score: float detected_at: datetime block_slot: int class ScanStatusResponse(BaseModel): last_scanned_block: int last_scan_time: datetime arbitrage_events_count: int scan_in_progress: bool class ScanRequest(BaseModel): num_blocks: int = Field(10, ge=1, le=100) start_slot: Optional[int] = None