Migrate CLI and Python packages to centralized aitbc package utilities

CLI migration:
- Migrate 11 CLI files from old import pattern to centralized aitbc imports
- wallet.py, exchange.py, gpu_marketplace.py, exchange_island.py, monitor.py, cross_chain.py
- aitbc_cli.py, handlers (account.py, bridge.py, pool_hub.py), utils (wallet_daemon_client.py)
- Replace 'from aitbc.aitbc_logging import' with 'from aitbc import get_logger'
- Replace 'from aitbc.http_client import' with 'from aitbc import AITBCHTTPClient'
- Replace 'from aitbc.exceptions import' with 'from aitbc import NetworkError'

Packages migration:
- aitbc-sdk: receipts.py - migrate from httpx to AITBCHTTPClient
- aitbc-agent-sdk: 5 files - migrate logging to get_logger
  - agent.py, compute_provider.py, compute_consumer.py, swarm_coordinator.py, platform_builder.py
This commit is contained in:
aitbc
2026-04-25 07:04:57 +02:00
parent 55060730b2
commit 119d0f42c0
17 changed files with 282 additions and 459 deletions

View File

@@ -37,12 +37,11 @@ import requests
from typing import Optional, Dict, Any, List from typing import Optional, Dict, Any, List
# Import shared modules # Import shared modules
from aitbc.constants import KEYSTORE_DIR, BLOCKCHAIN_RPC_PORT, DATA_DIR from aitbc import (
from aitbc.http_client import AITBCHTTPClient KEYSTORE_DIR, BLOCKCHAIN_RPC_PORT, DATA_DIR,
from aitbc.exceptions import NetworkError, ValidationError, ConfigurationError AITBCHTTPClient, NetworkError, ValidationError, ConfigurationError,
from aitbc.aitbc_logging import get_logger get_logger, get_keystore_path, ensure_dir, validate_address, validate_url
from aitbc.paths import get_keystore_path, ensure_dir )
from aitbc.validation import validate_address, validate_url
# Initialize logger # Initialize logger
logger = get_logger(__name__) logger = get_logger(__name__)

View File

@@ -8,9 +8,7 @@ from ..config import get_config
from ..utils import success, error, output from ..utils import success, error, output
# Import shared modules # Import shared modules
from aitbc.aitbc_logging import get_logger from aitbc import get_logger, AITBCHTTPClient, NetworkError
from aitbc.http_client import AITBCHTTPClient
from aitbc.exceptions import NetworkError
# Initialize logger # Initialize logger
logger = get_logger(__name__) logger = get_logger(__name__)

View File

@@ -10,9 +10,7 @@ from ..utils import output, error, success, warning
from ..config import get_config from ..config import get_config
# Import shared modules # Import shared modules
from aitbc.aitbc_logging import get_logger from aitbc import get_logger, AITBCHTTPClient, NetworkError
from aitbc.http_client import AITBCHTTPClient
from aitbc.exceptions import NetworkError
# Initialize logger # Initialize logger
logger = get_logger(__name__) logger = get_logger(__name__)

View File

