From 119d0f42c0e47e2df50389efb31d47e3185d802e Mon Sep 17 00:00:00 2001 From: aitbc Date: Sat, 25 Apr 2026 07:04:57 +0200 Subject: [PATCH] Migrate CLI and Python packages to centralized aitbc package utilities CLI migration: - Migrate 11 CLI files from old import pattern to centralized aitbc imports - wallet.py, exchange.py, gpu_marketplace.py, exchange_island.py, monitor.py, cross_chain.py - aitbc_cli.py, handlers (account.py, bridge.py, pool_hub.py), utils (wallet_daemon_client.py) - Replace 'from aitbc.aitbc_logging import' with 'from aitbc import get_logger' - Replace 'from aitbc.http_client import' with 'from aitbc import AITBCHTTPClient' - Replace 'from aitbc.exceptions import' with 'from aitbc import NetworkError' Packages migration: - aitbc-sdk: receipts.py - migrate from httpx to AITBCHTTPClient - aitbc-agent-sdk: 5 files - migrate logging to get_logger - agent.py, compute_provider.py, compute_consumer.py, swarm_coordinator.py, platform_builder.py --- cli/aitbc_cli.py | 11 +- cli/aitbc_cli/commands/cross_chain.py | 4 +- cli/aitbc_cli/commands/exchange.py | 4 +- cli/aitbc_cli/commands/exchange_island.py | 185 ++----- cli/aitbc_cli/commands/gpu_marketplace.py | 479 ++++++++---------- cli/aitbc_cli/commands/monitor.py | 4 +- cli/aitbc_cli/commands/wallet.py | 5 +- cli/handlers/account.py | 3 +- cli/handlers/bridge.py | 3 +- cli/handlers/pool_hub.py | 3 +- cli/utils/wallet_daemon_client.py | 3 +- .../aitbc-agent-sdk/src/aitbc_agent/agent.py | 5 +- .../src/aitbc_agent/compute_consumer.py | 5 +- .../src/aitbc_agent/compute_provider.py | 5 +- .../src/aitbc_agent/platform_builder.py | 5 +- .../src/aitbc_agent/swarm_coordinator.py | 5 +- .../py/aitbc-sdk/src/aitbc_sdk/receipts.py | 12 +- 17 files changed, 282 insertions(+), 459 deletions(-) diff --git a/cli/aitbc_cli.py b/cli/aitbc_cli.py index 496493e1..4c44a808 100755 --- a/cli/aitbc_cli.py +++ b/cli/aitbc_cli.py @@ -37,12 +37,11 @@ import requests from typing import Optional, Dict, Any, List # Import shared modules -from aitbc.constants import KEYSTORE_DIR, BLOCKCHAIN_RPC_PORT, DATA_DIR -from aitbc.http_client import AITBCHTTPClient -from aitbc.exceptions import NetworkError, ValidationError, ConfigurationError -from aitbc.aitbc_logging import get_logger -from aitbc.paths import get_keystore_path, ensure_dir -from aitbc.validation import validate_address, validate_url +from aitbc import ( + KEYSTORE_DIR, BLOCKCHAIN_RPC_PORT, DATA_DIR, + AITBCHTTPClient, NetworkError, ValidationError, ConfigurationError, + get_logger, get_keystore_path, ensure_dir, validate_address, validate_url +) # Initialize logger logger = get_logger(__name__) diff --git a/cli/aitbc_cli/commands/cross_chain.py b/cli/aitbc_cli/commands/cross_chain.py index c4931c58..f1e3edee 100755 --- a/cli/aitbc_cli/commands/cross_chain.py +++ b/cli/aitbc_cli/commands/cross_chain.py @@ -8,9 +8,7 @@ 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 +from aitbc import get_logger, AITBCHTTPClient, NetworkError # Initialize logger logger = get_logger(__name__) diff --git a/cli/aitbc_cli/commands/exchange.py b/cli/aitbc_cli/commands/exchange.py index 26ebef78..5214b184 100755 --- a/cli/aitbc_cli/commands/exchange.py +++ b/cli/aitbc_cli/commands/exchange.py @@ -10,9 +10,7 @@ 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 +from aitbc import get_logger, AITBCHTTPClient, NetworkError # Initialize logger logger = get_logger(__name__) diff --git a/cli/aitbc_cli/commands/exchange_island.py b/cli/aitbc_cli/commands/exchange_island.py index 30b11dfc..ddd9adbf 100644 --- a/cli/aitbc_cli/commands/exchange_island.py +++ b/cli/aitbc_cli/commands/exchange_island.py @@ -18,9 +18,7 @@ from ..utils.island_credentials import ( ) # Import shared modules -from aitbc.aitbc_logging import get_logger -from aitbc.http_client import AITBCHTTPClient -from aitbc.exceptions import NetworkError +from aitbc import get_logger, AITBCHTTPClient, NetworkError # Initialize logger logger = get_logger(__name__) @@ -313,49 +311,6 @@ def orderbook(ctx, pair: str, limit: int): raise click.Abort() except Exception as e: error(f"Error fetching order book: {str(e)}") - raise click.Abort() - "Amount": f"{order.get('amount', 0):.4f} AIT", - "Total": f"{order.get('min_price', 0) * order.get('amount', 0):.8f} {pair.split('/')[1]}", - "User": order.get('user_id', '')[:16] + "...", - "Order": order.get('order_id', '')[:16] + "..." - }) - - output(asks_data, ctx.obj.get('output_format', 'table'), title=f"Sell Orders (Asks) - {pair}") - - # Display buy orders (bids) - if buy_orders: - bids_data = [] - for order in buy_orders[:limit]: - bids_data.append({ - "Price": f"{order.get('max_price', 0):.8f}", - "Amount": f"{order.get('amount', 0):.4f} AIT", - "Total": f"{order.get('max_price', 0) * order.get('amount', 0):.8f} {pair.split('/')[1]}", - "User": order.get('user_id', '')[:16] + "...", - "Order": order.get('order_id', '')[:16] + "..." - }) - - output(bids_data, ctx.obj.get('output_format', 'table'), title=f"Buy Orders (Bids) - {pair}") - - # Calculate spread if both exist - if sell_orders and buy_orders: - best_ask = sell_orders[0].get('min_price', 0) - best_bid = buy_orders[0].get('max_price', 0) - spread = best_ask - best_bid - if best_bid > 0: - spread_pct = (spread / best_bid) * 100 - info(f"Spread: {spread:.8f} ({spread_pct:.4f}%)") - info(f"Best Bid: {best_bid:.8f} {pair.split('/')[1]}/AIT") - info(f"Best Ask: {best_ask:.8f} {pair.split('/')[1]}/AIT") - - else: - error(f"Failed to query blockchain: {response.status_code}") - raise click.Abort() - except Exception as e: - error(f"Network error querying blockchain: {e}") - raise click.Abort() - - except Exception as e: - error(f"Error viewing order book: {str(e)}") raise click.Abort() @@ -371,7 +326,6 @@ def rates(ctx): # Query blockchain for exchange orders to calculate rates try: - import httpx rates_data = [] for pair in SUPPORTED_PAIRS: @@ -383,44 +337,28 @@ def rates(ctx): 'limit': 100 } - with httpx.Client() as client: - response = client.get( - f"{rpc_endpoint}/transactions", - params=params, - timeout=10 - ) - - if response.status_code == 200: - orders = response.json() - - # Calculate rates from order book - buy_orders = [o for o in orders if o.get('side') == 'buy'] - sell_orders = [o for o in orders if o.get('side') == 'sell'] - - # Get best bid and ask - best_bid = max([o.get('max_price', 0) for o in buy_orders]) if buy_orders else 0 - best_ask = min([o.get('min_price', float('inf')) for o in sell_orders]) if sell_orders else 0 - - # Calculate mid price - mid_price = (best_bid + best_ask) / 2 if best_bid > 0 and best_ask < float('inf') else 0 - - rates_data.append({ - "Pair": pair, - "Best Bid": f"{best_bid:.8f}" if best_bid > 0 else "N/A", - "Best Ask": f"{best_ask:.8f}" if best_ask < float('inf') else "N/A", - "Mid Price": f"{mid_price:.8f}" if mid_price > 0 else "N/A", - "Buy Orders": len(buy_orders), - "Sell Orders": len(sell_orders) - }) - else: - rates_data.append({ - "Pair": pair, - "Best Bid": "Error", - "Best Ask": "Error", - "Mid Price": "Error", - "Buy Orders": 0, - "Sell Orders": 0 - }) + http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10) + orders = http_client.get("/transactions", params=params) + + # Calculate rates from order book + buy_orders = [o for o in orders if o.get('side') == 'buy'] + sell_orders = [o for o in orders if o.get('side') == 'sell'] + + # Get best bid and ask + best_bid = max([o.get('max_price', 0) for o in buy_orders]) if buy_orders else 0 + best_ask = min([o.get('min_price', float('inf')) for o in sell_orders]) if sell_orders else 0 + + # Calculate mid price + mid_price = (best_bid + best_ask) / 2 if best_bid > 0 and best_ask < float('inf') else 0 + + rates_data.append({ + "Pair": pair, + "Best Bid": f"{best_bid:.8f}" if best_bid > 0 else "N/A", + "Best Ask": f"{best_ask:.8f}" if best_ask < float('inf') else "N/A", + "Mid Price": f"{mid_price:.8f}" if mid_price > 0 else "N/A", + "Buy Orders": len(buy_orders), + "Sell Orders": len(sell_orders) + }) output(rates_data, ctx.obj.get('output_format', 'table'), title="Exchange Rates") @@ -448,7 +386,6 @@ def orders(ctx, user: Optional[str], status: Optional[str], pair: Optional[str]) # Query blockchain for exchange orders try: - import httpx params = { 'transaction_type': 'exchange', 'island_id': island_id @@ -460,39 +397,29 @@ def orders(ctx, user: Optional[str], status: Optional[str], pair: Optional[str]) if pair: params['pair'] = pair - with httpx.Client() as client: - response = client.get( - f"{rpc_endpoint}/transactions", - params=params, - timeout=10 - ) - - if response.status_code == 200: - orders = response.json() - - if not orders: - info("No exchange orders found") - return - - # Format output - orders_data = [] - for order in orders: - orders_data.append({ - "Order ID": order.get('order_id', '')[:20] + "...", - "Pair": order.get('pair'), - "Side": order.get('side', '').upper(), - "Amount": f"{order.get('amount', 0):.4f} AIT", - "Price": f"{order.get('max_price', order.get('min_price', 0)):.8f}" if order.get('max_price') or order.get('min_price') else "Market", - "Status": order.get('status'), - "User": order.get('user_id', '')[:16] + "...", - "Created": order.get('created_at', '')[:19] - }) - - output(orders_data, ctx.obj.get('output_format', 'table'), title=f"Exchange Orders ({island_id[:16]}...)") - else: - error(f"Failed to query blockchain: {response.status_code}") - raise click.Abort() - except Exception as e: + http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10) + orders = http_client.get("/transactions", params=params) + + if not orders: + info("No exchange orders found") + return + + # Format output + orders_data = [] + for order in orders: + orders_data.append({ + "Order ID": order.get('order_id', '')[:20] + "...", + "Pair": order.get('pair'), + "Side": order.get('side', '').upper(), + "Amount": f"{order.get('amount', 0):.4f} AIT", + "Price": f"{order.get('max_price', order.get('min_price', 0)):.8f}" if order.get('max_price') or order.get('min_price') else "Market", + "Status": order.get('status'), + "User": order.get('user_id', '')[:16] + "...", + "Created": order.get('created_at', '')[:19] + }) + + output(orders_data, ctx.obj.get('output_format', 'table'), title=f"Exchange Orders ({island_id[:16]}...)") + except NetworkError as e: error(f"Network error querying blockchain: {e}") raise click.Abort() @@ -544,22 +471,10 @@ def cancel(ctx, order_id: str): # Submit transaction to blockchain try: - import httpx - with httpx.Client() as client: - response = client.post( - f"{rpc_endpoint}/transaction", - json=cancel_data, - timeout=10 - ) - - if response.status_code == 200: - success(f"Order {order_id} cancelled successfully!") - else: - error(f"Failed to cancel order: {response.status_code}") - if response.text: - error(f"Error details: {response.text}") - raise click.Abort() - except Exception as e: + http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10) + result = http_client.post("/transaction", json=cancel_data) + success(f"Order {order_id} cancelled successfully!") + except NetworkError as e: error(f"Network error submitting transaction: {e}") raise click.Abort() diff --git a/cli/aitbc_cli/commands/gpu_marketplace.py b/cli/aitbc_cli/commands/gpu_marketplace.py index c34f5a2e..cc743722 100644 --- a/cli/aitbc_cli/commands/gpu_marketplace.py +++ b/cli/aitbc_cli/commands/gpu_marketplace.py @@ -18,6 +18,12 @@ from ..utils.island_credentials import ( get_island_id, get_island_name ) +# Import shared modules +from aitbc import get_logger, AITBCHTTPClient, NetworkError + +# Initialize logger +logger = get_logger(__name__) + @click.group() def gpu(): @@ -100,38 +106,25 @@ def offer(ctx, gpu_count: int, price_per_gpu: float, duration_hours: int, specs: # Submit transaction to blockchain try: - import httpx - with httpx.Client() as client: - response = client.post( - f"{rpc_endpoint}/transaction", - json=offer_data, - timeout=10 - ) - - if response.status_code == 200: - result = response.json() - success(f"GPU offer created successfully!") - success(f"Offer ID: {offer_id}") - success(f"Total Price: {total_price:.2f} AIT") - - offer_info = { - "Offer ID": offer_id, - "GPU Count": gpu_count, - "Price per GPU": f"{price_per_gpu:.4f} AIT/hour", - "Duration": f"{duration_hours} hours", - "Total Price": f"{total_price:.2f} AIT", - "Status": "active", - "Provider Node": provider_node_id[:16] + "...", - "Island": island_id[:16] + "..." - } - - output(offer_info, ctx.obj.get('output_format', 'table')) - else: - error(f"Failed to submit transaction: {response.status_code}") - if response.text: - error(f"Error details: {response.text}") - raise click.Abort() - except Exception as e: + http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10) + result = http_client.post("/transaction", json=offer_data) + success(f"GPU offer created successfully!") + success(f"Offer ID: {offer_id}") + success(f"Total Price: {total_price:.2f} AIT") + + offer_info = { + "Offer ID": offer_id, + "GPU Count": gpu_count, + "Price per GPU": f"{price_per_gpu:.4f} AIT/hour", + "Duration": f"{duration_hours} hours", + "Total Price": f"{total_price:.2f} AIT", + "Status": "active", + "Provider Node": provider_node_id[:16] + "...", + "Island": island_id[:16] + "..." + } + + output(offer_info, ctx.obj.get('output_format', 'table')) + except NetworkError as e: error(f"Network error submitting transaction: {e}") raise click.Abort() @@ -213,38 +206,25 @@ def bid(ctx, gpu_count: int, max_price: float, duration_hours: int, specs: Optio # Submit transaction to blockchain try: - import httpx - with httpx.Client() as client: - response = client.post( - f"{rpc_endpoint}/v1/transactions", - json=bid_data, - timeout=10 - ) - - if response.status_code == 200: - result = response.json() - success(f"GPU bid created successfully!") - success(f"Bid ID: {bid_id}") - success(f"Max Total Price: {max_total_price:.2f} AIT") - - bid_info = { - "Bid ID": bid_id, - "GPU Count": gpu_count, - "Max Price per GPU": f"{max_price:.4f} AIT/hour", - "Duration": f"{duration_hours} hours", - "Max Total Price": f"{max_total_price:.2f} AIT", - "Status": "pending", - "Bidder Node": bidder_node_id[:16] + "...", - "Island": island_id[:16] + "..." - } - - output(bid_info, ctx.obj.get('output_format', 'table')) - else: - error(f"Failed to submit transaction: {response.status_code}") - if response.text: - error(f"Error details: {response.text}") - raise click.Abort() - except Exception as e: + http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10) + result = http_client.post("/v1/transactions", json=bid_data) + success(f"GPU bid created successfully!") + success(f"Bid ID: {bid_id}") + success(f"Max Total Price: {max_total_price:.2f} AIT") + + bid_info = { + "Bid ID": bid_id, + "GPU Count": gpu_count, + "Max Price per GPU": f"{max_price:.4f} AIT/hour", + "Duration": f"{duration_hours} hours", + "Max Total Price": f"{max_total_price:.2f} AIT", + "Status": "pending", + "Bidder Node": bidder_node_id[:16] + "...", + "Island": island_id[:16] + "..." + } + + output(bid_info, ctx.obj.get('output_format', 'table')) + except NetworkError as e: error(f"Network error submitting transaction: {e}") raise click.Abort() @@ -268,7 +248,6 @@ def list(ctx, provider: Optional[str], status: Optional[str], type: str): # Query blockchain for GPU marketplace transactions try: - import httpx params = { 'transaction_type': 'gpu_marketplace', 'island_id': island_id @@ -280,54 +259,44 @@ def list(ctx, provider: Optional[str], status: Optional[str], type: str): if type != 'all': params['action'] = type - with httpx.Client() as client: - response = client.get( - f"{rpc_endpoint}/transactions", - params=params, - timeout=10 - ) - - if response.status_code == 200: - transactions = response.json() - - if not transactions: - info("No GPU marketplace transactions found") - return - - # Format output - market_data = [] - for tx in transactions: - action = tx.get('action') - if action == 'offer': - market_data.append({ - "ID": tx.get('offer_id', tx.get('transaction_id', 'N/A'))[:20] + "...", - "Type": "OFFER", - "GPU Count": tx.get('gpu_count'), - "Price": f"{tx.get('price_per_gpu', 0):.4f} AIT/h", - "Duration": f"{tx.get('duration_hours')}h", - "Total": f"{tx.get('total_price', 0):.2f} AIT", - "Status": tx.get('status'), - "Provider": tx.get('provider_node_id', '')[:16] + "...", - "Created": tx.get('created_at', '')[:19] - }) - elif action == 'bid': - market_data.append({ - "ID": tx.get('bid_id', tx.get('transaction_id', 'N/A'))[:20] + "...", - "Type": "BID", - "GPU Count": tx.get('gpu_count'), - "Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h", - "Duration": f"{tx.get('duration_hours')}h", - "Max Total": f"{tx.get('max_total_price', 0):.2f} AIT", - "Status": tx.get('status'), - "Bidder": tx.get('bidder_node_id', '')[:16] + "...", - "Created": tx.get('created_at', '')[:19] - }) - - output(market_data, ctx.obj.get('output_format', 'table'), title=f"GPU Marketplace ({island_id[:16]}...)") - else: - error(f"Failed to query blockchain: {response.status_code}") - raise click.Abort() - except Exception as e: + http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10) + transactions = http_client.get("/transactions", params=params) + + if not transactions: + info("No GPU marketplace transactions found") + return + + # Format output + market_data = [] + for tx in transactions: + action = tx.get('action') + if action == 'offer': + market_data.append({ + "ID": tx.get('offer_id', tx.get('transaction_id', 'N/A'))[:20] + "...", + "Type": "OFFER", + "GPU Count": tx.get('gpu_count'), + "Price": f"{tx.get('price_per_gpu', 0):.4f} AIT/h", + "Duration": f"{tx.get('duration_hours')}h", + "Total": f"{tx.get('total_price', 0):.2f} AIT", + "Status": tx.get('status'), + "Provider": tx.get('provider_node_id', '')[:16] + "...", + "Created": tx.get('created_at', '')[:19] + }) + elif action == 'bid': + market_data.append({ + "ID": tx.get('bid_id', tx.get('transaction_id', 'N/A'))[:20] + "...", + "Type": "BID", + "GPU Count": tx.get('gpu_count'), + "Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h", + "Duration": f"{tx.get('duration_hours')}h", + "Max Total": f"{tx.get('max_total_price', 0):.2f} AIT", + "Status": tx.get('status'), + "Bidder": tx.get('bidder_node_id', '')[:16] + "...", + "Created": tx.get('created_at', '')[:19] + }) + + output(market_data, ctx.obj.get('output_format', 'table'), title=f"GPU Marketplace ({island_id[:16]}...)") + except NetworkError as e: error(f"Network error querying blockchain: {e}") raise click.Abort() @@ -390,22 +359,10 @@ def cancel(ctx, order_id: str): # Submit transaction to blockchain try: - import httpx - with httpx.Client() as client: - response = client.post( - f"{rpc_endpoint}/transaction", - json=cancel_data, - timeout=10 - ) - - if response.status_code == 200: - success(f"Order {order_id} cancelled successfully!") - else: - error(f"Failed to cancel order: {response.status_code}") - if response.text: - error(f"Error details: {response.text}") - raise click.Abort() - except Exception as e: + http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10) + result = http_client.post("/transaction", json=cancel_data) + success(f"Order {order_id} cancelled successfully!") + except NetworkError as e: error(f"Network error submitting transaction: {e}") raise click.Abort() @@ -463,22 +420,10 @@ def accept(ctx, bid_id: str): # Submit transaction to blockchain try: - import httpx - with httpx.Client() as client: - response = client.post( - f"{rpc_endpoint}/transaction", - json=accept_data, - timeout=10 - ) - - if response.status_code == 200: - success(f"Bid {bid_id} accepted successfully!") - else: - error(f"Failed to accept bid: {response.status_code}") - if response.text: - error(f"Error details: {response.text}") - raise click.Abort() - except Exception as e: + http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10) + result = http_client.post("/transaction", json=accept_data) + success(f"Bid {bid_id} accepted successfully!") + except NetworkError as e: error(f"Network error submitting transaction: {e}") raise click.Abort() @@ -500,64 +445,53 @@ def status(ctx, order_id: str): # Query blockchain for the order try: - import httpx params = { 'transaction_type': 'gpu_marketplace', 'island_id': island_id, 'order_id': order_id } - with httpx.Client() as client: - response = client.get( - f"{rpc_endpoint}/transactions", - params=params, - timeout=10 - ) - - if response.status_code == 200: - transactions = response.json() - - if not transactions: - error(f"Order {order_id} not found") - raise click.Abort() - - tx = transactions[0] - action = tx.get('action') - - order_info = { - "Order ID": order_id, - "Type": action.upper(), - "Status": tx.get('status'), - "Created": tx.get('created_at'), - } - - if action == 'offer': - order_info.update({ - "GPU Count": tx.get('gpu_count'), - "Price per GPU": f"{tx.get('price_per_gpu', 0):.4f} AIT/h", - "Duration": f"{tx.get('duration_hours')}h", - "Total Price": f"{tx.get('total_price', 0):.2f} AIT", - "Provider": tx.get('provider_node_id', '')[:16] + "..." - }) - elif action == 'bid': - order_info.update({ - "GPU Count": tx.get('gpu_count'), - "Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h", - "Duration": f"{tx.get('duration_hours')}h", - "Max Total": f"{tx.get('max_total_price', 0):.2f} AIT", - "Bidder": tx.get('bidder_node_id', '')[:16] + "..." - }) - - if 'accepted_at' in tx: - order_info["Accepted"] = tx['accepted_at'] - if 'cancelled_at' in tx: - order_info["Cancelled"] = tx['cancelled_at'] - - output(order_info, ctx.obj.get('output_format', 'table'), title=f"Order Status: {order_id}") - else: - error(f"Failed to query blockchain: {response.status_code}") - raise click.Abort() - except Exception as e: + http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10) + transactions = http_client.get("/transactions", params=params) + + if not transactions: + error(f"Order {order_id} not found") + raise click.Abort() + + tx = transactions[0] + action = tx.get('action') + + order_info = { + "Order ID": order_id, + "Type": action.upper(), + "Status": tx.get('status'), + "Created": tx.get('created_at'), + } + + if action == 'offer': + order_info.update({ + "GPU Count": tx.get('gpu_count'), + "Price per GPU": f"{tx.get('price_per_gpu', 0):.4f} AIT/h", + "Duration": f"{tx.get('duration_hours')}h", + "Total Price": f"{tx.get('total_price', 0):.2f} AIT", + "Provider": tx.get('provider_node_id', '')[:16] + "..." + }) + elif action == 'bid': + order_info.update({ + "GPU Count": tx.get('gpu_count'), + "Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h", + "Duration": f"{tx.get('duration_hours')}h", + "Max Total": f"{tx.get('max_total_price', 0):.2f} AIT", + "Bidder": tx.get('bidder_node_id', '')[:16] + "..." + }) + + if 'accepted_at' in tx: + order_info["Accepted"] = tx['accepted_at'] + if 'cancelled_at' in tx: + order_info["Cancelled"] = tx['cancelled_at'] + + output(order_info, ctx.obj.get('output_format', 'table'), title=f"Order Status: {order_id}") + except NetworkError as e: error(f"Network error querying blockchain: {e}") raise click.Abort() @@ -578,96 +512,79 @@ def match(ctx): # Query blockchain for open offers and bids try: - import httpx params = { 'transaction_type': 'gpu_marketplace', 'island_id': island_id, 'status': 'active' } - with httpx.Client() as client: - response = client.get( - f"{rpc_endpoint}/transactions", - params=params, - timeout=10 - ) - - if response.status_code == 200: - transactions = response.json() - - # Separate offers and bids - offers = [] - bids = [] - - for tx in transactions: - if tx.get('action') == 'offer': - offers.append(tx) - elif tx.get('action') == 'bid': - bids.append(tx) - - if not offers or not bids: - info("No active offers or bids to match") - return - - # Sort offers by price (lowest first) - offers.sort(key=lambda x: x.get('price_per_gpu', float('inf'))) - # Sort bids by price (highest first) - bids.sort(key=lambda x: x.get('max_price_per_gpu', 0), reverse=True) - - # Match bids with offers - matches = [] - for bid in bids: - for offer in offers: - # Check if bid price >= offer price - if bid.get('max_price_per_gpu', 0) >= offer.get('price_per_gpu', float('inf')): - # Check if GPU count matches - if bid.get('gpu_count') == offer.get('gpu_count'): - # Check if duration matches - if bid.get('duration_hours') == offer.get('duration_hours'): - # Create match transaction - match_data = { - 'type': 'gpu_marketplace', - 'action': 'match', - 'bid_id': bid.get('bid_id'), - 'offer_id': offer.get('offer_id'), - 'bidder_node_id': bid.get('bidder_node_id'), - 'provider_node_id': offer.get('provider_node_id'), - 'gpu_count': bid.get('gpu_count'), - 'matched_price': offer.get('price_per_gpu'), - 'duration_hours': bid.get('duration_hours'), - 'total_price': offer.get('total_price'), - 'status': 'matched', - 'matched_at': datetime.now().isoformat(), - 'island_id': island_id, - 'chain_id': get_chain_id() - } - - # Submit match transaction - match_response = client.post( - f"{rpc_endpoint}/transaction", - json=match_data, - timeout=10 - ) - - if match_response.status_code == 200: - matches.append({ - "Bid ID": bid.get('bid_id')[:16] + "...", - "Offer ID": offer.get('offer_id')[:16] + "...", - "GPU Count": bid.get('gpu_count'), - "Matched Price": f"{offer.get('price_per_gpu', 0):.4f} AIT/h", - "Total Price": f"{offer.get('total_price', 0):.2f} AIT", - "Duration": f"{bid.get('duration_hours')}h" - }) - - if matches: - success(f"Matched {len(matches)} GPU orders!") - output(matches, ctx.obj.get('output_format', 'table'), title="GPU Order Matches") - else: - info("No matching orders found") - else: - error(f"Failed to query blockchain: {response.status_code}") - raise click.Abort() - except Exception as e: + http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10) + transactions = http_client.get("/transactions", params=params) + + # Separate offers and bids + offers = [] + bids = [] + + for tx in transactions: + if tx.get('action') == 'offer': + offers.append(tx) + elif tx.get('action') == 'bid': + bids.append(tx) + + if not offers or not bids: + info("No active offers or bids to match") + return + + # Sort offers by price (lowest first) + offers.sort(key=lambda x: x.get('price_per_gpu', float('inf'))) + # Sort bids by price (highest first) + bids.sort(key=lambda x: x.get('max_price_per_gpu', 0), reverse=True) + + # Match bids with offers + matches = [] + for bid in bids: + for offer in offers: + # Check if bid price >= offer price + if bid.get('max_price_per_gpu', 0) >= offer.get('price_per_gpu', float('inf')): + # Check if GPU count matches + if bid.get('gpu_count') == offer.get('gpu_count'): + # Check if duration matches + if bid.get('duration_hours') == offer.get('duration_hours'): + # Create match transaction + match_data = { + 'type': 'gpu_marketplace', + 'action': 'match', + 'bid_id': bid.get('bid_id'), + 'offer_id': offer.get('offer_id'), + 'bidder_node_id': bid.get('bidder_node_id'), + 'provider_node_id': offer.get('provider_node_id'), + 'gpu_count': bid.get('gpu_count'), + 'matched_price': offer.get('price_per_gpu'), + 'duration_hours': bid.get('duration_hours'), + 'total_price': offer.get('total_price'), + 'status': 'matched', + 'matched_at': datetime.now().isoformat(), + 'island_id': island_id, + 'chain_id': get_chain_id() + } + + # Submit match transaction + match_result = http_client.post("/transaction", json=match_data) + matches.append({ + "Bid ID": bid.get('bid_id')[:16] + "...", + "Offer ID": offer.get('offer_id')[:16] + "...", + "GPU Count": bid.get('gpu_count'), + "Matched Price": f"{offer.get('price_per_gpu', 0):.4f} AIT/h", + "Total Price": f"{offer.get('total_price', 0):.2f} AIT", + "Duration": f"{bid.get('duration_hours')}h" + }) + + if matches: + success(f"Matched {len(matches)} GPU orders!") + output(matches, ctx.obj.get('output_format', 'table'), title="GPU Order Matches") + else: + info("No matching orders found") + except NetworkError as e: error(f"Network error querying blockchain: {e}") raise click.Abort() diff --git a/cli/aitbc_cli/commands/monitor.py b/cli/aitbc_cli/commands/monitor.py index 65ca201f..41f5cb19 100755 --- a/cli/aitbc_cli/commands/monitor.py +++ b/cli/aitbc_cli/commands/monitor.py @@ -9,9 +9,7 @@ from datetime import datetime, timedelta from ..utils import output, error, success, console # Import shared modules -from aitbc.aitbc_logging import get_logger -from aitbc.http_client import AITBCHTTPClient -from aitbc.exceptions import NetworkError +from aitbc import get_logger, AITBCHTTPClient, NetworkError # Initialize logger logger = get_logger(__name__) diff --git a/cli/aitbc_cli/commands/wallet.py b/cli/aitbc_cli/commands/wallet.py index ccaa2955..1c1f6ef1 100644 --- a/cli/aitbc_cli/commands/wallet.py +++ b/cli/aitbc_cli/commands/wallet.py @@ -12,10 +12,7 @@ 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 +from aitbc import get_logger, AITBCHTTPClient, NetworkError, KEYSTORE_DIR # Initialize logger logger = get_logger(__name__) diff --git a/cli/handlers/account.py b/cli/handlers/account.py index 9ec8447d..2b45fcd8 100644 --- a/cli/handlers/account.py +++ b/cli/handlers/account.py @@ -3,8 +3,7 @@ import json import sys -from aitbc.http_client import AITBCHTTPClient -from aitbc.exceptions import NetworkError +from aitbc import AITBCHTTPClient, NetworkError def handle_account_get(args, default_rpc_url, output_format): diff --git a/cli/handlers/bridge.py b/cli/handlers/bridge.py index 92835fb9..43d26439 100644 --- a/cli/handlers/bridge.py +++ b/cli/handlers/bridge.py @@ -2,8 +2,7 @@ import subprocess -from aitbc.http_client import AITBCHTTPClient -from aitbc.exceptions import NetworkError +from aitbc import AITBCHTTPClient, NetworkError def handle_bridge_health(args): diff --git a/cli/handlers/pool_hub.py b/cli/handlers/pool_hub.py index 58e0c4b9..dd1d66ca 100644 --- a/cli/handlers/pool_hub.py +++ b/cli/handlers/pool_hub.py @@ -1,7 +1,6 @@ """Pool hub SLA and capacity management handlers.""" -from aitbc.http_client import AITBCHTTPClient -from aitbc.exceptions import NetworkError +from aitbc import AITBCHTTPClient, NetworkError def handle_pool_hub_sla_metrics(args): diff --git a/cli/utils/wallet_daemon_client.py b/cli/utils/wallet_daemon_client.py index 3f22cc32..cf9e1e7b 100755 --- a/cli/utils/wallet_daemon_client.py +++ b/cli/utils/wallet_daemon_client.py @@ -10,8 +10,7 @@ from typing import Dict, Any, Optional, List from pathlib import Path from dataclasses import dataclass -from aitbc.http_client import AITBCHTTPClient -from aitbc.exceptions import NetworkError +from aitbc import AITBCHTTPClient, NetworkError from utils import error, success from config import Config diff --git a/packages/py/aitbc-agent-sdk/src/aitbc_agent/agent.py b/packages/py/aitbc-agent-sdk/src/aitbc_agent/agent.py index 35b25935..17425ec8 100755 --- a/packages/py/aitbc-agent-sdk/src/aitbc_agent/agent.py +++ b/packages/py/aitbc-agent-sdk/src/aitbc_agent/agent.py @@ -4,7 +4,6 @@ Core Agent class for AITBC network participation import asyncio import json -import logging import uuid from datetime import datetime from typing import Dict, List, Optional, Any @@ -14,7 +13,9 @@ from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import padding -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) @dataclass diff --git a/packages/py/aitbc-agent-sdk/src/aitbc_agent/compute_consumer.py b/packages/py/aitbc-agent-sdk/src/aitbc_agent/compute_consumer.py index c228ab9c..76a66ba9 100644 --- a/packages/py/aitbc-agent-sdk/src/aitbc_agent/compute_consumer.py +++ b/packages/py/aitbc-agent-sdk/src/aitbc_agent/compute_consumer.py @@ -3,13 +3,14 @@ Compute Consumer Agent - for agents that consume computational resources """ import asyncio -import logging from typing import Dict, List, Optional, Any from datetime import datetime from dataclasses import dataclass from .agent import Agent, AgentCapabilities -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) @dataclass diff --git a/packages/py/aitbc-agent-sdk/src/aitbc_agent/compute_provider.py b/packages/py/aitbc-agent-sdk/src/aitbc_agent/compute_provider.py index 4517303a..e95fc172 100755 --- a/packages/py/aitbc-agent-sdk/src/aitbc_agent/compute_provider.py +++ b/packages/py/aitbc-agent-sdk/src/aitbc_agent/compute_provider.py @@ -3,13 +3,14 @@ Compute Provider Agent - for agents that provide computational resources """ import asyncio -import logging from typing import Dict, List, Optional, Any from datetime import datetime, timedelta from dataclasses import dataclass from .agent import Agent, AgentCapabilities -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) @dataclass diff --git a/packages/py/aitbc-agent-sdk/src/aitbc_agent/platform_builder.py b/packages/py/aitbc-agent-sdk/src/aitbc_agent/platform_builder.py index cde23bee..26cf3ae3 100644 --- a/packages/py/aitbc-agent-sdk/src/aitbc_agent/platform_builder.py +++ b/packages/py/aitbc-agent-sdk/src/aitbc_agent/platform_builder.py @@ -2,14 +2,15 @@ Platform Builder - factory for constructing AITBC agent platform configurations """ -import logging from typing import Dict, List, Any, Optional from .agent import Agent, AgentCapabilities, AgentIdentity from .compute_provider import ComputeProvider from .compute_consumer import ComputeConsumer from .swarm_coordinator import SwarmCoordinator -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) class PlatformBuilder: diff --git a/packages/py/aitbc-agent-sdk/src/aitbc_agent/swarm_coordinator.py b/packages/py/aitbc-agent-sdk/src/aitbc_agent/swarm_coordinator.py index fba2c762..8cbcb827 100755 --- a/packages/py/aitbc-agent-sdk/src/aitbc_agent/swarm_coordinator.py +++ b/packages/py/aitbc-agent-sdk/src/aitbc_agent/swarm_coordinator.py @@ -4,13 +4,14 @@ Swarm Coordinator - for agents participating in collective intelligence import asyncio import json -import logging from typing import Dict, List, Optional, Any # noqa: F401 from datetime import datetime from dataclasses import dataclass from .agent import Agent -logger = logging.getLogger(__name__) +from aitbc import get_logger + +logger = get_logger(__name__) @dataclass diff --git a/packages/py/aitbc-sdk/src/aitbc_sdk/receipts.py b/packages/py/aitbc-sdk/src/aitbc_sdk/receipts.py index a82cc97e..26c25412 100755 --- a/packages/py/aitbc-sdk/src/aitbc_sdk/receipts.py +++ b/packages/py/aitbc-sdk/src/aitbc_sdk/receipts.py @@ -4,9 +4,9 @@ import time from dataclasses import dataclass, field from typing import Any, Dict, Iterable, Iterator, List, Optional, cast -import httpx import base64 +from aitbc import AITBCHTTPClient, NetworkError from aitbc_crypto.signing import ReceiptVerifier @@ -83,8 +83,8 @@ class CoordinatorReceiptClient: self.max_retries = max_retries self.backoff_seconds = backoff_seconds - def _client(self) -> httpx.Client: - return httpx.Client( + def _client(self) -> AITBCHTTPClient: + return AITBCHTTPClient( base_url=self.base_url, timeout=self.timeout, headers={"X-Api-Key": self.api_key}, @@ -187,9 +187,9 @@ class CoordinatorReceiptClient: attempt = 0 while True: try: - with self._client() as client: - response = client.request(method=method, url=url, params=params) - except httpx.HTTPError: + client = self._client() + response = client.request(method=method, url=url, params=params) + except NetworkError: if attempt >= self.max_retries: raise attempt += 1