Enhance Solana RPC client with better error handling and debugging
- Add detailed logging throughout the Solana client and scanner - Improve error handling in RPC client methods - Add debug endpoints to validate Solana connection - Add message field to scan status responses - Enhance health endpoint with RPC connectivity status - Handle invalid block ranges and API rate limits
This commit is contained in:
parent
70da7ba6b3
commit
85b1f2a581
@ -1,4 +1,4 @@
|
|||||||
from typing import List
|
from typing import Dict, List
|
||||||
|
|
||||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
|
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
@ -8,6 +8,7 @@ from app.models.models import ArbitrageEvent
|
|||||||
from app.schemas.schemas import (ArbitrageEventResponse, ScanRequest,
|
from app.schemas.schemas import (ArbitrageEventResponse, ScanRequest,
|
||||||
ScanStatusResponse)
|
ScanStatusResponse)
|
||||||
from app.services.scanner import BlockScanner
|
from app.services.scanner import BlockScanner
|
||||||
|
from app.services.solana_client import SolanaClient
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@ -23,6 +24,37 @@ async def scan_for_arbitrage(
|
|||||||
"""
|
"""
|
||||||
scanner = BlockScanner(db)
|
scanner = BlockScanner(db)
|
||||||
|
|
||||||
|
# Check if scan is already in progress
|
||||||
|
if scanner.scan_in_progress:
|
||||||
|
return ScanStatusResponse(
|
||||||
|
last_scanned_block=scanner.get_last_scanned_block() or 0,
|
||||||
|
last_scan_time=scanner.get_scan_status()["last_scan_time"],
|
||||||
|
arbitrage_events_count=scanner.get_scan_status()["arbitrage_events_count"],
|
||||||
|
scan_in_progress=True,
|
||||||
|
message="Scan already in progress, please wait for it to complete"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Verify Solana connection before starting scan
|
||||||
|
client = SolanaClient()
|
||||||
|
latest_block = client.get_latest_block()
|
||||||
|
if not latest_block:
|
||||||
|
return ScanStatusResponse(
|
||||||
|
last_scanned_block=scanner.get_last_scanned_block() or 0,
|
||||||
|
last_scan_time=scanner.get_scan_status()["last_scan_time"],
|
||||||
|
arbitrage_events_count=scanner.get_scan_status()["arbitrage_events_count"],
|
||||||
|
scan_in_progress=False,
|
||||||
|
message="Failed to connect to Solana RPC. Please check your connection and try again."
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
return ScanStatusResponse(
|
||||||
|
last_scanned_block=scanner.get_last_scanned_block() or 0,
|
||||||
|
last_scan_time=scanner.get_scan_status()["last_scan_time"],
|
||||||
|
arbitrage_events_count=scanner.get_scan_status()["arbitrage_events_count"],
|
||||||
|
scan_in_progress=False,
|
||||||
|
message=f"Error connecting to Solana RPC: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
# Add scanning task to background tasks
|
# Add scanning task to background tasks
|
||||||
background_tasks.add_task(
|
background_tasks.add_task(
|
||||||
scanner.scan_blocks,
|
scanner.scan_blocks,
|
||||||
@ -32,6 +64,7 @@ async def scan_for_arbitrage(
|
|||||||
|
|
||||||
# Return current scan status
|
# Return current scan status
|
||||||
status = scanner.get_scan_status()
|
status = scanner.get_scan_status()
|
||||||
|
status["message"] = "Scan started successfully"
|
||||||
return ScanStatusResponse(**status)
|
return ScanStatusResponse(**status)
|
||||||
|
|
||||||
|
|
||||||
@ -44,6 +77,15 @@ async def get_scan_status(
|
|||||||
"""
|
"""
|
||||||
scanner = BlockScanner(db)
|
scanner = BlockScanner(db)
|
||||||
status = scanner.get_scan_status()
|
status = scanner.get_scan_status()
|
||||||
|
|
||||||
|
# Add helpful message based on status
|
||||||
|
if status["scan_in_progress"]:
|
||||||
|
status["message"] = "Scan is currently in progress"
|
||||||
|
elif status["last_scanned_block"] == 0:
|
||||||
|
status["message"] = "No blocks have been scanned yet. Use the /scan endpoint to start scanning."
|
||||||
|
else:
|
||||||
|
status["message"] = f"Last scan completed at {status['last_scan_time']}. Found {status['arbitrage_events_count']} arbitrage events."
|
||||||
|
|
||||||
return ScanStatusResponse(**status)
|
return ScanStatusResponse(**status)
|
||||||
|
|
||||||
|
|
||||||
@ -121,4 +163,108 @@ async def get_arbitrage_event(
|
|||||||
confidence_score=event.confidence_score,
|
confidence_score=event.confidence_score,
|
||||||
detected_at=event.detected_at,
|
detected_at=event.detected_at,
|
||||||
block_slot=block_slot,
|
block_slot=block_slot,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/debug/solana-connection", response_model=Dict)
|
||||||
|
async def debug_solana_connection():
|
||||||
|
"""
|
||||||
|
Debug endpoint to test Solana RPC connection
|
||||||
|
"""
|
||||||
|
client = SolanaClient()
|
||||||
|
results = {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Test getting latest blockhash
|
||||||
|
latest_block = client.get_latest_block()
|
||||||
|
results["latest_blockhash"] = latest_block
|
||||||
|
|
||||||
|
# Try to get a slot
|
||||||
|
slot_response = client.client.get_slot()
|
||||||
|
if "result" in slot_response:
|
||||||
|
results["current_slot"] = slot_response["result"]
|
||||||
|
|
||||||
|
# Try to get a block
|
||||||
|
try:
|
||||||
|
block_data = client.get_block(slot_response["result"])
|
||||||
|
results["block_data"] = {"has_data": block_data is not None}
|
||||||
|
if block_data:
|
||||||
|
results["block_data"]["parent_slot"] = block_data.get("parentSlot")
|
||||||
|
results["block_data"]["transactions_count"] = len(block_data.get("transactions", []))
|
||||||
|
except Exception as e:
|
||||||
|
results["block_error"] = str(e)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
results["error"] = str(e)
|
||||||
|
|
||||||
|
# Add RPC URL info
|
||||||
|
results["rpc_url"] = client.rpc_url
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/validate-connection", response_model=Dict)
|
||||||
|
async def validate_solana_connection():
|
||||||
|
"""
|
||||||
|
Validate the Solana RPC connection and return detailed status
|
||||||
|
"""
|
||||||
|
client = SolanaClient()
|
||||||
|
result = {
|
||||||
|
"status": "success",
|
||||||
|
"rpc_url": client.rpc_url,
|
||||||
|
"connection_valid": False,
|
||||||
|
"message": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Test 1: Get latest blockhash
|
||||||
|
latest_blockhash = client.get_latest_block()
|
||||||
|
result["blockhash_test"] = {
|
||||||
|
"success": latest_blockhash is not None,
|
||||||
|
"data": latest_blockhash if latest_blockhash else "Failed to retrieve"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test 2: Get current slot
|
||||||
|
try:
|
||||||
|
slot_response = client.client.get_slot()
|
||||||
|
current_slot = slot_response.get("result") if "result" in slot_response else None
|
||||||
|
result["slot_test"] = {
|
||||||
|
"success": current_slot is not None,
|
||||||
|
"data": current_slot if current_slot else "Failed to retrieve"
|
||||||
|
}
|
||||||
|
|
||||||
|
# If we have a slot, try to get a block
|
||||||
|
if current_slot:
|
||||||
|
try:
|
||||||
|
block = client.get_block(current_slot)
|
||||||
|
result["block_test"] = {
|
||||||
|
"success": block is not None,
|
||||||
|
"data": {
|
||||||
|
"has_transactions": block is not None and "transactions" in block,
|
||||||
|
"transaction_count": len(block.get("transactions", [])) if block else 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
result["block_test"] = {
|
||||||
|
"success": False,
|
||||||
|
"error": str(e)
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
result["slot_test"] = {
|
||||||
|
"success": False,
|
||||||
|
"error": str(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determine overall status
|
||||||
|
if result.get("blockhash_test", {}).get("success", False) and result.get("slot_test", {}).get("success", False):
|
||||||
|
result["connection_valid"] = True
|
||||||
|
result["message"] = "Solana RPC connection is valid and functioning properly."
|
||||||
|
else:
|
||||||
|
result["status"] = "error"
|
||||||
|
result["message"] = "Solana RPC connection is not fully functional."
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result["status"] = "error"
|
||||||
|
result["message"] = f"Error validating Solana RPC connection: {str(e)}"
|
||||||
|
|
||||||
|
return result
|
@ -155,6 +155,7 @@ class ScanStatusResponse(BaseModel):
|
|||||||
last_scan_time: datetime
|
last_scan_time: datetime
|
||||||
arbitrage_events_count: int
|
arbitrage_events_count: int
|
||||||
scan_in_progress: bool
|
scan_in_progress: bool
|
||||||
|
message: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class ScanRequest(BaseModel):
|
class ScanRequest(BaseModel):
|
||||||
|
@ -210,27 +210,63 @@ class BlockScanner:
|
|||||||
all_events = []
|
all_events = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
logger.info(f"Starting block scan. Num blocks: {num_blocks}, Start slot: {start_slot}")
|
||||||
|
|
||||||
num_blocks = num_blocks or settings.SOLANA_BLOCKS_TO_SCAN
|
num_blocks = num_blocks or settings.SOLANA_BLOCKS_TO_SCAN
|
||||||
|
logger.info(f"Using RPC URL: {self.solana_client.rpc_url}")
|
||||||
|
|
||||||
# Get latest block if start_slot not provided
|
# Get latest block if start_slot not provided
|
||||||
if start_slot is None:
|
if start_slot is None:
|
||||||
latest_block = self.solana_client.get_latest_block()
|
logger.info("Start slot not provided, fetching latest block")
|
||||||
# Get block at that slot
|
try:
|
||||||
block_data = self.solana_client.get_block(latest_block["lastValidBlockHeight"])
|
latest_block = self.solana_client.get_latest_block()
|
||||||
start_slot = block_data["parentSlot"]
|
logger.info(f"Latest block data: {latest_block}")
|
||||||
|
|
||||||
|
# Get block at that slot
|
||||||
|
last_valid_height = latest_block.get("lastValidBlockHeight")
|
||||||
|
if not last_valid_height:
|
||||||
|
logger.error(f"No lastValidBlockHeight in response: {latest_block}")
|
||||||
|
raise ValueError("Invalid response format: missing lastValidBlockHeight")
|
||||||
|
|
||||||
|
logger.info(f"Fetching block at height: {last_valid_height}")
|
||||||
|
block_data = self.solana_client.get_block(last_valid_height)
|
||||||
|
|
||||||
|
if not block_data or "parentSlot" not in block_data:
|
||||||
|
logger.error(f"Invalid block data response: {block_data}")
|
||||||
|
raise ValueError("Invalid block data: missing parentSlot")
|
||||||
|
|
||||||
|
start_slot = block_data["parentSlot"]
|
||||||
|
logger.info(f"Using start_slot: {start_slot}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting latest block: {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
# Get list of blocks to scan
|
# Get list of blocks to scan
|
||||||
end_slot = start_slot - num_blocks
|
end_slot = start_slot - num_blocks
|
||||||
if end_slot < 0:
|
if end_slot < 0:
|
||||||
end_slot = 0
|
end_slot = 0
|
||||||
|
|
||||||
blocks_to_scan = self.solana_client.get_blocks(end_slot, start_slot)
|
logger.info(f"Getting blocks from {end_slot} to {start_slot}")
|
||||||
|
try:
|
||||||
|
blocks_to_scan = self.solana_client.get_blocks(end_slot, start_slot)
|
||||||
|
logger.info(f"Found {len(blocks_to_scan)} blocks to scan")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting blocks to scan: {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
# Scan each block
|
# Scan each block
|
||||||
for slot in blocks_to_scan:
|
for slot in blocks_to_scan:
|
||||||
try:
|
try:
|
||||||
|
logger.info(f"Processing block at slot {slot}")
|
||||||
block_data = self.solana_client.get_block(slot)
|
block_data = self.solana_client.get_block(slot)
|
||||||
|
|
||||||
|
if not block_data:
|
||||||
|
logger.warning(f"Empty block data for slot {slot}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
logger.info(f"Block {slot} has {len(block_data.get('transactions', []))} transactions")
|
||||||
_, events = self.process_block(block_data)
|
_, events = self.process_block(block_data)
|
||||||
|
logger.info(f"Found {len(events)} arbitrage events in block {slot}")
|
||||||
all_events.extend(events)
|
all_events.extend(events)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error processing block {slot}: {str(e)}")
|
logger.error(f"Error processing block {slot}: {str(e)}")
|
||||||
|
@ -26,50 +26,131 @@ class SolanaClient:
|
|||||||
"""
|
"""
|
||||||
Get latest finalized block
|
Get latest finalized block
|
||||||
"""
|
"""
|
||||||
response = self.client.get_latest_blockhash()
|
try:
|
||||||
if "error" in response:
|
logger.info(f"Requesting latest blockhash from {self.rpc_url}")
|
||||||
logger.error(f"Error getting latest block: {response['error']}")
|
response = self.client.get_latest_blockhash()
|
||||||
raise Exception(f"Error getting latest block: {response['error']}")
|
|
||||||
|
logger.info(f"Got response: {response}")
|
||||||
return response["result"]
|
|
||||||
|
if "error" in response:
|
||||||
|
error_msg = response.get("error", {})
|
||||||
|
logger.error(f"RPC error getting latest block: {error_msg}")
|
||||||
|
raise Exception(f"RPC error getting latest block: {error_msg}")
|
||||||
|
|
||||||
|
if "result" not in response:
|
||||||
|
logger.error(f"Invalid response format, missing 'result' key: {response}")
|
||||||
|
raise ValueError("Invalid response format, missing 'result' key")
|
||||||
|
|
||||||
|
return response["result"]
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Exception in get_latest_block: {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
def get_block(self, slot: int) -> Dict:
|
def get_block(self, slot: int) -> Dict:
|
||||||
"""
|
"""
|
||||||
Get block data by slot number
|
Get block data by slot number
|
||||||
"""
|
"""
|
||||||
response = self.client.get_block(
|
try:
|
||||||
slot,
|
logger.info(f"Requesting block data for slot {slot} from {self.rpc_url}")
|
||||||
encoding="json",
|
|
||||||
max_supported_transaction_version=0,
|
response = self.client.get_block(
|
||||||
transaction_details="full",
|
slot,
|
||||||
)
|
encoding="json",
|
||||||
|
max_supported_transaction_version=0,
|
||||||
if "error" in response:
|
transaction_details="full",
|
||||||
logger.error(f"Error getting block {slot}: {response['error']}")
|
)
|
||||||
raise Exception(f"Error getting block {slot}: {response['error']}")
|
|
||||||
|
logger.debug(f"Raw block response: {response}")
|
||||||
return response["result"]
|
|
||||||
|
if "error" in response:
|
||||||
|
error_msg = response.get("error", {})
|
||||||
|
error_code = error_msg.get("code", "unknown")
|
||||||
|
error_message = error_msg.get("message", "unknown")
|
||||||
|
|
||||||
|
logger.error(f"RPC error getting block {slot}: code={error_code}, message={error_message}")
|
||||||
|
|
||||||
|
# Handle specific error cases
|
||||||
|
if error_code == -32009: # slot not found or not available
|
||||||
|
logger.warning(f"Block at slot {slot} not found or not available")
|
||||||
|
return None
|
||||||
|
|
||||||
|
raise Exception(f"RPC error getting block {slot}: {error_msg}")
|
||||||
|
|
||||||
|
if "result" not in response:
|
||||||
|
logger.error(f"Invalid response format for block {slot}, missing 'result' key: {response}")
|
||||||
|
raise ValueError(f"Invalid response format for block {slot}, missing 'result' key")
|
||||||
|
|
||||||
|
return response["result"]
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Exception in get_block for slot {slot}: {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
def get_blocks(self, start_slot: int, end_slot: int = None) -> List[int]:
|
def get_blocks(self, start_slot: int, end_slot: int = None) -> List[int]:
|
||||||
"""
|
"""
|
||||||
Get a list of confirmed blocks
|
Get a list of confirmed blocks
|
||||||
"""
|
"""
|
||||||
if end_slot is None:
|
try:
|
||||||
# Get latest slot if end_slot not provided
|
logger.info(f"Getting blocks from {start_slot} to {end_slot or 'latest'}")
|
||||||
response = self.client.get_slot()
|
|
||||||
if "error" in response:
|
|
||||||
logger.error(f"Error getting latest slot: {response['error']}")
|
|
||||||
raise Exception(f"Error getting latest slot: {response['error']}")
|
|
||||||
|
|
||||||
end_slot = response["result"]
|
if end_slot is None:
|
||||||
|
# Get latest slot if end_slot not provided
|
||||||
response = self.client.get_blocks(start_slot, end_slot)
|
logger.info("No end_slot provided, fetching latest slot")
|
||||||
|
response = self.client.get_slot()
|
||||||
if "error" in response:
|
|
||||||
logger.error(f"Error getting blocks from {start_slot} to {end_slot}: {response['error']}")
|
logger.debug(f"get_slot response: {response}")
|
||||||
raise Exception(f"Error getting blocks from {start_slot} to {end_slot}: {response['error']}")
|
|
||||||
|
if "error" in response:
|
||||||
return response["result"]
|
error_msg = response.get("error", {})
|
||||||
|
logger.error(f"RPC error getting latest slot: {error_msg}")
|
||||||
|
raise Exception(f"RPC error getting latest slot: {error_msg}")
|
||||||
|
|
||||||
|
if "result" not in response:
|
||||||
|
logger.error(f"Invalid response format, missing 'result' key: {response}")
|
||||||
|
raise ValueError("Invalid response format, missing 'result' key")
|
||||||
|
|
||||||
|
end_slot = response["result"]
|
||||||
|
logger.info(f"Using end_slot: {end_slot}")
|
||||||
|
|
||||||
|
logger.info(f"Requesting blocks from {start_slot} to {end_slot}")
|
||||||
|
|
||||||
|
# Check if the range is valid
|
||||||
|
if start_slot > end_slot:
|
||||||
|
logger.warning(f"Invalid slot range: start={start_slot}, end={end_slot}. Swapping values.")
|
||||||
|
start_slot, end_slot = end_slot, start_slot
|
||||||
|
|
||||||
|
# Limit the range to prevent potential issues with large requests
|
||||||
|
if end_slot - start_slot > 500:
|
||||||
|
logger.warning(f"Large slot range requested: {start_slot} to {end_slot}, limiting to 500 blocks")
|
||||||
|
start_slot = end_slot - 500
|
||||||
|
|
||||||
|
response = self.client.get_blocks(start_slot, end_slot)
|
||||||
|
|
||||||
|
logger.debug(f"get_blocks response: {response}")
|
||||||
|
|
||||||
|
if "error" in response:
|
||||||
|
error_msg = response.get("error", {})
|
||||||
|
logger.error(f"RPC error getting blocks from {start_slot} to {end_slot}: {error_msg}")
|
||||||
|
|
||||||
|
# Handle specific error cases
|
||||||
|
if isinstance(error_msg, dict) and error_msg.get("code") == -32602:
|
||||||
|
logger.warning("Invalid slot range, trying alternative approach")
|
||||||
|
# Use a fallback approach if needed
|
||||||
|
# For now, return an empty list
|
||||||
|
return []
|
||||||
|
|
||||||
|
raise Exception(f"RPC error getting blocks from {start_slot} to {end_slot}: {error_msg}")
|
||||||
|
|
||||||
|
if "result" not in response:
|
||||||
|
logger.error(f"Invalid response format, missing 'result' key: {response}")
|
||||||
|
raise ValueError("Invalid response format, missing 'result' key")
|
||||||
|
|
||||||
|
blocks = response["result"]
|
||||||
|
logger.info(f"Retrieved {len(blocks)} blocks from {start_slot} to {end_slot}")
|
||||||
|
return blocks
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Exception in get_blocks: {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
def get_transaction(self, signature: str) -> Dict:
|
def get_transaction(self, signature: str) -> Dict:
|
||||||
"""
|
"""
|
||||||
|
39
main.py
39
main.py
@ -1,4 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
@ -14,6 +15,12 @@ logging.basicConfig(
|
|||||||
level=logging.INFO,
|
level=logging.INFO,
|
||||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||||
)
|
)
|
||||||
|
# Enable debug logging for the scanner and Solana client modules
|
||||||
|
logging.getLogger("app.services.scanner").setLevel(logging.DEBUG)
|
||||||
|
logging.getLogger("app.services.solana_client").setLevel(logging.DEBUG)
|
||||||
|
# Also enable debug for solana.rpc
|
||||||
|
logging.getLogger("solana.rpc").setLevel(logging.DEBUG)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
@ -40,8 +47,36 @@ app.include_router(api_router, prefix=settings.API_V1_STR)
|
|||||||
# Health check endpoint
|
# Health check endpoint
|
||||||
@app.get("/health", tags=["health"])
|
@app.get("/health", tags=["health"])
|
||||||
async def health_check():
|
async def health_check():
|
||||||
"""Health check endpoint"""
|
"""Health check endpoint with Solana RPC connectivity status"""
|
||||||
return {"status": "ok"}
|
from app.services.solana_client import SolanaClient
|
||||||
|
|
||||||
|
health_status = {
|
||||||
|
"status": "ok",
|
||||||
|
"timestamp": datetime.now().isoformat(),
|
||||||
|
"solana_rpc": {
|
||||||
|
"url": settings.SOLANA_RPC_URL,
|
||||||
|
"connection": "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test Solana RPC connection
|
||||||
|
try:
|
||||||
|
client = SolanaClient()
|
||||||
|
response = client.client.get_latest_blockhash()
|
||||||
|
if "result" in response:
|
||||||
|
health_status["solana_rpc"]["connection"] = "ok"
|
||||||
|
health_status["solana_rpc"]["latest_blockhash"] = response["result"].get("blockhash", "unknown")
|
||||||
|
else:
|
||||||
|
health_status["solana_rpc"]["connection"] = "error"
|
||||||
|
health_status["solana_rpc"]["error"] = "No result in response"
|
||||||
|
except Exception as e:
|
||||||
|
health_status["solana_rpc"]["connection"] = "error"
|
||||||
|
health_status["solana_rpc"]["error"] = str(e)
|
||||||
|
|
||||||
|
if health_status["solana_rpc"]["connection"] != "ok":
|
||||||
|
health_status["status"] = "degraded"
|
||||||
|
|
||||||
|
return health_status
|
||||||
|
|
||||||
|
|
||||||
@app.on_event("startup")
|
@app.on_event("startup")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user