@@ -18,9 +18,7 @@ from ..utils.island_credentials import (
) )
# Import shared modules # Import shared modules
from aitbc.aitbc_logging import get_logger from aitbc import get_logger, AITBCHTTPClient, NetworkError
from aitbc.http_client import AITBCHTTPClient
from aitbc.exceptions import NetworkError
# Initialize logger # Initialize logger
logger = get_logger(__name__) logger = get_logger(__name__)
@@ -313,49 +311,6 @@ def orderbook(ctx, pair: str, limit: int):
raise click.Abort() raise click.Abort()
except Exception as e: except Exception as e:
error(f"Error fetching order book: {str(e)}") error(f"Error fetching order book: {str(e)}")
raise click.Abort()
"Amount": f"{order.get('amount', 0):.4f} AIT",
"Total": f"{order.get('min_price', 0) * order.get('amount', 0):.8f} {pair.split('/')[1]}",
"User": order.get('user_id', '')[:16] + "...",
"Order": order.get('order_id', '')[:16] + "..."
})
output(asks_data, ctx.obj.get('output_format', 'table'), title=f"Sell Orders (Asks) - {pair}")
# Display buy orders (bids)
if buy_orders:
bids_data = []
for order in buy_orders[:limit]:
bids_data.append({
"Price": f"{order.get('max_price', 0):.8f}",
"Amount": f"{order.get('amount', 0):.4f} AIT",
"Total": f"{order.get('max_price', 0) * order.get('amount', 0):.8f} {pair.split('/')[1]}",
"User": order.get('user_id', '')[:16] + "...",
"Order": order.get('order_id', '')[:16] + "..."
})
output(bids_data, ctx.obj.get('output_format', 'table'), title=f"Buy Orders (Bids) - {pair}")
# Calculate spread if both exist
if sell_orders and buy_orders:
best_ask = sell_orders[0].get('min_price', 0)
best_bid = buy_orders[0].get('max_price', 0)
spread = best_ask - best_bid
if best_bid > 0:
spread_pct = (spread / best_bid) * 100
info(f"Spread: {spread:.8f} ({spread_pct:.4f}%)")
info(f"Best Bid: {best_bid:.8f} {pair.split('/')[1]}/AIT")
info(f"Best Ask: {best_ask:.8f} {pair.split('/')[1]}/AIT")
else:
error(f"Failed to query blockchain: {response.status_code}")
raise click.Abort()
except Exception as e:
error(f"Network error querying blockchain: {e}")
raise click.Abort()
except Exception as e:
error(f"Error viewing order book: {str(e)}")
raise click.Abort() raise click.Abort()
@@ -371,7 +326,6 @@ def rates(ctx):
# Query blockchain for exchange orders to calculate rates # Query blockchain for exchange orders to calculate rates
try: try:
import httpx
rates_data = [] rates_data = []
for pair in SUPPORTED_PAIRS: for pair in SUPPORTED_PAIRS:
@@ -383,44 +337,28 @@ def rates(ctx):
'limit': 100 'limit': 100
} }
with httpx.Client() as client: http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10)
response = client.get( orders = http_client.get("/transactions", params=params)
f"{rpc_endpoint}/transactions",
params=params, # Calculate rates from order book
timeout=10 buy_orders = [o for o in orders if o.get('side') == 'buy']
) sell_orders = [o for o in orders if o.get('side') == 'sell']
if response.status_code == 200: # Get best bid and ask
orders = response.json() best_bid = max([o.get('max_price', 0) for o in buy_orders]) if buy_orders else 0
best_ask = min([o.get('min_price', float('inf')) for o in sell_orders]) if sell_orders else 0
# Calculate rates from order book
buy_orders = [o for o in orders if o.get('side') == 'buy'] # Calculate mid price
sell_orders = [o for o in orders if o.get('side') == 'sell'] mid_price = (best_bid + best_ask) / 2 if best_bid > 0 and best_ask < float('inf') else 0
# Get best bid and ask rates_data.append({
best_bid = max([o.get('max_price', 0) for o in buy_orders]) if buy_orders else 0 "Pair": pair,
best_ask = min([o.get('min_price', float('inf')) for o in sell_orders]) if sell_orders else 0 "Best Bid": f"{best_bid:.8f}" if best_bid > 0 else "N/A",
"Best Ask": f"{best_ask:.8f}" if best_ask < float('inf') else "N/A",
# Calculate mid price "Mid Price": f"{mid_price:.8f}" if mid_price > 0 else "N/A",
mid_price = (best_bid + best_ask) / 2 if best_bid > 0 and best_ask < float('inf') else 0 "Buy Orders": len(buy_orders),
"Sell Orders": len(sell_orders)
rates_data.append({ })
"Pair": pair,
"Best Bid": f"{best_bid:.8f}" if best_bid > 0 else "N/A",
"Best Ask": f"{best_ask:.8f}" if best_ask < float('inf') else "N/A",
"Mid Price": f"{mid_price:.8f}" if mid_price > 0 else "N/A",
"Buy Orders": len(buy_orders),
"Sell Orders": len(sell_orders)
})
else:
rates_data.append({
"Pair": pair,
"Best Bid": "Error",
"Best Ask": "Error",
"Mid Price": "Error",
"Buy Orders": 0,
"Sell Orders": 0
})
output(rates_data, ctx.obj.get('output_format', 'table'), title="Exchange Rates") output(rates_data, ctx.obj.get('output_format', 'table'), title="Exchange Rates")
@@ -448,7 +386,6 @@ def orders(ctx, user: Optional[str], status: Optional[str], pair: Optional[str])
# Query blockchain for exchange orders # Query blockchain for exchange orders
try: try:
import httpx
params = { params = {
'transaction_type': 'exchange', 'transaction_type': 'exchange',
'island_id': island_id 'island_id': island_id
@@ -460,39 +397,29 @@ def orders(ctx, user: Optional[str], status: Optional[str], pair: Optional[str])
if pair: if pair:
params['pair'] = pair params['pair'] = pair
with httpx.Client() as client: http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10)
response = client.get( orders = http_client.get("/transactions", params=params)
f"{rpc_endpoint}/transactions",
params=params, if not orders:
timeout=10 info("No exchange orders found")
) return
if response.status_code == 200: # Format output
orders = response.json() orders_data = []
for order in orders:
if not orders: orders_data.append({
info("No exchange orders found") "Order ID": order.get('order_id', '')[:20] + "...",
return "Pair": order.get('pair'),
"Side": order.get('side', '').upper(),
# Format output "Amount": f"{order.get('amount', 0):.4f} AIT",
orders_data = [] "Price": f"{order.get('max_price', order.get('min_price', 0)):.8f}" if order.get('max_price') or order.get('min_price') else "Market",
for order in orders: "Status": order.get('status'),
orders_data.append({ "User": order.get('user_id', '')[:16] + "...",
"Order ID": order.get('order_id', '')[:20] + "...", "Created": order.get('created_at', '')[:19]
"Pair": order.get('pair'), })
"Side": order.get('side', '').upper(),
"Amount": f"{order.get('amount', 0):.4f} AIT", output(orders_data, ctx.obj.get('output_format', 'table'), title=f"Exchange Orders ({island_id[:16]}...)")
"Price": f"{order.get('max_price', order.get('min_price', 0)):.8f}" if order.get('max_price') or order.get('min_price') else "Market", except NetworkError as e:
"Status": order.get('status'),
"User": order.get('user_id', '')[:16] + "...",
"Created": order.get('created_at', '')[:19]
})
output(orders_data, ctx.obj.get('output_format', 'table'), title=f"Exchange Orders ({island_id[:16]}...)")
else:
error(f"Failed to query blockchain: {response.status_code}")
raise click.Abort()
except Exception as e:
error(f"Network error querying blockchain: {e}") error(f"Network error querying blockchain: {e}")
raise click.Abort() raise click.Abort()
@@ -544,22 +471,10 @@ def cancel(ctx, order_id: str):
# Submit transaction to blockchain # Submit transaction to blockchain
try: try:
import httpx http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10)
with httpx.Client() as client: result = http_client.post("/transaction", json=cancel_data)
response = client.post( success(f"Order {order_id} cancelled successfully!")
f"{rpc_endpoint}/transaction", except NetworkError as e:
json=cancel_data,
timeout=10
)
if response.status_code == 200:
success(f"Order {order_id} cancelled successfully!")
else:
error(f"Failed to cancel order: {response.status_code}")
if response.text:
error(f"Error details: {response.text}")
raise click.Abort()
except Exception as e:
error(f"Network error submitting transaction: {e}") error(f"Network error submitting transaction: {e}")
raise click.Abort() raise click.Abort()

