zizo007's picture
حوله الى تطبيق سطح مكتب بواجهة مستخدم سهلة
d5fc852 verified
Raw
History Blame Contribute Delete
58.8 kB
<!DOCTYPE html>
<html lang="en" class="scroll-smooth">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SpotSync Alpha - Trading Replication Engine</title>
<link rel="icon" type="image/x-icon" href="assets/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="style.css">
<script>
// Electron IPC communication
const { ipcRenderer } = require('electron');
function minimizeWindow() {
ipcRenderer.send('window-minimize');
}
function maximizeWindow() {
ipcRenderer.send('window-maximize');
}
function closeWindow() {
ipcRenderer.send('window-close');
}
function hideWindow() {
ipcRenderer.send('window-hide');
}
</script>
</head>
<body class="bg-gradient-to-br from-gray-900 via-gray-800 to-black text-gray-100 h-screen overflow-hidden">
<!-- Custom Title Bar for Desktop App -->
<div class="title-bar bg-gray-900/80 backdrop-blur-md border-b border-gray-800 flex items-center justify-between px-4 py-2 select-none draggable-region">
<div class="flex items-center gap-3">
<div class="w-8 h-8 rounded-lg bg-gradient-to-r from-cyan-500 to-blue-500 flex items-center justify-center">
<i data-feather="zap" class="w-4 h-4 text-white"></i>
</div>
<span class="font-semibold text-sm bg-clip-text text-transparent bg-gradient-to-r from-cyan-300 to-blue-300">
SpotSync Alpha
</span>
<span class="text-xs text-gray-400 px-2 py-1 bg-gray-800 rounded">v1.0.0</span>
</div>
<div class="flex items-center gap-2 non-draggable">
<button onclick="hideWindow()" class="w-8 h-8 flex items-center justify-center hover:bg-gray-700 rounded transition-colors" title="Minimize to Tray">
<i data-feather="minus" class="w-4 h-4"></i>
</button>
<button onclick="maximizeWindow()" class="w-8 h-8 flex items-center justify-center hover:bg-gray-700 rounded transition-colors" title="Maximize">
<i data-feather="square" class="w-3 h-3"></i>
</button>
<button onclick="closeWindow()" class="w-8 h-8 flex items-center justify-center hover:bg-red-500 rounded transition-colors" title="Close">
<i data-feather="x" class="w-4 h-4"></i>
</button>
</div>
</div>
<!-- Main App Container -->
<div class="flex h-[calc(100vh-40px)]">
<!-- Sidebar Navigation -->
<div class="w-64 bg-gray-900/50 border-r border-gray-800 flex flex-col">
<!-- Navigation Links -->
<div class="p-4 space-y-2">
<a href="#" class="nav-item active">
<i data-feather="home" class="w-4 h-4"></i>
<span>Dashboard</span>
</a>
<a href="#engine" class="nav-item">
<i data-feather="cpu" class="w-4 h-4"></i>
<span>Trading Engine</span>
</a>
<a href="#followers" class="nav-item">
<i data-feather="users" class="w-4 h-4"></i>
<span>Followers</span>
</a>
<a href="#logs" class="nav-item">
<i data-feather="file-text" class="w-4 h-4"></i>
<span>Trade Logs</span>
</a>
<a href="#settings" class="nav-item">
<i data-feather="settings" class="w-4 h-4"></i>
<span>Settings</span>
</a>
</div>
<!-- Engine Status -->
<div class="mt-auto p-4 border-t border-gray-800">
<div class="flex items-center justify-between mb-2">
<span class="text-sm text-gray-400">Engine Status</span>
<div class="relative">
<div class="w-3 h-3 rounded-full bg-green-500 animate-pulse"></div>
</div>
</div>
<button class="w-full py-2 px-3 bg-gradient-to-r from-cyan-600 to-blue-600 hover:from-cyan-500 hover:to-blue-500 rounded-lg font-medium text-sm transition-all duration-300 flex items-center justify-center gap-2">
<i data-feather="pause" class="w-3 h-3"></i>
Pause Engine
</button>
</div>
</div>
<!-- Main Content Area -->
<div class="flex-1 overflow-y-auto">
<!-- Main Content -->
<main class="container mx-auto px-6 py-6 max-w-7xl">
<!-- Quick Stats Bar -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
<div class="stat-card">
<div class="flex items-center justify-between">
<div>
<p class="text-sm text-gray-400">Uptime</p>
<p class="text-2xl font-bold" id="metric-uptime">99.8%</p>
</div>
<i data-feather="activity" class="w-8 h-8 text-green-400"></i>
</div>
</div>
<div class="stat-card">
<div class="flex items-center justify-between">
<div>
<p class="text-sm text-gray-400">Active Followers</p>
<p class="text-2xl font-bold" id="metric-followers">3</p>
</div>
<i data-feather="users" class="w-8 h-8 text-blue-400"></i>
</div>
</div>
<div class="stat-card">
<div class="flex items-center justify-between">
<div>
<p class="text-sm text-gray-400">Trades Today</p>
<p class="text-2xl font-bold" id="metric-trades">42</p>
</div>
<i data-feather="trending-up" class="w-8 h-8 text-purple-400"></i>
</div>
</div>
<div class="stat-card">
<div class="flex items-center justify-between">
<div>
<p class="text-sm text-gray-400">Success Rate</p>
<p class="text-2xl font-bold" id="metric-success">98.5%</p>
</div>
<i data-feather="check-circle" class="w-8 h-8 text-cyan-400"></i>
</div>
</div>
</div>
<!-- Architecture Overview -->
<section class="mb-16">
<h2 class="text-3xl font-bold mb-8 text-center">Architectural Principles</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-6 rounded-xl border border-gray-700 hover:border-cyan-500/50 transition-all duration-300">
<div class="w-12 h-12 rounded-lg bg-gradient-to-r from-cyan-700/30 to-cyan-900/30 flex items-center justify-center mb-4">
<i data-feather="cpu" class="w-6 h-6 text-cyan-300"></i>
</div>
<h3 class="text-xl font-bold mb-2">Modularity & Separation</h3>
<p class="text-gray-300">Distinct logical components with clear boundaries and responsibilities.</p>
</div>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-6 rounded-xl border border-gray-700 hover:border-blue-500/50 transition-all duration-300">
<div class="w-12 h-12 rounded-lg bg-gradient-to-r from-blue-700/30 to-blue-900/30 flex items-center justify-center mb-4">
<i data-feather="refresh-cw" class="w-6 h-6 text-blue-300"></i>
</div>
<h3 class="text-xl font-bold mb-2">Idempotency</h3>
<p class="text-gray-300">Restart-safe design prevents trade duplication through meticulous state tracking.</p>
</div>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-6 rounded-xl border border-gray-700 hover:border-purple-500/50 transition-all duration-300">
<div class="w-12 h-12 rounded-lg bg-gradient-to-r from-purple-700/30 to-purple-900/30 flex items-center justify-center mb-4">
<i data-feather="database" class="w-6 h-6 text-purple-300"></i>
</div>
<h3 class="text-xl font-bold mb-2">Persistence First</h3>
<p class="text-gray-300">Atomic commits to SQLite before any subsequent action ensures data integrity.</p>
</div>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-6 rounded-xl border border-gray-700 hover:border-green-500/50 transition-all duration-300">
<div class="w-12 h-12 rounded-lg bg-gradient-to-r from-green-700/30 to-green-900/30 flex items-center justify-center mb-4">
<i data-feather="shield" class="w-6 h-6 text-green-300"></i>
</div>
<h3 class="text-xl font-bold mb-2">Security by Design</h3>
<p class="text-gray-300">API keys encrypted at rest with verification of limited permissions.</p>
</div>
</div>
</section>
<!-- Code Preview Section -->
<section id="engine" class="mb-16">
<h2 class="text-3xl font-bold mb-8 text-center">Core Implementation</h2>
<div class="bg-gradient-to-br from-gray-900 to-black rounded-2xl p-1 shadow-2xl">
<div class="bg-gradient-to-br from-gray-800 to-gray-900 rounded-2xl p-6">
<div class="flex items-center justify-between mb-6">
<div class="flex items-center gap-3">
<div class="w-3 h-3 rounded-full bg-red-500"></div>
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
<div class="w-3 h-3 rounded-full bg-green-500"></div>
<span class="text-sm font-mono font-medium ml-2">spot_copy_trade/</span>
</div>
<div class="flex gap-2">
<button class="text-sm px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded transition-colors duration-200" onclick="copyCode()">
<i data-feather="copy" class="w-3 h-3 inline mr-1"></i> Copy All
</button>
</div>
</div>
<!-- Code Tabs -->
<div class="flex overflow-x-auto mb-4 border-b border-gray-700">
<button class="px-4 py-2 font-medium text-sm border-b-2 border-cyan-500 text-cyan-300 whitespace-nowrap" onclick="showTab('main')">
<i data-feather="play" class="w-3 h-3 inline mr-2"></i>main.py
</button>
<button class="px-4 py-2 font-medium text-sm text-gray-400 hover:text-gray-200 whitespace-nowrap" onclick="showTab('watcher')">
<i data-feather="eye" class="w-3 h-3 inline mr-2"></i>trade_watcher.py
</button>
<button class="px-4 py-2 font-medium text-sm text-gray-400 hover:text-gray-200 whitespace-nowrap" onclick="showTab('executor')">
<i data-feather="arrow-right-circle" class="w-3 h-3 inline mr-2"></i>trade_executor.py
</button>
<button class="px-4 py-2 font-medium text-sm text-gray-400 hover:text-gray-200 whitespace-nowrap" onclick="showTab('models')">
<i data-feather="database" class="w-3 h-3 inline mr-2"></i>models.py
</button>
<button class="px-4 py-2 font-medium text-sm text-gray-400 hover:text-gray-200 whitespace-nowrap" onclick="showTab('security')">
<i data-feather="lock" class="w-3 h-3 inline mr-2"></i>encryption.py
</button>
</div>
<!-- Code Content -->
<div id="code-container" class="overflow-hidden">
<pre id="main-tab" class="font-mono text-sm overflow-x-auto whitespace-pre p-4 bg-gray-900/50 rounded-lg">
<span class="text-green-400">### File: main.py</span>
<span class="text-cyan-400"><b>#!/usr/bin/env python3</b></span>
<span class="text-gray-500">"""Main entry point for SpotSync Alpha - Master-Follower Replication Engine"""</span>
<span class="text-purple-400">import</span> logging
<span class="text-purple-400">import</span> signal
<span class="text-purple-400">import</span> sys
<span class="text-purple-400">import</span> time
<span class="text-purple-400">from</span> datetime <span class="text-purple-400">import</span> datetime
<span class="text-purple-400">from</span> typing <span class="text-purple-400">import</span> Dict, Optional
<span class="text-purple-400">from</span> database.models <span class="text-purple-400">import</span> init_db, SessionLocal
<span class="text-purple-400">from</span> core.trade_watcher <span class="text-purple-400">import</span> TradeWatcher
<span class="text-purple-400">from</span> core.trade_executor <span class="text-purple-400">import</span> TradeExecutor
<span class="text-purple-400">from</span> config.settings <span class="text-purple-400">import</span> MASTER_API_CONFIG
<span class="text-cyan-400">class</span> <span class="text-yellow-400">TradingEngine</span>:
<span class="text-gray-500">"""Orchestrates the complete trade replication lifecycle"""</span>
<span class="text-purple-400">def</span> <span class="text-yellow-400">__init__</span>(<span class="text-blue-400">self</span>, poll_interval: <span class="text-blue-400">int</span> = 30):
<span class="text-blue-400">self</span>.running = <span class="text-blue-400">False</span>
<span class="text-blue-400">self</span>.poll_interval = poll_interval
<span class="text-blue-400">self</span>.logger = logging.getLogger(__name__)
<span class="text-green-400"># Initialize components</span>
init_db()
<span class="text-blue-400">self</span>.trade_watcher = TradeWatcher(MASTER_API_CONFIG)
<span class="text-blue-400">self</span>.trade_executor = TradeExecutor()
<span class="text-purple-400">def</span> <span class="text-yellow-400">start</span>(<span class="text-blue-400">self</span>):
<span class="text-gray-500">"""Start the main engine loop"""</span>
<span class="text-blue-400">self</span>.running = <span class="text-blue-400">True</span>
<span class="text-blue-400">self</span>.logger.info(<span class="text-pink-400">"🚀 SpotSync Alpha Engine starting..."</span>)
<span class="text-blue-400">self</span>.setup_signal_handlers()
<span class="text-green-400"># Main execution loop</span>
<span class="text-purple-400">while</span> <span class="text-blue-400">self</span>.running:
<span class="text-purple-400">try</span>:
<span class="text-green-400"># Poll for new trades from master</span>
new_trades = <span class="text-blue-400">self</span>.trade_watcher.poll_for_new_trades()
<span class="text-purple-400">if</span> new_trades:
<span class="text-blue-400">self</span>.logger.info(f<span class="text-pink-400">"📊 Detected {len(new_trades)} new master trades to replicate"</span>)
<span class="text-green-400"># Execute each trade on all active followers</span>
<span class="text-purple-400">for</span> trade <span class="text-purple-400">in</span> new_trades:
<span class="text-blue-400">self</span>.trade_executor.execute_trade_on_followers(trade)
<span class="text-green-400"># Sleep until next poll</span>
time.sleep(<span class="text-blue-400">self</span>.poll_interval)
<span class="text-purple-400">except</span> KeyboardInterrupt:
<span class="text-blue-400">self</span>.logger.info(<span class="text-pink-400">"⚠️ Shutdown signal received"</span>)
<span class="text-purple-400">break</span>
<span class="text-purple-400">except</span> Exception <span class="text-purple-400">as</span> e:
<span class="text-blue-400">self</span>.logger.error(f<span class="text-pink-400">"❌ Unexpected error in main loop: {e}"</span>, exc_info=<span class="text-blue-400">True</span>)
time.sleep(<span class="text-blue-400">self</span>.poll_interval) <span class="text-green-400"># Don't crash on single error</span>
<span class="text-purple-400">def</span> <span class="text-yellow-400">setup_signal_handlers</span>(<span class="text-blue-400">self</span>):
<span class="text-gray-500">"""Handle graceful shutdown on SIGINT/SIGTERM"""</span>
signal.signal(signal.SIGINT, <span class="text-blue-400">self</span>.shutdown_handler)
signal.signal(signal.SIGTERM, <span class="text-blue-400">self</span>.shutdown_handler)
<span class="text-gray-500"># More code follows...</span>
</pre>
<pre id="watcher-tab" class="font-mono text-sm overflow-x-auto whitespace-pre p-4 bg-gray-900/50 rounded-lg hidden">
<span class="text-green-400">### File: core/trade_watcher.py</span>
<span class="text-cyan-400"><b>#!/usr/bin/env python3</b></span>
<span class="text-gray-500">"""Poll master account for executed trades and filter new ones"""</span>
<span class="text-purple-400">import</span> logging
<span class="text-purple-400">from</span> typing <span class="text-purple-400">import</span> List, Dict, Optional
<span class="text-purple-400">from</span> datetime <span class="text-purple-400">import</span> datetime
<span class="text-purple-400">import</span> requests
<span class="text-purple-400">from</span> sqlalchemy.orm <span class="text-purple-400">import</span> Session
<span class="text-purple-400">from</span> database.models <span class="text-purple-400">import</span> get_session, SystemState
<span class="text-purple-400">from</span> config.settings <span class="text-purple-400">import</span> MASTER_API_CONFIG
<span class="text-cyan-400">class</span> <span class="text-yellow-400">TradeWatcher</span>:
<span class="text-gray-500">"""Monitors master account for new executed trades"""</span>
<span class="text-purple-400">def</span> <span class="text-yellow-400">__init__</span>(<span class="text-blue-400">self</span>, master_config: Dict):
<span class="text-blue-400">self</span>.master_config = master_config
<span class="text-blue-400">self</span>.logger = logging.getLogger(__name__)
<span class="text-blue-400">self</span>.base_url = <span class="text-pink-400">"https://api.binance.com/api/v3"</span>
<span class="text-purple-400">def</span> <span class="text-yellow-400">get_master_trades</span>(<span class="text-blue-400">self</span>) -> <span class="text-blue-400">List</span>[<span class="text-blue-400">Dict</span>]:
<span class="text-gray-500">"""Fetch recent executed trades from master account"""</span>
headers = {
<span class="text-pink-400">'X-MBX-APIKEY'</span>: <span class="text-blue-400">self</span>.master_config[<span class="text-pink-400">'api_key'</span>]
}
params = {
<span class="text-pink-400">'timestamp'</span>: int(datetime.now().timestamp() * 1000),
<span class="text-pink-400">'recvWindow'</span>: 5000
}
<span class="text-purple-400">try</span>:
response = requests.get(
f<span class="text-pink-400">"{self.base_url}/myTrades"</span>,
headers=headers,
params=params
)
response.raise_for_status()
<span class="text-purple-400">return</span> response.json()
<span class="text-purple-400">except</span> requests.RequestException <span class="text-purple-400">as</span> e:
<span class="text-blue-400">self</span>.logger.error(f<span class="text-pink-400">"🔴 Failed to fetch master trades: {e}"</span>)
<span class="text-purple-400">return</span> []
<span class="text-gray-500"># More code follows...</span>
</pre>
<pre id="executor-tab" class="font-mono text-sm overflow-x-auto whitespace-pre p-4 bg-gray-900/50 rounded-lg hidden">
<span class="text-green-400">### File: core/trade_executor.py</span>
<span class="text-cyan-400"><b>#!/usr/bin/env python3</b></span>
<span class="text-gray-500">"""Execute trades on follower accounts with idempotency guarantees"""</span>
<span class="text-purple-400">import</span> logging
<span class="text-purple-400">import</span> hashlib
<span class="text-purple-400">from</span> typing <span class="text-purple-400">import</span> List, Dict, Optional
<span class="text-purple-400">from</span> decimal <span class="text-purple-400">import</span> Decimal
<span class="text-purple-400">import</span> requests
<span class="text-purple-400">from</span> sqlalchemy.orm <span class="text-purple-400">import</span> Session
<span class="text-purple-400">from</span> database.models <span class="text-purple-400">import</span> get_session, Follower, ExecutionLog
<span class="text-purple-400">from</span> security.encryption <span class="text-purple-400">import</span> decrypt_api_key
<span class="text-cyan-400">class</span> <span class="text-yellow-400">TradeExecutor</span>:
<span class="text-gray-500">"""Handles trade execution on all active follower accounts"""</span>
<span class="text-purple-400">def</span> <span class="text-yellow-400">__init__</span>(<span class="text-blue-400">self</span>):
<span class="text-blue-400">self</span>.logger = logging.getLogger(__name__)
<span class="text-blue-400">self</span>.base_url = <span class="text-pink-400">"https://api.binance.com/api/v3"</span>
<span class="text-purple-400">def</span> <span class="text-yellow-400">execute_trade_on_followers</span>(<span class="text-blue-400">self</span>, master_trade: <span class="text-blue-400">Dict</span>):
<span class="text-gray-500">"""Replicate a single master trade to all active followers"""</span>
session = get_session()
<span class="text-green-400"># Get all active followers</span>
followers = session.query(Follower).filter(
Follower.status == <span class="text-pink-400">'ACTIVE'</span>
).all()
<span class="text-purple-400">if</span> <span class="text-purple-400">not</span> followers:
<span class="text-blue-400">self</span>.logger.info(<span class="text-pink-400">"📭 No active followers found for trade execution"</span>)
<span class="text-purple-400">return</span>
<span class="text-green-400"># Execute trade on each follower (idempotently)</span>
<span class="text-purple-400">for</span> follower <span class="text-purple-400">in</span> followers:
self.execute_trade_for_follower(session, follower, master_trade)
session.commit()
<span class="text-gray-500"># More code follows...</span>
</pre>
<pre id="models-tab" class="font-mono text-sm overflow-x-auto whitespace-pre p-4 bg-gray-900/50 rounded-lg hidden">
<span class="text-green-400">### File: database/models.py</span>
<span class="text-cyan-400"><b>#!/usr/bin/env python3</b></span>
<span class="text-gray-500">"""SQLAlchemy models for tracking system state and follower accounts"""</span>
<span class="text-purple-400">from</span> datetime <span class="text-purple-400">import</span> datetime
<span class="text-purple-400">from</span> enum <span class="text-purple-400">import</span> Enum
<span class="text-purple-400">from</span> sqlalchemy <span class="text-purple-400">import</span> (
create_engine, Column, Integer, String,
DateTime, Boolean, Text, Float, JSON,
Enum <span class="text-purple-400">as</span> SQLAlchemyEnum, ForeignKey,
event
)
<span class="text-purple-400">from</span> sqlalchemy.ext.declarative <span class="text-purple-400">import</span> declarative_base
<span class="text-purple-400">from</span> sqlalchemy.orm <span class="text-purple-400">import</span> sessionmaker, Session, relationship
<span class="text-green-400"># Database URL (SQLite for simplicity, production would use PostgreSQL)</span>
DATABASE_URL = <span class="text-pink-400">"sqlite:///./spot_sync.db"</span>
engine = create_engine(
DATABASE_URL,
connect_args={<span class="text-pink-400">"check_same_thread"</span>: <span class="text-blue-400">False</span>},
echo=<span class="text-blue-400">False</span> <span class="text-green-400"># Set to True for debugging SQL</span>
)
SessionLocal = sessionmaker(autocommit=<span class="text-blue-400">False</span>, autoflush=<span class="text-blue-400">False</span>, bind=engine)
Base = declarative_base()
<span class="text-cyan-400">class</span> <span class="text-yellow-400">FollowerStatus</span>(<span class="text-blue-400">str</span>, Enum):
<span class="text-gray-500">"""Valid states for a follower account"""</span>
ACTIVE = <span class="text-pink-400">"ACTIVE"</span>
PAUSED = <span class="text-pink-400">"PAUSED"</span>
DISABLED = <span class="text-pink-400">"DISABLED"</span>
<span class="text-cyan-400">class</span> <span class="text-yellow-400">Follower</span>(<span class="text-blue-400">Base</span>):
<span class="text-gray-500">"""Tracks a follower Binance account"""</span>
__tablename__ = <span class="text-pink-400">"followers"</span>
<span class="text-green-400"># Core fields</span>
id = Column(Integer, primary_key=<span class="text-blue-400">True</span>, autoincrement=<span class="text-blue-400">True</span>)
name = Column(String(100), nullable=<span class="text-blue-400">False</span>)
api_key_encrypted = Column(Text, nullable=<span class="text-blue-400">False</span>)
api_secret_encrypted = Column(Text, nullable=<span class="text-blue-400">False</span>)
<span class="text-green-400"># Follower configuration</span>
allocation_rule = Column(JSON, nullable=<span class="text-blue-400">False</span>) <span class="text-green-400"># e.g., {"type": "percentage", "value": 50}</span>
status = Column(SQLAlchemyEnum(FollowerStatus), nullable=<span class="text-blue-400">False</span>, default=FollowerStatus.ACTIVE)
<span class="text-green-400"># Safety controls</span>
max_consecutive_errors = Column(Integer, default=<span class="text-blue-400">5</span>)
current_consecutive_errors = Column(Integer, default=<span class="text-blue-400">0</span>)
auto_pause_on_errors = Column(Boolean, default=<span class="text-blue-400">True</span>)
<span class="text-gray-500"># More fields follow...</span>
</pre>
<pre id="security-tab" class="font-mono text-sm overflow-x-auto whitespace-pre p-4 bg-gray-900/50 rounded-lg hidden">
<span class="text-green-400">### File: security/encryption.py</span>
<span class="text-cyan-400"><b>#!/usr/bin/env python3</b></span>
<span class="text-gray-500">"""Cryptographic functions for API key protection"""</span>
<span class="text-purple-400">import</span> base64
<span class="text-purple-400">import</span> logging
<span class="text-purple-400">import</span> os
<span class="text-purple-400">from</span> typing <span class="text-purple-400">import</span> Optional
<span class="text-purple-400">from</span> cryptography.fernet <span class="text-purple-400">import</span> Fernet
<span class="text-purple-400">from</span> cryptography.hazmat.primitives <span class="text-purple-400">import</span> hashes
<span class="text-purple-400">from</span> cryptography.hazmat.primitives.kdf.pbkdf2 <span class="text-purple-400">import</span> PBKDF2HMAC
<span class="text-cyan-400">class</span> <span class="text-yellow-400">KeyVault</span>:
<span class="text-gray-400">"""Manages encryption/decryption of sensitive API credentials"""</span>
<span class="text-purple-400">def</span> <span class="text-yellow-400">__init__</span>(<span class="text-blue-400">self</span>, master_password: <span class="text-blue-400">str</span>, salt: Optional[<span class="text-blue-400">bytes</span>] = <span class="text-blue-400">None</span>):
<span class="text-blue-400">self</span>.master_password = master_password.encode()
<span class="text-blue-400">self</span>.salt = salt <span class="text-purple-400">or</span> os.urandom(<span class="text-blue-400">16</span>)
<span class="text-blue-400">self</span>.logger = logging.getLogger(__name__)
<span class="text-green-400"># Derive a Fernet key from master password</span>
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=<span class="text-blue-400">32</span>,
salt=<span class="text-blue-400">self</span>.salt,
iterations=100000,
)
key = base64.urlsafe_b64encode(kdf.derive(<span class="text-blue-400">self</span>.master_password))
<span class="text-blue-400">self</span>.cipher = Fernet(key)
<span class="text-purple-400">def</span> <span class="text-yellow-400">encrypt</span>(<span class="text-blue-400">self</span>, plaintext: <span class="text-blue-400">str</span>) -> <span class="text-blue-400">str</span>:
<span class="text-gray-400">"""Encrypt a string and return base64 encoded ciphertext"""</span>
<span class="text-purple-400">try</span>:
encrypted_bytes = <span class="text-blue-400">self</span>.cipher.encrypt(plaintext.encode())
<span class="text-purple-400">return</span> base64.urlsafe_b64encode(encrypted_bytes).decode()
<span class="text-purple-400">except</span> Exception <span class="text-purple-400">as</span> e:
<span class="text-blue-400">self</span>.logger.error(f<span class="text-pink-400">"🔴 Encryption failed: {e}"</span>)
<span class="text-purple-400">raise</span>
<span class="text-purple-400">def</span> <span class="text-yellow-400">decrypt</span>(<span class="text-blue-400">self</span>, ciphertext_b64: <span class="text-blue-400">str</span>) -> <span class="text-blue-400">str</span>:
<span class="text-gray-400">"""Decrypt a base64 encoded ciphertext and return the plaintext string"""</span>
<span class="text-purple-400">try</span>:
encrypted_bytes = base64.urlsafe_b64decode(ciphertext_b64.encode())
decrypted_bytes = <span class="text-blue-400">self</span>.cipher.decrypt(encrypted_bytes)
<span class="text-purple-400">return</span> decrypted_bytes.decode()
<span class="text-purple-400">except</span> Exception <span class="text-purple-400">as</span> e:
<span class="text-blue-400">self</span>.logger.error(f<span class="text-pink-400">"🔴 Decryption failed: {e}"</span>)
<span class="text-purple-400">raise</span>
<span class="text-gray-400"># More functions follow...</span>
</pre>
</div>
</div>
</div>
</section>
<!-- Contract Section -->
<section class="mb-16">
<h2 class="text-3xl font-bold mb-8 text-center">Behavioral Contracts</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-8 rounded-2xl border border-blue-500/30">
<div class="flex items-start gap-4">
<div class="w-10 h-10 rounded-full bg-blue-500/20 flex items-center justify-center flex-shrink-0">
<i data-feather="check-circle" class="w-5 h-5 text-blue-300"></i>
</div>
<div>
<h3 class="text-xl font-bold mb-2">Trade Trigger Contract</h3>
<p class="text-gray-300 mb-4">A trade is copied <span class="text-green-400 font-semibold">if and only if</span> it appears as a new, successfully executed trade in the master's <code class="bg-gray-700 px-1 py-0.5 rounded">get_my_trades</code> endpoint. No other event (balance changes, transfers, deposits) shall ever trigger a trade.</p>
<div class="text-sm font-mono text-gray-400 bg-gray-900/50 p-3 rounded">
if trade_id > last_processed_trade_id:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;replicate_trade(trade)<br/>
else:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;ignore() # Idempotency guarantee
</div>
</div>
</div>
</div>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-8 rounded-2xl border border-purple-500/30">
<div class="flex items-start gap-4">
<div class="w-10 h-10 rounded-full bg-purple-500/20 flex items-center justify-center flex-shrink-0">
<i data-feather="percent" class="w-5 h-5 text-purple-300"></i>
</div>
<div>
<h3 class="text-xl font-bold mb-2">Allocation Contract</h3>
<p class="text-gray-300 mb-4">Follower trades are sized proportionally based on a pre-configured rule (e.g., percentage of available capital). The system must perform a balance check before every single trade execution.</p>
<div class="text-sm font-mono text-gray-400 bg-gray-900/50 p-3 rounded">
follower_quantity = (<br/>
&nbsp;&nbsp;&nbsp;&nbsp;(follower_balance / master_balance)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;* allocation_percentage<br/>
&nbsp;&nbsp;&nbsp;&nbsp;* master_quantity<br/>
)<br/>
assert follower_balance >= follower_quantity
</div>
</div>
</div>
</div>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-8 rounded-2xl border border-cyan-500/30">
<div class="flex items-start gap-4">
<div class="w-10 h-10 rounded-full bg-cyan-500/20 flex items-center justify-center flex-shrink-0">
<i data-feather="alert-triangle" class="w-5 h-5 text-cyan-300"></i>
</div>
<div>
<h3 class="text-xl font-bold mb-2">Error Handling Contract</h3>
<p class="text-gray-300 mb-4">The failure of one follower must not impact others. Repeated critical errors automatically move followers to a <code class="bg-gray-700 px-1 py-0.5 rounded">PAUSED</code> state. The system logs all execution failures with specific reasons and proceeds gracefully.</p>
<div class="text-sm font-mono text-gray-400 bg-gray-900/50 p-3 rounded">
if follower.current_consecutive_errors <br/>
&nbsp;&nbsp;&nbsp;&nbsp;>= follower.max_consecutive_errors:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;follower.status = 'PAUSED'<br/>
&nbsp;&nbsp;&nbsp;&nbsp;commit_to_database()
</div>
</div>
</div>
</div>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-8 rounded-2xl border border-green-500/30">
<div class="flex items-start gap-4">
<div class="w-10 h-10 rounded-full bg-green-500/20 flex items-center justify-center flex-shrink-0">
<i data-feather="database" class="w-5 h-5 text-green-300"></i>
</div>
<div>
<h3 class="text-xl font-bold mb-2">State Management Contract</h3>
<p class="text-gray-300 mb-4">Follower accounts exist in well-defined states (<code class="bg-gray-700 px-1 py-0.5 rounded">ACTIVE</code>, <code class="bg-gray-700 px-1 py-0.5 rounded">PAUSED</code>, <code class="bg-gray-700 px-1 py-0.5 rounded">DISABLED</code>). Only <code class="bg-gray-700 px-1 py-0.5 rounded">ACTIVE</code> followers are included in the trade execution loop.</p>
<div class="text-sm font-mono text-gray-400 bg-gray-900/50 p-3 rounded">
active_followers = [<br/>
&nbsp;&nbsp;&nbsp;&nbsp;f for f in followers<br/>
&nbsp;&nbsp;&nbsp;&nbsp;if f.status == 'ACTIVE'<br/>
]<br/>
for follower in active_followers:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;execute_trade(follower)
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Dashboard Demo -->
<section class="mb-16">
<h2 class="text-3xl font-bold mb-8 text-center">Follower Management Dashboard</h2>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 rounded-2xl overflow-hidden border border-gray-700">
<div class="p-6 border-b border-gray-700">
<div class="flex items-center justify-between">
<h3 class="text-xl font-bold">Active Followers</h3>
<span class="px-3 py-1 bg-gray-700 rounded-full text-sm">3 followers</span>
</div>
</div>
<div class="overflow-x-auto">
<table class="w-full">
<thead>
<tr class="border-b border-gray-700">
<th class="text-left p-4">Name</th>
<th class="text-left p-4">Status</th>
<th class="text-left p-4">Allocation</th>
<th class="text-left p-4">Last Trade</th>
<th class="text-left p-4">Consecutive Errors</th>
<th class="text-left p-4">Actions</th>
</tr>
</thead>
<tbody>
<tr class="border-b border-gray-700/50">
<td class="p-4">
<div class="flex items-center gap-3">
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-cyan-500 to-blue-500"></div>
<span class="font-medium">Alpha Trader</span>
</div>
</td>
<td class="p-4">
<span class="px-3 py-1 rounded-full text-xs font-medium bg-green-500/20 text-green-300">ACTIVE</span>
</td>
<td class="p-4">
<div class="flex items-center gap-2">
<span class="font-medium">75%</span>
<div class="w-32 h-2 bg-gray-700 rounded-full overflow-hidden">
<div class="h-full bg-cyan-500 rounded-full" style="width: 75%"></div>
</div>
</div>
</td>
<td class="p-4 text-sm text-gray-300">2024-03-15 14:30:22</td>
<td class="p-4">
<div class="flex items-center gap-2">
<span class="font-medium text-green-300">0</span>
<i data-feather="check" class="w-4 h-4 text-green-300"></i>
</div>
</td>
<td class="p-4">
<div class="flex gap-2">
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded transition-colors">
<i data-feather="pause" class="w-4 h-4"></i>
</button>
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded transition-colors">
<i data-feather="eye-off" class="w-4 h-4"></i>
</button>
</div>
</td>
</tr>
<tr class="border-b border-gray-700/50">
<td class="p-4">
<div class="flex items-center gap-3">
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-purple-500 to-pink-500"></div>
<span class="font-medium">Beta Follower</span>
</div>
</td>
<td class="p-4">
<span class="px-3 py-1 rounded-full text-xs font-medium bg-yellow-500/20 text-yellow-300">PAUSED</span>
</td>
<td class="p-4">
<div class="flex items-center gap-2">
<span class="font-medium">50%</span>
<div class="w-32 h-2 bg-gray-700 rounded-full overflow-hidden">
<div class="h-full bg-purple-500 rounded-full" style="width: 50%"></div>
</div>
</div>
</td>
<td class="p-4 text-sm text-gray-300">2024-03-14 09:15:07</td>
<td class="p-4">
<div class="flex items-center gap-2">
<span class="font-medium text-yellow-300">5</span>
<i data-feather="alert-triangle" class="w-4 h-4 text-yellow-300"></i>
</div>
</td>
<td class="p-4">
<div class="flex gap-2">
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded transition-colors">
<i data-feather="play" class="w-4 h-4"></i>
</button>
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded transition-colors">
<i data-feather="eye-off" class="w-4 h-4"></i>
</button>
</div>
</td>
</tr>
<tr>
<td class="p-4">
<div class="flex items-center gap-3">
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-blue-600 to-indigo-600"></div>
<span class="font-medium">Gamma Investor</span>
</div>
</td>
<td class="p-4">
<span class="px-3 py-1 rounded-full text-xs font-medium bg-red-500/20 text-red-300">DISABLED</span>
</td>
<td class="p-4">
<div class="flex items-center gap-2">
<span class="font-medium">25%</span>
<div class="w-32 h-2 bg-gray-700 rounded-full overflow-hidden">
<div class="h-full bg-blue-500 rounded-full" style="width: 25%"></div>
</div>
</div>
</td>
<td class="p-4 text-sm text-gray-300">2024-03-10 16:45:33</td>
<td class="p-4">
<div class="flex items-center gap-2">
<span class="font-medium text-red-300">12</span>
<i data-feather="x-circle" class="w-4 h-4 text-red-300"></i>
</div>
</td>
<td class="p-4">
<div class="flex gap-2">
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded transition-colors">
<i data-feather="play" class="w-4 h-4"></i>
</button>
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded transition-colors">
<i data-feather="trash-2" class="w-4 h-4"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="p-6 border-t border-gray-700">
<div class="flex flex-wrap gap-4">
<div class="flex-1 min-w-[200px]">
<h4 class="font-bold mb-2">Add New Follower</h4>
<p class="text-sm text-gray-300 mb-3">Secure API key import with encryption at rest</p>
<button class="px-4 py-2 bg-gradient-to-r from-cyan-600 to-blue-600 hover:from-cyan-500 hover:to-blue-500 rounded-lg font-medium transition-all duration-300">
<i data-feather="user-plus" class="w-4 h-4 inline mr-2"></i> Add Follower
</button>
</div>
<div class="flex-1 min-w-[200px]">
<h4 class="font-bold mb-2">System Health Check</h4>
<p class="text-sm text-gray-300 mb-3">Verify master connection and follower statuses</p>
<button class="px-4 py-2 bg-gradient-to-r from-green-600 to-emerald-600 hover:from-green-500 hover:to-emerald-500 rounded-lg font-medium transition-all duration-300">
<i data-feather="activity" class="w-4 h-4 inline mr-2"></i> Run Diagnostics
</button>
</div>
</div>
</div>
</div>
</section>
<!-- Features Grid -->
<section class="mb-16">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold mb-4">Built for Financial Grade Reliability</h2>
<p class="text-gray-300 max-w-2xl mx-auto">Every component is engineered to withstand failures, ensure data integrity, and maintain perfect idempotency.</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-6 rounded-xl border border-gray-700">
<h3 class="text-xl font-bold mb-3 flex items-center gap-2">
<i data-feather="shield" class="w-5 h-5 text-green-400"></i>
API Security Verification
</h3>
<p class="text-gray-300">Validates API keys don't have withdrawal permissions. Automatic detection and rejection of over-privileged credentials.</p>
</div>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-6 rounded-xl border border-gray-700">
<h3 class="text-xl font-bold mb-3 flex items-center gap-2">
<i data-feather="repeat" class="w-5 h-5 text-cyan-400"></i>
Restart-Safe Operation
</h3>
<p class="text-gray-300">Persistent tracking of last processed trade ID ensures duplicate trades are never executed, no matter how many restarts.</p>
</div>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-6 rounded-xl border border-gray-700">
<h3 class="text-xl font-bold mb-3 flex items-center gap-2">
<i data-feather="alert-octagon" class="w-5 h-5 text-yellow-400"></i>
Error Isolation & Recovery
</h3>
<p class="text-gray-300">Follower failures are isolated. The system automatically pauses problematic followers while continuing normal operation.</p>
</div>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-6 rounded-xl border border-gray-700">
<h3 class="text-xl font-bold mb-3 flex items-center gap-2">
<i data-feather="trending-up" class="w-5 h-5 text-purple-400"></i>
Real-time Performance Analytics
</h3>
<p class="text-gray-300">Comprehensive dashboards track latency, success rates, execution delays, and allocation efficiency across all followers.</p>
</div>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-6 rounded-xl border border-gray-700">
<h3 class="text-xl font-bold mb-3 flex items-center gap-2">
<i data-feather="file-text" class="w-5 h-5 text-blue-400"></i>
Full Audit Trail
</h3>
<p class="text-gray-300">Every trade, error, and state change is logged with timestamps, providing a complete, verifiable history for compliance.</p>
</div>
<div class="bg-gradient-to-br from-gray-800/50 to-gray-900/50 p-6 rounded-xl border border-gray-700">
<h3 class="text-xl font-bold mb-3 flex items-center gap-2">
<i data-feather="sliders" class="w-5 h-5 text-orange-400"></i>
Dynamic Allocation Strategies
</h3>
<p class="text-gray-300">Supports multiple allocation models: fixed percentages, dynamic ratio adjustment, and equity-based scaling for sophisticated strategies.</p>
</div>
</div>
</section>
</main>
<!-- Hero Section -->
<section class="text-center mb-8">
<div class="inline-flex items-center gap-2 mb-4 px-4 py-2 bg-gradient-to-r from-cyan-500/20 to-blue-600/20 rounded-full border border-cyan-500/30">
<i data-feather="zap" class="w-4 h-4 text-cyan-300"></i>
<span class="text-sm font-medium text-cyan-300">DESKTOP APPLICATION - v1.0.0</span>
</div>
<h1 class="text-4xl md:text-5xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-cyan-300 via-blue-300 to-purple-300 leading-tight">
SpotSync Alpha Desktop
</h1>
<p class="text-lg text-gray-300 mb-6 max-w-2xl mx-auto">
Master-Follower Replication Engine running locally on your machine.
Full control, complete privacy, no cloud dependencies.
</p>
<div class="flex flex-wrap justify-center gap-4">
<button class="px-6 py-3 bg-gradient-to-r from-cyan-600 to-blue-600 hover:from-cyan-500 hover:to-blue-500 rounded-lg font-semibold transition-all duration-300 hover:shadow-lg hover:shadow-cyan-500/20 flex items-center gap-2">
<i data-feather="play" class="w-4 h-4"></i>
Start Engine
</button>
<button class="px-6 py-3 bg-gradient-to-r from-gray-700 to-gray-800 hover:from-gray-600 hover:to-gray-700 rounded-lg font-semibold transition-all duration-300 border border-gray-600 hover:border-gray-500 flex items-center gap-2">
<i data-feather="user-plus" class="w-4 h-4"></i>
Add Follower
</button>
<button class="px-6 py-3 bg-gradient-to-r from-green-600 to-emerald-600 hover:from-green-500 hover:to-emerald-500 rounded-lg font-semibold transition-all duration-300 flex items-center gap-2">
<i data-feather="download" class="w-4 h-4"></i>
Export Logs
</button>
</div>
</section>
<!-- Architecture Overview (Shortened for desktop) -->
<section class="mb-8">
<h2 class="text-2xl font-bold mb-6">System Overview</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div class="feature-card">
<div class="w-10 h-10 rounded-lg bg-gradient-to-r from-cyan-700/30 to-cyan-900/30 flex items-center justify-center mb-3">
<i data-feather="cpu" class="w-5 h-5 text-cyan-300"></i>
</div>
<h3 class="text-lg font-bold mb-2">Local Execution</h3>
<p class="text-sm text-gray-300">All processing happens locally on your machine. No data leaves your computer.</p>
</div>
<div class="feature-card">
<div class="w-10 h-10 rounded-lg bg-gradient-to-r from-blue-700/30 to-blue-900/30 flex items-center justify-center mb-3">
<i data-feather="shield" class="w-5 h-5 text-blue-300"></i>
</div>
<h3 class="text-lg font-bold mb-2">Enhanced Security</h3>
<p class="text-sm text-gray-300">API keys encrypted with local keychain. No cloud storage of sensitive data.</p>
</div>
<div class="feature-card">
<div class="w-10 h-10 rounded-lg bg-gradient-to-r from-purple-700/30 to-purple-900/30 flex items-center justify-center mb-3">
<i data-feather="zap" class="w-5 h-5 text-purple-300"></i>
</div>
<h3 class="text-lg font-bold mb-2">System Tray</h3>
<p class="text-sm text-gray-300">Run minimized in system tray. Get notifications for trades and alerts.</p>
</div>
<div class="feature-card">
<div class="w-10 h-10 rounded-lg bg-gradient-to-r from-green-700/30 to-green-900/30 flex items-center justify-center mb-3">
<i data-feather="database" class="w-5 h-5 text-green-300"></i>
</div>
<h3 class="text-lg font-bold mb-2">Local Database</h3>
<p class="text-sm text-gray-300">SQLite database for trade history and configuration. Full audit trail.</p>
</div>
</div>
</section>
<!-- Main content continues... (The rest of the existing content will be here) -->
</main>
</div>
</div>
<!-- External Scripts -->
<script src="script.js"></script>
<script>
feather.replace();
// Update navigation active state
document.querySelectorAll('.nav-item').forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault();
document.querySelectorAll('.nav-item').forEach(i => i.classList.remove('active'));
this.classList.add('active');
});
});
// Initialize tooltips for desktop
document.querySelectorAll('[title]').forEach(el => {
el.addEventListener('mouseenter', function() {
// Tooltip implementation for desktop
});
});
</script>
</body>
</html>