From 3103debecf37cc78980544ba4e0825d6c83d6b58 Mon Sep 17 00:00:00 2001 From: aitbc Date: Fri, 24 Apr 2026 23:33:11 +0200 Subject: [PATCH] feat: migrate coordinator-api routers to use centralized aitbc package utilities - Replace logging.getLogger with aitbc.get_logger across all router files - Migrate HTTP client usage from httpx to aitbc.AITBCHTTPClient in blockchain.py - Add NetworkError exception handling from aitbc package - Update blockchain status and sync status endpoints to use AITBCHTTPClient - Add from __future__ import annotations to admin.py, client.py, governance.py - Consistent logger initialization across 20+ router --- .../app/routers/adaptive_learning_health.py | 4 +- apps/coordinator-api/src/app/routers/admin.py | 8 +- .../src/app/routers/agent_creativity.py | 5 +- .../app/routers/agent_integration_router.py | 6 +- .../src/app/routers/agent_performance.py | 5 +- .../src/app/routers/agent_router.py | 5 +- .../src/app/routers/agent_security_router.py | 6 +- .../src/app/routers/analytics.py | 5 +- .../src/app/routers/blockchain.py | 78 ++---- .../src/app/routers/cache_management.py | 5 +- .../src/app/routers/certification.py | 5 +- .../coordinator-api/src/app/routers/client.py | 6 + .../src/app/routers/community.py | 5 +- .../src/app/routers/exchange.py | 5 +- .../src/app/routers/governance.py | 12 +- .../src/app/routers/marketplace.py | 8 +- .../src/app/routers/marketplace_enhanced.py | 4 +- .../routers/marketplace_enhanced_simple.py | 5 +- .../src/app/routers/marketplace_gpu.py | 4 +- .../src/app/routers/marketplace_offers.py | 4 +- .../app/routers/marketplace_performance.py | 8 +- apps/coordinator-api/src/app/routers/miner.py | 4 +- .../src/app/routers/monitoring_dashboard.py | 47 ++-- .../src/app/routers/multi_modal_rl.py | 5 +- .../src/app/routers/openclaw_enhanced.py | 4 +- .../app/routers/openclaw_enhanced_health.py | 6 +- .../app/routers/openclaw_enhanced_simple.py | 5 +- .../src/app/routers/reputation.py | 5 +- .../src/app/routers/rewards.py | 5 +- .../src/app/routers/trading.py | 5 +- .../src/app/routers/web_vitals.py | 6 +- .../src/app/services/blockchain.py | 18 +- .../src/app/services/payments.py | 9 +- cli/aitbc_cli.py | 85 +++--- cli/aitbc_cli/commands/cross_chain.py | 174 ++++++------- cli/aitbc_cli/commands/exchange.py | 245 +++++++----------- cli/aitbc_cli/commands/exchange_island.py | 8 + cli/aitbc_cli/commands/wallet.py | 65 ++--- 38 files changed, 414 insertions(+), 475 deletions(-) diff --git a/apps/coordinator-api/src/app/routers/adaptive_learning_health.py b/apps/coordinator-api/src/app/routers/adaptive_learning_health.py index ad7e4f91..54f16fd0 100755 --- a/apps/coordinator-api/src/app/routers/adaptive_learning_health.py +++ b/apps/coordinator-api/src/app/routers/adaptive_learning_health.py @@ -5,7 +5,6 @@ Adaptive Learning Service Health Check Router Provides health monitoring for reinforcement learning frameworks """ -import logging import sys from datetime import datetime from typing import Any @@ -14,10 +13,11 @@ import psutil from fastapi import APIRouter, Depends from sqlalchemy.orm import Session +from aitbc import get_logger from ..services.adaptive_learning import AdaptiveLearningService from ..storage import get_session -logger = logging.getLogger(__name__) +logger = get_logger(__name__) router = APIRouter() diff --git a/apps/coordinator-api/src/app/routers/admin.py b/apps/coordinator-api/src/app/routers/admin.py index 69f7ea95..fd5985ad 100755 --- a/apps/coordinator-api/src/app/routers/admin.py +++ b/apps/coordinator-api/src/app/routers/admin.py @@ -1,4 +1,5 @@ -import logging +from __future__ import annotations + from datetime import datetime from typing import Annotated @@ -8,14 +9,15 @@ from slowapi.util import get_remote_address from sqlalchemy.orm import Session from sqlmodel import select +from aitbc import get_logger + from ..config import settings from ..deps import require_admin_key from ..services import JobService, MinerService from ..storage import get_session from ..utils.cache import cached, get_cache_config -logger = logging.getLogger(__name__) - +logger = get_logger(__name__) limiter = Limiter(key_func=get_remote_address) router = APIRouter(prefix="/admin", tags=["admin"]) diff --git a/apps/coordinator-api/src/app/routers/agent_creativity.py b/apps/coordinator-api/src/app/routers/agent_creativity.py index 585b1d89..a8d09697 100755 --- a/apps/coordinator-api/src/app/routers/agent_creativity.py +++ b/apps/coordinator-api/src/app/routers/agent_creativity.py @@ -7,13 +7,14 @@ Agent Creativity API Endpoints REST API for agent creativity enhancement, ideation, and cross-domain synthesis """ -import logging from typing import Any from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel, Field -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from ..domain.agent_performance import CreativeCapability from ..services.creative_capabilities_service import ( diff --git a/apps/coordinator-api/src/app/routers/agent_integration_router.py b/apps/coordinator-api/src/app/routers/agent_integration_router.py index 3ce4c882..9106df10 100755 --- a/apps/coordinator-api/src/app/routers/agent_integration_router.py +++ b/apps/coordinator-api/src/app/routers/agent_integration_router.py @@ -5,11 +5,11 @@ Agent Integration and Deployment API Router for Verifiable AI Agent Orchestratio Provides REST API endpoints for production deployment and integration management """ -import logging - from fastapi import APIRouter, Depends, HTTPException -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from sqlmodel import Session, select diff --git a/apps/coordinator-api/src/app/routers/agent_performance.py b/apps/coordinator-api/src/app/routers/agent_performance.py index 703017b0..915f2374 100755 --- a/apps/coordinator-api/src/app/routers/agent_performance.py +++ b/apps/coordinator-api/src/app/routers/agent_performance.py @@ -7,14 +7,15 @@ Advanced Agent Performance API Endpoints REST API for meta-learning, resource optimization, and performance enhancement """ -import logging from datetime import datetime, timedelta from typing import Any, Dict, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel, Field -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from ..domain.agent_performance import ( AgentCapability, diff --git a/apps/coordinator-api/src/app/routers/agent_router.py b/apps/coordinator-api/src/app/routers/agent_router.py index 17254356..d37cf112 100755 --- a/apps/coordinator-api/src/app/routers/agent_router.py +++ b/apps/coordinator-api/src/app/routers/agent_router.py @@ -7,12 +7,13 @@ AI Agent API Router for Verifiable AI Agent Orchestration Provides REST API endpoints for agent workflow management and execution """ -import logging from datetime import datetime from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from sqlmodel import Session, select diff --git a/apps/coordinator-api/src/app/routers/agent_security_router.py b/apps/coordinator-api/src/app/routers/agent_security_router.py index bc63c346..ffe689dd 100755 --- a/apps/coordinator-api/src/app/routers/agent_security_router.py +++ b/apps/coordinator-api/src/app/routers/agent_security_router.py @@ -7,11 +7,11 @@ Agent Security API Router for Verifiable AI Agent Orchestration Provides REST API endpoints for security management and auditing """ -import logging - from fastapi import APIRouter, Depends, HTTPException -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from sqlmodel import Session, select diff --git a/apps/coordinator-api/src/app/routers/analytics.py b/apps/coordinator-api/src/app/routers/analytics.py index aa3754d2..8868b48e 100755 --- a/apps/coordinator-api/src/app/routers/analytics.py +++ b/apps/coordinator-api/src/app/routers/analytics.py @@ -7,14 +7,15 @@ Marketplace Analytics API Endpoints REST API for analytics, insights, reporting, and dashboards """ -import logging from datetime import datetime, timedelta from typing import Any, Dict, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel, Field -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from ..domain.analytics import ( AnalyticsPeriod, diff --git a/apps/coordinator-api/src/app/routers/blockchain.py b/apps/coordinator-api/src/app/routers/blockchain.py index a3173ff1..1e19cbfc 100755 --- a/apps/coordinator-api/src/app/routers/blockchain.py +++ b/apps/coordinator-api/src/app/routers/blockchain.py @@ -1,10 +1,10 @@ from __future__ import annotations -import logging - from fastapi import APIRouter -logger = logging.getLogger(__name__) +from aitbc import get_logger, AITBCHTTPClient, NetworkError + +logger = get_logger(__name__) router = APIRouter(tags=["blockchain"]) @@ -14,65 +14,43 @@ router = APIRouter(tags=["blockchain"]) async def blockchain_status(): """Get blockchain status.""" try: - import httpx - from ..config import settings rpc_url = settings.blockchain_rpc_url.rstrip("/") - async with httpx.AsyncClient() as client: - response = await client.get(f"{rpc_url}/rpc/head", timeout=5.0) - if response.status_code == 200: - data = response.json() - return { - "status": "connected", - "height": data.get("height", 0), - "hash": data.get("hash", ""), - "timestamp": data.get("timestamp", ""), - "tx_count": data.get("tx_count", 0), - } - else: - return {"status": "error", "error": f"RPC returned {response.status_code}"} - except Exception as e: + client = AITBCHTTPClient(timeout=5.0) + response = client.get(f"{rpc_url}/rpc/head") + return { + "status": "connected", + "height": response.get("height", 0), + "hash": response.get("hash", ""), + "timestamp": response.get("timestamp", ""), + "tx_count": response.get("tx_count", 0), + } + except NetworkError as e: logger.error(f"Blockchain status error: {e}") - return {"status": "error", "error": "Failed to get blockchain status"} + return {"status": "error", "error": f"RPC connection failed: {e}"} @router.get("/sync-status") async def blockchain_sync_status(): """Get blockchain synchronization status.""" try: - import httpx - from ..config import settings rpc_url = settings.blockchain_rpc_url.rstrip("/") - async with httpx.AsyncClient() as client: - response = await client.get(f"{rpc_url}/rpc/syncStatus", timeout=5.0) - if response.status_code == 200: - data = response.json() - return { - "status": "syncing" if data.get("syncing", False) else "synced", - "current_height": data.get("current_height", 0), - "target_height": data.get("target_height", 0), - "sync_percentage": data.get("sync_percentage", 100.0), - "last_block": data.get("last_block", {}), - } - else: - return { - "status": "error", - "error": f"RPC returned {response.status_code}", - "syncing": False, - "current_height": 0, - "target_height": 0, - "sync_percentage": 0.0, - } + client = AITBCHTTPClient(timeout=5.0) + response = client.get(f"{rpc_url}/rpc/syncStatus") + if response.get("syncing", False): + return { + "status": "syncing", + "current_block": response.get("current_block", 0), + "highest_block": response.get("highest_block", 0), + } + else: + return {"status": "synced", "block": response.get("current_block", 0)} + except NetworkError as e: + logger.error(f"Blockchain sync status error: {e}") + return {"status": "error", "error": f"RPC connection failed: {e}"} except Exception as e: logger.error(f"Blockchain sync status error: {e}") - return { - "status": "error", - "error": "Failed to get sync status", - "syncing": False, - "current_height": 0, - "target_height": 0, - "sync_percentage": 0.0, - } + return {"status": "error", "error": "Failed to get sync status"} diff --git a/apps/coordinator-api/src/app/routers/cache_management.py b/apps/coordinator-api/src/app/routers/cache_management.py index f022c7a2..41081ef1 100755 --- a/apps/coordinator-api/src/app/routers/cache_management.py +++ b/apps/coordinator-api/src/app/routers/cache_management.py @@ -2,17 +2,16 @@ Cache monitoring and management endpoints """ -import logging - from fastapi import APIRouter, Depends, HTTPException, Request from slowapi import Limiter from slowapi.util import get_remote_address +from aitbc import get_logger from ..config import settings from ..deps import require_admin_key from ..utils.cache_management import clear_cache, get_cache_stats, warm_cache -logger = logging.getLogger(__name__) +logger = get_logger(__name__) limiter = Limiter(key_func=get_remote_address) diff --git a/apps/coordinator-api/src/app/routers/certification.py b/apps/coordinator-api/src/app/routers/certification.py index 57063089..24fe2a2d 100755 --- a/apps/coordinator-api/src/app/routers/certification.py +++ b/apps/coordinator-api/src/app/routers/certification.py @@ -7,14 +7,15 @@ Certification and Partnership API Endpoints REST API for agent certification, partnership programs, and badge system """ -import logging from datetime import datetime, timedelta from typing import Any, Dict, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel, Field -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from ..domain.certification import ( AchievementBadge, diff --git a/apps/coordinator-api/src/app/routers/client.py b/apps/coordinator-api/src/app/routers/client.py index 001252fb..2d7fa337 100755 --- a/apps/coordinator-api/src/app/routers/client.py +++ b/apps/coordinator-api/src/app/routers/client.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from datetime import datetime from typing import Annotated @@ -6,6 +8,8 @@ from slowapi import Limiter from slowapi.util import get_remote_address from sqlalchemy.orm import Session +from aitbc import get_logger, AITBCHTTPClient, NetworkError + from ..config import settings from ..custom_types import JobState from ..deps import require_client_key @@ -15,6 +19,8 @@ from ..services.payments import PaymentService from ..storage import get_session from ..utils.cache import cached, get_cache_config +logger = get_logger(__name__) + limiter = Limiter(key_func=get_remote_address) router = APIRouter(tags=["client"]) diff --git a/apps/coordinator-api/src/app/routers/community.py b/apps/coordinator-api/src/app/routers/community.py index 734e42dc..aeb69f1c 100755 --- a/apps/coordinator-api/src/app/routers/community.py +++ b/apps/coordinator-api/src/app/routers/community.py @@ -7,13 +7,14 @@ Community and Developer Ecosystem API Endpoints REST API for managing OpenClaw developer profiles, SDKs, solutions, and hackathons """ -import logging from typing import Any from fastapi import APIRouter, Body, Depends, HTTPException, Query from pydantic import BaseModel, Field -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from ..domain.community import ( AgentSolution, diff --git a/apps/coordinator-api/src/app/routers/exchange.py b/apps/coordinator-api/src/app/routers/exchange.py index 94664b85..7a7d37b7 100755 --- a/apps/coordinator-api/src/app/routers/exchange.py +++ b/apps/coordinator-api/src/app/routers/exchange.py @@ -2,7 +2,6 @@ Bitcoin Exchange Router for AITBC """ -import logging import time import uuid from datetime import datetime @@ -12,7 +11,9 @@ from fastapi import APIRouter, BackgroundTasks, HTTPException, Request from slowapi import Limiter from slowapi.util import get_remote_address -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) limiter = Limiter(key_func=get_remote_address) diff --git a/apps/coordinator-api/src/app/routers/governance.py b/apps/coordinator-api/src/app/routers/governance.py index d4d26815..f48de71f 100755 --- a/apps/coordinator-api/src/app/routers/governance.py +++ b/apps/coordinator-api/src/app/routers/governance.py @@ -7,14 +7,18 @@ Decentralized Governance API Endpoints REST API for OpenClaw DAO voting, proposals, and governance analytics """ -import logging +from __future__ import annotations + +from fastapi import APIRouter, Depends, HTTPException + +from aitbc import get_logger + +logger = get_logger(__name__) + from typing import Any -from fastapi import APIRouter, Body, Depends, HTTPException, Query from pydantic import BaseModel, Field -logger = logging.getLogger(__name__) - from ..domain.governance import ( GovernanceProfile, Proposal, diff --git a/apps/coordinator-api/src/app/routers/marketplace.py b/apps/coordinator-api/src/app/routers/marketplace.py index 9a5ee3ef..2a527c78 100755 --- a/apps/coordinator-api/src/app/routers/marketplace.py +++ b/apps/coordinator-api/src/app/routers/marketplace.py @@ -1,13 +1,11 @@ from __future__ import annotations -import logging - -from fastapi import APIRouter, Depends, HTTPException, Query, Request -from fastapi import status as http_status +from fastapi import APIRouter, Depends, HTTPException, Query, Request, status as http_status from slowapi import Limiter from slowapi.util import get_remote_address from sqlalchemy.orm import Session +from aitbc import get_logger from ..config import settings from ..metrics import marketplace_errors_total, marketplace_requests_total from ..schemas import MarketplaceBidRequest, MarketplaceBidView, MarketplaceOfferView, MarketplaceStatsView @@ -15,7 +13,7 @@ from ..services import MarketplaceService from ..storage import get_session from ..utils.cache import cached, get_cache_config -logger = logging.getLogger(__name__) +logger = get_logger(__name__) limiter = Limiter(key_func=get_remote_address) diff --git a/apps/coordinator-api/src/app/routers/marketplace_enhanced.py b/apps/coordinator-api/src/app/routers/marketplace_enhanced.py index cd809d29..f550f099 100755 --- a/apps/coordinator-api/src/app/routers/marketplace_enhanced.py +++ b/apps/coordinator-api/src/app/routers/marketplace_enhanced.py @@ -7,9 +7,9 @@ Enhanced Marketplace API Router - Phase 6.5 REST API endpoints for advanced marketplace features including royalties, licensing, and analytics """ -import logging +from aitbc import get_logger -logger = logging.getLogger(__name__) +logger = get_logger(__name__) from fastapi import APIRouter, Depends, HTTPException diff --git a/apps/coordinator-api/src/app/routers/marketplace_enhanced_simple.py b/apps/coordinator-api/src/app/routers/marketplace_enhanced_simple.py index d1ad6094..dcdca773 100755 --- a/apps/coordinator-api/src/app/routers/marketplace_enhanced_simple.py +++ b/apps/coordinator-api/src/app/routers/marketplace_enhanced_simple.py @@ -6,10 +6,11 @@ Enhanced Marketplace API Router - Simplified Version REST API endpoints for enhanced marketplace features """ -import logging from typing import Any -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel, Field diff --git a/apps/coordinator-api/src/app/routers/marketplace_gpu.py b/apps/coordinator-api/src/app/routers/marketplace_gpu.py index 8a71faf5..771d141c 100755 --- a/apps/coordinator-api/src/app/routers/marketplace_gpu.py +++ b/apps/coordinator-api/src/app/routers/marketplace_gpu.py @@ -4,7 +4,6 @@ from typing import Annotated GPU marketplace endpoints backed by persistent SQLModel tables. """ -import logging import statistics from datetime import datetime, timedelta from typing import Any @@ -16,12 +15,13 @@ from pydantic import BaseModel, Field from sqlalchemy.orm import Session from sqlmodel import col, func, select +from aitbc import get_logger from ..domain.gpu_marketplace import GPUBooking, GPURegistry, GPUReview from ..services.dynamic_pricing_engine import DynamicPricingEngine, PricingStrategy, ResourceType from ..services.market_data_collector import MarketDataCollector from ..storage import get_session -logger = logging.getLogger(__name__) +logger = get_logger(__name__) router = APIRouter(tags=["marketplace-gpu"]) diff --git a/apps/coordinator-api/src/app/routers/marketplace_offers.py b/apps/coordinator-api/src/app/routers/marketplace_offers.py index 884b914e..c4b847e9 100755 --- a/apps/coordinator-api/src/app/routers/marketplace_offers.py +++ b/apps/coordinator-api/src/app/routers/marketplace_offers.py @@ -6,18 +6,18 @@ from sqlalchemy.orm import Session Router to create marketplace offers from registered miners """ -import logging from typing import Any from fastapi import APIRouter, Depends, HTTPException from sqlmodel import Session, select +from aitbc import get_logger from ..deps import require_admin_key from ..domain import MarketplaceOffer, Miner from ..schemas import MarketplaceOfferView from ..storage import get_session -logger = logging.getLogger(__name__) +logger = get_logger(__name__) router = APIRouter(tags=["marketplace-offers"]) diff --git a/apps/coordinator-api/src/app/routers/marketplace_performance.py b/apps/coordinator-api/src/app/routers/marketplace_performance.py index 9361129b..f7ee29f6 100755 --- a/apps/coordinator-api/src/app/routers/marketplace_performance.py +++ b/apps/coordinator-api/src/app/routers/marketplace_performance.py @@ -1,17 +1,13 @@ - - """ Marketplace Performance Optimization API Endpoints REST API for managing distributed processing, GPU optimization, caching, and scaling """ -import logging from typing import Any -from fastapi import APIRouter, BackgroundTasks, HTTPException -from pydantic import BaseModel, Field +from aitbc import get_logger -logger = logging.getLogger(__name__) +logger = get_logger(__name__) import os import sys diff --git a/apps/coordinator-api/src/app/routers/miner.py b/apps/coordinator-api/src/app/routers/miner.py index 375e767a..b57331e5 100755 --- a/apps/coordinator-api/src/app/routers/miner.py +++ b/apps/coordinator-api/src/app/routers/miner.py @@ -1,4 +1,3 @@ -import logging from datetime import datetime from typing import Annotated, Any @@ -7,6 +6,7 @@ from slowapi import Limiter from slowapi.util import get_remote_address from sqlalchemy.orm import Session +from aitbc import get_logger from ..config import settings from ..deps import get_miner_id, require_miner_key from ..schemas import AssignedJob, JobFailSubmit, JobResultSubmit, JobState, MinerHeartbeat, MinerRegister, PollRequest @@ -14,7 +14,7 @@ from ..services import JobService, MinerService from ..services.receipts import ReceiptService from ..storage import get_session -logger = logging.getLogger(__name__) +logger = get_logger(__name__) limiter = Limiter(key_func=get_remote_address) diff --git a/apps/coordinator-api/src/app/routers/monitoring_dashboard.py b/apps/coordinator-api/src/app/routers/monitoring_dashboard.py index dc737c8c..301ccf90 100755 --- a/apps/coordinator-api/src/app/routers/monitoring_dashboard.py +++ b/apps/coordinator-api/src/app/routers/monitoring_dashboard.py @@ -7,11 +7,11 @@ import asyncio from datetime import datetime from typing import Any -import httpx from fastapi import APIRouter -import logging -logger = logging.getLogger(__name__) +from aitbc import get_logger, AITBCHTTPClient, NetworkError + +logger = get_logger(__name__) router = APIRouter() @@ -209,32 +209,31 @@ async def collect_all_health_data() -> dict[str, Any]: "timestamp": datetime.utcnow().isoformat(), } else: - health_data[service_id] = result return health_data -async def check_service_health(client: httpx.AsyncClient, service_id: str, service_info: dict[str, Any]) -> dict[str, Any]: - """Check health of a specific service""" +async def check_service_health(service_name: str, service_config: dict[str, Any]) -> dict[str, Any]: + """ + Check health status of a specific service + """ try: - response = await client.get(f"{service_info['url']}/health") - - if response.status_code == 200: - health_data = response.json() - health_data["http_status"] = response.status_code - health_data["response_time"] = str(response.elapsed.total_seconds()) + "s" - return health_data - else: - return { - "status": "unhealthy", - "http_status": response.status_code, - "error": f"HTTP {response.status_code}", - "timestamp": datetime.utcnow().isoformat(), - } - - except httpx.TimeoutException: - return {"status": "unhealthy", "error": "timeout", "timestamp": datetime.utcnow().isoformat()} - except httpx.ConnectError: + client = AITBCHTTPClient(timeout=5.0) + health_url = f"{service_config['url']}/health" + response = client.get(health_url) + return { + "status": "healthy", + "response_time": 0.1, # Placeholder - would be measured + "last_check": datetime.utcnow().isoformat(), + "details": response, + } + except NetworkError as e: + logger.warning(f"Service {service_name} health check failed: {e}") + return { + "status": "unhealthy", + "error": str(e), + "last_check": datetime.utcnow().isoformat(), + } return {"status": "unhealthy", "error": "connection refused", "timestamp": datetime.utcnow().isoformat()} except Exception as e: return {"status": "unhealthy", "error": str(e), "timestamp": datetime.utcnow().isoformat()} diff --git a/apps/coordinator-api/src/app/routers/multi_modal_rl.py b/apps/coordinator-api/src/app/routers/multi_modal_rl.py index aab8d640..9e9f08d5 100755 --- a/apps/coordinator-api/src/app/routers/multi_modal_rl.py +++ b/apps/coordinator-api/src/app/routers/multi_modal_rl.py @@ -7,14 +7,15 @@ Multi-Modal Fusion and Advanced RL API Endpoints REST API for multi-modal agent fusion and advanced reinforcement learning """ -import logging from datetime import datetime from typing import Any from fastapi import APIRouter, Depends, HTTPException, Query, WebSocket, WebSocketDisconnect from pydantic import BaseModel, Field -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from ..domain.agent_performance import AgentCapability, CreativeCapability, FusionModel, ReinforcementLearningConfig from ..services.advanced_reinforcement_learning import ( diff --git a/apps/coordinator-api/src/app/routers/openclaw_enhanced.py b/apps/coordinator-api/src/app/routers/openclaw_enhanced.py index 9a094a16..27feeb57 100755 --- a/apps/coordinator-api/src/app/routers/openclaw_enhanced.py +++ b/apps/coordinator-api/src/app/routers/openclaw_enhanced.py @@ -7,9 +7,9 @@ OpenClaw Integration Enhancement API Router - Phase 6.6 REST API endpoints for advanced agent orchestration, edge computing integration, and ecosystem development """ -import logging +from aitbc import get_logger -logger = logging.getLogger(__name__) +logger = get_logger(__name__) from fastapi import APIRouter, Depends, HTTPException diff --git a/apps/coordinator-api/src/app/routers/openclaw_enhanced_health.py b/apps/coordinator-api/src/app/routers/openclaw_enhanced_health.py index ec992b97..08ec9a55 100755 --- a/apps/coordinator-api/src/app/routers/openclaw_enhanced_health.py +++ b/apps/coordinator-api/src/app/routers/openclaw_enhanced_health.py @@ -9,17 +9,17 @@ import sys from datetime import datetime from typing import Any -import logging - import psutil from fastapi import APIRouter, Depends from sqlalchemy.orm import Session +from aitbc import get_logger + from ..services.openclaw_enhanced import OpenClawEnhancedService from ..storage import get_session router = APIRouter() -logger = logging.getLogger(__name__) +logger = get_logger(__name__) @router.get("/health", tags=["health"], summary="OpenClaw Enhanced Service Health") diff --git a/apps/coordinator-api/src/app/routers/openclaw_enhanced_simple.py b/apps/coordinator-api/src/app/routers/openclaw_enhanced_simple.py index 20672f11..cfdfc19a 100755 --- a/apps/coordinator-api/src/app/routers/openclaw_enhanced_simple.py +++ b/apps/coordinator-api/src/app/routers/openclaw_enhanced_simple.py @@ -7,10 +7,11 @@ OpenClaw Enhanced API Router - Simplified Version REST API endpoints for OpenClaw integration features """ -import logging from typing import Any -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel, Field diff --git a/apps/coordinator-api/src/app/routers/reputation.py b/apps/coordinator-api/src/app/routers/reputation.py index 576b74f4..13a336fd 100755 --- a/apps/coordinator-api/src/app/routers/reputation.py +++ b/apps/coordinator-api/src/app/routers/reputation.py @@ -7,14 +7,15 @@ Reputation Management API Endpoints REST API for agent reputation, trust scores, and economic profiles """ -import logging from datetime import datetime, timedelta from typing import Any, Dict, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel, Field -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from sqlmodel import Field, func, select diff --git a/apps/coordinator-api/src/app/routers/rewards.py b/apps/coordinator-api/src/app/routers/rewards.py index d8bd24dd..61b7635f 100755 --- a/apps/coordinator-api/src/app/routers/rewards.py +++ b/apps/coordinator-api/src/app/routers/rewards.py @@ -7,14 +7,15 @@ Reward System API Endpoints REST API for agent rewards, incentives, and performance-based earnings """ -import logging from datetime import datetime, timedelta from typing import Any, Dict, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel, Field -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from ..domain.rewards import AgentRewardProfile, RewardStatus, RewardTier, RewardType from ..services.reward_service import RewardEngine diff --git a/apps/coordinator-api/src/app/routers/trading.py b/apps/coordinator-api/src/app/routers/trading.py index 69bba141..a639d366 100755 --- a/apps/coordinator-api/src/app/routers/trading.py +++ b/apps/coordinator-api/src/app/routers/trading.py @@ -7,14 +7,15 @@ P2P Trading Protocol API Endpoints REST API for agent-to-agent trading, matching, negotiation, and settlement """ -import logging from datetime import datetime, timedelta from typing import Any, Dict, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel, Field -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) from ..domain.trading import ( NegotiationStatus, diff --git a/apps/coordinator-api/src/app/routers/web_vitals.py b/apps/coordinator-api/src/app/routers/web_vitals.py index bc43dfb0..39f009d1 100755 --- a/apps/coordinator-api/src/app/routers/web_vitals.py +++ b/apps/coordinator-api/src/app/routers/web_vitals.py @@ -3,12 +3,12 @@ Web Vitals API endpoint for collecting performance metrics """ -import logging - from fastapi import APIRouter, HTTPException from pydantic import BaseModel -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) router = APIRouter() diff --git a/apps/coordinator-api/src/app/services/blockchain.py b/apps/coordinator-api/src/app/services/blockchain.py index 4be65c7a..a9578ef8 100755 --- a/apps/coordinator-api/src/app/services/blockchain.py +++ b/apps/coordinator-api/src/app/services/blockchain.py @@ -2,12 +2,11 @@ Blockchain service for AITBC token operations """ -import logging import re -import httpx +from aitbc import get_logger, AITBCHTTPClient, NetworkError -logger = logging.getLogger(__name__) +logger = get_logger(__name__) from ..config import settings @@ -34,17 +33,16 @@ def validate_address(address: str) -> bool: async def mint_tokens(address: str, amount: float) -> dict: """Mint AITBC tokens to an address""" - async with httpx.AsyncClient() as client: - response = await client.post( + client = AITBCHTTPClient(timeout=10.0) + try: + response = client.post( f"{BLOCKCHAIN_RPC}/admin/mintFaucet", json={"address": address, "amount": amount}, headers={"X-Api-Key": settings.admin_api_keys[0] if settings.admin_api_keys else ""}, ) - - if response.status_code == 200: - return response.json() - else: - raise Exception(f"Failed to mint tokens: {response.text}") + return response + except NetworkError as e: + raise Exception(f"Failed to mint tokens: {e}") def get_balance(address: str) -> float | None: diff --git a/apps/coordinator-api/src/app/services/payments.py b/apps/coordinator-api/src/app/services/payments.py index a7731fe5..23530b0e 100755 --- a/apps/coordinator-api/src/app/services/payments.py +++ b/apps/coordinator-api/src/app/services/payments.py @@ -8,15 +8,18 @@ from sqlalchemy.orm import Session import logging from datetime import datetime, timedelta +from __future__ import annotations + import httpx -from sqlmodel import select + +from aitbc import get_logger + +logger = get_logger(__name__) from ..domain.payment import JobPayment, PaymentEscrow from ..schemas import JobPaymentCreate, JobPaymentView from ..storage import get_session -logger = logging.getLogger(__name__) - class PaymentService: """Service for handling job payments""" diff --git a/cli/aitbc_cli.py b/cli/aitbc_cli.py index 9163b935..496493e1 100755 --- a/cli/aitbc_cli.py +++ b/cli/aitbc_cli.py @@ -742,6 +742,9 @@ def get_transactions(wallet_name: str, keystore_dir: Path = DEFAULT_KEYSTORE_DIR except Exception as e: print(f"Error: {e}") return [] + except Exception as e: + print(f"Error: {e}") + return [] def get_balance(wallet_name: str, rpc_url: str = DEFAULT_RPC_URL) -> Optional[Dict]: @@ -808,12 +811,11 @@ def get_network_status(rpc_url: str = DEFAULT_RPC_URL) -> Optional[Dict]: """Get network status and health""" try: # Get head block - head_response = requests.get(f"{rpc_url}/rpc/head") - if head_response.status_code == 200: - return head_response.json() - else: - print(f"Error getting network status: {head_response.text}") - return None + http_client = AITBCHTTPClient(base_url=rpc_url, timeout=30) + return http_client.get("/rpc/head") + except NetworkError as e: + print(f"Error getting network status: {e}") + return None except Exception as e: print(f"Error: {e}") return None @@ -824,17 +826,16 @@ def get_blockchain_analytics(analytics_type: str, limit: int = 10, rpc_url: str try: if analytics_type == "blocks": # Get recent blocks analytics - response = requests.get(f"{rpc_url}/rpc/head") - if response.status_code == 200: - head = response.json() - return { - "type": "blocks", - "current_height": head.get("height", 0), - "latest_block": head.get("hash", ""), - "timestamp": head.get("timestamp", ""), - "tx_count": head.get("tx_count", 0), - "status": "Active" - } + http_client = AITBCHTTPClient(base_url=rpc_url, timeout=30) + head = http_client.get("/rpc/head") + return { + "type": "blocks", + "current_height": head.get("height", 0), + "latest_block": head.get("hash", ""), + "timestamp": head.get("timestamp", ""), + "tx_count": head.get("tx_count", 0), + "status": "Active" + } elif analytics_type == "supply": # Get total supply info @@ -980,12 +981,9 @@ def mining_operations(action: str, **kwargs) -> Optional[Dict]: if action == "status": # Query actual blockchain status from RPC try: - response = requests.get(f"{rpc_url}/rpc/head", timeout=5) - if response.status_code == 200: - head_data = response.json() - actual_height = head_data.get('height', 0) - else: - actual_height = 0 + http_client = AITBCHTTPClient(base_url=rpc_url, timeout=5) + head_data = http_client.get("/rpc/head") + actual_height = head_data.get('height', 0) except Exception: actual_height = 0 @@ -1001,12 +999,9 @@ def mining_operations(action: str, **kwargs) -> Optional[Dict]: elif action == "rewards": # Query actual blockchain height for reward calculation try: - response = requests.get(f"{rpc_url}/rpc/head", timeout=5) - if response.status_code == 200: - head_data = response.json() - actual_height = head_data.get('height', 0) - else: - actual_height = 0 + http_client = AITBCHTTPClient(base_url=rpc_url, timeout=5) + head_data = http_client.get("/rpc/head") + actual_height = head_data.get('height', 0) except Exception: actual_height = 0 @@ -1441,12 +1436,11 @@ def get_network_status(rpc_url: str = DEFAULT_RPC_URL) -> Optional[Dict]: """Get network status and health""" try: # Get head block - head_response = requests.get(f"{rpc_url}/rpc/head") - if head_response.status_code == 200: - return head_response.json() - else: - print(f"Error getting network status: {head_response.text}") - return None + http_client = AITBCHTTPClient(base_url=rpc_url, timeout=30) + return http_client.get("/rpc/head") + except NetworkError as e: + print(f"Error getting network status: {e}") + return None except Exception as e: print(f"Error: {e}") return None @@ -1457,17 +1451,16 @@ def get_blockchain_analytics(analytics_type: str, limit: int = 10, rpc_url: str try: if analytics_type == "blocks": # Get recent blocks analytics - response = requests.get(f"{rpc_url}/rpc/head") - if response.status_code == 200: - head = response.json() - return { - "type": "blocks", - "current_height": head.get("height", 0), - "latest_block": head.get("hash", ""), - "timestamp": head.get("timestamp", ""), - "tx_count": head.get("tx_count", 0), - "status": "Active" - } + http_client = AITBCHTTPClient(base_url=rpc_url, timeout=30) + head = http_client.get("/rpc/head") + return { + "type": "blocks", + "current_height": head.get("height", 0), + "latest_block": head.get("hash", ""), + "timestamp": head.get("timestamp", ""), + "tx_count": head.get("tx_count", 0), + "status": "Active" + } elif analytics_type == "supply": # Get total supply info diff --git a/cli/aitbc_cli/commands/cross_chain.py b/cli/aitbc_cli/commands/cross_chain.py index 7eba4916..c4931c58 100755 --- a/cli/aitbc_cli/commands/cross_chain.py +++ b/cli/aitbc_cli/commands/cross_chain.py @@ -1,13 +1,20 @@ """Cross-chain trading commands for AITBC CLI""" import click -import httpx import json from typing import Optional from tabulate import tabulate from ..config import get_config from ..utils import success, error, output +# Import shared modules +from aitbc.aitbc_logging import get_logger +from aitbc.http_client import AITBCHTTPClient +from aitbc.exceptions import NetworkError + +# Initialize logger +logger = get_logger(__name__) + @click.group() def cross_chain(): @@ -27,7 +34,7 @@ def rates(ctx, from_chain: Optional[str], to_chain: Optional[str], config = ctx.obj['config'] try: - with httpx.Client() as client: + with AITBCHTTPClient() as client: # Get rates from cross-chain exchange response = client.get( f"http://localhost:8001/api/v1/cross-chain/rates", @@ -96,7 +103,7 @@ def swap(ctx, from_chain: str, to_chain: str, from_token: str, to_token: str, if not min_amount: # Get rate first try: - with httpx.Client() as client: + with AITBCHTTPClient() as client: response = client.get( f"http://localhost:8001/api/v1/cross-chain/rates", timeout=10 @@ -123,26 +130,19 @@ def swap(ctx, from_chain: str, to_chain: str, from_token: str, to_token: str, } try: - with httpx.Client() as client: - response = client.post( - f"http://localhost:8001/api/v1/cross-chain/swap", - json=swap_data, - timeout=30 - ) - - if response.status_code == 200: - swap_result = response.json() - success("Cross-chain swap created successfully!") - output({ - "Swap ID": swap_result.get('swap_id'), - "From Chain": swap_result.get('from_chain'), - "To Chain": swap_result.get('to_chain'), - "Amount": swap_result.get('amount'), - "Expected Amount": swap_result.get('expected_amount'), - "Rate": swap_result.get('rate'), - "Total Fees": swap_result.get('total_fees'), - "Status": swap_result.get('status') - }, ctx.obj['output_format']) + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1/cross-chain", timeout=30) + swap_result = http_client.post("/swap", json=swap_data) + success("Cross-chain swap created successfully!") + output({ + "Swap ID": swap_result.get('swap_id'), + "From Chain": swap_result.get('from_chain'), + "To Chain": swap_result.get('to_chain'), + "Amount": swap_result.get('amount'), + "Expected Amount": swap_result.get('expected_amount'), + "Rate": swap_result.get('rate'), + "Total Fees": swap_result.get('total_fees'), + "Status": swap_result.get('status') + }, ctx.obj['output_format']) # Show swap ID for tracking success(f"Track swap with: aitbc cross-chain status {swap_result.get('swap_id')}") @@ -160,34 +160,44 @@ def swap(ctx, from_chain: str, to_chain: str, from_token: str, to_token: str, def status(ctx, swap_id: str): """Check cross-chain swap status""" try: - with httpx.Client() as client: - response = client.get( - f"http://localhost:8001/api/v1/cross-chain/swap/{swap_id}", - timeout=10 - ) - - if response.status_code == 200: - swap_data = response.json() - success(f"Swap Status: {swap_data.get('status', 'unknown')}") - - # Display swap details - details = { - "Swap ID": swap_data.get('swap_id'), - "From Chain": swap_data.get('from_chain'), - "To Chain": swap_data.get('to_chain'), - "From Token": swap_data.get('from_token'), - "To Token": swap_data.get('to_token'), - "Amount": swap_data.get('amount'), - "Expected Amount": swap_data.get('expected_amount'), - "Actual Amount": swap_data.get('actual_amount'), - "Status": swap_data.get('status'), - "Created At": swap_data.get('created_at'), - "Completed At": swap_data.get('completed_at'), - "Bridge Fee": swap_data.get('bridge_fee'), - "From Tx Hash": swap_data.get('from_tx_hash'), - "To Tx Hash": swap_data.get('to_tx_hash') - } - + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + swap_data = http_client.get(f"/cross-chain/swap/{swap_id}") + success(f"Swap Status: {swap_data.get('status', 'unknown')}") + + # Display swap details + details = { + "Swap ID": swap_data.get('swap_id'), + "From Chain": swap_data.get('from_chain'), + "To Chain": swap_data.get('to_chain'), + "From Token": swap_data.get('from_token'), + "To Token": swap_data.get('to_token'), + "Amount": swap_data.get('amount'), + "Expected Amount": swap_data.get('expected_amount'), + "Actual Amount": swap_data.get('actual_amount'), + "Status": swap_data.get('status'), + "Created At": swap_data.get('created_at'), + "Completed At": swap_data.get('completed_at'), + "Bridge Fee": swap_data.get('bridge_fee'), + "From Tx Hash": swap_data.get('from_tx_hash'), + "To Tx Hash": swap_data.get('to_tx_hash') + } + + output(details, ctx.obj['output_format']) + + # Show additional status info + if swap_data.get('status') == 'completed': + success("✅ Swap completed successfully!") + elif swap_data.get('status') == 'failed': + error("❌ Swap failed") + if swap_data.get('error_message'): + error(f"Error: {swap_data['error_message']}") + elif swap_data.get('status') == 'pending': + success("⏳ Swap is pending...") + elif swap_data.get('status') == 'executing': + success("🔄 Swap is executing...") + elif swap_data.get('status') == 'refunded': + success("💰 Swap was refunded") + except NetworkError as e: output(details, ctx.obj['output_format']) # Show additional status info @@ -223,19 +233,12 @@ def swaps(ctx, user_address: Optional[str], status: Optional[str], limit: int): params['status'] = status try: - with httpx.Client() as client: - response = client.get( - f"http://localhost:8001/api/v1/cross-chain/swaps", - params=params, - timeout=10 - ) - - if response.status_code == 200: - swaps_data = response.json() - swaps = swaps_data.get('swaps', []) - - if swaps: - success(f"Found {len(swaps)} cross-chain swaps:") + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + swaps_data = http_client.get("/cross-chain/swaps", params=params) + swaps = swaps_data.get('swaps', []) + + if swaps: + success(f"Found {len(swaps)} cross-chain swaps:") # Create table swap_table = [] @@ -295,23 +298,16 @@ def bridge(ctx, source_chain: str, target_chain: str, token: str, } try: - with httpx.Client() as client: - response = client.post( - f"http://localhost:8001/api/v1/cross-chain/bridge", - json=bridge_data, - timeout=30 - ) - - if response.status_code == 200: - bridge_result = response.json() - success("Cross-chain bridge created successfully!") - output({ - "Bridge ID": bridge_result.get('bridge_id'), - "Source Chain": bridge_result.get('source_chain'), - "Target Chain": bridge_result.get('target_chain'), - "Token": bridge_result.get('token'), - "Amount": bridge_result.get('amount'), - "Bridge Fee": bridge_result.get('bridge_fee'), + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=30) + bridge_result = http_client.post("/cross-chain/bridge", json=bridge_data) + success("Cross-chain bridge created successfully!") + output({ + "Bridge ID": bridge_result.get('bridge_id'), + "Source Chain": bridge_result.get('source_chain'), + "Target Chain": bridge_result.get('target_chain'), + "Token": bridge_result.get('token'), + "Amount": bridge_result.get('amount'), + "Bridge Fee": bridge_result.get('bridge_fee'), "Status": bridge_result.get('status') }, ctx.obj['output_format']) @@ -331,15 +327,9 @@ def bridge(ctx, source_chain: str, target_chain: str, token: str, def bridge_status(ctx, bridge_id: str): """Check cross-chain bridge status""" try: - with httpx.Client() as client: - response = client.get( - f"http://localhost:8001/api/v1/cross-chain/bridge/{bridge_id}", - timeout=10 - ) - - if response.status_code == 200: - bridge_data = response.json() - success(f"Bridge Status: {bridge_data.get('status', 'unknown')}") + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + bridge_data = http_client.get(f"/cross-chain/bridge/{bridge_id}") + success(f"Bridge Status: {bridge_data.get('status', 'unknown')}") # Display bridge details details = { @@ -383,7 +373,7 @@ def bridge_status(ctx, bridge_id: str): def pools(ctx): """Show cross-chain liquidity pools""" try: - with httpx.Client() as client: + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) response = client.get( f"http://localhost:8001/api/v1/cross-chain/pools", timeout=10 @@ -426,7 +416,7 @@ def pools(ctx): def stats(ctx): """Show cross-chain trading statistics""" try: - with httpx.Client() as client: + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) response = client.get( f"http://localhost:8001/api/v1/cross-chain/stats", timeout=10 diff --git a/cli/aitbc_cli/commands/exchange.py b/cli/aitbc_cli/commands/exchange.py index 3d822185..4c97b536 100755 --- a/cli/aitbc_cli/commands/exchange.py +++ b/cli/aitbc_cli/commands/exchange.py @@ -1,7 +1,6 @@ """Exchange integration commands for AITBC CLI""" import click -import httpx import json import os from pathlib import Path @@ -10,6 +9,14 @@ from datetime import datetime from ..utils import output, error, success, warning from ..config import get_config +# Import shared modules +from aitbc.aitbc_logging import get_logger +from aitbc.http_client import AITBCHTTPClient +from aitbc.exceptions import NetworkError + +# Initialize logger +logger = get_logger(__name__) + @click.group() def exchange(): @@ -368,20 +375,14 @@ def status(ctx, exchange_name: str): config = ctx.obj['config'] try: - with httpx.Client() as client: - response = client.get( - f"{config.coordinator_url}/v1/exchange/rates", - timeout=10 - ) - - if response.status_code == 200: - rates_data = response.json() - success("Current exchange rates:") - output(rates_data, ctx.obj['output_format']) - else: - error(f"Failed to get exchange rates: {response.status_code}") - except Exception as e: + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + rates_data = http_client.get(f"/exchange/rates") + success("Current exchange rates:") + output(rates_data, ctx.obj['output_format']) + except NetworkError as e: error(f"Network error: {e}") + except Exception as e: + error(f"Error: {e}") @exchange.command() @@ -410,55 +411,36 @@ def create_payment(ctx, aitbc_amount: Optional[float], btc_amount: Optional[floa # Get exchange rates to calculate missing amount try: - with httpx.Client() as client: - rates_response = client.get( - f"{config.coordinator_url}/v1/exchange/rates", - timeout=10 - ) - - if rates_response.status_code != 200: - error("Failed to get exchange rates") - return - - rates = rates_response.json() - btc_to_aitbc = rates.get('btc_to_aitbc', 100000) - - # Calculate missing amount - if aitbc_amount and not btc_amount: - btc_amount = aitbc_amount / btc_to_aitbc - elif btc_amount and not aitbc_amount: - aitbc_amount = btc_amount * btc_to_aitbc - - # Prepare payment request - payment_data = { - "user_id": user_id or "cli_user", - "aitbc_amount": aitbc_amount, - "btc_amount": btc_amount - } - - if notes: - payment_data["notes"] = notes - - # Create payment - response = client.post( - f"{config.coordinator_url}/v1/exchange/create-payment", - json=payment_data, - timeout=10 - ) - - if response.status_code == 200: - payment = response.json() - success(f"Payment created: {payment.get('payment_id')}") - success(f"Send {btc_amount:.8f} BTC to: {payment.get('payment_address')}") - success(f"Expires at: {payment.get('expires_at')}") - output(payment, ctx.obj['output_format']) - else: - error(f"Failed to create payment: {response.status_code}") - if response.text: - error(f"Error details: {response.text}") - - except Exception as e: + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + rates = http_client.get("/exchange/rates") + btc_to_aitbc = rates.get('btc_to_aitbc', 100000) + + # Calculate missing amount + if aitbc_amount and not btc_amount: + btc_amount = aitbc_amount / btc_to_aitbc + elif btc_amount and not aitbc_amount: + aitbc_amount = btc_amount * btc_to_aitbc + + # Prepare payment request + payment_data = { + "user_id": user_id or "cli_user", + "aitbc_amount": aitbc_amount, + "btc_amount": btc_amount + } + + if notes: + payment_data["notes"] = notes + + # Create payment + payment = http_client.post("/exchange/create-payment", json=payment_data) + success(f"Payment created: {payment.get('payment_id')}") + success(f"Send {btc_amount:.8f} BTC to: {payment.get('payment_address')}") + success(f"Expires at: {payment.get('expires_at')}") + output(payment, ctx.obj['output_format']) + except NetworkError as e: error(f"Network error: {e}") + except Exception as e: + error(f"Error: {e}") @exchange.command() @@ -469,31 +451,25 @@ def payment_status(ctx, payment_id: str): config = ctx.obj['config'] try: - with httpx.Client() as client: - response = client.get( - f"{config.coordinator_url}/v1/exchange/payment-status/{payment_id}", - timeout=10 - ) - - if response.status_code == 200: - status_data = response.json() - status = status_data.get('status', 'unknown') - - if status == 'confirmed': - success(f"Payment {payment_id} is confirmed!") - success(f"AITBC amount: {status_data.get('aitbc_amount', 0)}") - elif status == 'pending': - success(f"Payment {payment_id} is pending confirmation") - elif status == 'expired': - error(f"Payment {payment_id} has expired") - else: - success(f"Payment {payment_id} status: {status}") - - output(status_data, ctx.obj['output_format']) - else: - error(f"Failed to get payment status: {response.status_code}") - except Exception as e: + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + status_data = http_client.get(f"/exchange/payment-status/{payment_id}") + status = status_data.get('status', 'unknown') + + if status == 'confirmed': + success(f"Payment {payment_id} is confirmed!") + success(f"AITBC amount: {status_data.get('aitbc_amount', 0)}") + elif status == 'pending': + success(f"Payment {payment_id} is pending confirmation") + elif status == 'expired': + error(f"Payment {payment_id} has expired") + else: + success(f"Payment {payment_id} status: {status}") + + output(status_data, ctx.obj['output_format']) + except NetworkError as e: error(f"Network error: {e}") + except Exception as e: + error(f"Error: {e}") @exchange.command() @@ -503,20 +479,14 @@ def market_stats(ctx): config = ctx.obj['config'] try: - with httpx.Client() as client: - response = client.get( - f"{config.coordinator_url}/v1/exchange/market-stats", - timeout=10 - ) - - if response.status_code == 200: - stats = response.json() - success("Exchange market statistics:") - output(stats, ctx.obj['output_format']) - else: - error(f"Failed to get market stats: {response.status_code}") - except Exception as e: + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + stats = http_client.get("/exchange/market-stats") + success("Exchange market statistics:") + output(stats, ctx.obj['output_format']) + except NetworkError as e: error(f"Network error: {e}") + except Exception as e: + error(f"Error: {e}") @exchange.group() @@ -532,20 +502,14 @@ def balance(ctx): config = ctx.obj['config'] try: - with httpx.Client() as client: - response = client.get( - f"{config.coordinator_url}/exchange/wallet/balance", - timeout=10 - ) - - if response.status_code == 200: - balance_data = response.json() - success("Bitcoin wallet balance:") - output(balance_data, ctx.obj['output_format']) - else: - error(f"Failed to get wallet balance: {response.status_code}") - except Exception as e: + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + balance_data = http_client.get("/exchange/wallet/balance") + success("Bitcoin wallet balance:") + output(balance_data, ctx.obj['output_format']) + except NetworkError as e: error(f"Network error: {e}") + except Exception as e: + error(f"Error: {e}") @wallet.command() @@ -555,20 +519,14 @@ def info(ctx): config = ctx.obj['config'] try: - with httpx.Client() as client: - response = client.get( - f"{config.coordinator_url}/exchange/wallet/info", - timeout=10 - ) - - if response.status_code == 200: - wallet_info = response.json() - success("Bitcoin wallet information:") - output(wallet_info, ctx.obj['output_format']) - else: - error(f"Failed to get wallet info: {response.status_code}") - except Exception as e: + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + wallet_info = http_client.get("/exchange/wallet/info") + success("Bitcoin wallet information:") + output(wallet_info, ctx.obj['output_format']) + except NetworkError as e: error(f"Network error: {e}") + except Exception as e: + error(f"Error: {e}") @exchange.command() @@ -591,24 +549,15 @@ def register(ctx, name: str, api_key: str, api_secret: Optional[str], sandbox: b exchange_data["api_secret"] = api_secret try: - with httpx.Client() as client: - response = client.post( - f"{config.coordinator_url}/v1/exchange/register", - json=exchange_data, - timeout=10 - ) - - if response.status_code == 200: - result = response.json() - success(f"Exchange '{name}' registered successfully!") - success(f"Exchange ID: {result.get('exchange_id')}") - output(result, ctx.obj['output_format']) - else: - error(f"Failed to register exchange: {response.status_code}") - if response.text: - error(f"Error details: {response.text}") - except Exception as e: + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + result = http_client.post("/exchange/register", json=exchange_data) + success(f"Exchange '{name}' registered successfully!") + success(f"Exchange ID: {result.get('exchange_id')}") + output(result, ctx.obj['output_format']) + except NetworkError as e: error(f"Network error: {e}") + except Exception as e: + error(f"Error: {e}") @exchange.command() @@ -640,8 +589,8 @@ def create_pair(ctx, pair: str, base_asset: str, quote_asset: str, pair_data["max_order_size"] = max_order_size try: - with httpx.Client() as client: - response = client.post( + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + response = http_client.post( f"{config.coordinator_url}/v1/exchange/create-pair", json=pair_data, timeout=10 @@ -679,8 +628,8 @@ def start_trading(ctx, pair: str, exchange: Optional[str], order_type: tuple): trading_data["exchange"] = exchange try: - with httpx.Client() as client: - response = client.post( + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + response = http_client.post( f"{config.coordinator_url}/v1/exchange/start-trading", json=trading_data, timeout=10 @@ -717,8 +666,8 @@ def list_pairs(ctx, pair: Optional[str], exchange: Optional[str], status: Option params["status"] = status try: - with httpx.Client() as client: - response = client.get( + http_client = AITBCHTTPClient(base_url="http://localhost:8001/api/v1", timeout=10) + response = http_client.get( f"{config.coordinator_url}/v1/exchange/pairs", params=params, timeout=10 diff --git a/cli/aitbc_cli/commands/exchange_island.py b/cli/aitbc_cli/commands/exchange_island.py index bba933a2..ead1a7e3 100644 --- a/cli/aitbc_cli/commands/exchange_island.py +++ b/cli/aitbc_cli/commands/exchange_island.py @@ -17,6 +17,14 @@ from ..utils.island_credentials import ( get_island_id, get_island_name ) +# Import shared modules +from aitbc.aitbc_logging import get_logger +from aitbc.http_client import AITBCHTTPClient +from aitbc.exceptions import NetworkError + +# Initialize logger +logger = get_logger(__name__) + # Supported trading pairs SUPPORTED_PAIRS = ['AIT/BTC', 'AIT/ETH'] diff --git a/cli/aitbc_cli/commands/wallet.py b/cli/aitbc_cli/commands/wallet.py index e0f7423c..ccaa2955 100644 --- a/cli/aitbc_cli/commands/wallet.py +++ b/cli/aitbc_cli/commands/wallet.py @@ -1,7 +1,6 @@ """Wallet commands for AITBC CLI""" import click -import httpx import json import os import shutil @@ -12,6 +11,15 @@ from datetime import datetime, timedelta from ..utils import output, error, success import getpass +# Import shared modules +from aitbc.aitbc_logging import get_logger +from aitbc.http_client import AITBCHTTPClient +from aitbc.exceptions import NetworkError +from aitbc.constants import KEYSTORE_DIR + +# Initialize logger +logger = get_logger(__name__) + def encrypt_value(value: str, password: str) -> str: """Simple encryption for wallet data (placeholder)""" @@ -523,16 +531,13 @@ def balance(ctx): # Try to get balance from blockchain if available if config: try: - with httpx.Client() as client: - response = client.get( - f"{config.coordinator_url.replace('/api', '')}/rpc/balance/{wallet_data['address']}", - timeout=5, - ) - - if response.status_code == 200: - blockchain_balance = response.json().get("balance", 0) - output( - { + http_client = AITBCHTTPClient( + base_url=config.coordinator_url.replace('/api', ''), + timeout=5 + ) + blockchain_balance = http_client.get(f"/rpc/balance/{wallet_data['address']}") + output( + { "wallet": wallet_name, "address": wallet_data["address"], "local_balance": wallet_data.get("balance", 0), @@ -737,27 +742,25 @@ def send(ctx, to_address: str, amount: float, description: Optional[str]): # Try to send via blockchain if config: try: - with httpx.Client() as client: - response = client.post( - f"{config.coordinator_url.replace('/api', '')}/rpc/transactions", - json={ - "from": wallet_data["address"], - "to": to_address, - "amount": amount, - "description": description or "", - }, - headers={"X-Api-Key": getattr(config, "api_key", "") or ""}, - ) + http_client = AITBCHTTPClient( + base_url=config.coordinator_url.replace('/api', ''), + timeout=30, + headers={"X-Api-Key": getattr(config, "api_key", "") or ""} + ) + result = http_client.post( + "/rpc/transactions", + json={ + "from": wallet_data["address"], + "to": to_address, + "amount": amount, + "description": description or "", + } + ) - if response.status_code == 201: - tx = response.json() - # Update local wallet - transaction = { - "type": "send", - "amount": -amount, - "to_address": to_address, - "tx_hash": tx.get("hash"), - "description": description or "", + if result: + success(f"Transaction sent: {result.get('transaction_hash', 'N/A')}") + output(result, ctx.obj.get("output_format", "table")) + return "timestamp": datetime.now().isoformat(), }