View File

@@ -18,6 +18,12 @@ from ..utils.island_credentials import (
get_island_id, get_island_name get_island_id, get_island_name
) )
# Import shared modules
from aitbc import get_logger, AITBCHTTPClient, NetworkError
# Initialize logger
logger = get_logger(__name__)
@click.group() @click.group()
def gpu(): def gpu():
@@ -100,38 +106,25 @@ def offer(ctx, gpu_count: int, price_per_gpu: float, duration_hours: int, specs:
# Submit transaction to blockchain # Submit transaction to blockchain
try: try:
import httpx http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10)
with httpx.Client() as client: result = http_client.post("/transaction", json=offer_data)
response = client.post( success(f"GPU offer created successfully!")
f"{rpc_endpoint}/transaction", success(f"Offer ID: {offer_id}")
json=offer_data, success(f"Total Price: {total_price:.2f} AIT")
timeout=10
) offer_info = {
"Offer ID": offer_id,
if response.status_code == 200: "GPU Count": gpu_count,
result = response.json() "Price per GPU": f"{price_per_gpu:.4f} AIT/hour",
success(f"GPU offer created successfully!") "Duration": f"{duration_hours} hours",
success(f"Offer ID: {offer_id}") "Total Price": f"{total_price:.2f} AIT",
success(f"Total Price: {total_price:.2f} AIT") "Status": "active",
"Provider Node": provider_node_id[:16] + "...",
offer_info = { "Island": island_id[:16] + "..."
"Offer ID": offer_id, }
"GPU Count": gpu_count,
"Price per GPU": f"{price_per_gpu:.4f} AIT/hour", output(offer_info, ctx.obj.get('output_format', 'table'))
"Duration": f"{duration_hours} hours", except NetworkError as e:
"Total Price": f"{total_price:.2f} AIT",
"Status": "active",
"Provider Node": provider_node_id[:16] + "...",
"Island": island_id[:16] + "..."
}
output(offer_info, ctx.obj.get('output_format', 'table'))
else:
error(f"Failed to submit transaction: {response.status_code}")
if response.text:
error(f"Error details: {response.text}")
raise click.Abort()
except Exception as e:
error(f"Network error submitting transaction: {e}") error(f"Network error submitting transaction: {e}")
raise click.Abort() raise click.Abort()
@@ -213,38 +206,25 @@ def bid(ctx, gpu_count: int, max_price: float, duration_hours: int, specs: Optio
# Submit transaction to blockchain # Submit transaction to blockchain
try: try:
import httpx http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10)
with httpx.Client() as client: result = http_client.post("/v1/transactions", json=bid_data)
response = client.post( success(f"GPU bid created successfully!")
f"{rpc_endpoint}/v1/transactions", success(f"Bid ID: {bid_id}")
json=bid_data, success(f"Max Total Price: {max_total_price:.2f} AIT")
timeout=10
) bid_info = {
"Bid ID": bid_id,
if response.status_code == 200: "GPU Count": gpu_count,
result = response.json() "Max Price per GPU": f"{max_price:.4f} AIT/hour",
success(f"GPU bid created successfully!") "Duration": f"{duration_hours} hours",
success(f"Bid ID: {bid_id}") "Max Total Price": f"{max_total_price:.2f} AIT",
success(f"Max Total Price: {max_total_price:.2f} AIT") "Status": "pending",
"Bidder Node": bidder_node_id[:16] + "...",
bid_info = { "Island": island_id[:16] + "..."
"Bid ID": bid_id, }
"GPU Count": gpu_count,
"Max Price per GPU": f"{max_price:.4f} AIT/hour", output(bid_info, ctx.obj.get('output_format', 'table'))
"Duration": f"{duration_hours} hours", except NetworkError as e:
"Max Total Price": f"{max_total_price:.2f} AIT",
"Status": "pending",
"Bidder Node": bidder_node_id[:16] + "...",
"Island": island_id[:16] + "..."
}
output(bid_info, ctx.obj.get('output_format', 'table'))
else:
error(f"Failed to submit transaction: {response.status_code}")
if response.text:
error(f"Error details: {response.text}")
raise click.Abort()
except Exception as e:
error(f"Network error submitting transaction: {e}") error(f"Network error submitting transaction: {e}")
raise click.Abort() raise click.Abort()
@@ -268,7 +248,6 @@ def list(ctx, provider: Optional[str], status: Optional[str], type: str):
# Query blockchain for GPU marketplace transactions # Query blockchain for GPU marketplace transactions
try: try:
import httpx
params = { params = {
'transaction_type': 'gpu_marketplace', 'transaction_type': 'gpu_marketplace',
'island_id': island_id 'island_id': island_id
@@ -280,54 +259,44 @@ def list(ctx, provider: Optional[str], status: Optional[str], type: str):
if type != 'all': if type != 'all':
params['action'] = type params['action'] = type
with httpx.Client() as client: http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10)
response = client.get( transactions = http_client.get("/transactions", params=params)
f"{rpc_endpoint}/transactions",
params=params, if not transactions:
timeout=10 info("No GPU marketplace transactions found")
) return
if response.status_code == 200: # Format output
transactions = response.json() market_data = []
for tx in transactions:
if not transactions: action = tx.get('action')
info("No GPU marketplace transactions found") if action == 'offer':
return market_data.append({
"ID": tx.get('offer_id', tx.get('transaction_id', 'N/A'))[:20] + "...",
# Format output "Type": "OFFER",
market_data = [] "GPU Count": tx.get('gpu_count'),
for tx in transactions: "Price": f"{tx.get('price_per_gpu', 0):.4f} AIT/h",
action = tx.get('action') "Duration": f"{tx.get('duration_hours')}h",
if action == 'offer': "Total": f"{tx.get('total_price', 0):.2f} AIT",
market_data.append({ "Status": tx.get('status'),
"ID": tx.get('offer_id', tx.get('transaction_id', 'N/A'))[:20] + "...", "Provider": tx.get('provider_node_id', '')[:16] + "...",
"Type": "OFFER", "Created": tx.get('created_at', '')[:19]
"GPU Count": tx.get('gpu_count'), })
"Price": f"{tx.get('price_per_gpu', 0):.4f} AIT/h", elif action == 'bid':
"Duration": f"{tx.get('duration_hours')}h", market_data.append({
"Total": f"{tx.get('total_price', 0):.2f} AIT", "ID": tx.get('bid_id', tx.get('transaction_id', 'N/A'))[:20] + "...",
"Status": tx.get('status'), "Type": "BID",
"Provider": tx.get('provider_node_id', '')[:16] + "...", "GPU Count": tx.get('gpu_count'),
"Created": tx.get('created_at', '')[:19] "Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h",
}) "Duration": f"{tx.get('duration_hours')}h",
elif action == 'bid': "Max Total": f"{tx.get('max_total_price', 0):.2f} AIT",
market_data.append({ "Status": tx.get('status'),
"ID": tx.get('bid_id', tx.get('transaction_id', 'N/A'))[:20] + "...", "Bidder": tx.get('bidder_node_id', '')[:16] + "...",
"Type": "BID", "Created": tx.get('created_at', '')[:19]
"GPU Count": tx.get('gpu_count'), })
"Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h",
"Duration": f"{tx.get('duration_hours')}h", output(market_data, ctx.obj.get('output_format', 'table'), title=f"GPU Marketplace ({island_id[:16]}...)")
"Max Total": f"{tx.get('max_total_price', 0):.2f} AIT", except NetworkError as e:
"Status": tx.get('status'),
"Bidder": tx.get('bidder_node_id', '')[:16] + "...",
"Created": tx.get('created_at', '')[:19]
})
output(market_data, ctx.obj.get('output_format', 'table'), title=f"GPU Marketplace ({island_id[:16]}...)")
else:
error(f"Failed to query blockchain: {response.status_code}")
raise click.Abort()
except Exception as e:
error(f"Network error querying blockchain: {e}") error(f"Network error querying blockchain: {e}")
raise click.Abort() raise click.Abort()
@@ -390,22 +359,10 @@ def cancel(ctx, order_id: str):
# Submit transaction to blockchain # Submit transaction to blockchain
try: try:
import httpx http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10)
with httpx.Client() as client: result = http_client.post("/transaction", json=cancel_data)
response = client.post( success(f"Order {order_id} cancelled successfully!")
f"{rpc_endpoint}/transaction", except NetworkError as e:
json=cancel_data,
timeout=10
)
if response.status_code == 200:
success(f"Order {order_id} cancelled successfully!")
else:
error(f"Failed to cancel order: {response.status_code}")
if response.text:
error(f"Error details: {response.text}")
raise click.Abort()
except Exception as e:
error(f"Network error submitting transaction: {e}") error(f"Network error submitting transaction: {e}")
raise click.Abort() raise click.Abort()
@@ -463,22 +420,10 @@ def accept(ctx, bid_id: str):
# Submit transaction to blockchain # Submit transaction to blockchain
try: try:
import httpx http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10)
with httpx.Client() as client: result = http_client.post("/transaction", json=accept_data)
response = client.post( success(f"Bid {bid_id} accepted successfully!")
f"{rpc_endpoint}/transaction", except NetworkError as e:
json=accept_data,
timeout=10
)
if response.status_code == 200:
success(f"Bid {bid_id} accepted successfully!")
else:
error(f"Failed to accept bid: {response.status_code}")
if response.text:
error(f"Error details: {response.text}")
raise click.Abort()
except Exception as e:
error(f"Network error submitting transaction: {e}") error(f"Network error submitting transaction: {e}")
raise click.Abort() raise click.Abort()
@@ -500,64 +445,53 @@ def status(ctx, order_id: str):
# Query blockchain for the order # Query blockchain for the order
try: try:
import httpx
params = { params = {
'transaction_type': 'gpu_marketplace', 'transaction_type': 'gpu_marketplace',
'island_id': island_id, 'island_id': island_id,
'order_id': order_id 'order_id': order_id
} }
with httpx.Client() as client: http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10)
response = client.get( transactions = http_client.get("/transactions", params=params)
f"{rpc_endpoint}/transactions",
params=params, if not transactions:
timeout=10 error(f"Order {order_id} not found")
) raise click.Abort()
if response.status_code == 200: tx = transactions[0]
transactions = response.json() action = tx.get('action')
if not transactions: order_info = {
error(f"Order {order_id} not found") "Order ID": order_id,
raise click.Abort() "Type": action.upper(),
"Status": tx.get('status'),
tx = transactions[0] "Created": tx.get('created_at'),
action = tx.get('action') }
order_info = { if action == 'offer':
"Order ID": order_id, order_info.update({
"Type": action.upper(), "GPU Count": tx.get('gpu_count'),
"Status": tx.get('status'), "Price per GPU": f"{tx.get('price_per_gpu', 0):.4f} AIT/h",
"Created": tx.get('created_at'), "Duration": f"{tx.get('duration_hours')}h",
} "Total Price": f"{tx.get('total_price', 0):.2f} AIT",
"Provider": tx.get('provider_node_id', '')[:16] + "..."
if action == 'offer': })
order_info.update({ elif action == 'bid':
"GPU Count": tx.get('gpu_count'), order_info.update({
"Price per GPU": f"{tx.get('price_per_gpu', 0):.4f} AIT/h", "GPU Count": tx.get('gpu_count'),
"Duration": f"{tx.get('duration_hours')}h", "Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h",
"Total Price": f"{tx.get('total_price', 0):.2f} AIT", "Duration": f"{tx.get('duration_hours')}h",
"Provider": tx.get('provider_node_id', '')[:16] + "..." "Max Total": f"{tx.get('max_total_price', 0):.2f} AIT",
}) "Bidder": tx.get('bidder_node_id', '')[:16] + "..."
elif action == 'bid': })
order_info.update({
"GPU Count": tx.get('gpu_count'), if 'accepted_at' in tx:
"Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h", order_info["Accepted"] = tx['accepted_at']
"Duration": f"{tx.get('duration_hours')}h", if 'cancelled_at' in tx:
"Max Total": f"{tx.get('max_total_price', 0):.2f} AIT", order_info["Cancelled"] = tx['cancelled_at']
"Bidder": tx.get('bidder_node_id', '')[:16] + "..."
}) output(order_info, ctx.obj.get('output_format', 'table'), title=f"Order Status: {order_id}")
except NetworkError as e:
if 'accepted_at' in tx:
order_info["Accepted"] = tx['accepted_at']
if 'cancelled_at' in tx:
order_info["Cancelled"] = tx['cancelled_at']
output(order_info, ctx.obj.get('output_format', 'table'), title=f"Order Status: {order_id}")
else:
error(f"Failed to query blockchain: {response.status_code}")
raise click.Abort()
except Exception as e:
error(f"Network error querying blockchain: {e}") error(f"Network error querying blockchain: {e}")
raise click.Abort() raise click.Abort()
@@ -578,96 +512,79 @@ def match(ctx):
# Query blockchain for open offers and bids # Query blockchain for open offers and bids
try: try:
import httpx
params = { params = {
'transaction_type': 'gpu_marketplace', 'transaction_type': 'gpu_marketplace',
'island_id': island_id, 'island_id': island_id,
'status': 'active' 'status': 'active'
} }
with httpx.Client() as client: http_client = AITBCHTTPClient(base_url=rpc_endpoint, timeout=10)
response = client.get( transactions = http_client.get("/transactions", params=params)
f"{rpc_endpoint}/transactions",
params=params, # Separate offers and bids
timeout=10 offers = []
) bids = []
if response.status_code == 200: for tx in transactions:
transactions = response.json() if tx.get('action') == 'offer':
offers.append(tx)
# Separate offers and bids elif tx.get('action') == 'bid':
offers = [] bids.append(tx)
bids = []
if not offers or not bids:
for tx in transactions: info("No active offers or bids to match")
if tx.get('action') == 'offer': return
offers.append(tx)
elif tx.get('action') == 'bid': # Sort offers by price (lowest first)
bids.append(tx) offers.sort(key=lambda x: x.get('price_per_gpu', float('inf')))
# Sort bids by price (highest first)
if not offers or not bids: bids.sort(key=lambda x: x.get('max_price_per_gpu', 0), reverse=True)
info("No active offers or bids to match")
return # Match bids with offers
matches = []
# Sort offers by price (lowest first) for bid in bids:
offers.sort(key=lambda x: x.get('price_per_gpu', float('inf'))) for offer in offers:
# Sort bids by price (highest first) # Check if bid price >= offer price
bids.sort(key=lambda x: x.get('max_price_per_gpu', 0), reverse=True) if bid.get('max_price_per_gpu', 0) >= offer.get('price_per_gpu', float('inf')):
# Check if GPU count matches
# Match bids with offers if bid.get('gpu_count') == offer.get('gpu_count'):
matches = [] # Check if duration matches
for bid in bids: if bid.get('duration_hours') == offer.get('duration_hours'):
for offer in offers: # Create match transaction
# Check if bid price >= offer price match_data = {
if bid.get('max_price_per_gpu', 0) >= offer.get('price_per_gpu', float('inf')): 'type': 'gpu_marketplace',
# Check if GPU count matches 'action': 'match',
if bid.get('gpu_count') == offer.get('gpu_count'): 'bid_id': bid.get('bid_id'),
# Check if duration matches 'offer_id': offer.get('offer_id'),
if bid.get('duration_hours') == offer.get('duration_hours'): 'bidder_node_id': bid.get('bidder_node_id'),
# Create match transaction 'provider_node_id': offer.get('provider_node_id'),
match_data = { 'gpu_count': bid.get('gpu_count'),
'type': 'gpu_marketplace', 'matched_price': offer.get('price_per_gpu'),
'action': 'match', 'duration_hours': bid.get('duration_hours'),
'bid_id': bid.get('bid_id'), 'total_price': offer.get('total_price'),
'offer_id': offer.get('offer_id'), 'status': 'matched',
'bidder_node_id': bid.get('bidder_node_id'), 'matched_at': datetime.now().isoformat(),
'provider_node_id': offer.get('provider_node_id'), 'island_id': island_id,
'gpu_count': bid.get('gpu_count'), 'chain_id': get_chain_id()
'matched_price': offer.get('price_per_gpu'), }
'duration_hours': bid.get('duration_hours'),
'total_price': offer.get('total_price'), # Submit match transaction
'status': 'matched', match_result = http_client.post("/transaction", json=match_data)
'matched_at': datetime.now().isoformat(), matches.append({
'island_id': island_id, "Bid ID": bid.get('bid_id')[:16] + "...",
'chain_id': get_chain_id() "Offer ID": offer.get('offer_id')[:16] + "...",
} "GPU Count": bid.get('gpu_count'),
"Matched Price": f"{offer.get('price_per_gpu', 0):.4f} AIT/h",
# Submit match transaction "Total Price": f"{offer.get('total_price', 0):.2f} AIT",
match_response = client.post( "Duration": f"{bid.get('duration_hours')}h"
f"{rpc_endpoint}/transaction", })
json=match_data,
timeout=10 if matches:
) success(f"Matched {len(matches)} GPU orders!")
output(matches, ctx.obj.get('output_format', 'table'), title="GPU Order Matches")
if match_response.status_code == 200: else:
matches.append({ info("No matching orders found")
"Bid ID": bid.get('bid_id')[:16] + "...", except NetworkError as e:
"Offer ID": offer.get('offer_id')[:16] + "...",
"GPU Count": bid.get('gpu_count'),
"Matched Price": f"{offer.get('price_per_gpu', 0):.4f} AIT/h",
"Total Price": f"{offer.get('total_price', 0):.2f} AIT",
"Duration": f"{bid.get('duration_hours')}h"
})
if matches:
success(f"Matched {len(matches)} GPU orders!")
output(matches, ctx.obj.get('output_format', 'table'), title="GPU Order Matches")
else:
info("No matching orders found")
else:
error(f"Failed to query blockchain: {response.status_code}")
raise click.Abort()
except Exception as e:
error(f"Network error querying blockchain: {e}") error(f"Network error querying blockchain: {e}")
raise click.Abort() raise click.Abort()

