chore(systemd): remove obsolete systemd service files and update infrastructure documentation

- Remove 8 unused systemd service files from coordinator-api/systemd/
  - aitbc-adaptive-learning.service (port 8005)
  - aitbc-advanced-ai.service
  - aitbc-enterprise-api.service
  - aitbc-gpu-multimodal.service (port 8003)
  - aitbc-marketplace-enhanced.service (port 8006)
  - aitbc-modality-optimization.service (port 8004)
  - aitbc-multimodal.service (port 8002)
  - aitbc-openclaw-enhanced.service (port 8007
This commit is contained in:
oib
2026-03-04 12:16:50 +01:00
parent 581309369d
commit 50954a4b31
101 changed files with 1655 additions and 4871 deletions

131
dev/examples/README.md Normal file
View File

@@ -0,0 +1,131 @@
# AITBC Local Simulation
Simulate client and GPU provider interactions with independent wallets and AITBC transactions.
## Structure
```
home/
├── genesis.py # Creates genesis block and distributes initial AITBC
├── client/ # Customer/client wallet
│ └── wallet.py # Client wallet management
├── miner/ # GPU provider wallet
│ └── wallet.py # Miner wallet management
└── simulate.py # Complete workflow simulation
```
## Quick Start
### 1. Initialize the Economy
```bash
cd /home/oib/windsurf/aitbc/home
python3 genesis.py
```
This creates:
- Genesis wallet: 1,000,000 AITBC
- Client wallet: 10,000 AITBC
- Miner wallet: 1,000 AITBC
### 2. Check Wallets
```bash
# Client wallet
cd client && python3 wallet.py balance
# Miner wallet
cd miner && python3 wallet.py balance
```
### 3. Run Complete Simulation
```bash
cd /home/oib/windsurf/aitbc/home
python3 simulate.py
```
## Wallet Commands
### Client Wallet
```bash
cd client
# Check balance
python3 wallet.py balance
# Show address
python3 wallet.py address
# Pay for services
python3 wallet.py send <amount> <address> <description>
# Transaction history
python3 wallet.py history
```
### Miner Wallet
```bash
cd miner
# Check balance with stats
python3 wallet.py balance
# Add earnings from completed job
python3 wallet.py earn <amount> --job <job_id> --desc "Service description"
# Withdraw earnings
python3 wallet.py withdraw <amount> <address>
# Mining statistics
python3 wallet.py stats
```
## Example Workflow
### 1. Client Submits Job
```bash
cd /home/oib/windsurf/aitbc/cli
python3 client.py submit inference --model llama-2-7b --prompt "What is AI?"
```
### 2. Miner Processes Job
```bash
# Miner polls and gets job
python3 miner.py poll
# Miner earns AITBC
cd /home/oib/windsurf/aitbc/home/miner
python3 wallet.py earn 50.0 --job abc123 --desc "Inference task"
```
### 3. Client Pays
```bash
cd /home/oib/windsurf/aitbc/home/client
# Get miner address
cd ../miner && python3 wallet.py address
# Returns: aitbc1721d5bf8c0005ded6704
# Send payment
cd ../client
python3 wallet.py send 50.0 aitbc1721d5bf8c0005ded6704 "Payment for inference"
```
## Wallet Files
- `client/client_wallet.json` - Client's wallet data
- `miner/miner_wallet.json` - Miner's wallet data
- `genesis_wallet.json` - Genesis wallet with remaining AITBC
## Integration with CLI Tools
The home wallets integrate with the CLI tools:
1. Submit jobs using `cli/client.py`
2. Process jobs using `cli/miner.py`
3. Track payments using `home/*/wallet.py`
## Tips
- Each wallet has a unique address
- All transactions are recorded with timestamps
- Genesis wallet holds the remaining AITBC supply
- Use `simulate.py` for a complete demo
- Check `wallet.py history` to see all transactions

143
dev/examples/client_get_result.py Executable file
View File

@@ -0,0 +1,143 @@
#!/usr/bin/env python3
"""
Client retrieves job result from completed GPU processing
"""
import subprocess
import json
import sys
import os
# Add paths
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'cli'))
def get_job_result(job_id):
"""Get the result of a completed job"""
print(f"🔍 Retrieving result for job: {job_id}")
print("=" * 60)
# Check job status
print("\n1. Checking job status...")
status_result = subprocess.run(
f'cd ../cli && python3 client.py status {job_id}',
shell=True,
capture_output=True,
text=True
)
print(status_result.stdout)
# Check if job is completed
if "completed" in status_result.stdout:
print("\n2. ✅ Job completed! Retrieving result...")
# Parse the status to get result details
# In a real implementation, this would fetch from the coordinator API
print("\n📄 Job Result:")
print("-" * 40)
# Simulate getting the result from the blockchain/coordinator
print(f"Job ID: {job_id}")
print("Status: Completed")
print("Miner: ollama-miner")
print("Model: llama3.2:latest")
print("Processing Time: 2.3 seconds")
print("\nOutput:")
print("Hello! I'm an AI assistant powered by AITBC network.")
print("I'm running on GPU infrastructure provided by network miners.")
print("\nMetadata:")
print("- Tokens processed: 15")
print("- GPU utilization: 45%")
print("- Cost: 0.000025 AITBC")
return True
elif "queued" in status_result.stdout:
print("\n⏳ Job is still queued, waiting for miner...")
return False
elif "running" in status_result.stdout:
print("\n⚙️ Job is being processed by GPU provider...")
return False
elif "failed" in status_result.stdout:
print("\n❌ Job failed!")
return False
else:
print("\n❓ Unknown job status")
return False
def watch_job(job_id):
"""Watch a job until completion"""
print(f"👀 Watching job: {job_id}")
print("=" * 60)
import time
max_wait = 60 # Maximum wait time in seconds
start_time = time.time()
while time.time() - start_time < max_wait:
print(f"\n⏰ Checking... ({int(time.time() - start_time)}s elapsed)")
# Get status
result = subprocess.run(
f'cd ../cli && python3 client.py status {job_id}',
shell=True,
capture_output=True,
text=True
)
if "completed" in result.stdout:
print("\n✅ Job completed!")
return get_job_result(job_id)
elif "failed" in result.stdout:
print("\n❌ Job failed!")
return False
time.sleep(3)
print("\n⏰ Timeout waiting for job completion")
return False
def list_recent_results():
"""List recent completed jobs and their results"""
print("📋 Recent Job Results")
print("=" * 60)
# Get recent blocks/jobs from explorer
result = subprocess.run(
'cd ../cli && python3 client.py blocks --limit 5',
shell=True,
capture_output=True,
text=True
)
print(result.stdout)
print("\n💡 To get specific result:")
print(" python3 client_get_result.py <job_id>")
def main():
if len(sys.argv) < 2:
print("Usage:")
print(" python3 client_get_result.py <job_id> # Get specific job result")
print(" python3 client_get_result.py watch <job_id> # Watch job until complete")
print(" python3 client_get_result.py list # List recent results")
return
command = sys.argv[1]
if command == "list":
list_recent_results()
elif command == "watch" and len(sys.argv) > 2:
watch_job(sys.argv[2])
else:
get_job_result(command)
if __name__ == "__main__":
main()

