diff --git a/main.py b/main.py index 31b4c9f..3914a43 100644 --- a/main.py +++ b/main.py @@ -34,8 +34,7 @@ def load_config() -> dict: load_dotenv() return { - "rpc_port": int(os.getenv("RPC_PORT", 8545)), - "ws_port": int(os.getenv("WS_PORT", 8546)), + "proxy_port": int(os.getenv("PROXY_PORT", 8545)), "cache_size_gb": int(os.getenv("CACHE_SIZE_GB", 100)), "backoff_minutes": int(os.getenv("BACKOFF_MINUTES", 30)), "log_level": os.getenv("LOG_LEVEL", "INFO"), @@ -50,70 +49,40 @@ def setup_logging(log_level: str) -> None: ) -def create_rpc_app(config: dict, router: Router) -> web.Application: +def create_app(config: dict) -> web.Application: app = web.Application(middlewares=[cors_middleware]) - app['router'] = router - app['config'] = config - setup_routes(app) - return app -def create_ws_app(config: dict, router: Router) -> web.Application: - app = web.Application(middlewares=[cors_middleware]) - app['router'] = router - app['config'] = config - setup_ws_routes(app) - return app - - - - -async def run_servers(config: dict) -> None: - # Create shared components providers = create_providers() cache = Cache(size_limit_gb=config["cache_size_gb"]) error_logger = ErrorLogger(db_path=config["error_db_path"]) router = Router(providers, cache, error_logger) - # Create separate apps - rpc_app = create_rpc_app(config, router) - ws_app = create_ws_app(config, router) + app['router'] = router + app['config'] = config - # Create runners - rpc_runner = web.AppRunner(rpc_app) - ws_runner = web.AppRunner(ws_app) + setup_routes(app) + setup_ws_routes(app) - await rpc_runner.setup() - await ws_runner.setup() + return app - # Create sites - rpc_site = web.TCPSite(rpc_runner, '0.0.0.0', config["rpc_port"]) - ws_site = web.TCPSite(ws_runner, '0.0.0.0', config["ws_port"]) - - # Start both servers - await rpc_site.start() - await ws_site.start() - - logger = logging.getLogger(__name__) - logger.info(f"RPC server started on port {config['rpc_port']}") - logger.info(f"WebSocket server started on port {config['ws_port']}") - logger.info(f"Cache size limit: {config['cache_size_gb']}GB") - logger.info(f"Provider backoff time: {config['backoff_minutes']} minutes") - - # Keep servers running - try: - await asyncio.Event().wait() - except KeyboardInterrupt: - pass - finally: - await rpc_runner.cleanup() - await ws_runner.cleanup() def main() -> None: config = load_config() setup_logging(config["log_level"]) - asyncio.run(run_servers(config)) + logger = logging.getLogger(__name__) + logger.info(f"Starting Solana RPC Proxy on port {config['proxy_port']}") + logger.info(f"Cache size limit: {config['cache_size_gb']}GB") + logger.info(f"Provider backoff time: {config['backoff_minutes']} minutes") + + app = create_app(config) + + web.run_app( + app, + host='0.0.0.0', + port=config["proxy_port"] + ) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/normalizer.py b/normalizer.py index dfb94c0..98a9964 100644 --- a/normalizer.py +++ b/normalizer.py @@ -3,16 +3,16 @@ from typing import Dict, Any def normalize_response(provider: str, response: Dict[str, Any]) -> Dict[str, Any]: normalized = response.copy() - + # Ensure consistent field names if "result" in normalized and normalized["result"] is None: # Some providers return null, others omit the field pass - + # Handle null vs missing fields consistently if "error" in normalized and normalized["error"] is None: del normalized["error"] - + return normalized @@ -25,4 +25,4 @@ def normalize_error(error: Exception, error_id: str) -> Dict[str, Any]: "message": str(error), "data": {"error_id": error_id} } - } \ No newline at end of file + } diff --git a/ws_proxy.py b/ws_proxy.py index 9aeae94..0885337 100644 --- a/ws_proxy.py +++ b/ws_proxy.py @@ -162,4 +162,4 @@ async def handle_ws_connection(request: web.Request) -> web.WebSocketResponse: def setup_ws_routes(app: web.Application) -> None: - app.router.add_get('/', handle_ws_connection) + app.router.add_get('/ws', handle_ws_connection)