View File

@@ -9,9 +9,7 @@ from datetime import datetime, timedelta
from ..utils import output, error, success, console from ..utils import output, error, success, console
# Import shared modules # Import shared modules
from aitbc.aitbc_logging import get_logger from aitbc import get_logger, AITBCHTTPClient, NetworkError
from aitbc.http_client import AITBCHTTPClient
from aitbc.exceptions import NetworkError
# Initialize logger # Initialize logger
logger = get_logger(__name__) logger = get_logger(__name__)

View File

@@ -12,10 +12,7 @@ from ..utils import output, error, success
import getpass import getpass
# Import shared modules # Import shared modules
from aitbc.aitbc_logging import get_logger from aitbc import get_logger, AITBCHTTPClient, NetworkError, KEYSTORE_DIR
from aitbc.http_client import AITBCHTTPClient
from aitbc.exceptions import NetworkError
from aitbc.constants import KEYSTORE_DIR
# Initialize logger # Initialize logger
logger = get_logger(__name__) logger = get_logger(__name__)

View File

@@ -3,8 +3,7 @@
import json import json
import sys import sys
from aitbc.http_client import AITBCHTTPClient from aitbc import AITBCHTTPClient, NetworkError
from aitbc.exceptions import NetworkError
def handle_account_get(args, default_rpc_url, output_format): def handle_account_get(args, default_rpc_url, output_format):