126
dev/examples/client_send_job.py Executable file
View File

@@ -0,0 +1,126 @@
#!/usr/bin/env python3
"""
Client sends a job to GPU provider and pays for it
"""
import subprocess
import json
import time
import sys
import os
# Add paths
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'cli'))
sys.path.append(os.path.join(os.path.dirname(__file__)))
def send_job_to_gpu_provider():
print("🚀 Client: Sending Job to GPU Provider")
print("=" * 60)
# 1. Check client wallet balance
print("\n1. Checking client wallet...")
result = subprocess.run(
'cd client && python3 wallet.py balance',
shell=True,
capture_output=True,
text=True
)
print(result.stdout)
# 2. Submit job to coordinator
print("\n2. Submitting 'hello' job to network...")
job_result = subprocess.run(
'cd ../cli && python3 client.py submit inference --prompt "hello"',
shell=True,
capture_output=True,
text=True
)
print(job_result.stdout)
# Extract job ID
job_id = None
if "Job ID:" in job_result.stdout:
for line in job_result.stdout.split('\n'):
if "Job ID:" in line:
job_id = line.split()[-1]
break
if not job_id:
print("❌ Failed to submit job")
return
print(f"\n✅ Job submitted: {job_id}")
# 3. Wait for miner to process
print("\n3. Waiting for GPU provider to process job...")
print(" (Make sure miner is running: python3 cli/miner.py mine)")
# Check job status
max_wait = 30
for i in range(max_wait):
status_result = subprocess.run(
f'cd ../cli && python3 client.py status {job_id}',
shell=True,
capture_output=True,
text=True
)
if "completed" in status_result.stdout:
print("✅ Job completed by GPU provider!")
print(status_result.stdout)
break
elif "failed" in status_result.stdout:
print("❌ Job failed")
print(status_result.stdout)
break
else:
print(f" Waiting... ({i+1}s)")
time.sleep(1)
# 4. Get cost and pay
print("\n4. Processing payment...")
# For demo, assume cost is 10 AITBC
job_cost = 10.0
# Get miner address
miner_result = subprocess.run(
'cd miner && python3 wallet.py address',
shell=True,
capture_output=True,
text=True
)
miner_address = None
if "Miner Address:" in miner_result.stdout:
for line in miner_result.stdout.split('\n'):
if "Miner Address:" in line:
miner_address = line.split()[-1]
break
if miner_address:
print(f" Paying {job_cost} AITBC to miner...")
# Send payment
pay_result = subprocess.run(
f'cd client && python3 wallet.py send {job_cost} {miner_address} "Payment for job {job_id}"',
shell=True,
capture_output=True,
text=True
)
print(pay_result.stdout)
# 5. Show final balances
print("\n5. Final balances:")
print("\n Client:")
subprocess.run('cd client && python3 wallet.py balance', shell=True)
print("\n Miner:")
subprocess.run('cd miner && python3 wallet.py balance', shell=True)
print("\n✅ Job completed and paid for!")
if __name__ == "__main__":
send_job_to_gpu_provider()

74
dev/examples/client_wallet.py Executable file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/env python3
"""
Client wallet for managing AITBC tokens
"""
import argparse
import json
import os
import sys
from datetime import datetime
# Add parent directory to path to import wallet module
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import importlib.util
spec = importlib.util.spec_from_file_location("wallet", os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "wallet.py"))
wallet = importlib.util.module_from_spec(spec)
spec.loader.exec_module(wallet)
AITBCWallet = wallet.AITBCWallet
def main():
parser = argparse.ArgumentParser(description="Client Wallet - Manage AITBC for paying for GPU services")
parser.add_argument("--wallet", default="client_wallet.json", help="Wallet file name")
subparsers = parser.add_subparsers(dest="command", help="Commands")
# Balance command
balance_parser = subparsers.add_parser("balance", help="Show balance")
# Address command
address_parser = subparsers.add_parser("address", help="Show wallet address")
# History command
history_parser = subparsers.add_parser("history", help="Show transaction history")
# Send command (pay for services)
send_parser = subparsers.add_parser("send", help="Send AITBC to GPU provider")
send_parser.add_argument("amount", type=float, help="Amount to send")
send_parser.add_argument("to", help="Recipient address")
send_parser.add_argument("description", help="Payment description")
args = parser.parse_args()
if not args.command:
parser.print_help()
return
# Use client-specific wallet directory
wallet_dir = os.path.dirname(os.path.abspath(__file__))
wallet_path = os.path.join(wallet_dir, args.wallet)
wallet = AITBCWallet(wallet_path)
if args.command == "balance":
print("💼 CLIENT WALLET")
print("=" * 40)
wallet.show_balance()
print("\n💡 Use 'send' to pay for GPU services")
elif args.command == "address":
print(f"💼 Client Address: {wallet.data['address']}")
print(" Share this address to receive AITBC")
elif args.command == "history":
print("💼 CLIENT TRANSACTION HISTORY")
print("=" * 40)
wallet.show_history()
elif args.command == "send":
print(f"💸 Sending {args.amount} AITBC to {args.to}")
print(f" For: {args.description}")
wallet.spend(args.amount, args.description)
if __name__ == "__main__":
main()

199
dev/examples/enhanced_client.py Executable file
View File

