import secrets from typing import Any, List, Optional from pathlib import Path from pydantic import field_validator from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): # Basic application info PROJECT_NAME: str = "Solana Arbitrage Trading System" PROJECT_DESCRIPTION: str = "A backend system for detecting and executing arbitrage opportunities on Solana DEXes" VERSION: str = "0.1.0" API_V1_STR: str = "/api/v1" # Security SECRET_KEY: str = secrets.token_urlsafe(32) ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 8 # 8 days # Database DB_DIR: Path = Path("/app") / "storage" / "db" SQLALCHEMY_DATABASE_URL: str = f"sqlite:///{DB_DIR}/db.sqlite" # Solana configuration SOLANA_RPC_URL: str = "https://api.mainnet-beta.solana.com" SOLANA_NETWORK: str = "mainnet-beta" # Can be mainnet-beta, testnet, or devnet WALLET_KEYPAIR_PATH: Optional[str] = None # Path to the keypair JSON file # Trading parameters PROFIT_THRESHOLD_PERCENT: float = 1.0 # Minimum profit percentage to consider an opportunity MAX_SLIPPAGE_PERCENT: float = 0.5 # Maximum allowed slippage percentage EXECUTION_ENABLED: bool = False # Whether to actually execute trades or just monitor SCAN_INTERVAL_SECONDS: int = 10 # How often to scan for arbitrage opportunities # Monitored tokens - comma-separated list of token addresses to monitor MONITORED_TOKENS: List[str] = [] @field_validator("MONITORED_TOKENS", mode="before") def validate_monitored_tokens(cls, v: Any) -> List[str]: if isinstance(v, str) and v: return [token.strip() for token in v.split(",")] return [] # DEX configuration ENABLED_DEXES: List[str] = ["jupiter", "raydium"] @field_validator("ENABLED_DEXES", mode="before") def validate_enabled_dexes(cls, v: Any) -> List[str]: if isinstance(v, str) and v: return [dex.strip().lower() for dex in v.split(",")] return ["jupiter", "raydium"] # Default if not specified model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", case_sensitive=True, ) settings = Settings() # Create DB directory if it doesn't exist settings.DB_DIR.mkdir(parents=True, exist_ok=True)