View File

@@ -2,8 +2,7 @@
import subprocess import subprocess
from aitbc.http_client import AITBCHTTPClient from aitbc import AITBCHTTPClient, NetworkError
from aitbc.exceptions import NetworkError
def handle_bridge_health(args): def handle_bridge_health(args):

View File

@@ -1,7 +1,6 @@
"""Pool hub SLA and capacity management handlers.""" """Pool hub SLA and capacity management handlers."""
from aitbc.http_client import AITBCHTTPClient from aitbc import AITBCHTTPClient, NetworkError
from aitbc.exceptions import NetworkError
def handle_pool_hub_sla_metrics(args): def handle_pool_hub_sla_metrics(args):

View File

@@ -10,8 +10,7 @@ from typing import Dict, Any, Optional, List
from pathlib import Path from pathlib import Path
from dataclasses import dataclass from dataclasses import dataclass
from aitbc.http_client import AITBCHTTPClient from aitbc import AITBCHTTPClient, NetworkError
from aitbc.exceptions import NetworkError
from utils import error, success from utils import error, success
from config import Config from config import Config

View File

@@ -4,7 +4,6 @@ Core Agent class for AITBC network participation
import asyncio import asyncio
import json import json
import logging
import uuid import uuid
from datetime import datetime from datetime import datetime
from typing import Dict, List, Optional, Any from typing import Dict, List, Optional, Any
@@ -14,7 +13,9 @@ from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives.asymmetric import padding
logger = logging.getLogger(__name__) from aitbc import get_logger
logger = get_logger(__name__)
@dataclass @dataclass

