Files
aitbc/cli/commands/plugin_marketplace.py
aitbc d26e6d3772
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Successful in 22s
Blockchain Synchronization Verification / sync-verification (push) Successful in 3s
CLI Tests / test-cli (push) Failing after 13s
Cross-Chain Functionality Tests / test-cross-chain-sync (push) Failing after 3s
Cross-Chain Functionality Tests / test-cross-chain-transactions (push) Successful in 3s
Cross-Chain Functionality Tests / test-cross-chain-bridge (push) Has been skipped
Cross-Chain Functionality Tests / test-multi-chain-consensus (push) Failing after 3s
Cross-Chain Functionality Tests / aggregate-results (push) Has been skipped
Cross-Node Transaction Testing / transaction-test (push) Successful in 2s
Deploy to Testnet / deploy-testnet (push) Successful in 1m34s
Documentation Validation / validate-docs (push) Failing after 10s
Documentation Validation / validate-policies-strict (push) Successful in 3s
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
Integration Tests / test-service-integration (push) Successful in 2m42s
Multi-Chain Island Architecture Tests / test-multi-chain-island (push) Successful in 3s
Multi-Node Blockchain Health Monitoring / health-check (push) Successful in 5s
P2P Network Verification / p2p-verification (push) Successful in 3s
Package Tests / Python package - aitbc-agent-sdk (push) Failing after 33s
Package Tests / Python package - aitbc-core (push) Successful in 17s
Package Tests / Python package - aitbc-crypto (push) Successful in 11s
Security Scanning / security-scan (push) Has been cancelled
Package Tests / Python package - aitbc-sdk (push) Successful in 13s
Package Tests / JavaScript package - aitbc-sdk-js (push) Successful in 9s
Package Tests / JavaScript package - aitbc-token (push) Successful in 17s
Staking Tests / test-staking-service (push) Failing after 6s
Staking Tests / test-staking-integration (push) Has been skipped
Staking Tests / test-staking-contract (push) Has been skipped
Staking Tests / run-staking-test-runner (push) Has been skipped
fix: replace datetime.UTC with timezone.utc for Python 3.12+ compatibility
2026-05-09 12:03:26 +02:00

580 lines
25 KiB
Python
Executable File