@@ -0,0 +1,199 @@
#!/usr/bin/env python3
"""
Enhanced client that submits jobs and automatically retrieves results
"""
import subprocess
import json
import time
import sys
import os
# Add paths
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'cli'))
class AITBCClient:
def __init__(self):
self.coordinator_url = "http://localhost:8001"
self.api_key = "${CLIENT_API_KEY}"
def submit_job(self, prompt, model="llama3.2:latest", wait_for_result=True):
"""Submit a job and optionally wait for result"""
print(f"📤 Submitting job to AITBC network...")
print(f" Prompt: '{prompt}'")
print(f" Model: {model}")
print()
# Submit job
result = subprocess.run(
f'cd ../cli && python3 client.py submit inference --prompt "{prompt}"',
shell=True,
capture_output=True,
text=True
)
# Extract job ID
job_id = None
for line in result.stdout.split('\n'):
if "Job ID:" in line:
job_id = line.split()[-1]
break
if not job_id:
print("❌ Failed to submit job")
return None
print(f"✅ Job submitted: {job_id}")
if wait_for_result:
return self.wait_for_result(job_id)
else:
return job_id
def wait_for_result(self, job_id, timeout=60):
"""Wait for job completion and return result"""
print(f"⏳ Waiting for GPU provider to process job...")
print(f" Timeout: {timeout}s")
print()
start_time = time.time()
while time.time() - start_time < timeout:
# Check status
status_result = subprocess.run(
f'cd ../cli && python3 client.py status {job_id}',
shell=True,
capture_output=True,
text=True
)
if "completed" in status_result.stdout:
print(f"✅ Job completed by GPU provider!")
print()
return self.get_result(job_id)
elif "failed" in status_result.stdout:
print(f"❌ Job failed")
return None
elif "running" in status_result.stdout:
elapsed = int(time.time() - start_time)
print(f" ⚙️ Processing... ({elapsed}s)")
else:
elapsed = int(time.time() - start_time)
print(f" ⏳ Waiting in queue... ({elapsed}s)")
time.sleep(3)
print(f"⏰ Timeout after {timeout}s")
return None
def get_result(self, job_id):
"""Get and display job result"""
print(f"📄 Job Result for {job_id}")
print("=" * 60)
# In a real implementation, fetch from coordinator API
# For now, simulate the result
# Get job details
status_result = subprocess.run(
f'cd ../cli && python3 client.py status {job_id}',
shell=True,
capture_output=True,
text=True
)
print("Job Details:")
print(status_result.stdout)
print("\nGenerated Output:")
print("-" * 40)
# Simulate different outputs based on job
if "hello" in job_id.lower():
print("Hello! 👋")
print("I'm an AI assistant running on the AITBC network.")
print("Your request was processed by a GPU miner in the network.")
elif "blockchain" in job_id.lower():
print("Blockchain is a distributed ledger technology that maintains")
print("a secure and decentralized record of transactions across multiple")
print("computers. It's the foundation of cryptocurrencies like Bitcoin")
print("and has many other applications beyond digital currencies.")
else:
print("This is a sample response from the AITBC network.")
print("The actual output would be generated by the GPU provider")
print("based on your specific prompt and requirements.")
print("\nProcessing Details:")
print("-" * 40)
print(f"• Miner: GPU Provider")
print(f"• Model: llama3.2:latest")
print(f"• Tokens: ~25")
print(f"• Cost: 0.000025 AITBC")
print(f"• Network: AITBC")
return {
"job_id": job_id,
"status": "completed",
"output": "Generated response from GPU provider"
}
def pay_for_job(self, job_id, amount=25.0):
"""Pay for a completed job"""
print(f"\n💸 Paying for job {job_id}...")
# Get miner address
miner_result = subprocess.run(
'cd miner && python3 wallet.py address',
shell=True,
capture_output=True,
text=True
)
miner_address = None
for line in miner_result.stdout.split('\n'):
if "Miner Address:" in line:
miner_address = line.split()[-1]
break
if miner_address:
# Send payment
pay_result = subprocess.run(
f'cd client && python3 wallet.py send {amount} {miner_address} "Payment for job {job_id}"',
shell=True,
capture_output=True,
text=True
)
print(pay_result.stdout)
return True
else:
print("❌ Could not get miner address")
return False
def main():
client = AITBCClient()
print("🚀 AITBC Enhanced Client")
print("=" * 60)
# Example 1: Submit and wait for result
print("\n📝 Example 1: Submit job and wait for result")
print("-" * 40)
result = client.submit_job("hello", wait_for_result=True)
if result:
# Pay for the job
client.pay_for_job(result["job_id"])
print("\n" + "=" * 60)
print("✅ Complete workflow demonstrated!")
print("\n💡 To use with your own prompt:")
print(" python3 enhanced_client.py")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,109 @@
#!/usr/bin/env python3
"""
Example client using the remote AITBC coordinator
"""
import httpx
import json
from datetime import datetime
# Configuration - using the SSH tunnel to remote server
COORDINATOR_URL = "http://localhost:8001"
CLIENT_API_KEY = "${CLIENT_API_KEY}"
def create_job():
"""Create a job on the remote coordinator"""
job_data = {
"payload": {
"type": "inference",
"task": "text-generation",
"model": "llama-2-7b",
"parameters": {
"prompt": "Hello, AITBC!",
"max_tokens": 100
}
},
"ttl_seconds": 900
}
with httpx.Client() as client:
response = client.post(
f"{COORDINATOR_URL}/v1/jobs",
headers={
"Content-Type": "application/json",
"X-Api-Key": CLIENT_API_KEY
},
json=job_data
)
if response.status_code == 201:
job = response.json()
print(f"✅ Job created successfully!")
print(f" Job ID: {job['job_id']}")
print(f" State: {job['state']}")
print(f" Expires at: {job['expires_at']}")
return job['job_id']
else:
print(f"❌ Failed to create job: {response.status_code}")
print(f" Response: {response.text}")
return None
def check_job_status(job_id):
"""Check the status of a job"""
with httpx.Client() as client:
response = client.get(
f"{COORDINATOR_URL}/v1/jobs/{job_id}",
headers={"X-Api-Key": CLIENT_API_KEY}
)
if response.status_code == 200:
job = response.json()
print(f"\n📊 Job Status:")
print(f" Job ID: {job['job_id']}")
print(f" State: {job['state']}")
print(f" Assigned Miner: {job.get('assigned_miner_id', 'None')}")
print(f" Created: {job['requested_at']}")
return job
else:
print(f"❌ Failed to get job status: {response.status_code}")
return None
def list_blocks():
"""List blocks from the explorer"""
with httpx.Client() as client:
response = client.get(f"{COORDINATOR_URL}/v1/explorer/blocks")
if response.status_code == 200:
blocks = response.json()
print(f"\n📦 Recent Blocks ({len(blocks['items'])} total):")
for block in blocks['items'][:5]: # Show last 5 blocks
print(f" Height: {block['height']}")
print(f" Hash: {block['hash']}")
print(f" Time: {block['timestamp']}")
print(f" Transactions: {block['txCount']}")
print(f" Proposer: {block['proposer']}")
print()
else:
print(f"❌ Failed to list blocks: {response.status_code}")
def main():
print("🚀 AITBC Remote Client Example")
print(f" Connecting to: {COORDINATOR_URL}")
print()
# List current blocks
list_blocks()
# Create a new job
job_id = create_job()
if job_id:
# Check job status
check_job_status(job_id)
# List blocks again to see the new job
print("\n🔄 Updated block list:")
list_blocks()
if __name__ == "__main__":
main()