View File

@@ -3,13 +3,14 @@ Compute Consumer Agent - for agents that consume computational resources
""" """
import asyncio import asyncio
import logging
from typing import Dict, List, Optional, Any from typing import Dict, List, Optional, Any
from datetime import datetime from datetime import datetime
from dataclasses import dataclass from dataclasses import dataclass
from .agent import Agent, AgentCapabilities from .agent import Agent, AgentCapabilities
logger = logging.getLogger(__name__) from aitbc import get_logger
logger = get_logger(__name__)
@dataclass @dataclass

View File

@@ -3,13 +3,14 @@ Compute Provider Agent - for agents that provide computational resources
""" """
import asyncio import asyncio
import logging
from typing import Dict, List, Optional, Any from typing import Dict, List, Optional, Any
from datetime import datetime, timedelta from datetime import datetime, timedelta
from dataclasses import dataclass from dataclasses import dataclass
from .agent import Agent, AgentCapabilities from .agent import Agent, AgentCapabilities
logger = logging.getLogger(__name__) from aitbc import get_logger
logger = get_logger(__name__)
@dataclass @dataclass

View File

@@ -2,14 +2,15 @@
Platform Builder - factory for constructing AITBC agent platform configurations Platform Builder - factory for constructing AITBC agent platform configurations
""" """
import logging
from typing import Dict, List, Any, Optional from typing import Dict, List, Any, Optional
from .agent import Agent, AgentCapabilities, AgentIdentity from .agent import Agent, AgentCapabilities, AgentIdentity
from .compute_provider import ComputeProvider from .compute_provider import ComputeProvider
from .compute_consumer import ComputeConsumer from .compute_consumer import ComputeConsumer
from .swarm_coordinator import SwarmCoordinator from .swarm_coordinator import SwarmCoordinator
logger = logging.getLogger(__name__) from aitbc import get_logger
logger = get_logger(__name__)
class PlatformBuilder: class PlatformBuilder:

