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,
timeout=10
)
if response.status_code == 200: # Calculate rates from order book
orders = response.json() buy_orders = [o for o in orders if o.get('side') == 'buy']
sell_orders = [o for o in orders if o.get('side') == 'sell']
# Calculate rates from order book # Get best bid and ask
buy_orders = [o for o in orders if o.get('side') == 'buy'] best_bid = max([o.get('max_price', 0) for o in buy_orders]) if buy_orders else 0
sell_orders = [o for o in orders if o.get('side') == 'sell'] best_ask = min([o.get('min_price', float('inf')) for o in sell_orders]) if sell_orders else 0
# Get best bid and ask # Calculate mid price
best_bid = max([o.get('max_price', 0) for o in buy_orders]) if buy_orders else 0 mid_price = (best_bid + best_ask) / 2 if best_bid > 0 and best_ask < float('inf') else 0
best_ask = min([o.get('min_price', float('inf')) for o in sell_orders]) if sell_orders else 0
# Calculate mid price rates_data.append({
mid_price = (best_bid + best_ask) / 2 if best_bid > 0 and best_ask < float('inf') else 0 "Pair": pair,
"Best Bid": f"{best_bid:.8f}" if best_bid > 0 else "N/A",
rates_data.append({ "Best Ask": f"{best_ask:.8f}" if best_ask < float('inf') else "N/A",
"Pair": pair, "Mid Price": f"{mid_price:.8f}" if mid_price > 0 else "N/A",
"Best Bid": f"{best_bid:.8f}" if best_bid > 0 else "N/A", "Buy Orders": len(buy_orders),
"Best Ask": f"{best_ask:.8f}" if best_ask < float('inf') else "N/A", "Sell Orders": len(sell_orders)
"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,
timeout=10
)
if response.status_code == 200: if not orders:
orders = response.json() info("No exchange orders found")
return
if not orders: # Format output
info("No exchange orders found") orders_data = []
return for order in orders:
orders_data.append({
"Order ID": order.get('order_id', '')[:20] + "...",
"Pair": order.get('pair'),
"Side": order.get('side', '').upper(),
"Amount": f"{order.get('amount', 0):.4f} AIT",
"Price": f"{order.get('max_price', order.get('min_price', 0)):.8f}" if order.get('max_price') or order.get('min_price') else "Market",
"Status": order.get('status'),
"User": order.get('user_id', '')[:16] + "...",
"Created": order.get('created_at', '')[:19]
})
# Format output output(orders_data, ctx.obj.get('output_format', 'table'), title=f"Exchange Orders ({island_id[:16]}...)")
orders_data = [] except NetworkError as e:
for order in orders:
orders_data.append({
"Order ID": order.get('order_id', '')[:20] + "...",
"Pair": order.get('pair'),
"Side": order.get('side', '').upper(),
"Amount": f"{order.get('amount', 0):.4f} AIT",
"Price": f"{order.get('max_price', order.get('min_price', 0)):.8f}" if order.get('max_price') or order.get('min_price') else "Market",
"Status": order.get('status'),
"User": order.get('user_id', '')[:16] + "...",
"Created": order.get('created_at', '')[:19]
})
output(orders_data, ctx.obj.get('output_format', 'table'), title=f"Exchange Orders ({island_id[:16]}...)")
else:
error(f"Failed to query blockchain: {response.status_code}")
raise click.Abort()
except Exception as e:
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
)
if response.status_code == 200: offer_info = {
result = response.json() "Offer ID": offer_id,
success(f"GPU offer created successfully!") "GPU Count": gpu_count,
success(f"Offer ID: {offer_id}") "Price per GPU": f"{price_per_gpu:.4f} AIT/hour",
success(f"Total Price: {total_price:.2f} AIT") "Duration": f"{duration_hours} hours",
"Total Price": f"{total_price:.2f} AIT",
"Status": "active",
"Provider Node": provider_node_id[:16] + "...",
"Island": island_id[:16] + "..."
}
offer_info = { output(offer_info, ctx.obj.get('output_format', 'table'))
"Offer ID": offer_id, except NetworkError as e:
"GPU Count": gpu_count,
"Price per GPU": f"{price_per_gpu:.4f} AIT/hour",
"Duration": f"{duration_hours} hours",
"Total Price": f"{total_price:.2f} AIT",
"Status": "active",
"Provider Node": provider_node_id[:16] + "...",
"Island": island_id[:16] + "..."
}
output(offer_info, ctx.obj.get('output_format', 'table'))
else:
error(f"Failed to submit transaction: {response.status_code}")
if response.text:
error(f"Error details: {response.text}")
raise click.Abort()
except Exception as e:
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
)
if response.status_code == 200: bid_info = {
result = response.json() "Bid ID": bid_id,
success(f"GPU bid created successfully!") "GPU Count": gpu_count,
success(f"Bid ID: {bid_id}") "Max Price per GPU": f"{max_price:.4f} AIT/hour",
success(f"Max Total Price: {max_total_price:.2f} AIT") "Duration": f"{duration_hours} hours",
"Max Total Price": f"{max_total_price:.2f} AIT",
"Status": "pending",
"Bidder Node": bidder_node_id[:16] + "...",
"Island": island_id[:16] + "..."
}
bid_info = { output(bid_info, ctx.obj.get('output_format', 'table'))
"Bid ID": bid_id, except NetworkError as e:
"GPU Count": gpu_count,
"Max Price per GPU": f"{max_price:.4f} AIT/hour",
"Duration": f"{duration_hours} hours",
"Max Total Price": f"{max_total_price:.2f} AIT",
"Status": "pending",
"Bidder Node": bidder_node_id[:16] + "...",
"Island": island_id[:16] + "..."
}
output(bid_info, ctx.obj.get('output_format', 'table'))
else:
error(f"Failed to submit transaction: {response.status_code}")
if response.text:
error(f"Error details: {response.text}")
raise click.Abort()
except Exception as e:
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,
timeout=10
)
if response.status_code == 200: if not transactions:
transactions = response.json() info("No GPU marketplace transactions found")
return
if not transactions: # Format output
info("No GPU marketplace transactions found") market_data = []
return for tx in transactions:
action = tx.get('action')
if action == 'offer':
market_data.append({
"ID": tx.get('offer_id', tx.get('transaction_id', 'N/A'))[:20] + "...",
"Type": "OFFER",
"GPU Count": tx.get('gpu_count'),
"Price": f"{tx.get('price_per_gpu', 0):.4f} AIT/h",
"Duration": f"{tx.get('duration_hours')}h",
"Total": f"{tx.get('total_price', 0):.2f} AIT",
"Status": tx.get('status'),
"Provider": tx.get('provider_node_id', '')[:16] + "...",
"Created": tx.get('created_at', '')[:19]
})
elif action == 'bid':
market_data.append({
"ID": tx.get('bid_id', tx.get('transaction_id', 'N/A'))[:20] + "...",
"Type": "BID",
"GPU Count": tx.get('gpu_count'),
"Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h",
"Duration": f"{tx.get('duration_hours')}h",
"Max Total": f"{tx.get('max_total_price', 0):.2f} AIT",
"Status": tx.get('status'),
"Bidder": tx.get('bidder_node_id', '')[:16] + "...",
"Created": tx.get('created_at', '')[:19]
})
# Format output output(market_data, ctx.obj.get('output_format', 'table'), title=f"GPU Marketplace ({island_id[:16]}...)")
market_data = [] except NetworkError as e:
for tx in transactions:
action = tx.get('action')
if action == 'offer':
market_data.append({
"ID": tx.get('offer_id', tx.get('transaction_id', 'N/A'))[:20] + "...",
"Type": "OFFER",
"GPU Count": tx.get('gpu_count'),
"Price": f"{tx.get('price_per_gpu', 0):.4f} AIT/h",
"Duration": f"{tx.get('duration_hours')}h",
"Total": f"{tx.get('total_price', 0):.2f} AIT",
"Status": tx.get('status'),
"Provider": tx.get('provider_node_id', '')[:16] + "...",
"Created": tx.get('created_at', '')[:19]
})
elif action == 'bid':
market_data.append({
"ID": tx.get('bid_id', tx.get('transaction_id', 'N/A'))[:20] + "...",
"Type": "BID",
"GPU Count": tx.get('gpu_count'),
"Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h",
"Duration": f"{tx.get('duration_hours')}h",
"Max Total": f"{tx.get('max_total_price', 0):.2f} AIT",
"Status": tx.get('status'),
"Bidder": tx.get('bidder_node_id', '')[:16] + "...",
"Created": tx.get('created_at', '')[:19]
})
output(market_data, ctx.obj.get('output_format', 'table'), title=f"GPU Marketplace ({island_id[:16]}...)")
else:
error(f"Failed to query blockchain: {response.status_code}")
raise click.Abort()
except Exception as e:
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,
timeout=10
)
if response.status_code == 200: if not transactions:
transactions = response.json() error(f"Order {order_id} not found")
raise click.Abort()
if not transactions: tx = transactions[0]
error(f"Order {order_id} not found") action = tx.get('action')
raise click.Abort()
tx = transactions[0] order_info = {
action = tx.get('action') "Order ID": order_id,
"Type": action.upper(),
"Status": tx.get('status'),
"Created": tx.get('created_at'),
}
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] + "..."
})
elif action == 'bid':
order_info.update({
"GPU Count": tx.get('gpu_count'),
"Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h",
"Duration": f"{tx.get('duration_hours')}h",
"Max Total": f"{tx.get('max_total_price', 0):.2f} AIT",
"Bidder": tx.get('bidder_node_id', '')[:16] + "..."
})
if action == 'offer': if 'accepted_at' in tx:
order_info.update({ order_info["Accepted"] = tx['accepted_at']
"GPU Count": tx.get('gpu_count'), if 'cancelled_at' in tx:
"Price per GPU": f"{tx.get('price_per_gpu', 0):.4f} AIT/h", order_info["Cancelled"] = tx['cancelled_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] + "..."
})
elif action == 'bid':
order_info.update({
"GPU Count": tx.get('gpu_count'),
"Max Price": f"{tx.get('max_price_per_gpu', 0):.4f} AIT/h",
"Duration": f"{tx.get('duration_hours')}h",
"Max Total": f"{tx.get('max_total_price', 0):.2f} AIT",
"Bidder": tx.get('bidder_node_id', '')[:16] + "..."
})
if 'accepted_at' in tx: output(order_info, ctx.obj.get('output_format', 'table'), title=f"Order Status: {order_id}")
order_info["Accepted"] = tx['accepted_at'] except NetworkError as e:
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,
timeout=10
)
if response.status_code == 200: # Separate offers and bids
transactions = response.json() offers = []
bids = []
# Separate offers and bids for tx in transactions:
offers = [] if tx.get('action') == 'offer':
bids = [] offers.append(tx)
elif tx.get('action') == 'bid':
bids.append(tx)
for tx in transactions: if not offers or not bids:
if tx.get('action') == 'offer': info("No active offers or bids to match")
offers.append(tx) return
elif tx.get('action') == 'bid':
bids.append(tx)
if not offers or not bids: # Sort offers by price (lowest first)
info("No active offers or bids to match") offers.sort(key=lambda x: x.get('price_per_gpu', float('inf')))
return # Sort bids by price (highest first)
bids.sort(key=lambda x: x.get('max_price_per_gpu', 0), reverse=True)
# Sort offers by price (lowest first) # Match bids with offers
offers.sort(key=lambda x: x.get('price_per_gpu', float('inf'))) matches = []
# Sort bids by price (highest first) for bid in bids:
bids.sort(key=lambda x: x.get('max_price_per_gpu', 0), reverse=True) for offer in offers:
# Check if bid price >= offer price
if bid.get('max_price_per_gpu', 0) >= offer.get('price_per_gpu', float('inf')):
# Check if GPU count matches
if bid.get('gpu_count') == offer.get('gpu_count'):
# Check if duration matches
if bid.get('duration_hours') == offer.get('duration_hours'):
# Create match transaction
match_data = {
'type': 'gpu_marketplace',
'action': 'match',
'bid_id': bid.get('bid_id'),
'offer_id': offer.get('offer_id'),
'bidder_node_id': bid.get('bidder_node_id'),
'provider_node_id': offer.get('provider_node_id'),
'gpu_count': bid.get('gpu_count'),
'matched_price': offer.get('price_per_gpu'),
'duration_hours': bid.get('duration_hours'),
'total_price': offer.get('total_price'),
'status': 'matched',
'matched_at': datetime.now().isoformat(),
'island_id': island_id,
'chain_id': get_chain_id()
}
# Match bids with offers # Submit match transaction
matches = [] match_result = http_client.post("/transaction", json=match_data)
for bid in bids: matches.append({
for offer in offers: "Bid ID": bid.get('bid_id')[:16] + "...",
# Check if bid price >= offer price "Offer ID": offer.get('offer_id')[:16] + "...",
if bid.get('max_price_per_gpu', 0) >= offer.get('price_per_gpu', float('inf')): "GPU Count": bid.get('gpu_count'),
# Check if GPU count matches "Matched Price": f"{offer.get('price_per_gpu', 0):.4f} AIT/h",
if bid.get('gpu_count') == offer.get('gpu_count'): "Total Price": f"{offer.get('total_price', 0):.2f} AIT",
# Check if duration matches "Duration": f"{bid.get('duration_hours')}h"
if bid.get('duration_hours') == offer.get('duration_hours'): })
# Create match transaction
match_data = {
'type': 'gpu_marketplace',
'action': 'match',
'bid_id': bid.get('bid_id'),
'offer_id': offer.get('offer_id'),
'bidder_node_id': bid.get('bidder_node_id'),
'provider_node_id': offer.get('provider_node_id'),
'gpu_count': bid.get('gpu_count'),
'matched_price': offer.get('price_per_gpu'),
'duration_hours': bid.get('duration_hours'),
'total_price': offer.get('total_price'),
'status': 'matched',
'matched_at': datetime.now().isoformat(),
'island_id': island_id,
'chain_id': get_chain_id()
}
# Submit match transaction if matches:
match_response = client.post( success(f"Matched {len(matches)} GPU orders!")
f"{rpc_endpoint}/transaction", output(matches, ctx.obj.get('output_format', 'table'), title="GPU Order Matches")
json=match_data, else:
timeout=10 info("No matching orders found")
) except NetworkError as e:
if match_response.status_code == 200:
matches.append({
"Bid ID": bid.get('bid_id')[:16] + "...",
"Offer ID": offer.get('offer_id')[:16] + "...",
"GPU Count": bid.get('gpu_count'),
"Matched Price": f"{offer.get('price_per_gpu', 0):.4f} AIT/h",
"Total Price": f"{offer.get('total_price', 0):.2f} AIT",
"Duration": f"{bid.get('duration_hours')}h"
})
if matches:
success(f"Matched {len(matches)} GPU orders!")
output(matches, ctx.obj.get('output_format', 'table'), title="GPU Order Matches")
else:
info("No matching orders found")
else:
error(f"Failed to query blockchain: {response.status_code}")
raise click.Abort()
except Exception as e:
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