diff --git a/cli/aitbc_cli/commands/edge.py b/cli/aitbc_cli/commands/edge.py index af0525ee..a8fe00c3 100644 --- a/cli/aitbc_cli/commands/edge.py +++ b/cli/aitbc_cli/commands/edge.py @@ -80,7 +80,7 @@ def leave(island_id: str): error(f"Error leaving island: {str(e)}") -@island.command() +@island.command(name='list') def list_islands(): """List all islands""" try: diff --git a/cli/aitbc_cli/commands/exchange_island.py b/cli/aitbc_cli/commands/exchange_island.py index ddd9adbf..71e9727f 100644 --- a/cli/aitbc_cli/commands/exchange_island.py +++ b/cli/aitbc_cli/commands/exchange_island.py @@ -24,6 +24,16 @@ from aitbc import get_logger, AITBCHTTPClient, NetworkError logger = get_logger(__name__) +def safe_load_credentials(): + """Load island credentials with graceful error handling""" + try: + return load_island_credentials() + except FileNotFoundError as e: + error(f"Island credentials not found: {e}") + error("Run 'aitbc node island join' to join an island first") + return None + + # Supported trading pairs SUPPORTED_PAIRS = ['AIT/BTC', 'AIT/ETH'] @@ -47,7 +57,9 @@ def buy(ctx, ait_amount: float, quote_currency: str, max_price: Optional[float]) raise click.Abort() # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return rpc_endpoint = get_rpc_endpoint() chain_id = get_chain_id() island_id = get_island_id() @@ -144,7 +156,9 @@ def sell(ctx, ait_amount: float, quote_currency: str, min_price: Optional[float] raise click.Abort() # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return rpc_endpoint = get_rpc_endpoint() chain_id = get_chain_id() island_id = get_island_id() @@ -232,7 +246,9 @@ def orderbook(ctx, pair: str, limit: int): """View the order book for a trading pair""" try: # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return rpc_endpoint = get_rpc_endpoint() island_id = get_island_id() @@ -320,7 +336,9 @@ def rates(ctx): """View current exchange rates for AIT/BTC and AIT/ETH""" try: # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return rpc_endpoint = get_rpc_endpoint() island_id = get_island_id() @@ -380,7 +398,9 @@ def orders(ctx, user: Optional[str], status: Optional[str], pair: Optional[str]) """List exchange orders""" try: # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return rpc_endpoint = get_rpc_endpoint() island_id = get_island_id() @@ -435,7 +455,9 @@ def cancel(ctx, order_id: str): """Cancel an exchange order""" try: # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return rpc_endpoint = get_rpc_endpoint() chain_id = get_chain_id() island_id = get_island_id() diff --git a/cli/aitbc_cli/commands/gpu_marketplace.py b/cli/aitbc_cli/commands/gpu_marketplace.py index 3b4d2426..dbc9618e 100644 --- a/cli/aitbc_cli/commands/gpu_marketplace.py +++ b/cli/aitbc_cli/commands/gpu_marketplace.py @@ -15,7 +15,7 @@ from typing import Optional, List from ..utils import output, error, success, info, warning from ..utils.island_credentials import ( load_island_credentials, get_rpc_endpoint, get_chain_id, - get_island_id, get_island_name + get_island_id, get_island_name, validate_credentials ) from ..config import get_config @@ -26,6 +26,16 @@ from aitbc import get_logger, AITBCHTTPClient, NetworkError logger = get_logger(__name__) +def safe_load_credentials(): + """Load island credentials with graceful error handling""" + try: + return load_island_credentials() + except FileNotFoundError as e: + error(f"Island credentials not found: {e}") + error("Run 'aitbc node island join' to join an island first") + return None + + @click.group() def gpu(): """GPU marketplace commands for bidding and offering GPU power""" @@ -46,7 +56,9 @@ def offer(ctx, gpu_count: int, price_per_gpu: float, duration_hours: int, specs: config = get_config() # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return chain_id = get_chain_id() island_id = get_island_id() @@ -149,7 +161,9 @@ def bid(ctx, gpu_count: int, max_price: float, duration_hours: int, specs: Optio config = get_config() # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return chain_id = get_chain_id() island_id = get_island_id() @@ -250,7 +264,9 @@ def list(ctx, provider: Optional[str], status: Optional[str], type: str): config = get_config() # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return island_id = get_island_id() # Query GPU service for GPU marketplace transactions @@ -322,7 +338,9 @@ def cancel(ctx, order_id: str): config = get_config() # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return chain_id = get_chain_id() island_id = get_island_id() @@ -388,7 +406,9 @@ def accept(ctx, bid_id: str): config = get_config() # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return chain_id = get_chain_id() island_id = get_island_id() @@ -451,7 +471,9 @@ def status(ctx, order_id: str): config = get_config() # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return island_id = get_island_id() # Query GPU service for the order @@ -520,7 +542,9 @@ def match(ctx): config = get_config() # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return island_id = get_island_id() # Query GPU service for open offers and bids @@ -612,7 +636,9 @@ def providers(ctx): """Query island members for GPU providers""" try: # Load island credentials - credentials = load_island_credentials() + credentials = safe_load_credentials() + if not credentials: + return island_id = get_island_id() # Load island members from credentials diff --git a/cli/aitbc_cli/commands/mining.py b/cli/aitbc_cli/commands/mining.py index 00186c25..a365b70a 100644 --- a/cli/aitbc_cli/commands/mining.py +++ b/cli/aitbc_cli/commands/mining.py @@ -94,7 +94,7 @@ def status(rpc_url: Optional[str]): """Get mining status""" if not rpc_url: rpc_url = DEFAULT_RPC_URL - + try: http_client = AITBCHTTPClient(base_url=rpc_url, timeout=30) result = http_client.get("/rpc/mining/status") @@ -104,3 +104,21 @@ def status(rpc_url: Optional[str]): error(f"Error getting mining status: {e}") except Exception as e: error(f"Error: {e}") + + +@mining.command(name='list') +@click.option('--rpc-url', help='Blockchain RPC URL') +def list_miners(rpc_url: Optional[str]): + """List active miners""" + if not rpc_url: + rpc_url = DEFAULT_RPC_URL + + try: + http_client = AITBCHTTPClient(base_url=rpc_url, timeout=30) + result = http_client.get("/rpc/mining/miners") + success("Active miners:") + click.echo(json.dumps(result, indent=2)) + except NetworkError as e: + error(f"Error listing miners: {e}") + except Exception as e: + error(f"Error: {e}") diff --git a/cli/aitbc_cli/utils/__init__.py b/cli/aitbc_cli/utils/__init__.py index 64601143..7b185a08 100644 --- a/cli/aitbc_cli/utils/__init__.py +++ b/cli/aitbc_cli/utils/__init__.py @@ -16,8 +16,11 @@ from .wallet import decrypt_private_key from .blockchain import get_chain_info, get_network_status, get_blockchain_analytics -def output(message: str, **kwargs): - """Print a regular output message""" +def output(message, **kwargs): + """Print a regular output message (handles strings and structured data)""" + if not isinstance(message, str): + import json + message = json.dumps(message, indent=2) echo(message, **kwargs)