View File

@@ -4,13 +4,14 @@ Swarm Coordinator - for agents participating in collective intelligence
import asyncio import asyncio
import json import json
import logging
from typing import Dict, List, Optional, Any # noqa: F401 from typing import Dict, List, Optional, Any # noqa: F401
from datetime import datetime from datetime import datetime
from dataclasses import dataclass from dataclasses import dataclass
from .agent import Agent from .agent import Agent
logger = logging.getLogger(__name__) from aitbc import get_logger
logger = get_logger(__name__)
@dataclass @dataclass

View File

@@ -4,9 +4,9 @@ import time
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any, Dict, Iterable, Iterator, List, Optional, cast from typing import Any, Dict, Iterable, Iterator, List, Optional, cast
import httpx
import base64 import base64
from aitbc import AITBCHTTPClient, NetworkError
from aitbc_crypto.signing import ReceiptVerifier from aitbc_crypto.signing import ReceiptVerifier
@@ -83,8 +83,8 @@ class CoordinatorReceiptClient:
self.max_retries = max_retries self.max_retries = max_retries
self.backoff_seconds = backoff_seconds self.backoff_seconds = backoff_seconds
def _client(self) -> httpx.Client: def _client(self) -> AITBCHTTPClient:
return httpx.Client( return AITBCHTTPClient(
base_url=self.base_url, base_url=self.base_url,
timeout=self.timeout, timeout=self.timeout,
headers={"X-Api-Key": self.api_key}, headers={"X-Api-Key": self.api_key},
@@ -187,9 +187,9 @@ class CoordinatorReceiptClient:
attempt = 0 attempt = 0
while True: while True:
try: try:
with self._client() as client: client = self._client()
response = client.request(method=method, url=url, params=params) response = client.request(method=method, url=url, params=params)
except httpx.HTTPError: except NetworkError:
if attempt >= self.max_retries: if attempt >= self.max_retries:
raise raise
attempt += 1 attempt += 1