feat: migrate coordinator-api bitcoin wallet and explorer services to use centralized aitbc package HTTP client
- Replace httpx.Client with aitbc.AITBCHTTPClient in BitcoinWallet class - Remove HTTP_CLIENT_AVAILABLE check and httpx import guard - Replace logging.getLogger with aitbc.get_logger in bitcoin_wallet.py - Migrate explorer.py from httpx to aitbc.AITBCHTTPClient - Add NetworkError exception handling in explorer service - Remove async context manager and status code checks in favor of AITBCHTTPClient - Remove httpx imports from both services - Consistent
This commit is contained in:
@@ -5,18 +5,11 @@ Uses RPC to connect to Bitcoin Core (or alternative like Block.io)
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
from aitbc import get_logger, AITBCHTTPClient, NetworkError
|
||||||
|
|
||||||
try:
|
logger = get_logger(__name__)
|
||||||
import httpx
|
|
||||||
|
|
||||||
HTTP_CLIENT_AVAILABLE = True
|
|
||||||
except ImportError:
|
|
||||||
HTTP_CLIENT_AVAILABLE = False
|
|
||||||
logging.warning("httpx not available, bitcoin wallet functions will be disabled")
|
|
||||||
|
|
||||||
|
|
||||||
# Bitcoin wallet configuration (credentials from environment)
|
# Bitcoin wallet configuration (credentials from environment)
|
||||||
@@ -33,12 +26,7 @@ WALLET_CONFIG = {
|
|||||||
class BitcoinWallet:
|
class BitcoinWallet:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.config = WALLET_CONFIG
|
self.config = WALLET_CONFIG
|
||||||
if not HTTP_CLIENT_AVAILABLE:
|
self.client = AITBCHTTPClient(timeout=30.0)
|
||||||
logger.error("httpx not available - bitcoin wallet functions disabled")
|
|
||||||
self.session = None
|
|
||||||
else:
|
|
||||||
self.session = httpx.Client()
|
|
||||||
self.session.auth = (self.config["rpc_user"], self.config["rpc_password"])
|
|
||||||
|
|
||||||
def get_balance(self) -> float:
|
def get_balance(self) -> float:
|
||||||
"""Get the current Bitcoin balance"""
|
"""Get the current Bitcoin balance"""
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ from __future__ import annotations
|
|||||||
from collections import defaultdict, deque
|
from collections import defaultdict, deque
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
import httpx
|
|
||||||
from sqlmodel import Session, select
|
from sqlmodel import Session, select
|
||||||
|
|
||||||
|
from aitbc import AITBCHTTPClient, NetworkError
|
||||||
from ..config import settings
|
from ..config import settings
|
||||||
from ..domain import Job, JobReceipt
|
from ..domain import Job, JobReceipt
|
||||||
from ..schemas import (
|
from ..schemas import (
|
||||||
@@ -42,23 +42,18 @@ class ExplorerService:
|
|||||||
# Fetch real blockchain data via /rpc/head and /rpc/blocks-range
|
# Fetch real blockchain data via /rpc/head and /rpc/blocks-range
|
||||||
rpc_base = settings.blockchain_rpc_url.rstrip("/")
|
rpc_base = settings.blockchain_rpc_url.rstrip("/")
|
||||||
try:
|
try:
|
||||||
with httpx.Client(timeout=10.0) as client:
|
client = AITBCHTTPClient(timeout=10.0)
|
||||||
head_resp = client.get(f"{rpc_base}/rpc/head")
|
try:
|
||||||
if head_resp.status_code == 404:
|
head = client.get(f"{rpc_base}/rpc/head")
|
||||||
return BlockListResponse(items=[], next_offset=None)
|
|
||||||
head_resp.raise_for_status()
|
|
||||||
head = head_resp.json()
|
|
||||||
height = head.get("height", 0)
|
height = head.get("height", 0)
|
||||||
start = max(0, height - offset - limit + 1)
|
start = max(0, height - offset - limit + 1)
|
||||||
end = height - offset
|
end = height - offset
|
||||||
if start > end:
|
if start > end:
|
||||||
return BlockListResponse(items=[], next_offset=None)
|
return BlockListResponse(items=[], next_offset=None)
|
||||||
range_resp = client.get(
|
rpc_data = client.get(
|
||||||
f"{rpc_base}/rpc/blocks-range",
|
f"{rpc_base}/rpc/blocks-range",
|
||||||
params={"start": start, "end": end},
|
params={"start": start, "end": end},
|
||||||
)
|
)
|
||||||
range_resp.raise_for_status()
|
|
||||||
rpc_data = range_resp.json()
|
|
||||||
raw_blocks = rpc_data.get("blocks", [])
|
raw_blocks = rpc_data.get("blocks", [])
|
||||||
# Node returns ascending by height; explorer expects newest first
|
# Node returns ascending by height; explorer expects newest first
|
||||||
raw_blocks = list(reversed(raw_blocks))
|
raw_blocks = list(reversed(raw_blocks))
|
||||||
@@ -78,6 +73,8 @@ class ExplorerService:
|
|||||||
)
|
)
|
||||||
next_offset = offset + len(items) if len(items) == limit else None
|
next_offset = offset + len(items) if len(items) == limit else None
|
||||||
return BlockListResponse(items=items, next_offset=next_offset)
|
return BlockListResponse(items=items, next_offset=next_offset)
|
||||||
|
except NetworkError as e:
|
||||||
|
return BlockListResponse(items=[], next_offset=None)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Fallback to fake data if RPC is unavailable
|
# Fallback to fake data if RPC is unavailable
|
||||||
print(f"Warning: Failed to fetch blocks from RPC: {e}, falling back to fake data")
|
print(f"Warning: Failed to fetch blocks from RPC: {e}, falling back to fake data")
|
||||||
|
|||||||
Reference in New Issue
Block a user