fix: replace all print() with click.echo() or logger in CLI production code
- 55 CLI files: handlers/, aitbc_cli/commands/, cli/core/, cli/utils/, top-level scripts
- Click-based files: print() -> click.echo()
- Library modules: print() -> logger.info/error/warning
- Fixed pre-existing indentation bugs in monitor.py dashboard function
- Fixed bare print() -> logger.info('') in chain_manager.py
- 0 remaining print() in production CLI code
- All files compile cleanly
This commit is contained in:
@@ -4,6 +4,9 @@ import json
|
||||
import sys
|
||||
|
||||
from aitbc import AITBCHTTPClient, NetworkError
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_account_get(args, default_rpc_url, output_format):
|
||||
@@ -12,10 +15,10 @@ def handle_account_get(args, default_rpc_url, output_format):
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
if not args.address:
|
||||
print("Error: --address is required")
|
||||
logger.error("Error: --address is required")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Getting account {args.address} from {rpc_url}...")
|
||||
logger.info(f"Getting account {args.address} from {rpc_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -24,12 +27,12 @@ def handle_account_get(args, default_rpc_url, output_format):
|
||||
http_client = AITBCHTTPClient(base_url=rpc_url, timeout=10)
|
||||
account = http_client.get(f"/rpc/account/{args.address}", params=params)
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(account, indent=2))
|
||||
logger.info(json.dumps(account, indent=2))
|
||||
else:
|
||||
render_mapping(f"Account {args.address}:", account)
|
||||
except NetworkError as e:
|
||||
print(f"Error getting account: {e}")
|
||||
logger.error(f"Error getting account: {e}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error getting account: {e}")
|
||||
logger.error(f"Error getting account: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import json
|
||||
import sys
|
||||
import click
|
||||
|
||||
import requests
|
||||
|
||||
@@ -17,7 +18,7 @@ def handle_ai_submit(args, default_rpc_url, default_coordinator_url, first, read
|
||||
payment = first(getattr(args, "payment_arg", None), getattr(args, "payment", None))
|
||||
|
||||
if not wallet or not model or not prompt:
|
||||
print("Error: --wallet, --type, and --prompt are required")
|
||||
click.echo("Error: --wallet, --type, and --prompt are required")
|
||||
sys.exit(1)
|
||||
|
||||
# Get sender address (no password needed for Agent Coordinator)
|
||||
@@ -39,19 +40,19 @@ def handle_ai_submit(args, default_rpc_url, default_coordinator_url, first, read
|
||||
}
|
||||
}
|
||||
|
||||
print(f"Submitting AI job to {coordinator_url}...")
|
||||
click.echo(f"Submitting AI job to {coordinator_url}...")
|
||||
try:
|
||||
response = requests.post(f"{coordinator_url}/tasks/submit", json=job_data, timeout=30)
|
||||
if response.status_code in (200, 201):
|
||||
result = response.json()
|
||||
print("AI job submitted successfully")
|
||||
click.echo("AI job submitted successfully")
|
||||
render_mapping("Job:", result)
|
||||
else:
|
||||
print(f"Job submission failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
click.echo(f"Job submission failed: {response.status_code}")
|
||||
click.echo(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error submitting AI job: {e}")
|
||||
click.echo(f"Error submitting AI job: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -60,7 +61,7 @@ def handle_ai_jobs(args, default_rpc_url, default_coordinator_url, output_format
|
||||
coordinator_url = args.coordinator_url or default_coordinator_url
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
print(f"Getting AI jobs from {coordinator_url}...")
|
||||
click.echo(f"Getting AI jobs from {coordinator_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -72,17 +73,17 @@ def handle_ai_jobs(args, default_rpc_url, default_coordinator_url, output_format
|
||||
if response.status_code == 200:
|
||||
jobs = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(jobs, indent=2))
|
||||
click.echo(json.dumps(jobs, indent=2))
|
||||
else:
|
||||
print("AI jobs:")
|
||||
click.echo("AI jobs:")
|
||||
if isinstance(jobs, list):
|
||||
for job in jobs:
|
||||
print(f" Job ID: {job.get('job_id', 'N/A')}, Model: {job.get('model', 'N/A')}, Status: {job.get('status', 'N/A')}")
|
||||
click.echo(f" Job ID: {job.get('job_id', 'N/A')}, Model: {job.get('model', 'N/A')}, Status: {job.get('status', 'N/A')}")
|
||||
else:
|
||||
print(f" {jobs}")
|
||||
click.echo(f" {jobs}")
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
click.echo(f"Query failed: {response.status_code}")
|
||||
click.echo(f"Error: {response.text}")
|
||||
# Return stub data instead of failing
|
||||
stub_jobs = {
|
||||
"jobs": [
|
||||
@@ -92,7 +93,7 @@ def handle_ai_jobs(args, default_rpc_url, default_coordinator_url, output_format
|
||||
}
|
||||
render_mapping("AI Jobs (stub):", stub_jobs)
|
||||
except Exception as e:
|
||||
print(f"Error querying AI jobs: {e}")
|
||||
click.echo(f"Error querying AI jobs: {e}")
|
||||
# Return stub data instead of failing
|
||||
stub_jobs = {
|
||||
"jobs": [
|
||||
@@ -111,10 +112,10 @@ def handle_ai_job(args, default_rpc_url, output_format, render_mapping, first):
|
||||
job_id = first(getattr(args, "job_id_arg", None), getattr(args, "job_id", None))
|
||||
|
||||
if not job_id:
|
||||
print("Error: --job-id is required")
|
||||
click.echo("Error: --job-id is required")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Getting AI job {job_id} from {rpc_url}...")
|
||||
click.echo(f"Getting AI job {job_id} from {rpc_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -124,15 +125,15 @@ def handle_ai_job(args, default_rpc_url, output_format, render_mapping, first):
|
||||
if response.status_code == 200:
|
||||
job = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(job, indent=2))
|
||||
click.echo(json.dumps(job, indent=2))
|
||||
else:
|
||||
render_mapping(f"Job {job_id}:", job)
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
click.echo(f"Query failed: {response.status_code}")
|
||||
click.echo(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error getting AI job: {e}")
|
||||
click.echo(f"Error getting AI job: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -145,7 +146,7 @@ def handle_ai_cancel(args, default_rpc_url, read_password, render_mapping, first
|
||||
wallet = getattr(args, "wallet", None)
|
||||
|
||||
if not job_id or not wallet:
|
||||
print("Error: --job-id and --wallet are required")
|
||||
click.echo("Error: --job-id and --wallet are required")
|
||||
sys.exit(1)
|
||||
|
||||
# Get auth headers
|
||||
@@ -160,19 +161,19 @@ def handle_ai_cancel(args, default_rpc_url, read_password, render_mapping, first
|
||||
if chain_id:
|
||||
cancel_data["chain_id"] = chain_id
|
||||
|
||||
print(f"Cancelling AI job {job_id} on {rpc_url}...")
|
||||
click.echo(f"Cancelling AI job {job_id} on {rpc_url}...")
|
||||
try:
|
||||
response = requests.post(f"{rpc_url}/rpc/ai/job/{job_id}/cancel", json=cancel_data, headers=headers, timeout=30)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("AI job cancelled successfully")
|
||||
click.echo("AI job cancelled successfully")
|
||||
render_mapping("Cancel result:", result)
|
||||
else:
|
||||
print(f"Cancellation failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
click.echo(f"Cancellation failed: {response.status_code}")
|
||||
click.echo(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error cancelling AI job: {e}")
|
||||
click.echo(f"Error cancelling AI job: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -181,7 +182,7 @@ def handle_ai_stats(args, default_rpc_url, output_format, render_mapping):
|
||||
rpc_url = args.rpc_url or default_rpc_url
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
print(f"Getting AI service statistics from {rpc_url}...")
|
||||
click.echo(f"Getting AI service statistics from {rpc_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -191,15 +192,15 @@ def handle_ai_stats(args, default_rpc_url, output_format, render_mapping):
|
||||
if response.status_code == 200:
|
||||
stats = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(stats, indent=2))
|
||||
click.echo(json.dumps(stats, indent=2))
|
||||
else:
|
||||
render_mapping("AI service statistics:", stats)
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
click.echo(f"Query failed: {response.status_code}")
|
||||
click.echo(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error getting AI stats: {e}")
|
||||
click.echo(f"Error getting AI stats: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -207,21 +208,21 @@ def handle_ai_distribution_stats(args, default_coordinator_url, output_format, r
|
||||
"""Handle task distribution statistics query from agent coordinator."""
|
||||
coordinator_url = getattr(args, 'coordinator_url', None) or default_coordinator_url
|
||||
|
||||
print(f"Getting task distribution statistics from {coordinator_url}...")
|
||||
click.echo(f"Getting task distribution statistics from {coordinator_url}...")
|
||||
try:
|
||||
response = requests.get(f"{coordinator_url}/tasks/status", timeout=10)
|
||||
if response.status_code == 200:
|
||||
stats = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(stats, indent=2))
|
||||
click.echo(json.dumps(stats, indent=2))
|
||||
else:
|
||||
render_mapping("Task distribution statistics:", stats)
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
click.echo(f"Query failed: {response.status_code}")
|
||||
click.echo(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error getting distribution stats: {e}")
|
||||
click.echo(f"Error getting distribution stats: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -270,20 +271,20 @@ def handle_ai_status(args, default_coordinator_url, default_rpc_url, output_form
|
||||
}
|
||||
|
||||
# Check Agent Coordinator health
|
||||
print(f"Checking Agent Coordinator at {coordinator_url}...")
|
||||
click.echo(f"Checking Agent Coordinator at {coordinator_url}...")
|
||||
try:
|
||||
response = requests.get(f"{coordinator_url}/health", timeout=10)
|
||||
if response.status_code == 200:
|
||||
coordinator_data = response.json()
|
||||
combined_status["agent_coordinator"] = coordinator_data
|
||||
print(f" Agent Coordinator: {coordinator_data.get('status', 'unknown')} (v{coordinator_data.get('version', 'N/A')})")
|
||||
click.echo(f" Agent Coordinator: {coordinator_data.get('status', 'unknown')} (v{coordinator_data.get('version', 'N/A')})")
|
||||
else:
|
||||
print(f" Agent Coordinator: Failed (HTTP {response.status_code})")
|
||||
click.echo(f" Agent Coordinator: Failed (HTTP {response.status_code})")
|
||||
except Exception as e:
|
||||
print(f" Agent Coordinator: Error - {e}")
|
||||
click.echo(f" Agent Coordinator: Error - {e}")
|
||||
|
||||
# Check Blockchain AI stats
|
||||
print(f"Checking Blockchain AI stats at {rpc_url}...")
|
||||
click.echo(f"Checking Blockchain AI stats at {rpc_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if hasattr(args, "chain_id") and args.chain_id:
|
||||
@@ -292,11 +293,11 @@ def handle_ai_status(args, default_coordinator_url, default_rpc_url, output_form
|
||||
if response.status_code == 200:
|
||||
stats_data = response.json()
|
||||
combined_status["blockchain_ai"] = stats_data
|
||||
print(f" Blockchain AI Stats: Available")
|
||||
click.echo(f" Blockchain AI Stats: Available")
|
||||
else:
|
||||
print(f" Blockchain AI Stats: Not available (HTTP {response.status_code})")
|
||||
click.echo(f" Blockchain AI Stats: Not available (HTTP {response.status_code})")
|
||||
except Exception as e:
|
||||
print(f" Blockchain AI Stats: Error - {e}")
|
||||
click.echo(f" Blockchain AI Stats: Error - {e}")
|
||||
|
||||
# Calculate overall status
|
||||
if combined_status["agent_coordinator"].get("status") == "healthy" and combined_status["blockchain_ai"].get("status") != "unavailable":
|
||||
@@ -306,17 +307,17 @@ def handle_ai_status(args, default_coordinator_url, default_rpc_url, output_form
|
||||
|
||||
# Render output
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(combined_status, indent=2))
|
||||
click.echo(json.dumps(combined_status, indent=2))
|
||||
else:
|
||||
print(f"\nOverall Status: {combined_status['overall']}")
|
||||
click.echo(f"\nOverall Status: {combined_status['overall']}")
|
||||
if combined_status["agent_coordinator"].get("status") == "healthy":
|
||||
print(" Agent Coordinator: Operational")
|
||||
click.echo(" Agent Coordinator: Operational")
|
||||
elif combined_status["agent_coordinator"].get("status") != "unavailable":
|
||||
print(f" Agent Coordinator: {combined_status['agent_coordinator'].get('status')}")
|
||||
click.echo(f" Agent Coordinator: {combined_status['agent_coordinator'].get('status')}")
|
||||
else:
|
||||
print(" Agent Coordinator: Unavailable")
|
||||
click.echo(" Agent Coordinator: Unavailable")
|
||||
|
||||
if combined_status["blockchain_ai"].get("status") != "unavailable":
|
||||
print(" Blockchain AI: Operational")
|
||||
click.echo(" Blockchain AI: Operational")
|
||||
else:
|
||||
print(" Blockchain AI: Unavailable")
|
||||
click.echo(" Blockchain AI: Unavailable")
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"""Analytics command handlers for AITBC CLI."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_analytics_metrics(args, default_rpc_url, output_format, render_mapping):
|
||||
@@ -16,7 +19,7 @@ def handle_analytics_metrics(args, default_rpc_url, output_format, render_mappin
|
||||
}
|
||||
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(metrics_data, indent=2))
|
||||
logger.info(json.dumps(metrics_data, indent=2))
|
||||
else:
|
||||
render_mapping("Analytics Metrics:", metrics_data)
|
||||
|
||||
@@ -36,7 +39,7 @@ def handle_analytics_report(args, default_rpc_url, output_format, render_mapping
|
||||
}
|
||||
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(report_data, indent=2))
|
||||
logger.info(json.dumps(report_data, indent=2))
|
||||
else:
|
||||
render_mapping("Analytics Report:", report_data)
|
||||
|
||||
@@ -52,7 +55,7 @@ def handle_analytics_export(args, default_rpc_url, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Analytics exported as {format_type}")
|
||||
logger.info(f"Analytics exported as {format_type}")
|
||||
render_mapping("Export:", export_data)
|
||||
|
||||
|
||||
@@ -68,7 +71,7 @@ def handle_analytics_predict(args, default_rpc_url, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Prediction using {model} model for {target}")
|
||||
logger.info(f"Prediction using {model} model for {target}")
|
||||
render_mapping("Prediction:", prediction_data)
|
||||
|
||||
|
||||
@@ -84,5 +87,5 @@ def handle_analytics_optimize(args, default_rpc_url, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Analytics optimization applied for {target}")
|
||||
logger.info(f"Analytics optimization applied for {target}")
|
||||
render_mapping("Optimization:", optimization_data)
|
||||
|
||||
@@ -5,6 +5,9 @@ import os
|
||||
import sys
|
||||
|
||||
import requests
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_blockchain_info(args, get_chain_info, render_mapping):
|
||||
@@ -18,19 +21,16 @@ def handle_blockchain_info(args, get_chain_info, render_mapping):
|
||||
def handle_blockchain_height(args, get_chain_info):
|
||||
"""Handle blockchain height command."""
|
||||
chain_info = get_chain_info(rpc_url=args.rpc_url)
|
||||
print(chain_info.get("height", 0) if chain_info else 0)
|
||||
|
||||
|
||||
logger.info(chain_info.get("height", 0) if chain_info else 0)
|
||||
def handle_blockchain_block(args, default_rpc_url):
|
||||
"""Handle blockchain block command."""
|
||||
if args.number is None:
|
||||
print("Error: block number is required")
|
||||
logger.error("Error: block number is required")
|
||||
sys.exit(1)
|
||||
|
||||
rpc_url = args.rpc_url or os.getenv("NODE_URL", default_rpc_url)
|
||||
chain_id = getattr(args, 'chain_id', None) or os.getenv('CHAIN_ID', 'ait-mainnet')
|
||||
print(f"Querying block #{args.number} from {rpc_url} (chain: {chain_id})...")
|
||||
|
||||
logger.info(f"Querying block #{args.number} from {rpc_url} (chain: {chain_id})...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -38,40 +38,39 @@ def handle_blockchain_block(args, default_rpc_url):
|
||||
response = requests.get(f"{rpc_url}/rpc/blocks/{args.number}", params=params, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
print(f"Block #{args.number}:")
|
||||
print(f" Hash: {data.get('hash', 'N/A')}")
|
||||
print(f" Timestamp: {data.get('timestamp', 'N/A')}")
|
||||
print(f" Transactions: {data.get('tx_count', len(data.get('transactions', [])))}")
|
||||
print(f" Miner: {data.get('proposer', 'N/A')}")
|
||||
logger.info(f"Block #{args.number}:")
|
||||
logger.info(f" Hash: {data.get('hash', 'N/A')}")
|
||||
logger.info(f" Timestamp: {data.get('timestamp', 'N/A')}")
|
||||
logger.info(f" Transactions: {data.get('tx_count', len(data.get('transactions', [])))}")
|
||||
logger.info(f" Miner: {data.get('proposer', 'N/A')}")
|
||||
else:
|
||||
print(f"Failed to get block: {response.status_code}")
|
||||
logger.error(f"Failed to get block: {response.status_code}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error getting block: {e}")
|
||||
logger.error(f"Error getting block: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def handle_blockchain_init(args, default_rpc_url):
|
||||
"""Handle blockchain init command."""
|
||||
rpc_url = args.rpc_url or os.getenv("NODE_URL", default_rpc_url)
|
||||
print(f"Checking blockchain status on {rpc_url}...")
|
||||
|
||||
logger.info(f"Checking blockchain status on {rpc_url}...")
|
||||
try:
|
||||
# Check if blockchain is already initialized by checking for genesis block (block 0)
|
||||
response = requests.get(f"{rpc_url}/rpc/blocks/0", timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
print("Blockchain already initialized")
|
||||
print(f"Genesis block hash: {data.get('hash', 'N/A')}")
|
||||
print(f"Block number: {data.get('number', 0)}")
|
||||
logger.info("Blockchain already initialized")
|
||||
logger.info(f"Genesis block hash: {data.get('hash', 'N/A')}")
|
||||
logger.info(f"Block number: {data.get('number', 0)}")
|
||||
if args.force:
|
||||
print("Force flag ignored - blockchain already initialized")
|
||||
logger.info("Force flag ignored - blockchain already initialized")
|
||||
else:
|
||||
print(f"Blockchain not initialized or endpoint unavailable: {response.status_code}")
|
||||
logger.info(f"Blockchain not initialized or endpoint unavailable: {response.status_code}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error checking blockchain status: {e}")
|
||||
print("Note: Blockchain may not be initialized or RPC endpoint unavailable")
|
||||
logger.error(f"Error checking blockchain status: {e}")
|
||||
logger.info("Note: Blockchain may not be initialized or RPC endpoint unavailable")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -80,43 +79,43 @@ def handle_blockchain_genesis(args, default_rpc_url):
|
||||
rpc_url = args.rpc_url or os.getenv("NODE_URL", default_rpc_url)
|
||||
|
||||
if args.create:
|
||||
print(f"Creating genesis block on {rpc_url}...")
|
||||
logger.info(f"Creating genesis block on {rpc_url}...")
|
||||
try:
|
||||
# Check if genesis block already exists
|
||||
response = requests.get(f"{rpc_url}/rpc/blocks/0", timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
print("Genesis block already exists")
|
||||
print(f"Block hash: {data.get('hash', 'N/A')}")
|
||||
print(f"Block number: {data.get('number', 0)}")
|
||||
print(f"Timestamp: {data.get('timestamp', 'N/A')}")
|
||||
print("Skipping genesis block creation")
|
||||
logger.info("Genesis block already exists")
|
||||
logger.info(f"Block hash: {data.get('hash', 'N/A')}")
|
||||
logger.info(f"Block number: {data.get('number', 0)}")
|
||||
logger.info(f"Timestamp: {data.get('timestamp', 'N/A')}")
|
||||
logger.info("Skipping genesis block creation")
|
||||
return
|
||||
else:
|
||||
print(f"Cannot create genesis block - endpoint not available: {response.status_code}")
|
||||
print("Note: Genesis block creation may not be supported in current RPC implementation")
|
||||
logger.info(f"Cannot create genesis block - endpoint not available: {response.status_code}")
|
||||
logger.info("Note: Genesis block creation may not be supported in current RPC implementation")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error checking genesis block: {e}")
|
||||
print("Note: Genesis block creation may not be supported in current RPC implementation")
|
||||
logger.error(f"Error checking genesis block: {e}")
|
||||
logger.info("Note: Genesis block creation may not be supported in current RPC implementation")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(f"Inspecting genesis block on {rpc_url}...")
|
||||
logger.info(f"Inspecting genesis block on {rpc_url}...")
|
||||
try:
|
||||
response = requests.get(f"{rpc_url}/rpc/blocks/0", timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
print("Genesis block information:")
|
||||
print(f" Hash: {data.get('hash', 'N/A')}")
|
||||
print(f" Number: {data.get('number', 0)}")
|
||||
print(f" Timestamp: {data.get('timestamp', 'N/A')}")
|
||||
print(f" Miner: {data.get('miner', 'N/A')}")
|
||||
print(f" Reward: {data.get('reward', 'N/A')} AIT")
|
||||
logger.info("Genesis block information:")
|
||||
logger.info(f" Hash: {data.get('hash', 'N/A')}")
|
||||
logger.info(f" Number: {data.get('number', 0)}")
|
||||
logger.info(f" Timestamp: {data.get('timestamp', 'N/A')}")
|
||||
logger.info(f" Miner: {data.get('miner', 'N/A')}")
|
||||
logger.info(f" Reward: {data.get('reward', 'N/A')} AIT")
|
||||
else:
|
||||
print(f"Failed to get genesis block: {response.status_code}")
|
||||
logger.error(f"Failed to get genesis block: {response.status_code}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error inspecting genesis block: {e}")
|
||||
logger.error(f"Error inspecting genesis block: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -132,26 +131,26 @@ def handle_blockchain_import(args, default_rpc_url, render_mapping):
|
||||
elif args.json:
|
||||
block_data = json.loads(args.json)
|
||||
else:
|
||||
print("Error: --file or --json is required")
|
||||
logger.error("Error: --file or --json is required")
|
||||
sys.exit(1)
|
||||
|
||||
# Add chain_id if provided
|
||||
if chain_id:
|
||||
block_data["chain_id"] = chain_id
|
||||
|
||||
print(f"Importing block to {rpc_url}...")
|
||||
logger.info(f"Importing block to {rpc_url}...")
|
||||
try:
|
||||
response = requests.post(f"{rpc_url}/rpc/importBlock", json=block_data, timeout=30)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("Block imported successfully")
|
||||
logger.info("Block imported successfully")
|
||||
render_mapping("Import result:", result)
|
||||
else:
|
||||
print(f"Import failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Import failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error importing block: {e}")
|
||||
logger.error(f"Error importing block: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -160,7 +159,7 @@ def handle_blockchain_export(args, default_rpc_url):
|
||||
rpc_url = args.rpc_url or default_rpc_url
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
print(f"Exporting chain from {rpc_url}...")
|
||||
logger.info(f"Exporting chain from {rpc_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -172,15 +171,15 @@ def handle_blockchain_export(args, default_rpc_url):
|
||||
if args.output:
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(chain_data, f, indent=2)
|
||||
print(f"Chain exported to {args.output}")
|
||||
logger.info(f"Chain exported to {args.output}")
|
||||
else:
|
||||
print(json.dumps(chain_data, indent=2))
|
||||
logger.info(json.dumps(chain_data, indent=2))
|
||||
else:
|
||||
print(f"Export failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Export failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error exporting chain: {e}")
|
||||
logger.error(f"Error exporting chain: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -189,25 +188,25 @@ def handle_blockchain_import_chain(args, default_rpc_url, render_mapping):
|
||||
rpc_url = args.rpc_url or default_rpc_url
|
||||
|
||||
if not args.file:
|
||||
print("Error: --file is required")
|
||||
logger.error("Error: --file is required")
|
||||
sys.exit(1)
|
||||
|
||||
with open(args.file) as f:
|
||||
chain_data = json.load(f)
|
||||
|
||||
print(f"Importing chain state to {rpc_url}...")
|
||||
logger.info(f"Importing chain state to {rpc_url}...")
|
||||
try:
|
||||
response = requests.post(f"{rpc_url}/rpc/import-chain", json=chain_data, timeout=120)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("Chain state imported successfully")
|
||||
logger.info("Chain state imported successfully")
|
||||
render_mapping("Import result:", result)
|
||||
else:
|
||||
print(f"Import failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Import failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error importing chain state: {e}")
|
||||
logger.error(f"Error importing chain state: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -224,26 +223,26 @@ def handle_blockchain_blocks_range(args, default_rpc_url, output_format):
|
||||
if chain_id:
|
||||
params["chain_id"] = chain_id
|
||||
|
||||
print(f"Querying blocks range from {rpc_url}...")
|
||||
logger.info(f"Querying blocks range from {rpc_url}...")
|
||||
try:
|
||||
response = requests.get(f"{rpc_url}/rpc/blocks-range", params=params, timeout=30)
|
||||
if response.status_code == 200:
|
||||
blocks_data = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(blocks_data, indent=2))
|
||||
logger.info(json.dumps(blocks_data, indent=2))
|
||||
else:
|
||||
print(f"Blocks range: {args.start or 'head'} to {args.end or 'limit ' + str(args.limit)}")
|
||||
logger.info(f"Blocks range: {args.start or 'head'} to {args.end or 'limit ' + str(args.limit)}")
|
||||
if isinstance(blocks_data, list):
|
||||
for block in blocks_data:
|
||||
print(f" - Block #{block.get('height', 'N/A')}: {block.get('hash', 'N/A')}")
|
||||
logger.info(f" - Block #{block.get('height', 'N/A')}: {block.get('hash', 'N/A')}")
|
||||
else:
|
||||
print(json.dumps(blocks_data, indent=2))
|
||||
logger.info(json.dumps(blocks_data, indent=2))
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error querying blocks range: {e}")
|
||||
logger.error(f"Error querying blocks range: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -252,7 +251,7 @@ def handle_blockchain_transactions(args, default_rpc_url):
|
||||
rpc_url = args.rpc_url or default_rpc_url
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
print(f"Querying transactions from {rpc_url}...")
|
||||
logger.info(f"Querying transactions from {rpc_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if args.address:
|
||||
@@ -268,20 +267,20 @@ def handle_blockchain_transactions(args, default_rpc_url):
|
||||
if response.status_code == 200:
|
||||
transactions = response.json()
|
||||
if isinstance(transactions, list):
|
||||
print(f"Transactions: {len(transactions)} found")
|
||||
logger.info(f"Transactions: {len(transactions)} found")
|
||||
for tx in transactions[:args.limit]:
|
||||
print(f" - Hash: {tx.get('hash', 'N/A')}")
|
||||
print(f" From: {tx.get('from', 'N/A')}")
|
||||
print(f" To: {tx.get('to', 'N/A')}")
|
||||
print(f" Amount: {tx.get('value', 0)} AIT")
|
||||
logger.info(f" - Hash: {tx.get('hash', 'N/A')}")
|
||||
logger.info(f" From: {tx.get('from', 'N/A')}")
|
||||
logger.info(f" To: {tx.get('to', 'N/A')}")
|
||||
logger.info(f" Amount: {tx.get('value', 0)} AIT")
|
||||
else:
|
||||
print(json.dumps(transactions, indent=2))
|
||||
logger.info(json.dumps(transactions, indent=2))
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error querying transactions: {e}")
|
||||
logger.error(f"Error querying transactions: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -290,7 +289,7 @@ def handle_blockchain_mempool(args, default_rpc_url):
|
||||
rpc_url = args.rpc_url or default_rpc_url
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
print(f"Getting pending transactions from {rpc_url}...")
|
||||
logger.info(f"Getting pending transactions from {rpc_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -300,17 +299,17 @@ def handle_blockchain_mempool(args, default_rpc_url):
|
||||
if response.status_code == 200:
|
||||
mempool = response.json()
|
||||
if isinstance(mempool, list):
|
||||
print(f"Pending transactions: {len(mempool)}")
|
||||
logger.info(f"Pending transactions: {len(mempool)}")
|
||||
for tx in mempool:
|
||||
print(f" - Hash: {tx.get('hash', 'N/A')}")
|
||||
print(f" From: {tx.get('from', 'N/A')}")
|
||||
print(f" Amount: {tx.get('value', 0)} AIT")
|
||||
logger.info(f" - Hash: {tx.get('hash', 'N/A')}")
|
||||
logger.info(f" From: {tx.get('from', 'N/A')}")
|
||||
logger.info(f" Amount: {tx.get('value', 0)} AIT")
|
||||
else:
|
||||
print(json.dumps(mempool, indent=2))
|
||||
logger.info(json.dumps(mempool, indent=2))
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error getting mempool: {e}")
|
||||
logger.error(f"Error getting mempool: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
import subprocess
|
||||
|
||||
from aitbc import AITBCHTTPClient, NetworkError
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_bridge_health(args):
|
||||
@@ -12,24 +15,22 @@ def handle_bridge_health(args):
|
||||
config = get_bridge_config()
|
||||
|
||||
if args.test_mode:
|
||||
print("🏥 Blockchain Event Bridge Health (test mode):")
|
||||
print("✅ Status: healthy")
|
||||
print("📦 Service: blockchain-event-bridge")
|
||||
logger.info("🏥 Blockchain Event Bridge Health (test mode):")
|
||||
logger.info("✅ Status: healthy")
|
||||
logger.info("📦 Service: blockchain-event-bridge")
|
||||
return
|
||||
|
||||
bridge_url = getattr(config, "bridge_url", "http://localhost:8204")
|
||||
http_client = AITBCHTTPClient(base_url=bridge_url, timeout=10)
|
||||
health = http_client.get("/health")
|
||||
|
||||
print("🏥 Blockchain Event Bridge Health:")
|
||||
logger.info("🏥 Blockchain Event Bridge Health:")
|
||||
for key, value in health.items():
|
||||
print(f" {key}: {value}")
|
||||
logger.info(f" {key}: {value}")
|
||||
except NetworkError as e:
|
||||
print(f"❌ Health check failed: {e}")
|
||||
logger.error(f"❌ Health check failed: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error checking health: {e}")
|
||||
|
||||
|
||||
logger.error(f"❌ Error checking health: {e}")
|
||||
def handle_bridge_metrics(args):
|
||||
"""Get Prometheus metrics from blockchain event bridge service."""
|
||||
try:
|
||||
@@ -37,23 +38,21 @@ def handle_bridge_metrics(args):
|
||||
config = get_bridge_config()
|
||||
|
||||
if args.test_mode:
|
||||
print("📊 Prometheus Metrics (test mode):")
|
||||
print(" bridge_events_total: 103691")
|
||||
print(" bridge_events_processed_total: 103691")
|
||||
logger.info("📊 Prometheus Metrics (test mode):")
|
||||
logger.info(" bridge_events_total: 103691")
|
||||
logger.info(" bridge_events_processed_total: 103691")
|
||||
return
|
||||
|
||||
bridge_url = getattr(config, "bridge_url", "http://localhost:8204")
|
||||
http_client = AITBCHTTPClient(base_url=bridge_url, timeout=10)
|
||||
metrics = http_client.get("/metrics", return_response=True)
|
||||
|
||||
print("📊 Prometheus Metrics:")
|
||||
print(metrics.text)
|
||||
logger.info("📊 Prometheus Metrics:")
|
||||
logger.info(metrics.text)
|
||||
except NetworkError as e:
|
||||
print(f"❌ Failed to get metrics: {e}")
|
||||
logger.error(f"❌ Failed to get metrics: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error getting metrics: {e}")
|
||||
|
||||
|
||||
logger.error(f"❌ Error getting metrics: {e}")
|
||||
def handle_bridge_status(args):
|
||||
"""Get detailed status of blockchain event bridge service."""
|
||||
try:
|
||||
@@ -61,24 +60,22 @@ def handle_bridge_status(args):
|
||||
config = get_bridge_config()
|
||||
|
||||
if args.test_mode:
|
||||
print("📊 Blockchain Event Bridge Status (test mode):")
|
||||
print("✅ Status: running")
|
||||
print("🔔 Subscriptions: blocks, transactions, contract_events")
|
||||
logger.info("📊 Blockchain Event Bridge Status (test mode):")
|
||||
logger.info("✅ Status: running")
|
||||
logger.info("🔔 Subscriptions: blocks, transactions, contract_events")
|
||||
return
|
||||
|
||||
bridge_url = getattr(config, "bridge_url", "http://localhost:8204")
|
||||
http_client = AITBCHTTPClient(base_url=bridge_url, timeout=10)
|
||||
status = http_client.get("/")
|
||||
|
||||
print("📊 Blockchain Event Bridge Status:")
|
||||
logger.info("📊 Blockchain Event Bridge Status:")
|
||||
for key, value in status.items():
|
||||
print(f" {key}: {value}")
|
||||
logger.info(f" {key}: {value}")
|
||||
except NetworkError as e:
|
||||
print(f"❌ Failed to get status: {e}")
|
||||
logger.error(f"❌ Failed to get status: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error getting status: {e}")
|
||||
|
||||
|
||||
logger.error(f"❌ Error getting status: {e}")
|
||||
def handle_bridge_config(args):
|
||||
"""Show current configuration of blockchain event bridge service."""
|
||||
try:
|
||||
@@ -86,30 +83,28 @@ def handle_bridge_config(args):
|
||||
config = get_bridge_config()
|
||||
|
||||
if args.test_mode:
|
||||
print("⚙️ Blockchain Event Bridge Configuration (test mode):")
|
||||
print("🔗 Blockchain RPC URL: http://localhost:8006")
|
||||
print("💬 Gossip Backend: redis")
|
||||
logger.info("⚙️ Blockchain Event Bridge Configuration (test mode):")
|
||||
logger.info("🔗 Blockchain RPC URL: http://localhost:8006")
|
||||
logger.info("💬 Gossip Backend: redis")
|
||||
return
|
||||
|
||||
bridge_url = getattr(config, "bridge_url", "http://localhost:8204")
|
||||
http_client = AITBCHTTPClient(base_url=bridge_url, timeout=10)
|
||||
service_config = http_client.get("/config")
|
||||
|
||||
print("⚙️ Blockchain Event Bridge Configuration:")
|
||||
logger.info("⚙️ Blockchain Event Bridge Configuration:")
|
||||
for key, value in service_config.items():
|
||||
print(f" {key}: {value}")
|
||||
logger.info(f" {key}: {value}")
|
||||
except NetworkError as e:
|
||||
print(f"❌ Failed to get config: {e}")
|
||||
logger.error(f"❌ Failed to get config: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error getting config: {e}")
|
||||
|
||||
|
||||
logger.error(f"❌ Error getting config: {e}")
|
||||
def handle_bridge_restart(args):
|
||||
"""Restart blockchain event bridge service (via systemd)."""
|
||||
try:
|
||||
if args.test_mode:
|
||||
print("🔄 Blockchain event bridge restart triggered (test mode)")
|
||||
print("✅ Restart completed successfully")
|
||||
logger.info("🔄 Blockchain event bridge restart triggered (test mode)")
|
||||
logger.info("✅ Restart completed successfully")
|
||||
return
|
||||
|
||||
result = subprocess.run(
|
||||
@@ -120,13 +115,13 @@ def handle_bridge_restart(args):
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
print("🔄 Blockchain event bridge restart triggered")
|
||||
print("✅ Restart completed successfully")
|
||||
logger.info("🔄 Blockchain event bridge restart triggered")
|
||||
logger.info("✅ Restart completed successfully")
|
||||
else:
|
||||
print(f"❌ Restart failed: {result.stderr}")
|
||||
logger.error(f"❌ Restart failed: {result.stderr}")
|
||||
except subprocess.TimeoutExpired:
|
||||
print("❌ Restart timeout - service may be starting")
|
||||
logger.info("❌ Restart timeout - service may be starting")
|
||||
except FileNotFoundError:
|
||||
print("❌ systemctl not found - cannot restart service")
|
||||
logger.info("❌ systemctl not found - cannot restart service")
|
||||
except Exception as e:
|
||||
print(f"❌ Error restarting service: {e}")
|
||||
logger.error(f"❌ Error restarting service: {e}")
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
import requests
|
||||
from typing import Optional, Dict, Any
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_contract_list(args, default_rpc_url: str):
|
||||
@@ -16,21 +19,19 @@ def handle_contract_list(args, default_rpc_url: str):
|
||||
if data.get("success") is not False:
|
||||
contracts = data.get("contracts", [])
|
||||
if contracts:
|
||||
print(f"Deployed contracts ({len(contracts)}):")
|
||||
logger.info(f"Deployed contracts ({len(contracts)}):")
|
||||
for contract in contracts:
|
||||
print(f" - Address: {contract.get('address', 'N/A')}")
|
||||
print(f" Type: {contract.get('type', 'N/A')}")
|
||||
print(f" Deployed: {contract.get('deployed_at', 'N/A')}")
|
||||
logger.info(f" - Address: {contract.get('address', 'N/A')}")
|
||||
logger.info(f" Type: {contract.get('type', 'N/A')}")
|
||||
logger.info(f" Deployed: {contract.get('deployed_at', 'N/A')}")
|
||||
else:
|
||||
print("No contracts deployed")
|
||||
logger.info("No contracts deployed")
|
||||
else:
|
||||
print(f"Error: {data.get('error', 'Unknown error')}")
|
||||
logger.error(f"Error: {data.get('error', 'Unknown error')}")
|
||||
else:
|
||||
print(f"Error: RPC returned {response.status_code}")
|
||||
logger.error(f"Error: RPC returned {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"Error listing contracts: {e}")
|
||||
|
||||
|
||||
logger.error(f"Error listing contracts: {e}")
|
||||
def handle_contract_deploy(args, default_rpc_url: str, read_password, render_mapping):
|
||||
"""Handle contract deploy command"""
|
||||
rpc_url = args.rpc_url if hasattr(args, 'rpc_url') and args.rpc_url else default_rpc_url
|
||||
@@ -38,12 +39,12 @@ def handle_contract_deploy(args, default_rpc_url: str, read_password, render_map
|
||||
contract_type = getattr(args, 'type', 'zk-verifier')
|
||||
|
||||
if not contract_name:
|
||||
print("Error: Contract name is required (--name)")
|
||||
logger.error("Error: Contract name is required (--name)")
|
||||
return
|
||||
|
||||
password = read_password(args)
|
||||
if not password:
|
||||
print("Error: Wallet password is required (--password or --password-file)")
|
||||
logger.error("Error: Wallet password is required (--password or --password-file)")
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -64,13 +65,11 @@ def handle_contract_deploy(args, default_rpc_url: str, read_password, render_map
|
||||
if data.get("success"):
|
||||
render_mapping("Contract deployed successfully", data)
|
||||
else:
|
||||
print(f"Error: {data.get('error', 'Unknown error')}")
|
||||
logger.error(f"Error: {data.get('error', 'Unknown error')}")
|
||||
else:
|
||||
print(f"Error: RPC returned {response.status_code}")
|
||||
logger.error(f"Error: RPC returned {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"Error deploying contract: {e}")
|
||||
|
||||
|
||||
logger.error(f"Error deploying contract: {e}")
|
||||
def handle_contract_call(args, default_rpc_url: str, read_password):
|
||||
"""Handle contract call command"""
|
||||
rpc_url = args.rpc_url if hasattr(args, 'rpc_url') and args.rpc_url else default_rpc_url
|
||||
@@ -78,11 +77,11 @@ def handle_contract_call(args, default_rpc_url: str, read_password):
|
||||
method = getattr(args, 'method', None)
|
||||
|
||||
if not contract_address:
|
||||
print("Error: Contract address is required (--address)")
|
||||
logger.error("Error: Contract address is required (--address)")
|
||||
return
|
||||
|
||||
if not method:
|
||||
print("Error: Method name is required (--method)")
|
||||
logger.error("Error: Method name is required (--method)")
|
||||
return
|
||||
|
||||
password = read_password(args)
|
||||
@@ -112,25 +111,23 @@ def handle_contract_call(args, default_rpc_url: str, read_password):
|
||||
data = response.json()
|
||||
if data.get("success"):
|
||||
result = data.get("result")
|
||||
print(f"Contract call result:")
|
||||
print(f" Address: {contract_address}")
|
||||
print(f" Method: {method}")
|
||||
print(f" Result: {result}")
|
||||
logger.info(f"Contract call result:")
|
||||
logger.info(f" Address: {contract_address}")
|
||||
logger.info(f" Method: {method}")
|
||||
logger.info(f" Result: {result}")
|
||||
else:
|
||||
print(f"Error: {data.get('error', 'Unknown error')}")
|
||||
logger.error(f"Error: {data.get('error', 'Unknown error')}")
|
||||
else:
|
||||
print(f"Error: RPC returned {response.status_code}")
|
||||
logger.error(f"Error: RPC returned {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"Error calling contract: {e}")
|
||||
|
||||
|
||||
logger.error(f"Error calling contract: {e}")
|
||||
def handle_contract_verify(args, default_rpc_url: str, read_password):
|
||||
"""Handle contract verify command (for ZK proofs)"""
|
||||
rpc_url = args.rpc_url if hasattr(args, 'rpc_url') and args.rpc_url else default_rpc_url
|
||||
contract_address = getattr(args, 'address', None)
|
||||
|
||||
if not contract_address:
|
||||
print("Error: Contract address is required (--address)")
|
||||
logger.error("Error: Contract address is required (--address)")
|
||||
return
|
||||
|
||||
password = read_password(args)
|
||||
@@ -162,14 +159,14 @@ def handle_contract_verify(args, default_rpc_url: str, read_password):
|
||||
data = response.json()
|
||||
if data.get("success"):
|
||||
result = data.get("result")
|
||||
print(f"Verification result:")
|
||||
print(f" Address: {contract_address}")
|
||||
print(f" Valid: {result.get('valid', False)}")
|
||||
logger.info(f"Verification result:")
|
||||
logger.info(f" Address: {contract_address}")
|
||||
logger.info(f" Valid: {result.get('valid', False)}")
|
||||
if result.get('receipt_hash'):
|
||||
print(f" Receipt Hash: {result.get('receipt_hash')}")
|
||||
logger.info(f" Receipt Hash: {result.get('receipt_hash')}")
|
||||
else:
|
||||
print(f"Error: {data.get('error', 'Unknown error')}")
|
||||
logger.error(f"Error: {data.get('error', 'Unknown error')}")
|
||||
else:
|
||||
print(f"Error: RPC returned {response.status_code}")
|
||||
logger.error(f"Error: RPC returned {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"Error verifying contract: {e}")
|
||||
logger.error(f"Error verifying contract: {e}")
|
||||
@@ -4,6 +4,9 @@ import json
|
||||
import os
|
||||
import sys
|
||||
import requests
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def _marketplace_url(args, fallback=None):
|
||||
@@ -38,7 +41,7 @@ def handle_market_listings(args, default_coordinator_url, output_format, render_
|
||||
marketplace_url = _marketplace_url(args, default_coordinator_url)
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
print(f"Getting marketplace listings from {marketplace_url}...")
|
||||
logger.info(f"Getting marketplace listings from {marketplace_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -48,26 +51,26 @@ def handle_market_listings(args, default_coordinator_url, output_format, render_
|
||||
if response.status_code == 200:
|
||||
listings = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(listings, indent=2))
|
||||
logger.info(json.dumps(listings, indent=2))
|
||||
else:
|
||||
print("Marketplace listings:")
|
||||
logger.info("Marketplace listings:")
|
||||
if isinstance(listings, list):
|
||||
if listings:
|
||||
for listing in listings:
|
||||
print(f" - ID: {listing.get('id', 'N/A')}")
|
||||
print(f" Model: {listing.get('model', 'N/A')}")
|
||||
print(f" Price: {listing.get('price_per_hour', 0)} AIT/hour")
|
||||
print(f" Status: {listing.get('status', 'N/A')}")
|
||||
logger.info(f" - ID: {listing.get('id', 'N/A')}")
|
||||
logger.info(f" Model: {listing.get('model', 'N/A')}")
|
||||
logger.info(f" Price: {listing.get('price_per_hour', 0)} AIT/hour")
|
||||
logger.info(f" Status: {listing.get('status', 'N/A')}")
|
||||
else:
|
||||
print(" No GPU listings found")
|
||||
logger.info(" No GPU listings found")
|
||||
else:
|
||||
render_mapping("Listings:", listings)
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Error getting listings: {e}")
|
||||
logger.error(f"Error getting listings: {e}")
|
||||
return
|
||||
|
||||
|
||||
@@ -81,7 +84,7 @@ def handle_market_create(args, default_coordinator_url, read_password, render_ma
|
||||
price = getattr(args, "price", None)
|
||||
|
||||
if not wallet or price is None:
|
||||
print("Error: --wallet and --price are required")
|
||||
logger.error("Error: --wallet and --price are required")
|
||||
return
|
||||
|
||||
headers = _auth_headers(args, read_password)
|
||||
@@ -96,19 +99,19 @@ def handle_market_create(args, default_coordinator_url, read_password, render_ma
|
||||
if chain_id:
|
||||
listing_data["chain_id"] = chain_id
|
||||
|
||||
print(f"Creating marketplace listing on {marketplace_url}...")
|
||||
logger.info(f"Creating marketplace listing on {marketplace_url}...")
|
||||
try:
|
||||
response = requests.post(f"{marketplace_url}/v1/marketplace/offers", json=listing_data, headers=headers, timeout=30)
|
||||
if response.status_code in (200, 201):
|
||||
result = response.json()
|
||||
print("Listing created successfully")
|
||||
logger.info("Listing created successfully")
|
||||
render_mapping("Listing:", result)
|
||||
else:
|
||||
print(f"Creation failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Creation failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Error creating listing: {e}")
|
||||
logger.error(f"Error creating listing: {e}")
|
||||
return
|
||||
|
||||
|
||||
@@ -118,22 +121,22 @@ def handle_market_get(args, default_rpc_url):
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
if not args.listing_id:
|
||||
print("Error: --listing-id is required")
|
||||
logger.error("Error: --listing-id is required")
|
||||
return
|
||||
|
||||
print(f"Getting listing {args.listing_id} from {marketplace_url}...")
|
||||
logger.info(f"Getting listing {args.listing_id} from {marketplace_url}...")
|
||||
try:
|
||||
import requests
|
||||
response = requests.get(f"{marketplace_url}/v1/marketplace/offers/{args.listing_id}", timeout=10)
|
||||
if response.status_code == 200:
|
||||
listing = response.json()
|
||||
print(json.dumps(listing, indent=2))
|
||||
logger.info(json.dumps(listing, indent=2))
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Error getting listing: {e}")
|
||||
logger.error(f"Error getting listing: {e}")
|
||||
return
|
||||
|
||||
|
||||
@@ -143,25 +146,25 @@ def handle_market_delete(args, default_coordinator_url, read_password, render_ma
|
||||
listing_id = getattr(args, "listing_id", None) or getattr(args, "order", None)
|
||||
|
||||
if not listing_id:
|
||||
print("Error: --listing-id or --order is required")
|
||||
logger.error("Error: --listing-id or --order is required")
|
||||
return
|
||||
|
||||
headers = _auth_headers(args, read_password)
|
||||
endpoint_type = "orders" if str(listing_id).startswith("order_") else "offers"
|
||||
|
||||
print(f"Deleting {endpoint_type[:-1]} {listing_id} on {marketplace_url}...")
|
||||
logger.info(f"Deleting {endpoint_type[:-1]} {listing_id} on {marketplace_url}...")
|
||||
try:
|
||||
response = requests.delete(f"{marketplace_url}/v1/marketplace/{endpoint_type}/{listing_id}", headers=headers, timeout=30)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("Marketplace item deleted successfully")
|
||||
logger.info("Marketplace item deleted successfully")
|
||||
render_mapping("Delete result:", result)
|
||||
else:
|
||||
print(f"Deletion failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Deletion failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Error deleting listing: {e}")
|
||||
logger.error(f"Error deleting listing: {e}")
|
||||
return
|
||||
|
||||
|
||||
@@ -176,7 +179,7 @@ def handle_market_gpu_register(args, default_coordinator_url):
|
||||
compute_capability = getattr(args, "compute_capability", None)
|
||||
|
||||
if not gpu_name or memory_gb is None:
|
||||
print("Auto-detecting GPU specifications from nvidia-smi...")
|
||||
logger.info("Auto-detecting GPU specifications from nvidia-smi...")
|
||||
try:
|
||||
import subprocess
|
||||
result = subprocess.run(
|
||||
@@ -199,26 +202,25 @@ def handle_market_gpu_register(args, default_coordinator_url):
|
||||
|
||||
if not gpu_name:
|
||||
gpu_name = detected_name
|
||||
print(f" Detected GPU: {gpu_name}")
|
||||
logger.info(f" Detected GPU: {gpu_name}")
|
||||
if memory_gb is None:
|
||||
memory_gb = memory_gb_detected
|
||||
print(f" Detected Memory: {memory_gb} GB")
|
||||
logger.info(f" Detected Memory: {memory_gb} GB")
|
||||
if not compute_capability:
|
||||
compute_capability = detected_compute
|
||||
print(f" Detected Compute Capability: {compute_capability}")
|
||||
logger.info(f" Detected Compute Capability: {compute_capability}")
|
||||
else:
|
||||
print(" Warning: nvidia-smi failed, using manual input or defaults")
|
||||
logger.error(" Warning: nvidia-smi failed, using manual input or defaults")
|
||||
except (subprocess.TimeoutExpired, FileNotFoundError, Exception) as e:
|
||||
print(f" Warning: Could not run nvidia-smi: {e}")
|
||||
|
||||
logger.warning(f" Warning: Could not run nvidia-smi: {e}")
|
||||
# Fallback to manual input if auto-detection failed
|
||||
if not gpu_name or memory_gb is None:
|
||||
print("Error: Could not auto-detect GPU specs. Please provide --name and --memory manually.")
|
||||
print(" Example: aitbc-cli market gpu register --name 'NVIDIA GeForce RTX 4060 Ti' --memory 16 --price-per-hour 0.05")
|
||||
logger.error("Error: Could not auto-detect GPU specs. Please provide --name and --memory manually.")
|
||||
logger.info(" Example: aitbc-cli market gpu register --name 'NVIDIA GeForce RTX 4060 Ti' --memory 16 --price-per-hour 0.05")
|
||||
return
|
||||
|
||||
if not args.price_per_hour:
|
||||
print("Error: --price-per-hour is required (in AIT coins)")
|
||||
logger.error("Error: --price-per-hour is required (in AIT coins)")
|
||||
return
|
||||
|
||||
# Build GPU specs
|
||||
@@ -233,7 +235,7 @@ def handle_market_gpu_register(args, default_coordinator_url):
|
||||
"registered_at": __import__("datetime").datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Registering GPU on {gpu_url}...")
|
||||
logger.info(f"Registering GPU on {gpu_url}...")
|
||||
try:
|
||||
response = requests.post(
|
||||
f"{gpu_url}/v1/marketplace/gpu/register",
|
||||
@@ -246,15 +248,15 @@ def handle_market_gpu_register(args, default_coordinator_url):
|
||||
)
|
||||
if response.status_code in (200, 201):
|
||||
result = response.json()
|
||||
print(f"GPU registered successfully: {result.get('gpu_id', 'N/A')}")
|
||||
logger.info(f"GPU registered successfully: {result.get('gpu_id', 'N/A')}")
|
||||
from ..utils import render_mapping
|
||||
render_mapping("Registration result:", result)
|
||||
else:
|
||||
print(f"Registration failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Registration failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Error registering GPU: {e}")
|
||||
logger.error(f"Error registering GPU: {e}")
|
||||
return
|
||||
|
||||
|
||||
@@ -263,7 +265,7 @@ def handle_market_gpu_list(args, default_coordinator_url, output_format):
|
||||
# Use GPU service URL instead of coordinator URL
|
||||
gpu_url = getattr(args, 'gpu_url', 'http://localhost:8101')
|
||||
|
||||
print(f"Listing GPUs from {gpu_url}...")
|
||||
logger.info(f"Listing GPUs from {gpu_url}...")
|
||||
try:
|
||||
params = {
|
||||
"action": "offer",
|
||||
@@ -284,30 +286,30 @@ def handle_market_gpu_list(args, default_coordinator_url, output_format):
|
||||
if response.status_code == 200:
|
||||
gpus = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(gpus, indent=2))
|
||||
logger.info(json.dumps(gpus, indent=2))
|
||||
else:
|
||||
print("GPU Listings:")
|
||||
logger.info("GPU Listings:")
|
||||
if isinstance(gpus, list):
|
||||
if gpus:
|
||||
for gpu in gpus:
|
||||
if isinstance(gpu, dict):
|
||||
print(f" - ID: {gpu.get('id', 'N/A')}")
|
||||
print(f" Model: {gpu.get('model', 'N/A')}")
|
||||
print(f" Memory: {gpu.get('memory_gb', 'N/A')} GB")
|
||||
print(f" Price: {gpu.get('price_per_hour', 0)} AIT/hour")
|
||||
print(f" Status: {gpu.get('status', 'N/A')}")
|
||||
print(f" Region: {gpu.get('region', 'N/A')}")
|
||||
logger.info(f" - ID: {gpu.get('id', 'N/A')}")
|
||||
logger.info(f" Model: {gpu.get('model', 'N/A')}")
|
||||
logger.info(f" Memory: {gpu.get('memory_gb', 'N/A')} GB")
|
||||
logger.info(f" Price: {gpu.get('price_per_hour', 0)} AIT/hour")
|
||||
logger.info(f" Status: {gpu.get('status', 'N/A')}")
|
||||
logger.info(f" Region: {gpu.get('region', 'N/A')}")
|
||||
else:
|
||||
print(" No GPUs found")
|
||||
logger.info(" No GPUs found")
|
||||
else:
|
||||
from ..utils import render_mapping
|
||||
render_mapping("GPUs:", gpus)
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Error listing GPUs: {e}")
|
||||
logger.error(f"Error listing GPUs: {e}")
|
||||
return
|
||||
|
||||
|
||||
@@ -316,7 +318,7 @@ def handle_market_buy(args, default_coordinator_url, read_password, render_mappi
|
||||
marketplace_url = _marketplace_url(args, default_coordinator_url)
|
||||
|
||||
if not args.item or not args.wallet:
|
||||
print("Error: --item and --wallet are required")
|
||||
logger.error("Error: --item and --wallet are required")
|
||||
return
|
||||
|
||||
purchase_data = {
|
||||
@@ -325,19 +327,19 @@ def handle_market_buy(args, default_coordinator_url, read_password, render_mappi
|
||||
"price": getattr(args, "price", None)
|
||||
}
|
||||
|
||||
print(f"Submitting purchase to {marketplace_url}...")
|
||||
logger.info(f"Submitting purchase to {marketplace_url}...")
|
||||
try:
|
||||
response = requests.post(f"{marketplace_url}/v1/marketplace/offers/{args.item}/book", json=purchase_data, headers=_auth_headers(args, read_password), timeout=30)
|
||||
if response.status_code in (200, 201):
|
||||
result = response.json()
|
||||
print("Purchase submitted successfully")
|
||||
logger.info("Purchase submitted successfully")
|
||||
render_mapping("Purchase:", result)
|
||||
else:
|
||||
print(f"Purchase failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Purchase failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Error submitting purchase: {e}")
|
||||
logger.error(f"Error submitting purchase: {e}")
|
||||
return
|
||||
|
||||
|
||||
@@ -354,32 +356,32 @@ def handle_market_orders(args, default_coordinator_url, output_format, render_ma
|
||||
if wallet:
|
||||
params["wallet"] = wallet
|
||||
|
||||
print(f"Getting marketplace orders from {marketplace_url}...")
|
||||
logger.info(f"Getting marketplace orders from {marketplace_url}...")
|
||||
try:
|
||||
response = requests.get(f"{marketplace_url}/v1/marketplace/orders", params=params, timeout=10)
|
||||
if response.status_code == 200:
|
||||
orders = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(orders, indent=2))
|
||||
logger.info(json.dumps(orders, indent=2))
|
||||
return
|
||||
if isinstance(orders, dict):
|
||||
orders = orders.get("orders", [])
|
||||
print("Active marketplace orders:")
|
||||
logger.info("Active marketplace orders:")
|
||||
if not orders:
|
||||
print(" No active orders found")
|
||||
logger.info(" No active orders found")
|
||||
return
|
||||
for order in orders:
|
||||
print(f" - ID: {order.get('id', 'N/A')}")
|
||||
print(f" Type: {order.get('order_type', 'N/A')}")
|
||||
print(f" Item: {order.get('item', 'N/A')}")
|
||||
print(f" Price: {order.get('price', 0)} AIT")
|
||||
print(f" Status: {order.get('status', 'N/A')}")
|
||||
logger.info(f" - ID: {order.get('id', 'N/A')}")
|
||||
logger.info(f" Type: {order.get('order_type', 'N/A')}")
|
||||
logger.info(f" Item: {order.get('item', 'N/A')}")
|
||||
logger.info(f" Price: {order.get('price', 0)} AIT")
|
||||
logger.info(f" Status: {order.get('status', 'N/A')}")
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Error getting orders: {e}")
|
||||
logger.error(f"Error getting orders: {e}")
|
||||
return
|
||||
|
||||
|
||||
@@ -387,31 +389,31 @@ def handle_market_list_plugins(args, default_coordinator_url, output_format, ren
|
||||
"""Handle marketplace plugin listing command."""
|
||||
marketplace_url = _marketplace_url(args, default_coordinator_url)
|
||||
|
||||
print(f"Getting marketplace plugins from {marketplace_url}...")
|
||||
logger.info(f"Getting marketplace plugins from {marketplace_url}...")
|
||||
try:
|
||||
response = requests.get(f"{marketplace_url}/v1/marketplace/plugins", timeout=10)
|
||||
if response.status_code == 200:
|
||||
plugins = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(plugins, indent=2))
|
||||
logger.info(json.dumps(plugins, indent=2))
|
||||
return
|
||||
if isinstance(plugins, dict):
|
||||
plugins = plugins.get("plugins", [])
|
||||
print("Available marketplace plugins:")
|
||||
logger.info("Available marketplace plugins:")
|
||||
if not plugins:
|
||||
print(" No plugins found")
|
||||
logger.info(" No plugins found")
|
||||
return
|
||||
for plugin in plugins:
|
||||
print(f" - ID: {plugin.get('id', 'N/A')}")
|
||||
print(f" Name: {plugin.get('name', 'N/A')}")
|
||||
print(f" Type: {plugin.get('type', 'N/A')}")
|
||||
print(f" Author: {plugin.get('author', 'N/A')}")
|
||||
print(f" Description: {plugin.get('description', 'N/A')}")
|
||||
print(f" Version: {plugin.get('version', 'N/A')}")
|
||||
logger.info(f" - ID: {plugin.get('id', 'N/A')}")
|
||||
logger.info(f" Name: {plugin.get('name', 'N/A')}")
|
||||
logger.info(f" Type: {plugin.get('type', 'N/A')}")
|
||||
logger.info(f" Author: {plugin.get('author', 'N/A')}")
|
||||
logger.info(f" Description: {plugin.get('description', 'N/A')}")
|
||||
logger.info(f" Version: {plugin.get('version', 'N/A')}")
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Error getting plugins: {e}")
|
||||
logger.error(f"Error getting plugins: {e}")
|
||||
return
|
||||
|
||||
@@ -4,6 +4,9 @@ import json
|
||||
import sys
|
||||
|
||||
import requests
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_messaging_deploy(args, default_rpc_url, render_mapping):
|
||||
@@ -11,7 +14,7 @@ def handle_messaging_deploy(args, default_rpc_url, render_mapping):
|
||||
rpc_url = args.rpc_url or default_rpc_url
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
print(f"Deploying messaging contract to {rpc_url}...")
|
||||
logger.info(f"Deploying messaging contract to {rpc_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -20,14 +23,14 @@ def handle_messaging_deploy(args, default_rpc_url, render_mapping):
|
||||
response = requests.post(f"{rpc_url}/rpc/contracts/deploy/messaging", json={}, params=params, timeout=30)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("Messaging contract deployed successfully")
|
||||
logger.info("Messaging contract deployed successfully")
|
||||
render_mapping("Deployment result:", result)
|
||||
else:
|
||||
print(f"Deployment failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Deployment failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error deploying messaging contract: {e}")
|
||||
logger.error(f"Error deploying messaging contract: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -36,7 +39,7 @@ def handle_messaging_state(args, default_rpc_url, output_format, render_mapping)
|
||||
rpc_url = args.rpc_url or default_rpc_url
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
print(f"Getting messaging contract state from {rpc_url}...")
|
||||
logger.info(f"Getting messaging contract state from {rpc_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -46,15 +49,15 @@ def handle_messaging_state(args, default_rpc_url, output_format, render_mapping)
|
||||
if response.status_code == 200:
|
||||
state = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(state, indent=2))
|
||||
logger.info(json.dumps(state, indent=2))
|
||||
else:
|
||||
render_mapping("Messaging contract state:", state)
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error getting contract state: {e}")
|
||||
logger.error(f"Error getting contract state: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -63,7 +66,7 @@ def handle_messaging_topics(args, default_rpc_url, output_format, render_mapping
|
||||
rpc_url = args.rpc_url or default_rpc_url
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
print(f"Getting forum topics from {rpc_url}...")
|
||||
logger.info(f"Getting forum topics from {rpc_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -73,20 +76,20 @@ def handle_messaging_topics(args, default_rpc_url, output_format, render_mapping
|
||||
if response.status_code == 200:
|
||||
topics = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(topics, indent=2))
|
||||
logger.info(json.dumps(topics, indent=2))
|
||||
else:
|
||||
print("Forum topics:")
|
||||
logger.info("Forum topics:")
|
||||
if isinstance(topics, list):
|
||||
for topic in topics:
|
||||
print(f" ID: {topic.get('topic_id', 'N/A')}, Title: {topic.get('title', 'N/A')}")
|
||||
logger.info(f" ID: {topic.get('topic_id', 'N/A')}, Title: {topic.get('title', 'N/A')}")
|
||||
else:
|
||||
render_mapping("Topics:", topics)
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error getting topics: {e}")
|
||||
logger.error(f"Error getting topics: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -96,7 +99,7 @@ def handle_messaging_create_topic(args, default_rpc_url, read_password, render_m
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
if not args.title or not args.content:
|
||||
print("Error: --title and --content are required")
|
||||
logger.error("Error: --title and --content are required")
|
||||
sys.exit(1)
|
||||
|
||||
# Get auth headers if wallet provided
|
||||
@@ -113,19 +116,19 @@ def handle_messaging_create_topic(args, default_rpc_url, read_password, render_m
|
||||
if chain_id:
|
||||
topic_data["chain_id"] = chain_id
|
||||
|
||||
print(f"Creating forum topic on {rpc_url}...")
|
||||
logger.info(f"Creating forum topic on {rpc_url}...")
|
||||
try:
|
||||
response = requests.post(f"{rpc_url}/rpc/messaging/topics/create", json=topic_data, headers=headers, timeout=30)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("Topic created successfully")
|
||||
logger.info("Topic created successfully")
|
||||
render_mapping("Topic:", result)
|
||||
else:
|
||||
print(f"Creation failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Creation failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error creating topic: {e}")
|
||||
logger.error(f"Error creating topic: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -135,10 +138,10 @@ def handle_messaging_messages(args, default_rpc_url, output_format, render_mappi
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
if not args.topic_id:
|
||||
print("Error: --topic-id is required")
|
||||
logger.error("Error: --topic-id is required")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Getting messages for topic {args.topic_id} from {rpc_url}...")
|
||||
logger.info(f"Getting messages for topic {args.topic_id} from {rpc_url}...")
|
||||
try:
|
||||
params = {"topic_id": args.topic_id}
|
||||
if chain_id:
|
||||
@@ -148,20 +151,20 @@ def handle_messaging_messages(args, default_rpc_url, output_format, render_mappi
|
||||
if response.status_code == 200:
|
||||
messages = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(messages, indent=2))
|
||||
logger.info(json.dumps(messages, indent=2))
|
||||
else:
|
||||
print(f"Messages for topic {args.topic_id}:")
|
||||
logger.info(f"Messages for topic {args.topic_id}:")
|
||||
if isinstance(messages, list):
|
||||
for msg in messages:
|
||||
print(f" Message ID: {msg.get('message_id', 'N/A')}, Author: {msg.get('author', 'N/A')}")
|
||||
logger.info(f" Message ID: {msg.get('message_id', 'N/A')}, Author: {msg.get('author', 'N/A')}")
|
||||
else:
|
||||
render_mapping("Messages:", messages)
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error getting messages: {e}")
|
||||
logger.error(f"Error getting messages: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -171,7 +174,7 @@ def handle_messaging_post(args, default_rpc_url, read_password, render_mapping):
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
if not args.topic_id or not args.content:
|
||||
print("Error: --topic-id and --content are required")
|
||||
logger.error("Error: --topic-id and --content are required")
|
||||
sys.exit(1)
|
||||
|
||||
# Get auth headers if wallet provided
|
||||
@@ -188,19 +191,19 @@ def handle_messaging_post(args, default_rpc_url, read_password, render_mapping):
|
||||
if chain_id:
|
||||
message_data["chain_id"] = chain_id
|
||||
|
||||
print(f"Posting message to topic {args.topic_id} on {rpc_url}...")
|
||||
logger.info(f"Posting message to topic {args.topic_id} on {rpc_url}...")
|
||||
try:
|
||||
response = requests.post(f"{rpc_url}/rpc/messaging/messages/post", json=message_data, headers=headers, timeout=30)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("Message posted successfully")
|
||||
logger.info("Message posted successfully")
|
||||
render_mapping("Message:", result)
|
||||
else:
|
||||
print(f"Post failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Post failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error posting message: {e}")
|
||||
logger.error(f"Error posting message: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -210,7 +213,7 @@ def handle_messaging_vote(args, default_rpc_url, read_password, render_mapping):
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
if not args.message_id or not args.vote:
|
||||
print("Error: --message-id and --vote are required")
|
||||
logger.error("Error: --message-id and --vote are required")
|
||||
sys.exit(1)
|
||||
|
||||
# Get auth headers if wallet provided
|
||||
@@ -227,19 +230,19 @@ def handle_messaging_vote(args, default_rpc_url, read_password, render_mapping):
|
||||
if chain_id:
|
||||
vote_data["chain_id"] = chain_id
|
||||
|
||||
print(f"Voting on message {args.message_id} on {rpc_url}...")
|
||||
logger.info(f"Voting on message {args.message_id} on {rpc_url}...")
|
||||
try:
|
||||
response = requests.post(f"{rpc_url}/rpc/messaging/messages/{args.message_id}/vote", json=vote_data, headers=headers, timeout=30)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("Vote recorded successfully")
|
||||
logger.info("Vote recorded successfully")
|
||||
render_mapping("Vote result:", result)
|
||||
else:
|
||||
print(f"Vote failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Vote failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error voting on message: {e}")
|
||||
logger.error(f"Error voting on message: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -249,10 +252,10 @@ def handle_messaging_search(args, default_rpc_url, output_format, render_mapping
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
if not args.query:
|
||||
print("Error: --query is required")
|
||||
logger.error("Error: --query is required")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Searching messages for '{args.query}' on {rpc_url}...")
|
||||
logger.info(f"Searching messages for '{args.query}' on {rpc_url}...")
|
||||
try:
|
||||
params = {"query": args.query}
|
||||
if chain_id:
|
||||
@@ -262,20 +265,20 @@ def handle_messaging_search(args, default_rpc_url, output_format, render_mapping
|
||||
if response.status_code == 200:
|
||||
results = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(results, indent=2))
|
||||
logger.info(json.dumps(results, indent=2))
|
||||
else:
|
||||
print(f"Search results for '{args.query}':")
|
||||
logger.info(f"Search results for '{args.query}':")
|
||||
if isinstance(results, list):
|
||||
for msg in results:
|
||||
print(f" Message ID: {msg.get('message_id', 'N/A')}, Topic: {msg.get('topic_id', 'N/A')}")
|
||||
logger.info(f" Message ID: {msg.get('message_id', 'N/A')}, Topic: {msg.get('topic_id', 'N/A')}")
|
||||
else:
|
||||
render_mapping("Search results:", results)
|
||||
else:
|
||||
print(f"Search failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Search failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error searching messages: {e}")
|
||||
logger.error(f"Error searching messages: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -285,10 +288,10 @@ def handle_messaging_reputation(args, default_rpc_url, output_format, render_map
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
if not args.agent_id:
|
||||
print("Error: --agent-id is required")
|
||||
logger.error("Error: --agent-id is required")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Getting reputation for agent {args.agent_id} from {rpc_url}...")
|
||||
logger.info(f"Getting reputation for agent {args.agent_id} from {rpc_url}...")
|
||||
try:
|
||||
params = {}
|
||||
if chain_id:
|
||||
@@ -298,15 +301,15 @@ def handle_messaging_reputation(args, default_rpc_url, output_format, render_map
|
||||
if response.status_code == 200:
|
||||
reputation = response.json()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(reputation, indent=2))
|
||||
logger.info(json.dumps(reputation, indent=2))
|
||||
else:
|
||||
render_mapping(f"Agent {args.agent_id} reputation:", reputation)
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error getting reputation: {e}")
|
||||
logger.error(f"Error getting reputation: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -316,7 +319,7 @@ def handle_messaging_moderate(args, default_rpc_url, read_password, render_mappi
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
if not args.message_id or not args.action:
|
||||
print("Error: --message-id and --action are required")
|
||||
logger.error("Error: --message-id and --action are required")
|
||||
sys.exit(1)
|
||||
|
||||
# Get auth headers if wallet provided
|
||||
@@ -333,17 +336,17 @@ def handle_messaging_moderate(args, default_rpc_url, read_password, render_mappi
|
||||
if chain_id:
|
||||
moderation_data["chain_id"] = chain_id
|
||||
|
||||
print(f"Moderating message {args.message_id} on {rpc_url}...")
|
||||
logger.info(f"Moderating message {args.message_id} on {rpc_url}...")
|
||||
try:
|
||||
response = requests.post(f"{rpc_url}/rpc/messaging/messages/{args.message_id}/moderate", json=moderation_data, headers=headers, timeout=30)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("Moderation action completed successfully")
|
||||
logger.info("Moderation action completed successfully")
|
||||
render_mapping("Moderation result:", result)
|
||||
else:
|
||||
print(f"Moderation failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Moderation failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error moderating message: {e}")
|
||||
logger.error(f"Error moderating message: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -5,42 +5,39 @@ import sys
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import requests
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_network_status(args, default_rpc_url, get_network_snapshot):
|
||||
"""Handle network status query."""
|
||||
snapshot = get_network_snapshot(getattr(args, "rpc_url", default_rpc_url))
|
||||
print("Network status:")
|
||||
print(f" Connected nodes: {snapshot['connected_count']}")
|
||||
logger.info("Network status:")
|
||||
logger.info(f" Connected nodes: {snapshot['connected_count']}")
|
||||
for index, node in enumerate(snapshot["nodes"]):
|
||||
label = "Local" if index == 0 else f"Peer {node['name']}"
|
||||
health = "healthy" if node["healthy"] else "unreachable"
|
||||
print(f" {label}: {health}")
|
||||
print(f" Sync status: {snapshot['sync_status']}")
|
||||
|
||||
|
||||
logger.info(f" {label}: {health}")
|
||||
logger.info(f" Sync status: {snapshot['sync_status']}")
|
||||
def handle_network_peers(args, default_rpc_url, get_network_snapshot):
|
||||
"""Handle network peers query."""
|
||||
snapshot = get_network_snapshot(getattr(args, "rpc_url", default_rpc_url))
|
||||
print("Network peers:")
|
||||
logger.info("Network peers:")
|
||||
for node in snapshot["nodes"]:
|
||||
endpoint = urlparse(node["rpc_url"]).netloc
|
||||
status = "Connected" if node["healthy"] else f"Unreachable ({node['error'] or 'unknown error'})"
|
||||
print(f" - {node['name']} ({endpoint}) - {status}")
|
||||
|
||||
|
||||
logger.info(f" - {node['name']} ({endpoint}) - {status}")
|
||||
def handle_network_sync(args, default_rpc_url, get_network_snapshot):
|
||||
"""Handle network sync status query."""
|
||||
snapshot = get_network_snapshot(getattr(args, "rpc_url", default_rpc_url))
|
||||
print("Network sync status:")
|
||||
print(f" Status: {snapshot['sync_status']}")
|
||||
logger.info("Network sync status:")
|
||||
logger.info(f" Status: {snapshot['sync_status']}")
|
||||
for node in snapshot["nodes"]:
|
||||
height = node["height"] if node["height"] is not None else "unknown"
|
||||
print(f" {node['name']} height: {height}")
|
||||
logger.info(f" {node['name']} height: {height}")
|
||||
local_timestamp = snapshot["nodes"][0].get("timestamp") if snapshot["nodes"] else None
|
||||
print(f" Last local block: {local_timestamp or 'unknown'}")
|
||||
|
||||
|
||||
logger.info(f" Last local block: {local_timestamp or 'unknown'}")
|
||||
def handle_network_ping(args, default_rpc_url, read_blockchain_env, normalize_rpc_url, first, probe_rpc_node):
|
||||
"""Handle network ping command."""
|
||||
env_config = read_blockchain_env()
|
||||
@@ -55,29 +52,25 @@ def handle_network_ping(args, default_rpc_url, read_blockchain_env, normalize_rp
|
||||
target_url = node if "://" in node else f"http://{node}:{peer_rpc_port}"
|
||||
target = probe_rpc_node(node, target_url, chain_id=env_config.get("chain_id") or None)
|
||||
|
||||
print(f"Ping: Node {node} {'reachable' if target['healthy'] else 'unreachable'}")
|
||||
print(f" Endpoint: {urlparse(target['rpc_url']).netloc}")
|
||||
logger.info(f"Ping: Node {node} {'reachable' if target['healthy'] else 'unreachable'}")
|
||||
logger.info(f" Endpoint: {urlparse(target['rpc_url']).netloc}")
|
||||
if target["latency_ms"] is not None:
|
||||
print(f" Latency: {target['latency_ms']}ms")
|
||||
print(f" Status: {'connected' if target['healthy'] else 'error'}")
|
||||
|
||||
|
||||
logger.info(f" Latency: {target['latency_ms']}ms")
|
||||
logger.error(f" Status: {'connected' if target['healthy'] else 'error'}")
|
||||
def handle_network_propagate(args, default_rpc_url, get_network_snapshot, first):
|
||||
"""Handle network data propagation."""
|
||||
data = first(getattr(args, "data_opt", None), getattr(args, "data", None), "test-data")
|
||||
snapshot = get_network_snapshot(getattr(args, "rpc_url", default_rpc_url))
|
||||
print("Data propagation: Complete")
|
||||
print(f" Data: {data}")
|
||||
print(f" Nodes: {snapshot['connected_count']}/{len(snapshot['nodes'])} reachable")
|
||||
|
||||
|
||||
logger.info("Data propagation: Complete")
|
||||
logger.info(f" Data: {data}")
|
||||
logger.info(f" Nodes: {snapshot['connected_count']}/{len(snapshot['nodes'])} reachable")
|
||||
def handle_network_force_sync(args, default_rpc_url, render_mapping):
|
||||
"""Handle network force sync command."""
|
||||
rpc_url = args.rpc_url or default_rpc_url
|
||||
chain_id = getattr(args, "chain_id", None)
|
||||
|
||||
if not args.peer:
|
||||
print("Error: --peer is required")
|
||||
logger.error("Error: --peer is required")
|
||||
sys.exit(1)
|
||||
|
||||
sync_data = {
|
||||
@@ -86,17 +79,17 @@ def handle_network_force_sync(args, default_rpc_url, render_mapping):
|
||||
if chain_id:
|
||||
sync_data["chain_id"] = chain_id
|
||||
|
||||
print(f"Forcing sync to peer {args.peer} on {rpc_url}...")
|
||||
logger.info(f"Forcing sync to peer {args.peer} on {rpc_url}...")
|
||||
try:
|
||||
response = requests.post(f"{rpc_url}/rpc/force-sync", json=sync_data, timeout=60)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("Force sync initiated successfully")
|
||||
logger.info("Force sync initiated successfully")
|
||||
render_mapping("Sync result:", result)
|
||||
else:
|
||||
print(f"Force sync failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Force sync failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error forcing sync: {e}")
|
||||
logger.error(f"Error forcing sync: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"""Performance command handlers for AITBC CLI."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_performance_benchmark(args, output_format, render_mapping):
|
||||
@@ -15,16 +18,14 @@ def handle_performance_benchmark(args, output_format, render_mapping):
|
||||
}
|
||||
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(benchmark_data, indent=2))
|
||||
logger.info(json.dumps(benchmark_data, indent=2))
|
||||
else:
|
||||
print("Performance Benchmark:")
|
||||
print(f" TPS: {benchmark_data['tps']}")
|
||||
print(f" Latency: {benchmark_data['latency_ms']}ms")
|
||||
print(f" Throughput: {benchmark_data['throughput_mbps']}Mbps")
|
||||
print(f" CPU Usage: {benchmark_data['cpu_usage']}%")
|
||||
print(f" Memory Usage: {benchmark_data['memory_usage']}%")
|
||||
|
||||
|
||||
logger.info("Performance Benchmark:")
|
||||
logger.info(f" TPS: {benchmark_data['tps']}")
|
||||
logger.info(f" Latency: {benchmark_data['latency_ms']}ms")
|
||||
logger.info(f" Throughput: {benchmark_data['throughput_mbps']}Mbps")
|
||||
logger.info(f" CPU Usage: {benchmark_data['cpu_usage']}%")
|
||||
logger.info(f" Memory Usage: {benchmark_data['memory_usage']}%")
|
||||
def handle_performance_optimize(args, render_mapping):
|
||||
"""Handle performance optimize command."""
|
||||
target = getattr(args, "target", "general")
|
||||
@@ -36,7 +37,7 @@ def handle_performance_optimize(args, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Performance optimization applied for {target}")
|
||||
logger.info(f"Performance optimization applied for {target}")
|
||||
render_mapping("Optimization:", optimization_data)
|
||||
|
||||
|
||||
@@ -52,5 +53,5 @@ def handle_performance_tune(args, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print("Performance tuning applied")
|
||||
logger.info("Performance tuning applied")
|
||||
render_mapping("Tuning:", tune_data)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"""Pool hub SLA and capacity management handlers."""
|
||||
|
||||
from aitbc import AITBCHTTPClient, NetworkError
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_pool_hub_sla_metrics(args):
|
||||
@@ -10,10 +13,10 @@ def handle_pool_hub_sla_metrics(args):
|
||||
config = get_pool_hub_config()
|
||||
|
||||
if args.test_mode:
|
||||
print(" SLA Metrics (test mode):")
|
||||
print(" Uptime: 97.5%")
|
||||
print(" Response Time: 850ms")
|
||||
print(" Job Completion Rate: 92.3%")
|
||||
logger.info(" SLA Metrics (test mode):")
|
||||
logger.info(" Uptime: 97.5%")
|
||||
logger.info(" Response Time: 850ms")
|
||||
logger.info(" Job Completion Rate: 92.3%")
|
||||
return
|
||||
|
||||
pool_hub_url = getattr(config, "pool_hub_url", "http://localhost:8012")
|
||||
@@ -25,15 +28,13 @@ def handle_pool_hub_sla_metrics(args):
|
||||
else:
|
||||
metrics = http_client.get("/v1/sla/metrics")
|
||||
|
||||
print(" SLA Metrics:")
|
||||
logger.info(" SLA Metrics:")
|
||||
for key, value in metrics.items():
|
||||
print(f" {key}: {value}")
|
||||
logger.info(f" {key}: {value}")
|
||||
except NetworkError as e:
|
||||
print(f"❌ Failed to get SLA metrics: {e}")
|
||||
logger.error(f"❌ Failed to get SLA metrics: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error getting SLA metrics: {e}")
|
||||
|
||||
|
||||
logger.error(f"❌ Error getting SLA metrics: {e}")
|
||||
def handle_pool_hub_sla_violations(args):
|
||||
"""Get SLA violations across all miners."""
|
||||
try:
|
||||
@@ -41,23 +42,21 @@ def handle_pool_hub_sla_violations(args):
|
||||
config = get_pool_hub_config()
|
||||
|
||||
if args.test_mode:
|
||||
print("⚠️ SLA Violations (test mode):")
|
||||
print(" miner_001: response_time violation")
|
||||
logger.info("⚠️ SLA Violations (test mode):")
|
||||
logger.info(" miner_001: response_time violation")
|
||||
return
|
||||
|
||||
pool_hub_url = getattr(config, "pool_hub_url", "http://localhost:8012")
|
||||
http_client = AITBCHTTPClient(base_url=pool_hub_url, timeout=30)
|
||||
violations = http_client.get("/v1/sla/violations")
|
||||
|
||||
print("⚠️ SLA Violations:")
|
||||
logger.info("⚠️ SLA Violations:")
|
||||
for v in violations:
|
||||
print(f" {v}")
|
||||
logger.info(f" {v}")
|
||||
except NetworkError as e:
|
||||
print(f"❌ Failed to get violations: {e}")
|
||||
logger.error(f"❌ Failed to get violations: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error getting violations: {e}")
|
||||
|
||||
|
||||
logger.error(f"❌ Error getting violations: {e}")
|
||||
def handle_pool_hub_capacity_snapshots(args):
|
||||
"""Get capacity planning snapshots."""
|
||||
try:
|
||||
@@ -65,24 +64,22 @@ def handle_pool_hub_capacity_snapshots(args):
|
||||
config = get_pool_hub_config()
|
||||
|
||||
if args.test_mode:
|
||||
print("📊 Capacity Snapshots (test mode):")
|
||||
print(" Total Capacity: 1250 GPU")
|
||||
print(" Available: 320 GPU")
|
||||
logger.info("📊 Capacity Snapshots (test mode):")
|
||||
logger.info(" Total Capacity: 1250 GPU")
|
||||
logger.info(" Available: 320 GPU")
|
||||
return
|
||||
|
||||
pool_hub_url = getattr(config, "pool_hub_url", "http://localhost:8012")
|
||||
http_client = AITBCHTTPClient(base_url=pool_hub_url, timeout=30)
|
||||
snapshots = http_client.get("/v1/sla/capacity/snapshots")
|
||||
|
||||
print("📊 Capacity Snapshots:")
|
||||
logger.info("📊 Capacity Snapshots:")
|
||||
for s in snapshots:
|
||||
print(f" {s}")
|
||||
logger.info(f" {s}")
|
||||
except NetworkError as e:
|
||||
print(f"❌ Failed to get snapshots: {e}")
|
||||
logger.error(f"❌ Failed to get snapshots: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error getting snapshots: {e}")
|
||||
|
||||
|
||||
logger.error(f"❌ Error getting snapshots: {e}")
|
||||
def handle_pool_hub_capacity_forecast(args):
|
||||
"""Get capacity forecast."""
|
||||
try:
|
||||
@@ -90,24 +87,22 @@ def handle_pool_hub_capacity_forecast(args):
|
||||
config = get_pool_hub_config()
|
||||
|
||||
if args.test_mode:
|
||||
print("🔮 Capacity Forecast (test mode):")
|
||||
print(" Projected Capacity: 1400 GPU")
|
||||
print(" Growth Rate: 12%")
|
||||
logger.info("🔮 Capacity Forecast (test mode):")
|
||||
logger.info(" Projected Capacity: 1400 GPU")
|
||||
logger.info(" Growth Rate: 12%")
|
||||
return
|
||||
|
||||
pool_hub_url = getattr(config, "pool_hub_url", "http://localhost:8012")
|
||||
http_client = AITBCHTTPClient(base_url=pool_hub_url, timeout=30)
|
||||
forecast = http_client.get("/v1/sla/capacity/forecast")
|
||||
|
||||
print("🔮 Capacity Forecast:")
|
||||
logger.info("🔮 Capacity Forecast:")
|
||||
for key, value in forecast.items():
|
||||
print(f" {key}: {value}")
|
||||
logger.info(f" {key}: {value}")
|
||||
except NetworkError as e:
|
||||
print(f"❌ Failed to get forecast: {e}")
|
||||
logger.error(f"❌ Failed to get forecast: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error getting forecast: {e}")
|
||||
|
||||
|
||||
logger.error(f"❌ Error getting forecast: {e}")
|
||||
def handle_pool_hub_capacity_recommendations(args):
|
||||
"""Get scaling recommendations."""
|
||||
try:
|
||||
@@ -115,24 +110,22 @@ def handle_pool_hub_capacity_recommendations(args):
|
||||
config = get_pool_hub_config()
|
||||
|
||||
if args.test_mode:
|
||||
print("💡 Capacity Recommendations (test mode):")
|
||||
print(" Type: scale_up")
|
||||
print(" Action: Add 50 GPU capacity")
|
||||
logger.info("💡 Capacity Recommendations (test mode):")
|
||||
logger.info(" Type: scale_up")
|
||||
logger.info(" Action: Add 50 GPU capacity")
|
||||
return
|
||||
|
||||
pool_hub_url = getattr(config, "pool_hub_url", "http://localhost:8012")
|
||||
http_client = AITBCHTTPClient(base_url=pool_hub_url, timeout=30)
|
||||
recommendations = http_client.get("/v1/sla/capacity/recommendations")
|
||||
|
||||
print("💡 Capacity Recommendations:")
|
||||
logger.info("💡 Capacity Recommendations:")
|
||||
for r in recommendations:
|
||||
print(f" {r}")
|
||||
logger.info(f" {r}")
|
||||
except NetworkError as e:
|
||||
print(f"❌ Failed to get recommendations: {e}")
|
||||
logger.error(f"❌ Failed to get recommendations: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error getting recommendations: {e}")
|
||||
|
||||
|
||||
logger.error(f"❌ Error getting recommendations: {e}")
|
||||
def handle_pool_hub_billing_usage(args):
|
||||
"""Get billing usage data."""
|
||||
try:
|
||||
@@ -140,24 +133,22 @@ def handle_pool_hub_billing_usage(args):
|
||||
config = get_pool_hub_config()
|
||||
|
||||
if args.test_mode:
|
||||
print("💰 Billing Usage (test mode):")
|
||||
print(" Total GPU Hours: 45678")
|
||||
print(" Total Cost: $12500.50")
|
||||
logger.info("💰 Billing Usage (test mode):")
|
||||
logger.info(" Total GPU Hours: 45678")
|
||||
logger.info(" Total Cost: $12500.50")
|
||||
return
|
||||
|
||||
pool_hub_url = getattr(config, "pool_hub_url", "http://localhost:8012")
|
||||
http_client = AITBCHTTPClient(base_url=pool_hub_url, timeout=30)
|
||||
usage = http_client.get("/v1/sla/billing/usage")
|
||||
|
||||
print("💰 Billing Usage:")
|
||||
logger.info("💰 Billing Usage:")
|
||||
for key, value in usage.items():
|
||||
print(f" {key}: {value}")
|
||||
logger.info(f" {key}: {value}")
|
||||
except NetworkError as e:
|
||||
print(f"❌ Failed to get billing usage: {e}")
|
||||
logger.error(f"❌ Failed to get billing usage: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error getting billing usage: {e}")
|
||||
|
||||
|
||||
logger.error(f"❌ Error getting billing usage: {e}")
|
||||
def handle_pool_hub_billing_sync(args):
|
||||
"""Trigger billing sync with coordinator-api."""
|
||||
try:
|
||||
@@ -165,22 +156,20 @@ def handle_pool_hub_billing_sync(args):
|
||||
config = get_pool_hub_config()
|
||||
|
||||
if args.test_mode:
|
||||
print("🔄 Billing sync triggered (test mode)")
|
||||
print("✅ Sync completed successfully")
|
||||
logger.info("🔄 Billing sync triggered (test mode)")
|
||||
logger.info("✅ Sync completed successfully")
|
||||
return
|
||||
|
||||
pool_hub_url = getattr(config, "pool_hub_url", "http://localhost:8012")
|
||||
http_client = AITBCHTTPClient(base_url=pool_hub_url, timeout=60)
|
||||
result = http_client.post("/v1/sla/billing/sync")
|
||||
|
||||
print("🔄 Billing sync triggered")
|
||||
print(f"✅ {result.get('message', 'Success')}")
|
||||
logger.info("🔄 Billing sync triggered")
|
||||
logger.info(f"✅ {result.get('message', 'Success')}")
|
||||
except NetworkError as e:
|
||||
print(f"❌ Billing sync failed: {e}")
|
||||
logger.error(f"❌ Billing sync failed: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error triggering billing sync: {e}")
|
||||
|
||||
|
||||
logger.error(f"❌ Error triggering billing sync: {e}")
|
||||
def handle_pool_hub_collect_metrics(args):
|
||||
"""Trigger SLA metrics collection."""
|
||||
try:
|
||||
@@ -188,17 +177,17 @@ def handle_pool_hub_collect_metrics(args):
|
||||
config = get_pool_hub_config()
|
||||
|
||||
if args.test_mode:
|
||||
print("📊 SLA metrics collection triggered (test mode)")
|
||||
print("✅ Collection completed successfully")
|
||||
logger.info("📊 SLA metrics collection triggered (test mode)")
|
||||
logger.info("✅ Collection completed successfully")
|
||||
return
|
||||
|
||||
pool_hub_url = getattr(config, "pool_hub_url", "http://localhost:8012")
|
||||
http_client = AITBCHTTPClient(base_url=pool_hub_url, timeout=60)
|
||||
result = http_client.post("/v1/sla/metrics/collect")
|
||||
|
||||
print("📊 SLA metrics collection triggered")
|
||||
print(f"✅ {result.get('message', 'Success')}")
|
||||
logger.info("📊 SLA metrics collection triggered")
|
||||
logger.info(f"✅ {result.get('message', 'Success')}")
|
||||
except NetworkError as e:
|
||||
print(f"❌ Metrics collection failed: {e}")
|
||||
logger.error(f"❌ Metrics collection failed: {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error triggering metrics collection: {e}")
|
||||
logger.error(f"❌ Error triggering metrics collection: {e}")
|
||||
@@ -1,6 +1,9 @@
|
||||
"""Resource command handlers for AITBC CLI."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_resource_status(args, output_format, render_mapping):
|
||||
@@ -14,7 +17,7 @@ def handle_resource_status(args, output_format, render_mapping):
|
||||
}
|
||||
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(status_data, indent=2))
|
||||
logger.info(json.dumps(status_data, indent=2))
|
||||
else:
|
||||
render_mapping("Resource Status:", status_data)
|
||||
|
||||
@@ -33,7 +36,7 @@ def handle_resource_allocate(args, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Resources allocated to {agent_id}")
|
||||
logger.info(f"Resources allocated to {agent_id}")
|
||||
render_mapping("Allocation:", allocation_data)
|
||||
|
||||
|
||||
@@ -50,7 +53,7 @@ def handle_resource_monitor(args, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Resource monitoring started (interval: {interval}s, duration: {duration}s)")
|
||||
logger.info(f"Resource monitoring started (interval: {interval}s, duration: {duration}s)")
|
||||
render_mapping("Monitor:", monitor_data)
|
||||
|
||||
|
||||
@@ -65,7 +68,7 @@ def handle_resource_optimize(args, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Resource optimization applied for {target}")
|
||||
logger.info(f"Resource optimization applied for {target}")
|
||||
render_mapping("Optimization:", optimization_data)
|
||||
|
||||
|
||||
@@ -80,5 +83,5 @@ def handle_resource_benchmark(args, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Resource benchmark completed for {benchmark_type}")
|
||||
logger.info(f"Resource benchmark completed for {benchmark_type}")
|
||||
render_mapping("Benchmark:", benchmark_data)
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
"""System and utility handlers."""
|
||||
|
||||
import sys
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_system_status(args, cli_version):
|
||||
"""Handle system status command."""
|
||||
print("System status: OK")
|
||||
print(f" Version: aitbc-cli v{cli_version}")
|
||||
print(" Services: Running")
|
||||
print(" Nodes: 2 connected")
|
||||
|
||||
|
||||
logger.info("System status: OK")
|
||||
logger.info(f" Version: aitbc-cli v{cli_version}")
|
||||
logger.info(" Services: Running")
|
||||
logger.info(" Nodes: 2 connected")
|
||||
def handle_analytics(args, default_rpc_url, get_blockchain_analytics):
|
||||
"""Handle analytics command."""
|
||||
analytics_type = getattr(args, "analytics_type", None) or getattr(args, "analytics_action", None) or getattr(args, "type", "blocks")
|
||||
@@ -63,10 +64,10 @@ def handle_analytics(args, default_rpc_url, get_blockchain_analytics):
|
||||
else:
|
||||
analytics = get_blockchain_analytics(analytics_type, limit, rpc_url=rpc_url)
|
||||
if analytics:
|
||||
print(f"Blockchain Analytics ({analytics['type']}):")
|
||||
logger.info(f"Blockchain Analytics ({analytics['type']}):")
|
||||
for key, value in analytics.items():
|
||||
if key != "type":
|
||||
print(f" {key}: {value}")
|
||||
logger.info(f" {key}: {value}")
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
@@ -88,7 +89,7 @@ def handle_agent_action(args, agent_operations, render_mapping):
|
||||
"status": "simulated",
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
print(f"Agent {args.agent_action} (simulated)")
|
||||
logger.info(f"Agent {args.agent_action} (simulated)")
|
||||
render_mapping(f"Agent {args.agent_action}:", stub_result)
|
||||
return
|
||||
# Handle case where result doesn't have 'action' field (e.g., message send)
|
||||
@@ -96,7 +97,7 @@ def handle_agent_action(args, agent_operations, render_mapping):
|
||||
render_mapping(f"Agent {result['action']}:", result)
|
||||
else:
|
||||
# Just print success message for message send
|
||||
print("Agent operation completed successfully")
|
||||
logger.info("Agent operation completed successfully")
|
||||
except Exception as e:
|
||||
# Return stub data on error
|
||||
stub_result = {
|
||||
@@ -105,7 +106,7 @@ def handle_agent_action(args, agent_operations, render_mapping):
|
||||
"error": str(e),
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
print(f"Agent {args.agent_action} (simulated - error: {e})")
|
||||
logger.error(f"Agent {args.agent_action} (simulated - error: {e})")
|
||||
render_mapping(f"Agent {args.agent_action}:", stub_result)
|
||||
|
||||
|
||||
@@ -125,7 +126,7 @@ def handle_agent_sdk_action(args, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Agent SDK created: {name}")
|
||||
logger.info(f"Agent SDK created: {name}")
|
||||
render_mapping("Agent SDK:", sdk_data)
|
||||
|
||||
elif action == "update-status":
|
||||
@@ -135,7 +136,7 @@ def handle_agent_sdk_action(args, render_mapping):
|
||||
coordinator_url = getattr(args, "coordinator_url", "http://localhost:9001")
|
||||
|
||||
if not agent_id or not status:
|
||||
print("Error: --agent-id and --status are required")
|
||||
logger.error("Error: --agent-id and --status are required")
|
||||
sys.exit(1)
|
||||
|
||||
status_update_request = {
|
||||
@@ -143,8 +144,7 @@ def handle_agent_sdk_action(args, render_mapping):
|
||||
"load_metrics": load_metrics if isinstance(load_metrics, dict) else {}
|
||||
}
|
||||
|
||||
print(f"Updating agent {agent_id} status to {status}...")
|
||||
|
||||
logger.info(f"Updating agent {agent_id} status to {status}...")
|
||||
try:
|
||||
import requests
|
||||
response = requests.put(
|
||||
@@ -155,14 +155,14 @@ def handle_agent_sdk_action(args, render_mapping):
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print(f"Agent status updated successfully")
|
||||
logger.info(f"Agent status updated successfully")
|
||||
render_mapping("Status Update:", result)
|
||||
else:
|
||||
print(f"Status update failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Status update failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error updating agent status: {e}")
|
||||
logger.error(f"Error updating agent status: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
elif action == "register":
|
||||
@@ -184,8 +184,7 @@ def handle_agent_sdk_action(args, render_mapping):
|
||||
"metadata": metadata if isinstance(metadata, dict) else (json.loads(metadata) if metadata else {})
|
||||
}
|
||||
|
||||
print(f"Registering agent {agent_id} with coordinator at {coordinator_url}...")
|
||||
|
||||
logger.info(f"Registering agent {agent_id} with coordinator at {coordinator_url}...")
|
||||
try:
|
||||
import requests
|
||||
response = requests.post(
|
||||
@@ -196,14 +195,14 @@ def handle_agent_sdk_action(args, render_mapping):
|
||||
|
||||
if response.status_code in (200, 201):
|
||||
result = response.json()
|
||||
print(f"Agent registered successfully")
|
||||
logger.info(f"Agent registered successfully")
|
||||
render_mapping("Registration:", result)
|
||||
else:
|
||||
print(f"Registration failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Registration failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error registering agent: {e}")
|
||||
logger.error(f"Error registering agent: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
elif action == "list":
|
||||
@@ -218,8 +217,7 @@ def handle_agent_sdk_action(args, render_mapping):
|
||||
if agent_type:
|
||||
query["agent_type"] = agent_type
|
||||
|
||||
print(f"Discovering agents from coordinator at {coordinator_url}...")
|
||||
|
||||
logger.info(f"Discovering agents from coordinator at {coordinator_url}...")
|
||||
try:
|
||||
import requests
|
||||
response = requests.post(
|
||||
@@ -230,22 +228,21 @@ def handle_agent_sdk_action(args, render_mapping):
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print(f"Found {result.get('count', 0)} agents")
|
||||
logger.info(f"Found {result.get('count', 0)} agents")
|
||||
render_mapping("Agents:", result)
|
||||
else:
|
||||
print(f"Discovery failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Discovery failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error discovering agents: {e}")
|
||||
logger.error(f"Error discovering agents: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
elif action == "status":
|
||||
agent_id = getattr(args, "agent_id", None)
|
||||
coordinator_url = getattr(args, "coordinator_url", "http://localhost:9001")
|
||||
|
||||
print(f"Getting agent info for {agent_id} from coordinator at {coordinator_url}...")
|
||||
|
||||
logger.info(f"Getting agent info for {agent_id} from coordinator at {coordinator_url}...")
|
||||
try:
|
||||
import requests
|
||||
response = requests.get(
|
||||
@@ -255,17 +252,17 @@ def handle_agent_sdk_action(args, render_mapping):
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print(f"Agent info retrieved")
|
||||
logger.info(f"Agent info retrieved")
|
||||
render_mapping("Agent:", result)
|
||||
elif response.status_code == 404:
|
||||
print(f"Agent not found: {agent_id}")
|
||||
logger.info(f"Agent not found: {agent_id}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(f"Query failed: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Query failed: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error getting agent info: {e}")
|
||||
logger.error(f"Error getting agent info: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
elif action == "capabilities":
|
||||
@@ -276,7 +273,7 @@ def handle_agent_sdk_action(args, render_mapping):
|
||||
"max_concurrent_jobs": 2
|
||||
}
|
||||
|
||||
print("System capabilities")
|
||||
logger.info("System capabilities")
|
||||
render_mapping("Capabilities:", caps_data)
|
||||
|
||||
else:
|
||||
@@ -287,7 +284,7 @@ def handle_agent_sdk_action(args, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Agent SDK {action} (simulated)")
|
||||
logger.info(f"Agent SDK {action} (simulated)")
|
||||
render_mapping("SDK Operation:", sdk_result)
|
||||
|
||||
|
||||
@@ -369,7 +366,7 @@ def handle_simulate_action(args, simulate_blockchain, simulate_wallets, simulate
|
||||
elif args.simulate_command == "ai-jobs":
|
||||
simulate_ai_jobs(args.jobs, args.models, args.duration_range)
|
||||
else:
|
||||
print(f"Unknown simulate command: {args.simulate_command}")
|
||||
logger.info(f"Unknown simulate command: {args.simulate_command}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -440,7 +437,7 @@ def handle_economics_action(args, render_mapping):
|
||||
}
|
||||
render_mapping("Token Balance:", result)
|
||||
else:
|
||||
print(f"Unknown economics action: {action}")
|
||||
logger.info(f"Unknown economics action: {action}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -466,7 +463,7 @@ def handle_cluster_action(args, render_mapping):
|
||||
}
|
||||
render_mapping("Cluster Status:", result)
|
||||
else:
|
||||
print(f"Unknown cluster action: {action}")
|
||||
logger.info(f"Unknown cluster action: {action}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -491,7 +488,7 @@ def handle_performance_action(args, render_mapping):
|
||||
}
|
||||
render_mapping("Performance Profile:", result)
|
||||
else:
|
||||
print(f"Unknown performance action: {action}")
|
||||
logger.info(f"Unknown performance action: {action}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -523,7 +520,7 @@ def handle_security_action(args, render_mapping):
|
||||
}
|
||||
render_mapping("Security Patch:", result)
|
||||
else:
|
||||
print(f"Unknown security action: {action}")
|
||||
logger.info(f"Unknown security action: {action}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -538,7 +535,7 @@ def handle_compliance_check(args, render_mapping):
|
||||
"issues_found": 0
|
||||
}
|
||||
|
||||
print(f"Compliance check for {standard}")
|
||||
logger.info(f"Compliance check for {standard}")
|
||||
render_mapping("Compliance:", compliance_data)
|
||||
|
||||
|
||||
@@ -553,7 +550,7 @@ def handle_compliance_report(args, render_mapping):
|
||||
"overall_status": "compliant"
|
||||
}
|
||||
|
||||
print(f"Compliance report ({format_type})")
|
||||
logger.info(f"Compliance report ({format_type})")
|
||||
render_mapping("Report:", report_data)
|
||||
|
||||
|
||||
@@ -583,7 +580,7 @@ def handle_cluster_sync(args, render_mapping):
|
||||
"last_sync": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print("Cluster sync completed")
|
||||
logger.info("Cluster sync completed")
|
||||
render_mapping("Cluster Sync:", sync_data)
|
||||
|
||||
|
||||
@@ -598,7 +595,7 @@ def handle_cluster_balance(args, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print("Workload balanced across cluster")
|
||||
logger.info("Workload balanced across cluster")
|
||||
render_mapping("Cluster Balance:", balance_data)
|
||||
|
||||
|
||||
@@ -614,7 +611,7 @@ def handle_script_run(args, render_mapping):
|
||||
"timestamp": __import__('datetime').datetime.now().isoformat()
|
||||
}
|
||||
|
||||
print(f"Script executed: {file_path}")
|
||||
logger.info(f"Script executed: {file_path}")
|
||||
render_mapping("Script:", script_data)
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ import json
|
||||
import requests
|
||||
import sys
|
||||
from aitbc.utils.paths import get_data_path
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_wallet_create(args, create_wallet, read_password, first):
|
||||
@@ -11,65 +14,59 @@ def handle_wallet_create(args, create_wallet, read_password, first):
|
||||
wallet_name = first(getattr(args, "wallet_name", None), getattr(args, "wallet_name_opt", None))
|
||||
password = read_password(args, "wallet_password")
|
||||
if not wallet_name or not password:
|
||||
print("Error: Wallet name and password are required")
|
||||
logger.error("Error: Wallet name and password are required")
|
||||
sys.exit(1)
|
||||
address = create_wallet(wallet_name, password)
|
||||
print(f"Wallet address: {address}")
|
||||
|
||||
|
||||
logger.info(f"Wallet address: {address}")
|
||||
def handle_wallet_list(args, list_wallets, output_format):
|
||||
"""Handle wallet list command."""
|
||||
wallets = list_wallets()
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(wallets, indent=2))
|
||||
logger.info(json.dumps(wallets, indent=2))
|
||||
return
|
||||
print("Wallets:")
|
||||
logger.info("Wallets:")
|
||||
for wallet in wallets:
|
||||
print(f" {wallet['name']}: {wallet['address']}")
|
||||
|
||||
|
||||
logger.info(f" {wallet['name']}: {wallet['address']}")
|
||||
def handle_wallet_balance(args, default_rpc_url, list_wallets, get_balance, first):
|
||||
"""Handle wallet balance command."""
|
||||
rpc_url = getattr(args, "rpc_url", default_rpc_url)
|
||||
if getattr(args, "all", False):
|
||||
print("All wallet balances:")
|
||||
logger.info("All wallet balances:")
|
||||
for wallet in list_wallets():
|
||||
balance_info = get_balance(wallet["name"], rpc_url=rpc_url)
|
||||
if balance_info:
|
||||
print(f" {wallet['name']}: {balance_info['balance']} AIT")
|
||||
logger.info(f" {wallet['name']}: {balance_info['balance']} AIT")
|
||||
else:
|
||||
print(f" {wallet['name']}: unavailable")
|
||||
logger.info(f" {wallet['name']}: unavailable")
|
||||
return
|
||||
wallet_name = first(getattr(args, "wallet_name", None), getattr(args, "wallet_name_opt", None))
|
||||
if not wallet_name:
|
||||
print("Error: Wallet name is required")
|
||||
logger.error("Error: Wallet name is required")
|
||||
sys.exit(1)
|
||||
balance_info = get_balance(wallet_name, rpc_url=rpc_url)
|
||||
if not balance_info:
|
||||
sys.exit(1)
|
||||
print(f"Wallet: {balance_info['wallet_name']}")
|
||||
print(f"Address: {balance_info['address']}")
|
||||
print(f"Balance: {balance_info['balance']} AIT")
|
||||
print(f"Nonce: {balance_info['nonce']}")
|
||||
|
||||
|
||||
logger.info(f"Wallet: {balance_info['wallet_name']}")
|
||||
logger.info(f"Address: {balance_info['address']}")
|
||||
logger.info(f"Balance: {balance_info['balance']} AIT")
|
||||
logger.info(f"Nonce: {balance_info['nonce']}")
|
||||
def handle_wallet_transactions(args, get_transactions, output_format, first):
|
||||
"""Handle wallet transactions command."""
|
||||
wallet_name = first(getattr(args, "wallet_name", None), getattr(args, "wallet_name_opt", None))
|
||||
if not wallet_name:
|
||||
print("Error: Wallet name is required")
|
||||
logger.error("Error: Wallet name is required")
|
||||
sys.exit(1)
|
||||
transactions = get_transactions(wallet_name, limit=args.limit, rpc_url=args.rpc_url)
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(transactions, indent=2))
|
||||
logger.info(json.dumps(transactions, indent=2))
|
||||
return
|
||||
print(f"Transactions for {wallet_name}:")
|
||||
logger.info(f"Transactions for {wallet_name}:")
|
||||
for index, tx in enumerate(transactions, 1):
|
||||
print(f" {index}. Hash: {tx.get('hash', 'N/A')}")
|
||||
print(f" Amount: {tx.get('value', 0)} AIT")
|
||||
print(f" Fee: {tx.get('fee', 0)} AIT")
|
||||
print(f" Type: {tx.get('type', 'N/A')}")
|
||||
print()
|
||||
logger.info(f" {index}. Hash: {tx.get('hash', 'N/A')}")
|
||||
logger.info(f" Amount: {tx.get('value', 0)} AIT")
|
||||
logger.info(f" Fee: {tx.get('fee', 0)} AIT")
|
||||
logger.info(f" Type: {tx.get('type', 'N/A')}")
|
||||
logger.info("")
|
||||
|
||||
|
||||
def handle_wallet_send(args, send_transaction, read_password, first):
|
||||
@@ -86,11 +83,11 @@ def handle_wallet_send(args, send_transaction, read_password, first):
|
||||
password = read_password(args, "wallet_password")
|
||||
|
||||
if not from_wallet or not to_address or amount_value is None:
|
||||
print("Error: From wallet, destination, and amount are required")
|
||||
logger.error("Error: From wallet, destination, and amount are required")
|
||||
sys.exit(1)
|
||||
|
||||
if not password:
|
||||
print("Error: Password is required for signing transaction")
|
||||
logger.error("Error: Password is required for signing transaction")
|
||||
sys.exit(1)
|
||||
|
||||
# Use default fee if not specified
|
||||
@@ -103,7 +100,7 @@ def handle_wallet_send(args, send_transaction, read_password, first):
|
||||
sender_keystore = keystore_dir / f"{from_wallet}.json"
|
||||
|
||||
if not sender_keystore.exists():
|
||||
print(f"Error: Wallet '{from_wallet}' not found")
|
||||
logger.error(f"Error: Wallet '{from_wallet}' not found")
|
||||
sys.exit(1)
|
||||
|
||||
with open(sender_keystore) as f:
|
||||
@@ -121,7 +118,7 @@ def handle_wallet_send(args, send_transaction, read_password, first):
|
||||
private_key_hex = aitbc_cli_module.decrypt_private_key(sender_keystore, password)
|
||||
private_key = ed25519.Ed25519PrivateKey.from_private_bytes(bytes.fromhex(private_key_hex))
|
||||
except Exception as e:
|
||||
print(f"Error decrypting wallet: {e}")
|
||||
logger.error(f"Error decrypting wallet: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
# Get RPC URL
|
||||
@@ -173,17 +170,17 @@ def handle_wallet_send(args, send_transaction, read_password, first):
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
if result.get("success"):
|
||||
print("Transaction sent successfully")
|
||||
print(f"Transaction hash: {result.get('transaction_hash')}")
|
||||
logger.info("Transaction sent successfully")
|
||||
logger.info(f"Transaction hash: {result.get('transaction_hash')}")
|
||||
else:
|
||||
print(f"Transaction failed: {result.get('message', 'Unknown error')}")
|
||||
logger.error(f"Transaction failed: {result.get('message', 'Unknown error')}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(f"Error submitting transaction: {response.status_code}")
|
||||
print(f"Error: {response.text}")
|
||||
logger.error(f"Error submitting transaction: {response.status_code}")
|
||||
logger.error(f"Error: {response.text}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error submitting transaction: {e}")
|
||||
logger.error(f"Error submitting transaction: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -193,32 +190,28 @@ def handle_wallet_import(args, import_wallet, read_password, first):
|
||||
private_key = first(getattr(args, "private_key_arg", None), getattr(args, "private_key_opt", None))
|
||||
password = read_password(args, "wallet_password")
|
||||
if not wallet_name or not private_key or not password:
|
||||
print("Error: Wallet name, private key, and password are required")
|
||||
logger.error("Error: Wallet name, private key, and password are required")
|
||||
sys.exit(1)
|
||||
address = import_wallet(wallet_name, private_key, password)
|
||||
if not address:
|
||||
sys.exit(1)
|
||||
print(f"Wallet address: {address}")
|
||||
|
||||
|
||||
logger.info(f"Wallet address: {address}")
|
||||
def handle_wallet_export(args, export_wallet, read_password, first):
|
||||
"""Handle wallet export command."""
|
||||
wallet_name = first(getattr(args, "wallet_name", None), getattr(args, "wallet_name_opt", None))
|
||||
password = read_password(args, "wallet_password")
|
||||
if not wallet_name or not password:
|
||||
print("Error: Wallet name and password are required")
|
||||
logger.error("Error: Wallet name and password are required")
|
||||
sys.exit(1)
|
||||
private_key = export_wallet(wallet_name, password)
|
||||
if not private_key:
|
||||
sys.exit(1)
|
||||
print(private_key)
|
||||
|
||||
|
||||
logger.info(private_key)
|
||||
def handle_wallet_delete(args, delete_wallet, first):
|
||||
"""Handle wallet delete command."""
|
||||
wallet_name = first(getattr(args, "wallet_name", None), getattr(args, "wallet_name_opt", None))
|
||||
if not wallet_name or not args.confirm:
|
||||
print("Error: Wallet name and --confirm are required")
|
||||
logger.error("Error: Wallet name and --confirm are required")
|
||||
sys.exit(1)
|
||||
if not delete_wallet(wallet_name):
|
||||
sys.exit(1)
|
||||
@@ -229,7 +222,7 @@ def handle_wallet_rename(args, rename_wallet, first):
|
||||
old_name = first(getattr(args, "old_name_arg", None), getattr(args, "old_name", None))
|
||||
new_name = first(getattr(args, "new_name_arg", None), getattr(args, "new_name", None))
|
||||
if not old_name or not new_name:
|
||||
print("Error: Old and new wallet names are required")
|
||||
logger.error("Error: Old and new wallet names are required")
|
||||
sys.exit(1)
|
||||
if not rename_wallet(old_name, new_name):
|
||||
sys.exit(1)
|
||||
@@ -239,33 +232,29 @@ def handle_wallet_backup(args, first):
|
||||
"""Handle wallet backup command."""
|
||||
wallet_name = first(getattr(args, "wallet_name", None), getattr(args, "wallet_name_opt", None))
|
||||
if not wallet_name:
|
||||
print("Error: Wallet name is required")
|
||||
logger.error("Error: Wallet name is required")
|
||||
sys.exit(1)
|
||||
print(f"Wallet backup: {wallet_name}")
|
||||
logger.info(f"Wallet backup: {wallet_name}")
|
||||
backup_path = get_data_path("backups")
|
||||
print(f" Backup created: {backup_path}/{wallet_name}_$(date +%Y%m%d).json")
|
||||
print(" Status: completed")
|
||||
|
||||
|
||||
logger.info(f" Backup created: {backup_path}/{wallet_name}_$(date +%Y%m%d).json")
|
||||
logger.info(" Status: completed")
|
||||
def handle_wallet_sync(args, first):
|
||||
"""Handle wallet sync command."""
|
||||
wallet_name = first(getattr(args, "wallet_name", None), getattr(args, "wallet_name_opt", None))
|
||||
if args.all:
|
||||
print("Wallet sync: All wallets")
|
||||
logger.info("Wallet sync: All wallets")
|
||||
elif wallet_name:
|
||||
print(f"Wallet sync: {wallet_name}")
|
||||
logger.info(f"Wallet sync: {wallet_name}")
|
||||
else:
|
||||
print("Error: Wallet name or --all is required")
|
||||
logger.error("Error: Wallet name or --all is required")
|
||||
sys.exit(1)
|
||||
print(" Sync status: completed")
|
||||
print(" Last sync: $(date)")
|
||||
|
||||
|
||||
logger.info(" Sync status: completed")
|
||||
logger.info(" Last sync: $(date)")
|
||||
def handle_wallet_batch(args, send_batch_transactions, read_password):
|
||||
"""Handle wallet batch command."""
|
||||
password = read_password(args)
|
||||
if not password:
|
||||
print("Error: Password is required")
|
||||
logger.error("Error: Password is required")
|
||||
sys.exit(1)
|
||||
with open(args.file) as handle:
|
||||
transactions = json.load(handle)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"""Workflow command handlers for AITBC CLI."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def handle_workflow_create(args, render_mapping):
|
||||
@@ -18,7 +21,7 @@ def handle_workflow_create(args, render_mapping):
|
||||
"estimated_duration": f"{steps * 2}-{steps * 3} minutes"
|
||||
}
|
||||
|
||||
print(f"Workflow created: {workflow_data['workflow_id']}")
|
||||
logger.info(f"Workflow created: {workflow_data['workflow_id']}")
|
||||
render_mapping("Workflow:", workflow_data)
|
||||
|
||||
|
||||
@@ -37,7 +40,7 @@ def handle_workflow_schedule(args, render_mapping):
|
||||
"next_run": "pending"
|
||||
}
|
||||
|
||||
print(f"Workflow scheduled: {schedule_data['schedule_id']}")
|
||||
logger.info(f"Workflow scheduled: {schedule_data['schedule_id']}")
|
||||
render_mapping("Schedule:", schedule_data)
|
||||
|
||||
|
||||
@@ -54,6 +57,6 @@ def handle_workflow_monitor(args, output_format, render_mapping):
|
||||
}
|
||||
|
||||
if output_format(args) == "json":
|
||||
print(json.dumps(monitor_data, indent=2))
|
||||
logger.info(json.dumps(monitor_data, indent=2))
|
||||
else:
|
||||
render_mapping("Workflow Monitor:", monitor_data)
|
||||
|
||||
Reference in New Issue
Block a user