85
dev/examples/genesis.py Executable file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""
Genesis wallet - Distributes initial AITBC from genesis block
"""
import os
import sys
import json
from datetime import datetime
# Add parent directory to path
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'cli'))
from wallet import AITBCWallet
def main():
print("🌍 GENESIS BLOCK - Initial AITBC Distribution")
print("=" * 60)
# Create genesis wallet with large initial balance
genesis = AITBCWallet("genesis_wallet.json")
genesis.data["balance"] = 1000000.0 # 1 million AITBC
genesis.data["transactions"] = [{
"type": "genesis",
"amount": 1000000.0,
"description": "Genesis block creation",
"timestamp": datetime.now().isoformat()
}]
genesis.save()
print(f"💰 Genesis Wallet Created")
print(f" Address: {genesis.data['address']}")
print(f" Balance: {genesis.data['balance']} AITBC")
print()
# Distribute to client and miner
client_wallet = AITBCWallet(os.path.join("client", "client_wallet.json"))
miner_wallet = AITBCWallet(os.path.join("miner", "miner_wallet.json"))
print("📤 Distributing Initial AITBC")
print("-" * 40)
# Give client 10,000 AITBC to spend
client_address = client_wallet.data["address"]
print(f"💸 Sending 10,000 AITBC to Client ({client_address[:20]}...)")
client_wallet.add_earnings(10000.0, "genesis_distribution", "Initial funding from genesis block")
# Give miner 1,000 AITBC to start
miner_address = miner_wallet.data["address"]
print(f"💸 Sending 1,000 AITBC to Miner ({miner_address[:20]}...)")
miner_wallet.add_earnings(1000.0, "genesis_distribution", "Initial funding from genesis block")
# Update genesis wallet
genesis.data["balance"] -= 11000.0
genesis.data["transactions"].extend([
{
"type": "transfer",
"amount": -10000.0,
"to": client_address,
"description": "Initial client funding",
"timestamp": datetime.now().isoformat()
},
{
"type": "transfer",
"amount": -1000.0,
"to": miner_address,
"description": "Initial miner funding",
"timestamp": datetime.now().isoformat()
}
])
genesis.save()
print()
print("✅ Distribution Complete!")
print("=" * 60)
print(f"Genesis Balance: {genesis.data['balance']} AITBC")
print(f"Client Balance: {client_wallet.data['balance']} AITBC")
print(f"Miner Balance: {miner_wallet.data['balance']} AITBC")
print()
print("💡 Next Steps:")
print(" 1. Client: Submit jobs and pay for GPU services")
print(" 2. Miner: Process jobs and earn AITBC")
print(" 3. Track everything with the wallet CLI tools")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,144 @@
#!/usr/bin/env python3
"""
Demonstration: How customers get replies from GPU providers
"""
import subprocess
import time
def main():
print("📨 How Customers Get Replies in AITBC")
print("=" * 60)
print("\n🔄 Complete Flow:")
print("1. Customer submits job")
print("2. GPU provider processes job")
print("3. Result stored on blockchain")
print("4. Customer retrieves result")
print("5. Customer pays for service")
print("\n" + "=" * 60)
print("\n📝 STEP 1: Customer Submits Job")
print("-" * 40)
# Submit a job
result = subprocess.run(
'cd ../cli && python3 client.py submit inference --prompt "What is AI?"',
shell=True,
capture_output=True,
text=True
)
print(result.stdout)
# Extract job ID
job_id = None
for line in result.stdout.split('\n'):
if "Job ID:" in line:
job_id = line.split()[-1]
break
if not job_id:
print("❌ Failed to submit job")
return
print(f"\n✅ Job submitted with ID: {job_id}")
print("\n⚙️ STEP 2: GPU Provider Processes Job")
print("-" * 40)
print(" • Miner polls for jobs")
print(" • Job assigned to miner")
print(" • GPU processes the request")
print(" • Result submitted to network")
# Simulate processing
print("\n 💭 Simulating GPU processing...")
time.sleep(2)
print("\n📦 STEP 3: Result Stored on Blockchain")
print("-" * 40)
print(f" • Job {job_id} marked as completed")
print(f" • Result stored with job metadata")
print(f" • Block created with job details")
# Show block
print("\n 📋 Blockchain Entry:")
print(f" Block Hash: {job_id}")
print(f" Proposer: gpu-miner")
print(f" Status: COMPLETED")
print(f" Result: Available for retrieval")
print("\n🔍 STEP 4: Customer Retrieves Result")
print("-" * 40)
print(" Method 1: Check job status")
print(f" $ python3 cli/client.py status {job_id}")
print()
# Show status
status_result = subprocess.run(
f'cd ../cli && python3 client.py status {job_id}',
shell=True,
capture_output=True,
text=True
)
print(" Status Result:")
for line in status_result.stdout.split('\n'):
if line.strip():
print(f" {line}")
print("\n Method 2: Get full result")
print(f" $ python3 client_get_result.py {job_id}")
print()
print(" 📄 Full Result:")
print(" ----------")
print(" Output: AI stands for Artificial Intelligence, which refers")
print(" to the simulation of human intelligence in machines")
print(" that are programmed to think and learn.")
print(" Tokens: 28")
print(" Cost: 0.000028 AITBC")
print(" Miner: GPU Provider #1")
print("\n💸 STEP 5: Customer Pays for Service")
print("-" * 40)
# Get miner address
miner_result = subprocess.run(
'cd miner && python3 wallet.py address',
shell=True,
capture_output=True,
text=True
)
miner_address = None
for line in miner_result.stdout.split('\n'):
if "Miner Address:" in line:
miner_address = line.split()[-1]
break
if miner_address:
print(f" Payment sent to: {miner_address}")
print(" Amount: 25.0 AITBC")
print(" Status: ✅ Paid")
print("\n" + "=" * 60)
print("✅ Customer successfully received reply!")
print("\n📋 Summary of Retrieval Methods:")
print("-" * 40)
print("1. Job Status: python3 cli/client.py status <job_id>")
print("2. Full Result: python3 client_get_result.py <job_id>")
print("3. Watch Job: python3 client_get_result.py watch <job_id>")
print("4. List Recent: python3 client_get_result.py list")
print("5. Enhanced Client: python3 enhanced_client.py")
print("\n💡 In production:")
print(" • Results are stored on-chain")
print(" • Customers can retrieve anytime")
print(" • Results are immutable and verifiable")
print(" • Payment is required to unlock full results")
if __name__ == "__main__":
main()

113
dev/examples/miner_wallet.py Executable file
View File

@@ -0,0 +1,113 @@
#!/usr/bin/env python3
"""
GPU Provider wallet for managing earnings from mining
"""
import argparse
import json
import os
import sys
from datetime import datetime
# Add parent directory to path to import wallet module
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import importlib.util
spec = importlib.util.spec_from_file_location("wallet", os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "wallet.py"))
wallet = importlib.util.module_from_spec(spec)
spec.loader.exec_module(wallet)
AITBCWallet = wallet.AITBCWallet
def main():
parser = argparse.ArgumentParser(description="GPU Provider Wallet - Manage earnings from mining services")
parser.add_argument("--wallet", default="miner_wallet.json", help="Wallet file name")
subparsers = parser.add_subparsers(dest="command", help="Commands")
# Balance command
balance_parser = subparsers.add_parser("balance", help="Show balance")
# Address command
address_parser = subparsers.add_parser("address", help="Show wallet address")
# History command
history_parser = subparsers.add_parser("history", help="Show transaction history")
# Earn command (receive payment for completed jobs)
earn_parser = subparsers.add_parser("earn", help="Add earnings from completed job")
earn_parser.add_argument("amount", type=float, help="Amount earned")
earn_parser.add_argument("--job", required=True, help="Job ID that was completed")
earn_parser.add_argument("--desc", default="GPU computation", help="Service description")
# Withdraw command
withdraw_parser = subparsers.add_parser("withdraw", help="Withdraw AITBC to external wallet")
withdraw_parser.add_argument("amount", type=float, help="Amount to withdraw")
withdraw_parser.add_argument("address", help="Destination address")
# Stats command
stats_parser = subparsers.add_parser("stats", help="Show mining statistics")
args = parser.parse_args()
if not args.command:
parser.print_help()
return
# Use miner-specific wallet directory
wallet_dir = os.path.dirname(os.path.abspath(__file__))
wallet_path = os.path.join(wallet_dir, args.wallet)
wallet = AITBCWallet(wallet_path)
if args.command == "balance":
print("⛏️ GPU PROVIDER WALLET")
print("=" * 40)
wallet.show_balance()
# Show additional stats
earnings = sum(t['amount'] for t in wallet.data['transactions'] if t['type'] == 'earn')
jobs_completed = sum(1 for t in wallet.data['transactions'] if t['type'] == 'earn')
print(f"\n📊 Mining Stats:")
print(f" Total Earned: {earnings} AITBC")
print(f" Jobs Completed: {jobs_completed}")
print(f" Average per Job: {earnings/jobs_completed if jobs_completed > 0 else 0} AITBC")
elif args.command == "address":
print(f"⛏️ Miner Address: {wallet.data['address']}")
print(" Share this address to receive payments")
elif args.command == "history":
print("⛏️ MINER TRANSACTION HISTORY")
print("=" * 40)
wallet.show_history()
elif args.command == "earn":
print(f"💰 Adding earnings for job {args.job}")
wallet.add_earnings(args.amount, args.job, args.desc)
elif args.command == "withdraw":
print(f"💸 Withdrawing {args.amount} AITBC to {args.address}")
wallet.spend(args.amount, f"Withdrawal to {args.address}")
elif args.command == "stats":
print("⛏️ MINING STATISTICS")
print("=" * 40)
transactions = wallet.data['transactions']
earnings = [t for t in transactions if t['type'] == 'earn']
spends = [t for t in transactions if t['type'] == 'spend']
total_earned = sum(t['amount'] for t in earnings)
total_spent = sum(t['amount'] for t in spends)
print(f"💰 Total Earned: {total_earned} AITBC")
print(f"💸 Total Spent: {total_spent} AITBC")
print(f"💳 Net Balance: {wallet.data['balance']} AITBC")
print(f"📊 Jobs Completed: {len(earnings)}")
if earnings:
print(f"\n📈 Recent Earnings:")
for earning in earnings[-5:]:
print(f" +{earning['amount']} AITBC | Job: {earning.get('job_id', 'N/A')}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,265 @@
#!/usr/bin/env python3
"""
Python 3.13.5 Features Demonstration for AITBC
This script showcases the new features and improvements available in Python 3.13.5
that can benefit the AITBC project.
"""
import sys
import time
import asyncio
from typing import Generic, TypeVar, override, List, Optional
from pathlib import Path
print(f"🚀 Python 3.13.5 Features Demo - Running on Python {sys.version}")
print("=" * 60)
# ============================================================================
# 1. Enhanced Error Messages
# ============================================================================
def demonstrate_enhanced_errors():
"""Demonstrate improved error messages in Python 3.13"""
print("\n1. Enhanced Error Messages:")
print("-" * 30)
try:
# This will show a much clearer error message in Python 3.13
data = {"name": "AITBC", "version": "1.0"}
result = data["missing_key"]
except KeyError as e:
print(f"KeyError: {e}")
print("✅ Clearer error messages with exact location and suggestions")
# ============================================================================
# 2. Type Parameter Defaults
# ============================================================================
T = TypeVar('T')
class DataContainer(Generic[T]):
"""Generic container with type parameter defaults (Python 3.13+)"""
def __init__(self, items: List[T] | None = None) -> None:
# Type parameter defaults allow more flexible generic classes
self.items = items or []
def add_item(self, item: T) -> None:
self.items.append(item)
def get_items(self) -> List[T]:
return self.items.copy()
def demonstrate_type_defaults():
"""Demonstrate type parameter defaults"""
print("\n2. Type Parameter Defaults:")
print("-" * 30)
# Can now create containers without specifying type
container = DataContainer()
container.add_item("test_string")
container.add_item(42)
print("✅ Generic classes with default type parameters")
print(f" Items: {container.get_items()}")
# ============================================================================
# 3. @override Decorator
# ============================================================================
class BaseProcessor:
"""Base class for demonstrating @override decorator"""
def process(self, data: str) -> str:
return data.upper()
class AdvancedProcessor(BaseProcessor):
"""Advanced processor using @override decorator"""
@override
def process(self, data: str) -> str:
# Enhanced processing with validation
if not data:
raise ValueError("Data cannot be empty")
return data.lower().strip()
def demonstrate_override_decorator():
"""Demonstrate @override decorator for method overriding"""
print("\n3. @override Decorator:")
print("-" * 30)
processor = AdvancedProcessor()
result = processor.process(" HELLO AITBC ")
print("✅ Method overriding with @override decorator")
print(f" Result: '{result}'")
# ============================================================================
# 4. Performance Improvements
# ============================================================================
def demonstrate_performance():
"""Demonstrate Python 3.13 performance improvements"""
print("\n4. Performance Improvements:")
print("-" * 30)
# List comprehension performance
start_time = time.time()
result = [i * i for i in range(100000)]
list_time = (time.time() - start_time) * 1000
# Dictionary comprehension performance
start_time = time.time()
result_dict = {i: i * i for i in range(100000)}
dict_time = (time.time() - start_time) * 1000
print(f"✅ List comprehension (100k items): {list_time:.2f}ms")
print(f"✅ Dict comprehension (100k items): {dict_time:.2f}ms")
print("✅ 5-10% performance improvement over Python 3.11")
# ============================================================================
# 5. Asyncio Improvements
# ============================================================================
async def demonstrate_asyncio():
"""Demonstrate asyncio performance improvements"""
print("\n5. Asyncio Improvements:")
print("-" * 30)
async def fast_task():
await asyncio.sleep(0.001)
return "completed"
# Run multiple concurrent tasks
start_time = time.time()
tasks = [fast_task() for _ in range(100)]
results = await asyncio.gather(*tasks)
async_time = (time.time() - start_time) * 1000
print(f"✅ 100 concurrent async tasks: {async_time:.2f}ms")
print("✅ Enhanced asyncio performance and task scheduling")
# ============================================================================
# 6. Standard Library Improvements
# ============================================================================
def demonstrate_stdlib_improvements():
"""Demonstrate standard library improvements"""
print("\n6. Standard Library Improvements:")
print("-" * 30)
# Pathlib improvements
config_path = Path("/home/oib/windsurf/aitbc/config")
print(f"✅ Enhanced pathlib: {config_path}")
# HTTP server improvements
print("✅ Improved http.server with better error handling")
# JSON improvements
import json
data = {"status": "ok", "python": "3.13.5"}
json_str = json.dumps(data, indent=2)
print("✅ Enhanced JSON serialization with better formatting")
# ============================================================================
# 7. Security Improvements
# ============================================================================
def demonstrate_security():
"""Demonstrate security improvements"""
print("\n7. Security Improvements:")
print("-" * 30)
# Hash randomization
import hashlib
data = b"aitbc_security_test"
hash_result = hashlib.sha256(data).hexdigest()
print(f"✅ Enhanced hash randomization: {hash_result[:16]}...")
# Memory safety
try:
# Memory-safe operations
large_list = list(range(1000000))
print(f"✅ Better memory safety: Created list with {len(large_list)} items")
except MemoryError:
print("✅ Improved memory error handling")
# ============================================================================
# 8. AITBC-Specific Applications
# ============================================================================
class AITBCReceiptProcessor(Generic[T]):
"""Generic receipt processor using Python 3.13 features"""
def __init__(self, validator: Optional[callable] = None) -> None:
self.validator = validator or (lambda x: True)
self.receipts: List[T] = []
def add_receipt(self, receipt: T) -> bool:
"""Add receipt with validation"""
if self.validator(receipt):
self.receipts.append(receipt)
return True
return False
@override
def process_receipts(self) -> List[T]:
"""Process all receipts with enhanced validation"""
return [receipt for receipt in self.receipts if self.validator(receipt)]
def demonstrate_aitbc_applications():
"""Demonstrate Python 3.13 features in AITBC context"""
print("\n8. AITBC-Specific Applications:")
print("-" * 30)
# Generic receipt processor
def validate_receipt(receipt: dict) -> bool:
return receipt.get("valid", False)
processor = AITBCReceiptProcessor[dict](validate_receipt)
# Add sample receipts
processor.add_receipt({"id": 1, "valid": True, "amount": 100})
processor.add_receipt({"id": 2, "valid": False, "amount": 50})
processed = processor.process_receipts()
print(f"✅ Generic receipt processor: {len(processed)} valid receipts")
# Enhanced error handling for blockchain operations
try:
block_data = {"height": 1000, "hash": "0x123..."}
next_hash = block_data["next_hash"] # This will show enhanced error
except KeyError as e:
print(f"✅ Enhanced blockchain error handling: {e}")
# ============================================================================
# Main Execution
# ============================================================================
def main():
"""Run all demonstrations"""
try:
demonstrate_enhanced_errors()
demonstrate_type_defaults()
demonstrate_override_decorator()
demonstrate_performance()
# Run async demo
asyncio.run(demonstrate_asyncio())
demonstrate_stdlib_improvements()
demonstrate_security()
demonstrate_aitbc_applications()
print("\n" + "=" * 60)
print("🎉 Python 3.13.5 Features Demo Complete!")
print("🚀 AITBC is ready to leverage these improvements!")
except Exception as e:
print(f"❌ Demo failed: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
main()

42
dev/examples/quick_job.py Executable file
View File

@@ -0,0 +1,42 @@
#!/usr/bin/env python3
"""
Quick job submission and payment
Usage: python3 quick_job.py "your prompt"
"""
import subprocess
import sys
import time
if len(sys.argv) < 2:
print("Usage: python3 quick_job.py \"your prompt\"")
sys.exit(1)
prompt = sys.argv[1]
print(f"🚀 Submitting job: '{prompt}'")
# Submit job
result = subprocess.run(
f'cd ../cli && python3 client.py submit inference --prompt "{prompt}"',
shell=True,
capture_output=True,
text=True
)
# Extract job ID
job_id = None
for line in result.stdout.split('\n'):
if "Job ID:" in line:
job_id = line.split()[-1]
break
if job_id:
print(f"✅ Job submitted: {job_id}")
print("\n💡 Next steps:")
print(f" 1. Start miner: python3 cli/miner.py mine")
print(f" 2. Check status: python3 cli/client.py status {job_id}")
print(f" 3. After completion, pay with:")
print(f" cd home/client && python3 wallet.py send 25.0 $(cd home/miner && python3 wallet.py address | grep Address | cut -d' ' -f4) 'Payment for {job_id}'")
else:
print("❌ Failed to submit job")

104
dev/examples/simple_job_flow.py Executable file
View File

@@ -0,0 +1,104 @@
#!/usr/bin/env python3
"""
Simple job flow: Client -> GPU Provider -> Payment
"""
import subprocess
import time
def main():
print("📋 AITBC Job Flow: Client -> GPU Provider -> Payment")
print("=" * 60)
print("\n📝 STEP 1: Client submits job 'hello'")
print("-" * 40)
# Submit job
result = subprocess.run(
'cd ../cli && python3 client.py demo',
shell=True,
capture_output=True,
text=True
)
print(result.stdout)
# Extract job ID
job_id = None
if "Job ID:" in result.stdout:
for line in result.stdout.split('\n'):
if "Job ID:" in line:
job_id = line.split()[-1]
break
if not job_id:
print("❌ Failed to submit job")
return
print(f"\n📮 Job submitted: {job_id}")
print("\n⛏️ STEP 2: GPU Provider processes job")
print("-" * 40)
print(" (Start miner with: python3 cli/miner.py mine)")
print(" The miner will automatically pick up the job")
# Simulate miner processing
print("\n 💭 Simulating job processing...")
time.sleep(2)
# Miner earns AITBC
print(" ✅ Job processed!")
print(" 💰 Miner earned 25 AITBC")
# Add to miner wallet
subprocess.run(
f'cd miner && python3 wallet.py earn 25.0 --job {job_id} --desc "Processed hello job"',
shell=True,
capture_output=True,
text=True
)
print("\n💸 STEP 3: Client pays for service")
print("-" * 40)
# Get miner address
miner_result = subprocess.run(
'cd miner && python3 wallet.py address',
shell=True,
capture_output=True,
text=True
)
miner_address = None
if "Miner Address:" in miner_result.stdout:
for line in miner_result.stdout.split('\n'):
if "Miner Address:" in line:
miner_address = line.split()[-1]
break
if miner_address:
# Client pays
subprocess.run(
f'cd client && python3 wallet.py send 25.0 {miner_address} "Payment for job {job_id}"',
shell=True,
capture_output=True,
text=True
)
print("\n📊 STEP 4: Final balances")
print("-" * 40)
print("\n Client Wallet:")
subprocess.run('cd client && python3 wallet.py balance', shell=True)
print("\n Miner Wallet:")
subprocess.run('cd miner && python3 wallet.py balance', shell=True)
print("\n✅ Complete workflow demonstrated!")
print("\n💡 To run with real GPU processing:")
print(" 1. Start miner: python3 cli/miner.py mine")
print(" 2. Submit job: python3 cli/client.py submit inference --prompt 'hello'")
print(" 3. Check status: python3 cli/client.py status <job_id>")
print(" 4. Pay manually: cd home/client && python3 wallet.py send <amount> <miner_address>")
if __name__ == "__main__":
main()

136
dev/examples/simulate.py Executable file
View File

@@ -0,0 +1,136 @@
#!/usr/bin/env python3
"""
Complete simulation: Client pays for GPU services, Miner earns AITBC
"""
import os
import sys
import time
import subprocess
def run_wallet_command(wallet_type, command, description):
"""Run a wallet command and display results"""
print(f"\n{'='*60}")
print(f"💼 {wallet_type}: {description}")
print(f"{'='*60}")
wallet_dir = os.path.join(os.path.dirname(__file__), wallet_type.lower())
cmd = f"cd {wallet_dir} && python3 wallet.py {command}"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
print(result.stdout)
if result.stderr:
print(f"Error: {result.stderr}")
return result
def main():
print("🎭 AITBC Local Simulation")
print("=" * 60)
print("Simulating client and GPU provider interactions")
print()
# Step 1: Initialize wallets with genesis distribution
print("📋 STEP 1: Initialize Wallets")
os.system("cd /home/oib/windsurf/aitbc/home && python3 genesis.py")
input("\nPress Enter to continue...")
# Step 2: Check initial balances
print("\n📋 STEP 2: Check Initial Balances")
run_wallet_command("Client", "balance", "Initial client balance")
run_wallet_command("Miner", "balance", "Initial miner balance")
input("\nPress Enter to continue...")
# Step 3: Client submits a job (using CLI tool)
print("\n📋 STEP 3: Client Submits Job")
print("-" * 40)
# Submit job to coordinator
result = subprocess.run(
"cd /home/oib/windsurf/aitbc/cli && python3 client.py submit inference --model llama-2-7b --prompt 'What is the future of AI?'",
shell=True,
capture_output=True,
text=True
)
print(result.stdout)
# Extract job ID if successful
job_id = None
if "Job ID:" in result.stdout:
for line in result.stdout.split('\n'):
if "Job ID:" in line:
job_id = line.split()[-1]
break
input("\nPress Enter to continue...")
# Step 4: Miner processes the job
print("\n📋 STEP 4: Miner Processes Job")
print("-" * 40)
if job_id:
print(f"⛏️ Miner found job: {job_id}")
print("⚙️ Processing job...")
time.sleep(2)
# Miner earns AITBC for completing the job
run_wallet_command(
"Miner",
f"earn 50.0 --job {job_id} --desc 'Inference task completed'",
"Miner earns AITBC"
)
input("\nPress Enter to continue...")
# Step 5: Client pays for the service
print("\n📋 STEP 5: Client Pays for Service")
print("-" * 40)
if job_id:
# Get miner address
miner_result = subprocess.run(
"cd /home/oib/windsurf/aitbc/home/miner && python3 wallet.py address",
shell=True,
capture_output=True,
text=True
)
miner_address = None
if "Miner Address:" in miner_result.stdout:
for line in miner_result.stdout.split('\n'):
if "Miner Address:" in line:
miner_address = line.split()[-1]
break
if miner_address:
run_wallet_command(
"Client",
f"send 50.0 {miner_address} 'Payment for inference job {job_id}'",
"Client pays for completed job"
)
input("\nPress Enter to continue...")
# Step 6: Check final balances
print("\n📋 STEP 6: Final Balances")
run_wallet_command("Client", "balance", "Final client balance")
run_wallet_command("Miner", "balance", "Final miner balance")
print("\n🎉 Simulation Complete!")
print("=" * 60)
print("Summary:")
print(" • Client submitted job and paid 50 AITBC")
print(" • Miner processed job and earned 50 AITBC")
print(" • Transaction recorded on blockchain")
print()
print("💡 You can:")
print(" • Run 'cd home/client && python3 wallet.py history' to see client transactions")
print(" • Run 'cd home/miner && python3 wallet.py stats' to see miner earnings")
print(" • Submit more jobs with the CLI tools")
if __name__ == "__main__":
main()

158
dev/examples/wallet.py Executable file
View File

@@ -0,0 +1,158 @@
#!/usr/bin/env python3
"""
AITBC Wallet CLI Tool - Track earnings and manage wallet
"""
import argparse
import json
import os
from datetime import datetime
from typing import Dict, List
class AITBCWallet:
def __init__(self, wallet_file: str = None):
if wallet_file is None:
wallet_file = os.path.expanduser("~/.aitbc_wallet.json")
self.wallet_file = wallet_file
self.data = self._load_wallet()
def _load_wallet(self) -> dict:
"""Load wallet data from file"""
if os.path.exists(self.wallet_file):
try:
with open(self.wallet_file, 'r') as f:
return json.load(f)
except:
pass
# Create new wallet
return {
"address": "aitbc1" + os.urandom(10).hex(),
"balance": 0.0,
"transactions": [],
"created_at": datetime.now().isoformat()
}
def save(self):
"""Save wallet to file"""
with open(self.wallet_file, 'w') as f:
json.dump(self.data, f, indent=2)
def add_earnings(self, amount: float, job_id: str, description: str = ""):
"""Add earnings from completed job"""
transaction = {
"type": "earn",
"amount": amount,
"job_id": job_id,
"description": description or f"Job {job_id}",
"timestamp": datetime.now().isoformat()
}
self.data["transactions"].append(transaction)
self.data["balance"] += amount
self.save()
print(f"💰 Added {amount} AITBC to wallet")
print(f" New balance: {self.data['balance']} AITBC")
def spend(self, amount: float, description: str):
"""Spend AITBC"""
if self.data["balance"] < amount:
print(f"❌ Insufficient balance!")
print(f" Balance: {self.data['balance']} AITBC")
print(f" Needed: {amount} AITBC")
return False
transaction = {
"type": "spend",
"amount": -amount,
"description": description,
"timestamp": datetime.now().isoformat()
}
self.data["transactions"].append(transaction)
self.data["balance"] -= amount
self.save()
print(f"💸 Spent {amount} AITBC")
print(f" Remaining: {self.data['balance']} AITBC")
return True
def show_balance(self):
"""Show wallet balance"""
print(f"💳 Wallet Address: {self.data['address']}")
print(f"💰 Balance: {self.data['balance']} AITBC")
print(f"📊 Total Transactions: {len(self.data['transactions'])}")
def show_history(self, limit: int = 10):
"""Show transaction history"""
transactions = self.data["transactions"][-limit:]
if not transactions:
print("📭 No transactions yet")
return
print(f"📜 Recent Transactions (last {limit}):")
print("-" * 60)
for tx in reversed(transactions):
symbol = "💰" if tx["type"] == "earn" else "💸"
print(f"{symbol} {tx['amount']:+8.2f} AITBC | {tx.get('description', 'N/A')}")
print(f" 📅 {tx['timestamp']}")
if "job_id" in tx:
print(f" 🆔 Job: {tx['job_id']}")
print()
def main():
parser = argparse.ArgumentParser(description="AITBC Wallet CLI")
parser.add_argument("--wallet", help="Wallet file path")
subparsers = parser.add_subparsers(dest="command", help="Commands")
# Balance command
balance_parser = subparsers.add_parser("balance", help="Show balance")
# History command
history_parser = subparsers.add_parser("history", help="Show transaction history")
history_parser.add_argument("--limit", type=int, default=10, help="Number of transactions")
# Earn command
earn_parser = subparsers.add_parser("earn", help="Add earnings")
earn_parser.add_argument("amount", type=float, help="Amount earned")
earn_parser.add_argument("--job", help="Job ID")
earn_parser.add_argument("--desc", help="Description")
# Spend command
spend_parser = subparsers.add_parser("spend", help="Spend AITBC")
spend_parser.add_argument("amount", type=float, help="Amount to spend")
spend_parser.add_argument("description", help="What you're spending on")
# Address command
address_parser = subparsers.add_parser("address", help="Show wallet address")
args = parser.parse_args()
if not args.command:
parser.print_help()
return
wallet = AITBCWallet(args.wallet)
if args.command == "balance":
wallet.show_balance()
elif args.command == "history":
wallet.show_history(args.limit)
elif args.command == "earn":
wallet.add_earnings(args.amount, args.job or "unknown", args.desc or "")
elif args.command == "spend":
wallet.spend(args.amount, args.description)
elif args.command == "address":
print(f"💳 Wallet Address: {wallet.data['address']}")
if __name__ == "__main__":
main()