"""
Plugin Marketplace CLI Commands for AITBC
Commands for browsing, purchasing, and managing plugins from the marketplace
"""
import click
import json
import requests
from datetime import datetime, timezone
from typing import Dict, Any, List, Optional
@click.group()
def plugin_marketplace():
"""Plugin marketplace commands"""
pass
@plugin_marketplace.command()
@click.option('--category', help='Filter by category')
@click.option('--price-min', type=float, help='Minimum price filter')
@click.option('--price-max', type=float, help='Maximum price filter')
@click.option('--rating-min', type=float, help='Minimum rating filter')
@click.option('--sort', default='popularity', help='Sort by (popularity, rating, price, newest)')
@click.option('--limit', type=int, default=20, help='Number of results')
@click.option('--test-mode', is_flag=True, help='Run in test mode')
def browse(category, price_min, price_max, rating_min, sort, limit, test_mode):
"""Browse plugins in the marketplace"""
try:
params = {
"limit": limit,
"sort": sort
}
if category:
params["category"] = category
if price_min is not None:
params["price_min"] = price_min
if price_max is not None:
params["price_max"] = price_max
if rating_min is not None:
params["rating_min"] = rating_min
if test_mode:
# Mock marketplace data
mock_plugins = [
{
"plugin_id": "trading-bot",
"name": "Advanced Trading Bot",
"version": "1.0.0",
"description": "Automated trading bot with advanced algorithms",
"author": "AITBC Team",
"category": "trading",
"price": 99.99,
"rating": 4.5,
"reviews_count": 42,
"downloads": 1250,
"featured": True,
"tags": ["trading", "automation", "bot"],
"preview_image": "https://marketplace.aitbc.dev/plugins/trading-bot/preview.png"
},
{
"plugin_id": "oracle-feed",
"name": "Oracle Price Feed",
"version": "2.1.0",
"description": "Real-time price oracle integration",
"author": "Oracle Developer",
"category": "oracle",
"price": 49.99,
"rating": 4.8,
"reviews_count": 28,
"downloads": 890,
"featured": True,
"tags": ["oracle", "price", "feed"],
"preview_image": "https://marketplace.aitbc.dev/plugins/oracle-feed/preview.png"
},
{
"plugin_id": "security-scanner",
"name": "Security Scanner Pro",
"version": "3.0.0",
"description": "Advanced security scanning and vulnerability detection",
"author": "Security Labs",
"category": "security",
"price": 199.99,
"rating": 4.7,
"reviews_count": 15,
"downloads": 567,
"featured": False,
"tags": ["security", "scanning", "vulnerability"],
"preview_image": "https://marketplace.aitbc.dev/plugins/security-scanner/preview.png"
}
]
click.echo("🛒 Plugin Marketplace:")
click.echo("=" * 60)
for plugin in mock_plugins[:limit]:
featured_badge = "" if plugin.get('featured') else ""
click.echo(f"{featured_badge} {plugin['name']} (v{plugin['version']})")
click.echo(f" 💰 Price: ${plugin['price']}")
click.echo(f" ⭐ Rating: {plugin['rating']}/5.0 ({plugin['reviews_count']} reviews)")
click.echo(f" 📥 Downloads: {plugin['downloads']}")
click.echo(f" 📂 Category: {plugin['category']}")
click.echo(f" 👤 Author: {plugin['author']}")
click.echo(f" 📝 {plugin['description'][:60]}...")
click.echo("")
return
# Fetch from marketplace service
config = get_config()
response = requests.get(
f"{config.coordinator_url}/api/v1/marketplace/browse",
params=params,
headers={"Authorization": f"Bearer {config.api_key}"},
timeout=30
)
if response.status_code == 200:
result = response.json()
plugins = result.get("plugins", [])
click.echo("🛒 Plugin Marketplace:")
click.echo("=" * 60)
for plugin in plugins:
featured_badge = "" if plugin.get('featured') else ""
click.echo(f"{featured_badge} {plugin['name']} (v{plugin['version']})")
click.echo(f" 💰 Price: ${plugin.get('price', 0.0)}")
click.echo(f" ⭐ Rating: {plugin.get('rating', 0)}/5.0 ({plugin.get('reviews_count', 0)} reviews)")
click.echo(f" 📥 Downloads: {plugin.get('downloads', 0)}")
click.echo(f" 📂 Category: {plugin.get('category', 'N/A')}")
click.echo(f" 👤 Author: {plugin.get('author', 'N/A')}")
click.echo(f" 📝 {plugin['description'][:60]}...")
click.echo("")
else:
click.echo(f"❌ Failed to browse marketplace: {response.text}", err=True)
except Exception as e:
click.echo(f"❌ Error browsing marketplace: {str(e)}", err=True)
@plugin_marketplace.command()
@click.argument('plugin_id')
@click.option('--test-mode', is_flag=True, help='Run in test mode')
def details(plugin_id, test_mode):
"""Get detailed information about a marketplace plugin"""
try:
if test_mode:
# Mock plugin details
mock_plugin = {
"plugin_id": plugin_id,
"name": "Advanced Trading Bot",
"version": "1.0.0",
"description": "Automated trading bot with advanced algorithms and machine learning capabilities. Features include real-time market analysis, automated trading strategies, risk management, and portfolio optimization.",
"author": "AITBC Team",
"category": "trading",
"price": 99.99,
"rating": 4.5,
"reviews_count": 42,
"downloads": 1250,
"featured": True,
"tags": ["trading", "automation", "bot", "ml", "risk-management"],
"repository": "https://github.com/aitbc/trading-bot",
"homepage": "https://aitbc.dev/plugins/trading-bot",
"license": "MIT",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-03-01T14:20:00Z",
"preview_image": "https://marketplace.aitbc.dev/plugins/trading-bot/preview.png",
"screenshots": [
"https://marketplace.aitbc.dev/plugins/trading-bot/screenshot1.png",
"https://marketplace.aitbc.dev/plugins/trading-bot/screenshot2.png"
],
"documentation": "https://docs.aitbc.dev/plugins/trading-bot",
"support": "support@aitbc.dev",
"compatibility": {
"aitbc_version": ">=1.0.0",
"python_version": ">=3.8",
"dependencies": ["exchange-integration", "oracle-feed"]
},
"pricing": {
"type": "one-time",
"amount": 99.99,
"currency": "USD",
"includes_support": True,
"includes_updates": True
},
"reviews": [
{
"id": 1,
"user": "trader123",
"rating": 5,
"title": "Excellent trading bot!",
"comment": "This bot has significantly improved my trading performance. Highly recommended!",
"date": "2024-02-15T10:30:00Z"
},
{
"id": 2,
"user": "alice_trader",
"rating": 4,
"title": "Good but needs improvements",
"comment": "Great features but the UI could be more intuitive.",
"date": "2024-02-10T14:20:00Z"
}
]
}
click.echo(f"🛒 Plugin Details: {mock_plugin['name']}")
click.echo("=" * 60)
click.echo(f"📦 Version: {mock_plugin['version']}")
click.echo(f"👤 Author: {mock_plugin['author']}")
click.echo(f"📂 Category: {mock_plugin['category']}")
click.echo(f"💰 Price: ${mock_plugin['price']} {mock_plugin['pricing']['currency']}")
click.echo(f"⭐ Rating: {mock_plugin['rating']}/5.0 ({mock_plugin['reviews_count']} reviews)")
click.echo(f"📥 Downloads: {mock_plugin['downloads']}")
click.echo(f"🏷️ Tags: {', '.join(mock_plugin['tags'])}")
click.echo(f"📄 License: {mock_plugin['license']}")
click.echo(f"📅 Created: {mock_plugin['created_at']}")
click.echo(f"🔄 Updated: {mock_plugin['updated_at']}")
click.echo("")
click.echo("📝 Description:")
click.echo(f" {mock_plugin['description']}")
click.echo("")
click.echo("💰 Pricing:")
click.echo(f" Type: {mock_plugin['pricing']['type']}")
click.echo(f" Amount: ${mock_plugin['pricing']['amount']} {mock_plugin['pricing']['currency']}")
click.echo(f" Includes Support: {'Yes' if mock_plugin['pricing']['includes_support'] else 'No'}")
click.echo(f" Includes Updates: {'Yes' if mock_plugin['pricing']['includes_updates'] else 'No'}")
click.echo("")
click.echo("🔗 Links:")
click.echo(f" 📦 Repository: {mock_plugin['repository']}")
click.echo(f" 🌐 Homepage: {mock_plugin['homepage']}")
click.echo(f" 📚 Documentation: {mock_plugin['documentation']}")
click.echo(f" 📧 Support: {mock_plugin['support']}")
click.echo("")
click.echo("🔧 Compatibility:")
click.echo(f" AITBC Version: {mock_plugin['compatibility']['aitbc_version']}")
click.echo(f" Python Version: {mock_plugin['compatibility']['python_version']}")
click.echo(f" Dependencies: {', '.join(mock_plugin['compatibility']['dependencies'])}")
click.echo("")
click.echo("⭐ Recent Reviews:")
for review in mock_plugin['reviews'][:3]:
stars = "" * review['rating']
click.echo(f" {stars} {review['title']}")
click.echo(f" 👤 {review['user']} - {review['date']}")
click.echo(f" 📝 {review['comment']}")
click.echo("")
return
# Fetch from marketplace service
config = get_config()
response = requests.get(
f"{config.coordinator_url}/api/v1/marketplace/plugins/{plugin_id}",
headers={"Authorization": f"Bearer {config.api_key}"},
timeout=30
)
if response.status_code == 200:
plugin = response.json()
click.echo(f"🛒 Plugin Details: {plugin['name']}")
click.echo("=" * 60)
click.echo(f"📦 Version: {plugin['version']}")
click.echo(f"👤 Author: {plugin['author']}")
click.echo(f"📂 Category: {plugin['category']}")
click.echo(f"💰 Price: ${plugin.get('price', 0.0)}")
click.echo(f"⭐ Rating: {plugin.get('rating', 0)}/5.0 ({plugin.get('reviews_count', 0)} reviews)")
click.echo(f"📥 Downloads: {plugin.get('downloads', 0)}")
click.echo(f"🏷️ Tags: {', '.join(plugin.get('tags', []))}")
click.echo(f"📄 License: {plugin.get('license', 'N/A')}")
click.echo(f"📅 Created: {plugin['created_at']}")
click.echo(f"🔄 Updated: {plugin['updated_at']}")
click.echo("")
click.echo("📝 Description:")
click.echo(f" {plugin['description']}")
else:
click.echo(f"❌ Plugin not found: {response.text}", err=True)
except Exception as e:
click.echo(f"❌ Error getting plugin details: {str(e)}", err=True)
@plugin_marketplace.command()
@click.argument('plugin_id')
@click.option('--test-mode', is_flag=True, help='Run in test mode')
def purchase(plugin_id, test_mode):
"""Purchase a plugin from the marketplace"""
try:
if test_mode:
click.echo(f"💰 Purchase initiated (test mode)")
click.echo(f"📦 Plugin ID: {plugin_id}")
click.echo(f"💳 Payment method: Test Card")
click.echo(f"💰 Amount: $99.99")
click.echo(f"✅ Purchase completed successfully")
click.echo(f"📧 License key: TEST-KEY-{plugin_id.upper()}")
click.echo(f"📥 Download link: https://marketplace.aitbc.dev/download/{plugin_id}")
return
# Get plugin details first
config = get_config()
response = requests.get(
f"{config.coordinator_url}/api/v1/marketplace/plugins/{plugin_id}",
headers={"Authorization": f"Bearer {config.api_key}"},
timeout=30
)
if response.status_code != 200:
click.echo(f"❌ Plugin not found: {response.text}", err=True)
return
plugin = response.json()
# Create purchase order
purchase_data = {
"plugin_id": plugin_id,
"price": plugin.get('price', 0.0),
"currency": plugin.get('pricing', {}).get('currency', 'USD'),
"payment_method": "credit_card",
"purchased_at": datetime.now(timezone.utc).isoformat()
}
response = requests.post(
f"{config.coordinator_url}/api/v1/marketplace/purchase",
json=purchase_data,
headers={"Authorization": f"Bearer {config.api_key}"},
timeout=30
)
if response.status_code == 201:
result = response.json()
click.echo(f"💰 Purchase completed successfully!")
click.echo(f"📦 Plugin: {result['plugin_name']}")
click.echo(f"💳 Amount: ${result['amount']} {result['currency']}")
click.echo(f"📧 License Key: {result['license_key']}")
click.echo(f"📥 Download: {result['download_url']}")
click.echo(f"📧 Support: {result['support_email']}")
else:
click.echo(f"❌ Purchase failed: {response.text}", err=True)
except Exception as e:
click.echo(f"❌ Error purchasing plugin: {str(e)}", err=True)
@plugin_marketplace.command()
@click.option('--category', help='Filter by category')
@click.option('--price-min', type=float, help='Minimum price filter')
@click.option('--price-max', type=float, help='Maximum price filter')
@click.option('--rating-min', type=float, help='Minimum rating filter')
@click.option('--limit', type=int, default=10, help='Number of results')
@click.option('--test-mode', is_flag=True, help='Run in test mode')
def featured(category, price_min, price_max, rating_min, limit, test_mode):
"""Browse featured plugins"""
try:
params = {
"featured": True,
"limit": limit
}
if category:
params["category"] = category
if price_min is not None:
params["price_min"] = price_min
if price_max is not None:
params["price_max"] = price_max
if rating_min is not None:
params["rating_min"] = rating_min
if test_mode:
# Mock featured plugins
mock_featured = [
{
"plugin_id": "trading-bot",
"name": "Advanced Trading Bot",
"version": "1.0.0",
"description": "Automated trading bot with advanced algorithms",
"author": "AITBC Team",
"category": "trading",
"price": 99.99,
"rating": 4.5,
"downloads": 1250,
"featured": True,
"featured_reason": "Top-rated trading automation tool"
},
{
"plugin_id": "oracle-feed",
"name": "Oracle Price Feed",
"version": "2.1.0",
"description": "Real-time price oracle integration",
"author": "Oracle Developer",
"category": "oracle",
"price": 49.99,
"rating": 4.8,
"downloads": 890,
"featured": True,
"featured_reason": "Most reliable oracle integration"
}
]
click.echo("⭐ Featured Plugins:")
click.echo("=" * 60)
for plugin in mock_featured[:limit]:
click.echo(f"{plugin['name']} (v{plugin['version']})")
click.echo(f" 💰 Price: ${plugin['price']}")
click.echo(f" ⭐ Rating: {plugin['rating']}/5.0")
click.echo(f" 📥 Downloads: {plugin['downloads']}")
click.echo(f" 📂 Category: {plugin['category']}")
click.echo(f" 👤 Author: {plugin['author']}")
click.echo(f" 🏆 {plugin['featured_reason']}")
click.echo("")
return
# Fetch from marketplace service
config = get_config()
response = requests.get(
f"{config.coordinator_url}/api/v1/marketplace/featured",
params=params,
headers={"Authorization": f"Bearer {config.api_key}"},
timeout=30
)
if response.status_code == 200:
result = response.json()
plugins = result.get("plugins", [])
click.echo("⭐ Featured Plugins:")
click.echo("=" * 60)
for plugin in plugins:
click.echo(f"{plugin['name']} (v{plugin['version']})")
click.echo(f" 💰 Price: ${plugin.get('price', 0.0)}")
click.echo(f" ⭐ Rating: {plugin.get('rating', 0)}/5.0")
click.echo(f" 📥 Downloads: {plugin.get('downloads', 0)}")
click.echo(f" 📂 Category: {plugin.get('category', 'N/A')}")
click.echo(f" 👤 Author: {plugin.get('author', 'N/A')}")
click.echo(f" 🏆 {plugin.get('featured_reason', 'Featured plugin')}")
click.echo("")
else:
click.echo(f"❌ Failed to get featured plugins: {response.text}", err=True)
except Exception as e:
click.echo(f"❌ Error getting featured plugins: {str(e)}", err=True)
@plugin_marketplace.command()
@click.option('--test-mode', is_flag=True, help='Run in test mode')
def my_purchases(test_mode):
"""View your purchased plugins"""
try:
if test_mode:
# Mock purchase history
mock_purchases = [
{
"plugin_id": "trading-bot",
"name": "Advanced Trading Bot",
"version": "1.0.0",
"purchase_date": "2024-02-15T10:30:00Z",
"price": 99.99,
"license_key": "TEST-KEY-TRADING-BOT",
"status": "active",
"download_count": 5
},
{
"plugin_id": "oracle-feed",
"name": "Oracle Price Feed",
"version": "2.1.0",
"purchase_date": "2024-02-10T14:20:00Z",
"price": 49.99,
"license_key": "TEST-KEY-ORACLE-FEED",
"status": "active",
"download_count": 3
}
]
click.echo("📋 Your Purchased Plugins:")
click.echo("=" * 60)
for purchase in mock_purchases:
status_icon = "" if purchase['status'] == 'active' else ""
click.echo(f"{status_icon} {purchase['name']} (v{purchase['version']})")
click.echo(f" 📅 Purchased: {purchase['purchase_date']}")
click.echo(f" 💰 Price: ${purchase['price']}")
click.echo(f" 📧 License Key: {purchase['license_key']}")
click.echo(f" 📥 Downloads: {purchase['download_count']}")
click.echo("")
return
# Get user's purchases
config = get_config()
response = requests.get(
f"{config.coordinator_url}/api/v1/marketplace/purchases",
headers={"Authorization": f"Bearer {config.api_key}"},
timeout=30
)
if response.status_code == 200:
result = response.json()
purchases = result.get("purchases", [])
click.echo("📋 Your Purchased Plugins:")
click.echo("=" * 60)
for purchase in purchases:
status_icon = "" if purchase['status'] == 'active' else ""
click.echo(f"{status_icon} {purchase['plugin_name']} (v{purchase['version']})")
click.echo(f" 📅 Purchased: {purchase['purchase_date']}")
click.echo(f" 💰 Price: ${purchase['price']} {purchase['currency']}")
click.echo(f" 📧 License Key: {purchase['license_key']}")
click.echo(f" 📥 Downloads: {purchase.get('download_count', 0)}")
click.echo("")
else:
click.echo(f"❌ Failed to get purchases: {response.text}", err=True)
except Exception as e:
click.echo(f"❌ Error getting purchases: {str(e)}", err=True)
@plugin_marketplace.command()
@click.argument('plugin_id')
@click.option('--license-key', help='License key for the plugin')
@click.option('--test-mode', is_flag=True, help='Run in test mode')
def download(plugin_id, license_key, test_mode):
"""Download a purchased plugin"""
try:
if test_mode:
click.echo(f"📥 Download started (test mode)")
click.echo(f"📦 Plugin ID: {plugin_id}")
click.echo(f"📧 License Key: {license_key or 'TEST-KEY'}")
click.echo(f"✅ Download completed successfully")
click.echo(f"📁 Download location: /tmp/{plugin_id}.zip")
return
# Validate license key
config = get_config()
response = requests.post(
f"{config.coordinator_url}/api/v1/marketplace/download/{plugin_id}",
json={"license_key": license_key},
headers={"Authorization": f"Bearer {config.api_key}"},
timeout=30
)
if response.status_code == 200:
result = response.json()
click.echo(f"📥 Download started!")
click.echo(f"📦 Plugin: {result['plugin_name']}")
click.echo(f"📁 Download URL: {result['download_url']}")
click.echo(f"📦 File Size: {result['file_size_mb']} MB")
click.echo(f"🔑 Checksum: {result['checksum']}")
# Download the file
download_response = requests.get(result['download_url'], timeout=60)
if download_response.status_code == 200:
filename = f"{plugin_id}.zip"
with open(filename, 'wb') as f:
f.write(download_response.content)
click.echo(f"✅ Download completed!")
click.echo(f"📁 Saved as: {filename}")
click.echo(f"📁 Size: {len(download_response.content) / 1024 / 1024:.1f} MB")
else:
click.echo(f"❌ Download failed: {download_response.text}", err=True)
else:
click.echo(f"❌ Download failed: {response.text}", err=True)
except Exception as e:
click.echo(f"❌ Error downloading plugin: {str(e)}", err=True)
# Helper function to get config
def get_config():
"""Get CLI configuration"""
try:
from config import get_config
return get_config()
except ImportError:
# Fallback for testing
from types import SimpleNamespace
return SimpleNamespace(
coordinator_url="http://localhost:8014",
api_key="test-api-key"
)
if __name__ == "__main__":
plugin_marketplace()