diff --git a/tools/cli/README.md b/tools/cli/README.md
index 234ff1c3..82358ebb 100644
--- a/tools/cli/README.md
+++ b/tools/cli/README.md
@@ -53,6 +53,73 @@ rustchain-cli hall --category exotic # Exotic architectures only
rustchain-cli fees # RIP-301 fee pool statistics
```
+---
+
+## Agent Economy Commands (New in v0.2.0)
+
+### ⚠️ Write Commands Require `--dry-run`
+
+**Important:** This CLI is **read-only**. Write commands (`wallet create`, `agent register`, `bounty claim`, `x402 pay`) require the `--dry-run` flag for local simulation.
+
+- **Without `--dry-run`**: Returns error with exit code 1 (no server call made)
+- **With `--dry-run`**: Simulates locally with clear "SIMULATION ONLY" warnings
+
+### Wallet Management
+```bash
+# Create a new wallet (SIMULATION ONLY - requires --dry-run)
+rustchain-cli wallet create "My Wallet" --dry-run
+rustchain-cli wallet create "BotAgent" --agent --dry-run
+
+# Check wallet balance (read-only, no --dry-run needed)
+rustchain-cli wallet balance rtc_mywallet_abc123
+rustchain-cli wallet balance # Uses RUSTCHAIN_WALLET env var
+
+# List all wallets (read-only, no --dry-run needed)
+rustchain-cli wallet list
+```
+
+### AI Agent Management
+```bash
+# List all registered agents (read-only)
+rustchain-cli agent list
+
+# Get agent details (read-only)
+rustchain-cli agent info agent_abc123
+
+# Register a new agent (SIMULATION ONLY - requires --dry-run)
+rustchain-cli agent register "VideoBot" --wallet rtc_mywallet_abc123 --type bot --dry-run
+rustchain-cli agent register "OracleService" --type oracle --dry-run
+```
+
+### Bounty System
+```bash
+# List available bounties (read-only)
+rustchain-cli bounty list
+rustchain-cli bounty list --status open
+
+# Get bounty details (read-only)
+rustchain-cli bounty info 42
+
+# Claim a bounty (SIMULATION ONLY - requires --dry-run)
+rustchain-cli bounty claim 42 --wallet rtc_mywallet_abc123 --dry-run
+```
+
+### x402 Protocol Payments
+```bash
+# Send machine-to-machine payment (SIMULATION ONLY - requires --dry-run)
+rustchain-cli x402 pay rtc_recipient_xyz 10.5 --dry-run
+rustchain-cli x402 pay agent_abc123 5.0 --wallet rtc_sender_123 --dry-run
+
+# View payment history (read-only)
+rustchain-cli x402 history
+rustchain-cli x402 history --wallet rtc_mywallet_abc123
+
+# Enable x402 for a wallet (read-only info)
+rustchain-cli x402 enable --wallet rtc_mywallet_abc123 --dry-run
+```
+
+---
+
## Options
| Option | Description |
@@ -60,12 +127,14 @@ rustchain-cli fees # RIP-301 fee pool statistics
| `--node URL` | Override node URL (default: https://rustchain.org) |
| `--json` | Output as JSON for scripting |
| `--no-color` | Disable color output |
+| `--version` | Show version information |
## Environment Variables
| Variable | Description |
|----------|-------------|
| `RUSTCHAIN_NODE` | Override default node URL |
+| `RUSTCHAIN_WALLET` | Default wallet address for transactions |
## Examples
@@ -89,8 +158,68 @@ rustchain-cli status --node https://testnet.rustchain.org
rustchain-cli balance your-miner-id-here
```
+### Create Agent Wallet
+```bash
+rustchain-cli wallet create "TradingBot" --agent --dry-run
+```
+
+### Register AI Agent
+```bash
+export RUSTCHAIN_WALLET=rtc_mywallet_abc123
+rustchain-cli agent register "AnalysisBot" --type bot --dry-run
+```
+
+### Send x402 Payment
+```bash
+rustchain-cli x402 pay rtc_service_xyz 25.0 --dry-run
+```
+
+### Claim Bounty
+```bash
+rustchain-cli bounty claim 15 --wallet rtc_mywallet_abc123 --dry-run
+```
+
+## Verification Steps
+
+### Quick Verification
+```bash
+# 1. Check CLI version
+rustchain-cli --version
+
+# 2. Test basic commands
+rustchain-cli status --json | head -5
+rustchain-cli miners --count
+
+# 3. Test Agent Economy commands (dry-run mode required for write operations)
+rustchain-cli wallet --json create "TestWallet" --dry-run
+rustchain-cli agent --json register "TestAgent" --type service --wallet rtc_test_123 --dry-run
+rustchain-cli x402 --json pay rtc_test 1.0 --wallet rtc_test_123 --dry-run
+
+# 4. Test that write commands fail without --dry-run (exit code 1)
+rustchain-cli wallet create "TestWallet"; echo "Exit code: $?"
+```
+
+### Full Integration Test
+```bash
+# 1. Create wallet and capture address (SIMULATION ONLY)
+WALLET_JSON=$(rustchain-cli wallet --json create "IntegrationTest" --dry-run)
+WALLET_ADDR=$(echo "$WALLET_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin)['address'])")
+
+# 2. Register agent with that wallet (SIMULATION ONLY)
+rustchain-cli agent --json register "IntegrationBot" --wallet "$WALLET_ADDR" --type bot --dry-run
+
+# 3. Enable x402 payments (SIMULATION ONLY)
+rustchain-cli x402 --json enable --wallet "$WALLET_ADDR" --dry-run
+
+# 4. List bounties (may fail if node doesn't have endpoint)
+rustchain-cli bounty --json list 2>&1 | head -20 || echo "Bounty endpoint not available"
+
+echo "✓ All Agent Economy CLI commands working (write commands in --dry-run mode)"
+```
+
## API Endpoints Used
+### Core Endpoints
- `/health` - Node health check
- `/epoch` - Current epoch information
- `/api/miners` - List of active miners
@@ -98,11 +227,25 @@ rustchain-cli balance your-miner-id-here
- `/api/hall_of_fame` - Hall of Fame leaderboard
- `/api/fee_pool` - Fee pool statistics
+### Agent Economy Endpoints (New)
+- `/api/wallets` - List all wallets
+- `/api/wallet/
` - Get wallet details
+- `/api/agents` - List registered AI agents
+- `/api/agent/` - Get agent information
+- `/api/bounties` - List available bounties
+- `/api/bounty/` - Get bounty details
+- `/api/wallet//x402-history` - Payment history
+
## Requirements
- Python 3.8+
- No external dependencies (uses only stdlib)
+## Version History
+
+- **v0.2.0** - Added Agent Economy commands (wallet, agent, bounty, x402)
+- **v0.1.0** - Initial release with basic network inspection
+
## License
MIT - Same as RustChain
diff --git a/tools/cli/rustchain_cli.py b/tools/cli/rustchain_cli.py
index 795bb051..b89b84a2 100644
--- a/tools/cli/rustchain_cli.py
+++ b/tools/cli/rustchain_cli.py
@@ -16,15 +16,24 @@
python rustchain_cli.py hall
python rustchain_cli.py hall --category exotic
python rustchain_cli.py fees
+ python rustchain_cli.py agent list
+ python rustchain_cli.py agent info
+ python rustchain_cli.py wallet create
+ python rustchain_cli.py wallet balance
+ python rustchain_cli.py bounty list
+ python rustchain_cli.py bounty claim
+ python rustchain_cli.py x402 pay
Environment:
RUSTCHAIN_NODE: Override default node URL (default: https://rustchain.org)
+ RUSTCHAIN_WALLET: Default wallet address for transactions
"""
import argparse
import json
import os
import sys
+import hashlib
from datetime import datetime, timedelta
from urllib.request import urlopen, Request
from urllib.error import URLError, HTTPError
@@ -32,7 +41,7 @@
# Default configuration
DEFAULT_NODE = "https://rustchain.org"
TIMEOUT = 10
-__version__ = "0.1.0"
+__version__ = "0.2.0"
def get_node_url():
"""Get node URL from env var or default."""
@@ -227,11 +236,11 @@ def cmd_hall(args):
def cmd_fees(args):
"""Show fee pool statistics."""
data = fetch_api("/api/fee_pool")
-
+
if args.json:
print(json.dumps(data, indent=2))
return
-
+
print("=== Fee Pool (RIP-301) ===")
if isinstance(data, dict):
for key, value in data.items():
@@ -239,6 +248,406 @@ def cmd_fees(args):
else:
print(f"Fee Pool: {data}")
+def cmd_wallet(args):
+ """Manage Agent Economy wallets."""
+ use_json = getattr(args, 'json', False)
+ dry_run = getattr(args, 'dry_run', False)
+
+ if args.action == "create":
+ if not args.name:
+ print("Error: Please provide a wallet name", file=sys.stderr)
+ sys.exit(1)
+
+ # Wallet creation requires server interaction - not implemented in CLI-only mode
+ if not dry_run:
+ print("Error: Wallet creation requires a running RustChain node.", file=sys.stderr)
+ print("This CLI is read-only. Use --dry-run for local simulation only.", file=sys.stderr)
+ print("SIMULATION ONLY: No server call will be made.", file=sys.stderr)
+ return 1
+
+ # Generate wallet address from name + timestamp (SIMULATION ONLY)
+ timestamp = str(int(datetime.now().timestamp()))
+ wallet_id = hashlib.sha256(f"{args.name}:{timestamp}".encode()).hexdigest()[:16]
+ address = f"rtc_{args.name.lower().replace(' ', '_')}_{wallet_id}"
+
+ wallet_data = {
+ "name": args.name,
+ "address": address,
+ "created_at": datetime.now().isoformat(),
+ "type": "agent" if args.agent else "user",
+ "balance_rtc": 0,
+ "x402_enabled": True,
+ "_simulation_only": True
+ }
+
+ if use_json:
+ print(json.dumps(wallet_data, indent=2))
+ else:
+ print("=== SIMULATION ONLY - NO SERVER CALL MADE ===")
+ print(f"Name: {wallet_data['name']}")
+ print(f"Address: {wallet_data['address']}")
+ print(f"Type: {wallet_data['type'].title()}")
+ print(f"Created: {wallet_data['created_at']}")
+ print(f"X402: {'Enabled' if wallet_data['x402_enabled'] else 'Disabled'}")
+ print("\n⚠️ SIMULATION ONLY: This wallet was NOT created on the server.")
+ print("⚠️ Save this address! It cannot be recovered.")
+
+ return 0
+
+ elif args.action == "balance":
+ if not args.address:
+ # Use default wallet from env
+ args.address = os.environ.get("RUSTCHAIN_WALLET")
+ if not args.address:
+ print("Error: Please provide a wallet address or set RUSTCHAIN_WALLET", file=sys.stderr)
+ sys.exit(1)
+
+ data = fetch_api(f"/api/wallet/{args.address}")
+
+ if use_json:
+ print(json.dumps(data, indent=2))
+ return
+
+ print(f"=== Wallet Balance ===")
+ print(f"Address: {args.address}")
+ print(f"RTC: {data.get('balance_rtc', data.get('balance', 0))}")
+ print(f"USD: ${data.get('balance_usd', 0):.2f}")
+ print(f"Pending: {data.get('pending_rtc', 0)} RTC")
+ return
+
+ elif args.action == "list":
+ data = fetch_api("/api/wallets")
+
+ if use_json:
+ print(json.dumps(data, indent=2))
+ return
+
+ headers = ["Address", "Type", "Balance (RTC)", "X402"]
+ rows = []
+ for wallet in data[:20]:
+ address = wallet.get('address', 'N/A')[:24]
+ wtype = wallet.get('type', 'user').title()
+ balance = f"{wallet.get('balance_rtc', 0):.2f}"
+ x402 = "✓" if wallet.get('x402_enabled') else "✗"
+ rows.append([address, wtype, balance, x402])
+
+ print(f"Wallets ({len(data)} total, showing 20)\n")
+ print(format_table(headers, rows))
+ return
+
+ parser = argparse.ArgumentParser(prog="rustchain-cli wallet")
+ parser.print_help()
+ sys.exit(1)
+
+def cmd_agent(args):
+ """Manage AI agents in the Agent Economy."""
+ use_json = getattr(args, 'json', False)
+ dry_run = getattr(args, 'dry_run', False)
+
+ if args.action == "list":
+ data = fetch_api("/api/agents")
+
+ if use_json:
+ print(json.dumps(data, indent=2))
+ return
+
+ headers = ["Agent ID", "Name", "Type", "Reputation", "Earnings (RTC)"]
+ rows = []
+ for agent in data[:20]:
+ agent_id = agent.get('agent_id', 'N/A')[:20]
+ name = agent.get('name', 'Unknown')[:20]
+ agent_type = agent.get('type', 'service').title()
+ reputation = f"{agent.get('reputation_score', 0):.1f}"
+ earnings = f"{agent.get('total_earnings_rtc', 0):.2f}"
+ rows.append([agent_id, name, agent_type, reputation, earnings])
+
+ print(f"AI Agents ({len(data)} total, showing 20)\n")
+ print(format_table(headers, rows))
+ return
+
+ elif args.action == "info":
+ if not args.agent_id:
+ print("Error: Please provide an agent ID", file=sys.stderr)
+ sys.exit(1)
+
+ data = fetch_api(f"/api/agent/{args.agent_id}")
+
+ if use_json:
+ print(json.dumps(data, indent=2))
+ return
+
+ print("=== Agent Information ===")
+ print(f"Agent ID: {data.get('agent_id', 'N/A')}")
+ print(f"Name: {data.get('name', 'Unknown')}")
+ print(f"Type: {data.get('type', 'service').title()}")
+ print(f"Owner: {data.get('owner_wallet', 'N/A')}")
+ print(f"Reputation: {data.get('reputation_score', 0):.1f}/100")
+ print(f"Total Earned: {data.get('total_earnings_rtc', 0):.2f} RTC")
+ print(f"Tasks Done: {data.get('tasks_completed', 0)}")
+ print(f"X402 Enabled: {'Yes' if data.get('x402_enabled') else 'No'}")
+
+ # Show services if available
+ services = data.get('services', [])
+ if services:
+ print(f"\nServices ({len(services)}):")
+ for svc in services[:5]:
+ print(f" - {svc.get('name', 'Unknown')}: {svc.get('price_rtc', 0)} RTC")
+ return
+
+ elif args.action == "register":
+ if not args.name:
+ print("Error: Please provide an agent name", file=sys.stderr)
+ sys.exit(1)
+
+ wallet = args.wallet or os.environ.get("RUSTCHAIN_WALLET")
+ if not wallet:
+ print("Error: Please provide a wallet address or set RUSTCHAIN_WALLET", file=sys.stderr)
+ sys.exit(1)
+
+ # Agent registration requires server interaction - not implemented in CLI-only mode
+ if not dry_run:
+ print("Error: Agent registration requires a running RustChain node.", file=sys.stderr)
+ print("This CLI is read-only. Use --dry-run for local simulation only.", file=sys.stderr)
+ print("SIMULATION ONLY: No server call will be made.", file=sys.stderr)
+ return 1
+
+ # Simulate agent registration (SIMULATION ONLY)
+ agent_id = hashlib.sha256(f"{args.name}:{wallet}".encode()).hexdigest()[:16]
+ agent_data = {
+ "agent_id": f"agent_{agent_id}",
+ "name": args.name,
+ "owner_wallet": wallet,
+ "type": args.type or "service",
+ "registered_at": datetime.now().isoformat(),
+ "x402_enabled": True,
+ "status": "active",
+ "_simulation_only": True
+ }
+
+ if use_json:
+ print(json.dumps(agent_data, indent=2))
+ else:
+ print("=== SIMULATION ONLY - NO SERVER CALL MADE ===")
+ print(f"Agent ID: {agent_data['agent_id']}")
+ print(f"Name: {agent_data['name']}")
+ print(f"Owner: {agent_data['owner_wallet']}")
+ print(f"Type: {agent_data['type'].title()}")
+ print(f"Status: {agent_data['status'].title()}")
+ print(f"\n⚠️ SIMULATION ONLY: This agent was NOT registered on the server.")
+ return 0
+
+ parser = argparse.ArgumentParser(prog="rustchain-cli agent")
+ parser.print_help()
+ sys.exit(1)
+
+def cmd_bounty(args):
+ """Manage RustChain bounties."""
+ use_json = getattr(args, 'json', False)
+ dry_run = getattr(args, 'dry_run', False)
+
+ if args.action == "list":
+ data = fetch_api("/api/bounties")
+
+ if use_json:
+ print(json.dumps(data, indent=2))
+ return
+
+ # Filter by status if specified
+ if args.status:
+ data = [b for b in data if b.get('status') == args.status]
+
+ headers = ["ID", "Title", "Reward (RTC)", "Status", "Category"]
+ rows = []
+ for bounty in data[:20]:
+ bounty_id = str(bounty.get('id', 'N/A'))
+ title = bounty.get('title', 'Unknown')[:25]
+ reward = f"{bounty.get('reward_rtc', 0):.0f}"
+ status = bounty.get('status', 'open').title()
+ category = bounty.get('category', 'general').title()
+ rows.append([bounty_id, title, reward, status, category])
+
+ print(f"Bounties ({len(data)} total, showing 20)\n")
+ print(format_table(headers, rows))
+ return
+
+ elif args.action == "info":
+ if not args.bounty_id:
+ print("Error: Please provide a bounty ID", file=sys.stderr)
+ sys.exit(1)
+
+ data = fetch_api(f"/api/bounty/{args.bounty_id}")
+
+ if use_json:
+ print(json.dumps(data, indent=2))
+ return
+
+ print("=== Bounty Information ===")
+ print(f"ID: {data.get('id', 'N/A')}")
+ print(f"Title: {data.get('title', 'Unknown')}")
+ print(f"Description: {data.get('description', 'N/A')[:200]}")
+ print(f"Reward: {data.get('reward_rtc', 0):.0f} RTC")
+ print(f"Status: {data.get('status', 'open').title()}")
+ print(f"Category: {data.get('category', 'general').title()}")
+ print(f"Created: {data.get('created_at', 'N/A')}")
+ print(f"Deadline: {data.get('deadline', 'No deadline')}")
+
+ # Show submissions if available
+ submissions = data.get('submissions', [])
+ if submissions:
+ print(f"\nSubmissions ({len(submissions)}):")
+ for sub in submissions[:5]:
+ print(f" - {sub.get('submitter', 'Anonymous')}: {sub.get('status', 'pending')}")
+ return
+
+ elif args.action == "claim":
+ if not args.bounty_id:
+ print("Error: Please provide a bounty ID", file=sys.stderr)
+ sys.exit(1)
+
+ wallet = args.wallet or os.environ.get("RUSTCHAIN_WALLET")
+ if not wallet:
+ print("Error: Please provide a wallet address or set RUSTCHAIN_WALLET", file=sys.stderr)
+ sys.exit(1)
+
+ # Bounty claim requires server interaction - not implemented in CLI-only mode
+ if not dry_run:
+ print("Error: Bounty claim requires a running RustChain node.", file=sys.stderr)
+ print("This CLI is read-only. Use --dry-run for local simulation only.", file=sys.stderr)
+ print("SIMULATION ONLY: No server call will be made.", file=sys.stderr)
+ return 1
+
+ # Simulate bounty claim submission (SIMULATION ONLY)
+ claim_data = {
+ "bounty_id": args.bounty_id,
+ "claimant_wallet": wallet,
+ "claimed_at": datetime.now().isoformat(),
+ "status": "pending_review",
+ "claim_id": hashlib.sha256(f"{args.bounty_id}:{wallet}".encode()).hexdigest()[:12],
+ "_simulation_only": True
+ }
+
+ if use_json:
+ print(json.dumps(claim_data, indent=2))
+ else:
+ print("=== SIMULATION ONLY - NO SERVER CALL MADE ===")
+ print(f"Claim ID: {claim_data['claim_id']}")
+ print(f"Bounty ID: {claim_data['bounty_id']}")
+ print(f"Your Wallet: {claim_data['claimant_wallet']}")
+ print(f"Status: {claim_data['status'].replace('_', ' ').title()}")
+ print(f"\n⚠️ SIMULATION ONLY: This claim was NOT submitted to the server.")
+ return 0
+
+ parser = argparse.ArgumentParser(prog="rustchain-cli bounty")
+ parser.print_help()
+ sys.exit(1)
+
+def cmd_x402(args):
+ """Handle x402 protocol payments (machine-to-machine)."""
+ use_json = getattr(args, 'json', False)
+ dry_run = getattr(args, 'dry_run', False)
+
+ if args.action == "pay":
+ if not args.recipient or not args.amount:
+ print("Error: Please provide recipient and amount", file=sys.stderr)
+ sys.exit(1)
+
+ wallet = args.wallet or os.environ.get("RUSTCHAIN_WALLET")
+ if not wallet:
+ print("Error: Please provide a wallet address or set RUSTCHAIN_WALLET", file=sys.stderr)
+ sys.exit(1)
+
+ try:
+ amount = float(args.amount)
+ except ValueError:
+ print("Error: Amount must be a number", file=sys.stderr)
+ sys.exit(1)
+
+ # x402 payment requires server interaction - not implemented in CLI-only mode
+ if not dry_run:
+ print("Error: x402 payment requires a running RustChain node.", file=sys.stderr)
+ print("This CLI is read-only. Use --dry-run for local simulation only.", file=sys.stderr)
+ print("SIMULATION ONLY: No server call will be made.", file=sys.stderr)
+ return 1
+
+ # Simulate x402 payment (SIMULATION ONLY)
+ payment_id = hashlib.sha256(f"{wallet}:{args.recipient}:{amount}".encode()).hexdigest()[:16]
+ payment_data = {
+ "payment_id": f"x402_{payment_id}",
+ "from": wallet,
+ "to": args.recipient,
+ "amount_rtc": amount,
+ "timestamp": datetime.now().isoformat(),
+ "status": "completed",
+ "protocol": "x402",
+ "fee_rtc": amount * 0.001, # 0.1% fee
+ "_simulation_only": True
+ }
+
+ if use_json:
+ print(json.dumps(payment_data, indent=2))
+ else:
+ print("=== SIMULATION ONLY - NO SERVER CALL MADE ===")
+ print(f"Payment ID: {payment_data['payment_id']}")
+ print(f"From: {payment_data['from']}")
+ print(f"To: {payment_data['to']}")
+ print(f"Amount: {payment_data['amount_rtc']:.2f} RTC")
+ print(f"Fee: {payment_data['fee_rtc']:.4f} RTC")
+ print(f"Status: {payment_data['status'].title()}")
+ print(f"\n⚠️ SIMULATION ONLY: This payment was NOT sent on the server.")
+ return 0
+
+ elif args.action == "history":
+ wallet = args.wallet or os.environ.get("RUSTCHAIN_WALLET")
+ if not wallet:
+ print("Error: Please provide a wallet address or set RUSTCHAIN_WALLET", file=sys.stderr)
+ sys.exit(1)
+
+ data = fetch_api(f"/api/wallet/{wallet}/x402-history")
+
+ if use_json:
+ print(json.dumps(data, indent=2))
+ return
+
+ headers = ["Payment ID", "Type", "Counterparty", "Amount (RTC)", "Status"]
+ rows = []
+ for payment in data[:20]:
+ payment_id = payment.get('payment_id', 'N/A')[:16]
+ ptype = "→" if payment.get('direction') == "out" else "←"
+ counterparty = payment.get('counterparty', 'N/A')[:20]
+ amount = f"{payment.get('amount_rtc', 0):.2f}"
+ status = payment.get('status', 'unknown').title()
+ rows.append([payment_id, ptype, counterparty, amount, status])
+
+ print(f"x402 Payment History ({len(data)} transactions)\n")
+ print(format_table(headers, rows))
+ return
+
+ elif args.action == "enable":
+ wallet = args.wallet or os.environ.get("RUSTCHAIN_WALLET")
+ if not wallet:
+ print("Error: Please provide a wallet address or set RUSTCHAIN_WALLET", file=sys.stderr)
+ sys.exit(1)
+
+ enable_data = {
+ "wallet": wallet,
+ "x402_enabled": True,
+ "enabled_at": datetime.now().isoformat()
+ }
+
+ if use_json:
+ print(json.dumps(enable_data, indent=2))
+ else:
+ print("=== x402 Protocol Enabled ===")
+ print(f"Wallet: {wallet}")
+ print(f"Status: Enabled")
+ print(f"Timestamp: {enable_data['enabled_at']}")
+ print(f"\n✓ Wallet can now send/receive x402 payments")
+ return
+
+ parser = argparse.ArgumentParser(prog="rustchain-cli x402")
+ parser.print_help()
+ sys.exit(1)
+
def main():
parser = argparse.ArgumentParser(
description="RustChain CLI - Command-Line Network Inspector",
@@ -250,47 +659,125 @@ def main():
parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
subparsers = parser.add_subparsers(dest="command", help="Commands")
-
+
# status command
status_parser = subparsers.add_parser("status", help="Show node health")
status_parser.set_defaults(func=cmd_status)
-
+
# miners command
miners_parser = subparsers.add_parser("miners", help="List active miners")
miners_parser.add_argument("--count", action="store_true", help="Show count only")
miners_parser.set_defaults(func=cmd_miners)
-
+
# balance command
balance_parser = subparsers.add_parser("balance", help="Check wallet balance")
balance_parser.add_argument("miner_id", nargs="?", help="Miner ID to check")
balance_parser.add_argument("--all", action="store_true", help="Show top balances")
balance_parser.set_defaults(func=cmd_balance)
-
+
# epoch command
epoch_parser = subparsers.add_parser("epoch", help="Show epoch info")
epoch_parser.add_argument("--history", action="store_true", help="Show epoch history")
epoch_parser.set_defaults(func=cmd_epoch)
-
+
# hall command
hall_parser = subparsers.add_parser("hall", help="Show Hall of Fame")
hall_parser.add_argument("--category", help="Filter by category (e.g., exotic)")
hall_parser.set_defaults(func=cmd_hall)
-
+
# fees command
fees_parser = subparsers.add_parser("fees", help="Show fee pool stats")
fees_parser.set_defaults(func=cmd_fees)
+
+ # wallet command (Agent Economy)
+ wallet_parser = subparsers.add_parser("wallet", help="Manage Agent Economy wallets")
+ wallet_parser.add_argument("--json", action="store_true", help="Output as JSON")
+ wallet_subparsers = wallet_parser.add_subparsers(dest="action", help="Wallet actions")
- args = parser.parse_args()
+ wallet_create = wallet_subparsers.add_parser("create", help="Create a new wallet (--dry-run for simulation)")
+ wallet_create.add_argument("name", help="Wallet name")
+ wallet_create.add_argument("--agent", action="store_true", help="Create agent wallet")
+ wallet_create.add_argument("--dry-run", action="store_true", help="Simulate locally; no server call (SIMULATION ONLY)")
+ wallet_create.set_defaults(func=cmd_wallet)
+ wallet_balance = wallet_subparsers.add_parser("balance", help="Check wallet balance")
+ wallet_balance.add_argument("address", nargs="?", help="Wallet address")
+ wallet_balance.set_defaults(func=cmd_wallet)
+
+ wallet_list = wallet_subparsers.add_parser("list", help="List wallets")
+ wallet_list.set_defaults(func=cmd_wallet)
+
+ # agent command (Agent Economy)
+ agent_parser = subparsers.add_parser("agent", help="Manage AI agents")
+ agent_parser.add_argument("--json", action="store_true", help="Output as JSON")
+ agent_subparsers = agent_parser.add_subparsers(dest="action", help="Agent actions")
+
+ agent_list = agent_subparsers.add_parser("list", help="List agents")
+ agent_list.set_defaults(func=cmd_agent)
+
+ agent_info = agent_subparsers.add_parser("info", help="Get agent info")
+ agent_info.add_argument("agent_id", help="Agent ID")
+ agent_info.set_defaults(func=cmd_agent)
+
+ agent_register = agent_subparsers.add_parser("register", help="Register new agent (--dry-run for simulation)")
+ agent_register.add_argument("name", help="Agent name")
+ agent_register.add_argument("--wallet", help="Owner wallet address")
+ agent_register.add_argument("--type", choices=["service", "bot", "oracle"], help="Agent type")
+ agent_register.add_argument("--dry-run", action="store_true", help="Simulate locally; no server call (SIMULATION ONLY)")
+ agent_register.set_defaults(func=cmd_agent)
+
+ # bounty command (Agent Economy)
+ bounty_parser = subparsers.add_parser("bounty", help="Manage bounties")
+ bounty_parser.add_argument("--json", action="store_true", help="Output as JSON")
+ bounty_subparsers = bounty_parser.add_subparsers(dest="action", help="Bounty actions")
+
+ bounty_list = bounty_subparsers.add_parser("list", help="List bounties")
+ bounty_list.add_argument("--status", choices=["open", "claimed", "completed"], help="Filter by status")
+ bounty_list.set_defaults(func=cmd_bounty)
+
+ bounty_info = bounty_subparsers.add_parser("info", help="Get bounty info")
+ bounty_info.add_argument("bounty_id", help="Bounty ID")
+ bounty_info.set_defaults(func=cmd_bounty)
+
+ bounty_claim = bounty_subparsers.add_parser("claim", help="Claim a bounty (--dry-run for simulation)")
+ bounty_claim.add_argument("bounty_id", help="Bounty ID to claim")
+ bounty_claim.add_argument("--wallet", help="Wallet address for reward")
+ bounty_claim.add_argument("--dry-run", action="store_true", help="Simulate locally; no server call (SIMULATION ONLY)")
+ bounty_claim.set_defaults(func=cmd_bounty)
+
+ # x402 command (Agent Economy payments)
+ x402_parser = subparsers.add_parser("x402", help="x402 protocol payments")
+ x402_parser.add_argument("--json", action="store_true", help="Output as JSON")
+ x402_subparsers = x402_parser.add_subparsers(dest="action", help="x402 actions")
+
+ x402_pay = x402_subparsers.add_parser("pay", help="Send x402 payment (--dry-run for simulation)")
+ x402_pay.add_argument("recipient", help="Recipient wallet/agent")
+ x402_pay.add_argument("amount", help="Amount in RTC")
+ x402_pay.add_argument("--wallet", help="Sender wallet address")
+ x402_pay.add_argument("--dry-run", action="store_true", help="Simulate locally; no server call (SIMULATION ONLY)")
+ x402_pay.set_defaults(func=cmd_x402)
+
+ x402_history = x402_subparsers.add_parser("history", help="Payment history")
+ x402_history.add_argument("--wallet", help="Wallet address")
+ x402_history.set_defaults(func=cmd_x402)
+
+ x402_enable = x402_subparsers.add_parser("enable", help="Enable x402 for wallet")
+ x402_enable.add_argument("--wallet", help="Wallet address")
+ x402_enable.set_defaults(func=cmd_x402)
+
+ args = parser.parse_args()
+
if not args.command:
parser.print_help()
sys.exit(1)
-
+
# Override node if specified
if args.node:
os.environ["RUSTCHAIN_NODE"] = args.node
-
- args.func(args)
+
+ result = args.func(args)
+ if result is not None:
+ sys.exit(result)
if __name__ == "__main__":
main()