solana-proxy/main.py
2025-07-25 16:20:48 +05:30

119 lines
3.4 KiB
Python

import os
import logging
import asyncio
from dotenv import load_dotenv
from aiohttp import web
from providers import create_providers
from cache import Cache
from errors import ErrorLogger
from router import Router
from http_proxy import setup_routes
from ws_proxy import setup_ws_routes
@web.middleware
async def cors_middleware(request, handler):
"""Add CORS headers to all responses"""
if request.method == 'OPTIONS':
# Handle preflight requests
return web.Response(headers={
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': '*',
'Access-Control-Max-Age': '86400'
})
response = await handler(request)
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
response.headers['Access-Control-Allow-Headers'] = '*'
return response
def load_config() -> dict:
load_dotenv()
return {
"rpc_port": int(os.getenv("RPC_PORT", 8545)),
"ws_port": int(os.getenv("WS_PORT", 8546)),
"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"),
"error_db_path": os.getenv("ERROR_DB_PATH", "./errors.db"),
}
def setup_logging(log_level: str) -> None:
logging.basicConfig(
level=getattr(logging, log_level.upper()),
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
def create_rpc_app(config: dict, router: Router) -> 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)
# Create runners
rpc_runner = web.AppRunner(rpc_app)
ws_runner = web.AppRunner(ws_app)
await rpc_runner.setup()
await ws_runner.setup()
# 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))
if __name__ == "__main__":
main()