Spaces:
Paused
Paused
Download static/index.html from arudradey/agent-loop: direct link, hf CLI and curl.
- Browser
- Download file 32.3 kB
-
https://huggingface.co/spaces/arudradey/agent-loop/resolve/main/static/index.html
- Command line
-
hf download hf://spaces/arudradey/agent-loop/static/index.html
-
curl -L -o index.html https://huggingface.co/spaces/arudradey/agent-loop/resolve/main/static/index.html
32.3 kB
| <html lang="en" class="dark"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>SOLANA // QUANT • Autonomous Hedge Fund</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script> | |
| tailwind.config = { | |
| darkMode: 'class', | |
| theme: { | |
| extend: { | |
| fontFamily: { | |
| sans: ['Inter', 'system-ui', '-apple-system', 'sans-serif'], | |
| mono: ['JetBrains Mono', 'ui-monospace', 'monospace'] | |
| }, | |
| colors: { | |
| sol: { | |
| purple: '#9945FF', | |
| green: '#14F195', | |
| }, | |
| zinc: { | |
| 850: '#1c1c22', | |
| 900: '#111115', | |
| 925: '#0c0c0f', | |
| 950: '#060608', | |
| } | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <!-- Google Fonts: Inter & JetBrains Mono --> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet"> | |
| <!-- Lucide Icons --> | |
| <script src="https://unpkg.com/lucide@latest"></script> | |
| <style> | |
| body { | |
| background-color: #060608; | |
| color: #fafafa; | |
| font-feature-settings: "cv02", "cv03", "cv04", "cv11"; | |
| -webkit-font-smoothing: antialiased; | |
| } | |
| ::selection { | |
| background: #14F195; | |
| color: #000000; | |
| } | |
| .custom-scroll::-webkit-scrollbar { | |
| width: 5px; | |
| height: 5px; | |
| } | |
| .custom-scroll::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| .custom-scroll::-webkit-scrollbar-thumb { | |
| background: #27272a; | |
| border-radius: 9999px; | |
| } | |
| .custom-scroll::-webkit-scrollbar-thumb:hover { | |
| background: #3f3f46; | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen flex flex-col font-sans selection:bg-sol-green selection:text-black"> | |
| <!-- Top Minimalist Bar --> | |
| <header class="border-b border-zinc-800/80 bg-zinc-950/90 backdrop-blur-md sticky top-0 z-50"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 h-16 flex items-center justify-between"> | |
| <!-- Brand & Status --> | |
| <div class="flex items-center space-x-4"> | |
| <a href="/" class="flex items-center space-x-2 group"> | |
| <div class="w-7 h-7 rounded-lg bg-gradient-to-tr from-sol-purple to-sol-green p-[1px] flex items-center justify-center shadow-lg shadow-sol-green/10"> | |
| <div class="w-full h-full bg-zinc-950 rounded-[7px] flex items-center justify-center font-mono font-black text-xs text-sol-green"> | |
| ◎ | |
| </div> | |
| </div> | |
| <div> | |
| <div class="font-extrabold text-sm sm:text-base tracking-tight uppercase text-white"> | |
| SOLANA <span class="text-zinc-500 font-normal">//</span> QUANT | |
| </div> | |
| <div class="text-[10px] font-mono text-zinc-500 -mt-0.5">Autonomous Hedge Fund</div> | |
| </div> | |
| </a> | |
| <div class="hidden sm:flex items-center space-x-2 pl-3 border-l border-zinc-800 text-xs font-mono"> | |
| <span class="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-sol-green/10 text-sol-green text-[11px] font-semibold"> | |
| <span class="w-1.5 h-1.5 rounded-full bg-sol-green animate-pulse"></span> | |
| ACTIVE | |
| </span> | |
| <span class="text-zinc-500 text-[11px]">Qwen2.5-0.5B (Local CPU)</span> | |
| </div> | |
| </div> | |
| <!-- Navigation Tabs (Segmented Control) --> | |
| <nav class="flex items-center p-1 rounded-lg bg-zinc-900 border border-zinc-800 text-xs font-medium"> | |
| <button onclick="switchTab('overview')" id="btn-tab-overview" class="px-3 py-1.5 rounded-md bg-white text-zinc-950 font-bold transition"> | |
| Overview | |
| </button> | |
| <button onclick="switchTab('ai')" id="btn-tab-ai" class="px-3 py-1.5 rounded-md text-zinc-400 hover:text-white transition"> | |
| AI Copilot | |
| </button> | |
| <button onclick="switchTab('arbitrage')" id="btn-tab-arbitrage" class="px-3 py-1.5 rounded-md text-zinc-400 hover:text-white transition"> | |
| DEX Spreads | |
| </button> | |
| <button onclick="switchTab('blotter')" id="btn-tab-blotter" class="px-3 py-1.5 rounded-md text-zinc-400 hover:text-white transition"> | |
| Blotter | |
| </button> | |
| <button onclick="switchTab('storage')" id="btn-tab-storage" class="px-3 py-1.5 rounded-md text-zinc-400 hover:text-white transition"> | |
| Storage | |
| </button> | |
| </nav> | |
| <!-- External Links --> | |
| <div class="hidden md:flex items-center space-x-3 text-xs font-mono"> | |
| <a href="/docs" target="_blank" class="text-zinc-400 hover:text-white transition"> | |
| /docs | |
| </a> | |
| <a href="https://huggingface.co/spaces/arudradey/agent-loop" target="_blank" class="px-3 py-1.5 rounded-lg border border-zinc-700 bg-zinc-900 hover:bg-zinc-800 text-zinc-200 font-semibold transition flex items-center space-x-1"> | |
| <span>HF Space</span> | |
| <i data-lucide="arrow-up-right" class="w-3.5 h-3.5"></i> | |
| </a> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Live Ticker Strip --> | |
| <div class="border-b border-zinc-800/60 bg-zinc-950/60 px-4 py-2 text-xs font-mono overflow-x-auto whitespace-nowrap custom-scroll"> | |
| <div class="max-w-7xl mx-auto flex items-center justify-between gap-6 text-[11px]"> | |
| <div class="flex items-center space-x-6"> | |
| <span class="flex items-center space-x-1.5"> | |
| <span class="text-zinc-500 font-semibold">SOL/USD:</span> | |
| <span id="ticker-sol" class="text-white font-bold">$148.50</span> | |
| <span class="text-sol-green font-semibold">+4.8%</span> | |
| </span> | |
| <span class="flex items-center space-x-1.5"> | |
| <span class="text-zinc-500 font-semibold">JUP/USD:</span> | |
| <span id="ticker-jup" class="text-white font-bold">$0.985</span> | |
| <span class="text-sol-green font-semibold">+2.1%</span> | |
| </span> | |
| <span class="flex items-center space-x-1.5"> | |
| <span class="text-zinc-500 font-semibold">RAY/USD:</span> | |
| <span id="ticker-ray" class="text-white font-bold">$2.15</span> | |
| <span class="text-sol-green font-semibold">+6.4%</span> | |
| </span> | |
| <span class="flex items-center space-x-1.5"> | |
| <span class="text-zinc-500 font-semibold">WIF/USD:</span> | |
| <span id="ticker-wif" class="text-white font-bold">$1.84</span> | |
| <span class="text-red-400 font-semibold">-1.2%</span> | |
| </span> | |
| </div> | |
| <div class="text-zinc-500 hidden sm:block"> | |
| Jupiter Aggregator v6 • Raydium CPMM • Orca Whirlpools | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Main Container --> | |
| <main class="flex-1 max-w-7xl w-full mx-auto p-4 sm:p-6 lg:p-8"> | |
| <!-- ============================================================= --> | |
| <!-- TAB 1: OVERVIEW & POSITIONS --> | |
| <!-- ============================================================= --> | |
| <div id="tab-overview" class="space-y-6"> | |
| <!-- Bold AUM & Performance Metrics --> | |
| <div class="grid grid-cols-2 lg:grid-cols-4 gap-4"> | |
| <div class="p-5 rounded-2xl border border-zinc-800 bg-zinc-925/80"> | |
| <div class="text-[11px] font-mono uppercase tracking-wider text-zinc-500">Total Fund AUM</div> | |
| <div id="stat-aum" class="text-2xl sm:text-3xl font-black font-mono tracking-tight text-white mt-1">$14,250,000</div> | |
| <div class="text-xs font-mono text-sol-green mt-1">+$482,150 (+3.49% 24h)</div> | |
| </div> | |
| <div class="p-5 rounded-2xl border border-zinc-800 bg-zinc-925/80"> | |
| <div class="text-[11px] font-mono uppercase tracking-wider text-zinc-500">Solana Exposure</div> | |
| <div id="stat-sol-exposure" class="text-2xl sm:text-3xl font-black font-mono tracking-tight text-white mt-1">56.5%</div> | |
| <div class="text-xs font-mono text-zinc-400 mt-1">54,200 SOL ($8.04M)</div> | |
| </div> | |
| <div class="p-5 rounded-2xl border border-zinc-800 bg-zinc-925/80"> | |
| <div class="text-[11px] font-mono uppercase tracking-wider text-zinc-500">Sharpe Ratio</div> | |
| <div class="text-2xl sm:text-3xl font-black font-mono tracking-tight text-white mt-1">3.42</div> | |
| <div class="text-xs font-mono text-zinc-400 mt-1">Max Drawdown: 4.1%</div> | |
| </div> | |
| <div class="p-5 rounded-2xl border border-zinc-800 bg-zinc-925/80"> | |
| <div class="text-[11px] font-mono uppercase tracking-wider text-zinc-500">AI Quant Engine</div> | |
| <div class="text-2xl sm:text-3xl font-black font-mono tracking-tight text-sol-green mt-1">0.5B CPU</div> | |
| <div class="text-xs font-mono text-zinc-400 mt-1">Sub-second inference</div> | |
| </div> | |
| </div> | |
| <!-- Two Column Layout: Positions & Quick Trade --> | |
| <div class="grid grid-cols-1 lg:grid-cols-12 gap-6 items-start"> | |
| <!-- Left: Asset Allocation Table (8 Cols) --> | |
| <div class="lg:col-span-8 rounded-2xl border border-zinc-800 bg-zinc-925/50 p-6 space-y-4 shadow-xl"> | |
| <div class="flex items-center justify-between border-b border-zinc-800 pb-3"> | |
| <h2 class="text-xs font-mono font-bold tracking-wider uppercase text-zinc-200 flex items-center space-x-2"> | |
| <i data-lucide="pie-chart" class="w-4 h-4 text-sol-purple"></i> | |
| <span>Active Portfolio Positions</span> | |
| </h2> | |
| <span class="text-xs font-mono text-zinc-500">Auto-Rebalance: <strong class="text-sol-green">ON</strong></span> | |
| </div> | |
| <div class="rounded-xl border border-zinc-800/80 overflow-hidden font-mono text-xs"> | |
| <div class="grid grid-cols-12 bg-zinc-950 p-3 text-zinc-500 font-semibold border-b border-zinc-800"> | |
| <span class="col-span-4">ASSET</span> | |
| <span class="col-span-3 text-right">HOLDINGS</span> | |
| <span class="col-span-3 text-right">VALUE (USDC)</span> | |
| <span class="col-span-2 text-right">WEIGHT</span> | |
| </div> | |
| <div id="positions-table" class="divide-y divide-zinc-900 bg-zinc-925/40"> | |
| <!-- Rendered via JS --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Right: Instant Order Dispatch (4 Cols) --> | |
| <div class="lg:col-span-4 rounded-2xl border border-zinc-800 bg-zinc-925/50 p-6 space-y-4 shadow-xl"> | |
| <div class="flex items-center justify-between border-b border-zinc-800 pb-3"> | |
| <h2 class="text-xs font-mono font-bold tracking-wider uppercase text-zinc-200 flex items-center space-x-2"> | |
| <i data-lucide="zap" class="w-4 h-4 text-sol-green"></i> | |
| <span>Instant DEX Order</span> | |
| </h2> | |
| <span class="text-[10px] font-mono px-2 py-0.5 rounded bg-zinc-900 border border-zinc-800 text-zinc-400">JUPITER v6</span> | |
| </div> | |
| <div class="space-y-3 font-mono text-xs"> | |
| <div> | |
| <label class="block text-zinc-500 mb-1">Asset</label> | |
| <select id="trade-symbol" class="w-full bg-zinc-950 border border-zinc-800 rounded-lg p-2 text-white font-bold focus:outline-none"> | |
| <option value="SOL">SOL (Solana)</option> | |
| <option value="JUP">JUP (Jupiter)</option> | |
| <option value="RAY">RAY (Raydium)</option> | |
| <option value="WIF">WIF (dogwifhat)</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-zinc-500 mb-1">Side</label> | |
| <div class="grid grid-cols-2 gap-2"> | |
| <button onclick="setTradeSide('BUY')" id="btn-side-buy" class="py-1.5 rounded-lg border font-bold text-xs bg-sol-green/10 text-sol-green border-sol-green/30">BUY</button> | |
| <button onclick="setTradeSide('SELL')" id="btn-side-sell" class="py-1.5 rounded-lg border border-zinc-800 bg-zinc-900 text-zinc-400 hover:text-white font-bold text-xs">SELL</button> | |
| </div> | |
| </div> | |
| <div> | |
| <label class="block text-zinc-500 mb-1">Notional Size (USDC)</label> | |
| <input id="trade-amount" type="number" value="100000" class="w-full bg-zinc-950 border border-zinc-800 rounded-lg p-2 text-white font-bold focus:outline-none"> | |
| </div> | |
| <div class="pt-2"> | |
| <button onclick="submitTradeOrder()" id="btn-submit-order" class="w-full py-2.5 rounded-lg bg-white hover:bg-zinc-200 text-black font-extrabold text-xs uppercase tracking-wider transition flex items-center justify-center space-x-2"> | |
| <span>Dispatch To Solana</span> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ============================================================= --> | |
| <!-- TAB 2: LOCAL SMALL AI QUANT COPILOT --> | |
| <!-- ============================================================= --> | |
| <div id="tab-ai" class="space-y-6 hidden"> | |
| <div class="rounded-2xl border border-zinc-800 bg-zinc-925/80 p-6 sm:p-8 space-y-6 shadow-2xl"> | |
| <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-3"> | |
| <div> | |
| <div class="flex items-center space-x-2"> | |
| <span class="px-2 py-0.5 rounded text-[10px] font-mono font-bold bg-white text-black uppercase">Qwen2.5-0.5B-Instruct</span> | |
| <span class="px-2 py-0.5 rounded text-[10px] font-mono font-bold bg-sol-green/10 text-sol-green border border-sol-green/20 uppercase">494M Params • Local CPU</span> | |
| </div> | |
| <h1 class="text-2xl sm:text-3xl font-black tracking-tight text-white uppercase mt-2"> | |
| SolQuant Autonomous Copilot | |
| </h1> | |
| <p class="text-xs sm:text-sm text-zinc-400 mt-1"> | |
| High-frequency on-chain trading signals, Raydium/Orca arbitrage analysis, and portfolio risk management generated directly on CPU in milliseconds. | |
| </p> | |
| </div> | |
| <div class="text-right font-mono text-xs text-zinc-500"> | |
| <div>Engine: <span class="text-white font-bold">PyTorch SIMD</span></div> | |
| <div>Latency: <span class="text-sol-green font-bold">< 15ms TTFT</span></div> | |
| </div> | |
| </div> | |
| <!-- Presets --> | |
| <div class="flex flex-wrap gap-2 text-xs font-mono"> | |
| <span class="text-zinc-500 self-center">Presets:</span> | |
| <button onclick="setAiPrompt('sol_momentum')" class="px-2.5 py-1 rounded-md bg-zinc-900 hover:bg-zinc-800 border border-zinc-800 text-zinc-300 transition"> | |
| $SOL Momentum & Sizing | |
| </button> | |
| <button onclick="setAiPrompt('arb_scan')" class="px-2.5 py-1 rounded-md bg-zinc-900 hover:bg-zinc-800 border border-zinc-800 text-zinc-300 transition"> | |
| Raydium vs Orca Arbitrage | |
| </button> | |
| <button onclick="setAiPrompt('rebalance')" class="px-2.5 py-1 rounded-md bg-zinc-900 hover:bg-zinc-800 border border-zinc-800 text-zinc-300 transition"> | |
| Portfolio Rebalancing | |
| </button> | |
| </div> | |
| <!-- Prompt Textarea --> | |
| <div class="relative"> | |
| <textarea id="ai-prompt" rows="3" class="w-full rounded-xl bg-zinc-950 border border-zinc-800 focus:border-zinc-500 focus:ring-1 focus:ring-zinc-500 p-4 text-sm font-medium text-white placeholder-zinc-600 focus:outline-none transition resize-none custom-scroll leading-relaxed" placeholder="Ask SolQuant AI for portfolio signals, arbitrage strategies, or risk sizing...">Analyze current SOL/USDC momentum, calculate 24h risk-adjusted sizing, and recommend optimal slippage bounds for Raydium liquidity pools.</textarea> | |
| </div> | |
| <!-- Trigger Button --> | |
| <div class="flex items-center justify-between pt-1 font-mono text-xs"> | |
| <span class="text-zinc-500">Zero external API dependencies • runs 100% locally</span> | |
| <button onclick="queryQuantAi()" id="btn-run-ai" class="px-6 py-2.5 rounded-lg bg-white hover:bg-zinc-200 text-black font-extrabold text-xs uppercase tracking-wider transition flex items-center space-x-2 shadow-lg active:scale-95"> | |
| <i data-lucide="zap" class="w-4 h-4 fill-black"></i> | |
| <span>Run Analysis</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Real-Time AI Stream Output --> | |
| <div class="rounded-2xl border border-zinc-800 bg-zinc-925/50 p-6 space-y-4 shadow-xl"> | |
| <div class="flex items-center justify-between border-b border-zinc-800 pb-3"> | |
| <div class="flex items-center space-x-2 text-xs font-mono font-bold text-zinc-200 uppercase"> | |
| <i data-lucide="cpu" class="w-4 h-4 text-sol-green"></i> | |
| <span>Live Quant Intelligence Output</span> | |
| </div> | |
| <button onclick="copyAiOutput()" id="btn-copy-ai" class="text-[11px] font-mono px-2 py-1 rounded bg-zinc-900 border border-zinc-800 text-zinc-400 hover:text-white transition"> | |
| COPY | |
| </button> | |
| </div> | |
| <pre id="ai-output-box" class="p-4 rounded-xl bg-zinc-950 border border-zinc-900 text-zinc-200 font-mono text-xs whitespace-pre-wrap leading-relaxed min-h-[220px] max-h-[480px] overflow-y-auto custom-scroll"> | |
| Enter an objective above and click "Run Analysis" to receive real-time quant alpha. | |
| </pre> | |
| </div> | |
| </div> | |
| <!-- ============================================================= --> | |
| <!-- TAB 3: DEX ARBITRAGE SPREADS --> | |
| <!-- ============================================================= --> | |
| <div id="tab-arbitrage" class="space-y-6 hidden"> | |
| <div class="rounded-2xl border border-zinc-800 bg-zinc-925/50 p-6 space-y-4 shadow-xl"> | |
| <div class="flex items-center justify-between border-b border-zinc-800 pb-3"> | |
| <h2 class="text-xs font-mono font-bold tracking-wider uppercase text-zinc-200 flex items-center space-x-2"> | |
| <i data-lucide="refresh-ccw" class="w-4 h-4 text-sol-green"></i> | |
| <span>Cross-DEX Arbitrage Opportunities</span> | |
| </h2> | |
| <span class="text-xs font-mono text-zinc-500">Scan Interval: <strong class="text-white">100ms</strong></span> | |
| </div> | |
| <div id="arb-cards-container" class="grid grid-cols-1 md:grid-cols-3 gap-4"> | |
| <!-- Rendered via JS --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ============================================================= --> | |
| <!-- TAB 4: TRADE BLOTTER (Persistent Bucket Log) --> | |
| <!-- ============================================================= --> | |
| <div id="tab-blotter" class="space-y-6 hidden"> | |
| <div class="rounded-2xl border border-zinc-800 bg-zinc-925/50 p-6 space-y-4 shadow-xl"> | |
| <div class="flex items-center justify-between border-b border-zinc-800 pb-3"> | |
| <h2 class="text-xs font-mono font-bold tracking-wider uppercase text-zinc-200 flex items-center space-x-2"> | |
| <i data-lucide="list" class="w-4 h-4 text-sol-purple"></i> | |
| <span>On-Chain Trade Execution Blotter</span> | |
| </h2> | |
| <span class="text-xs font-mono text-zinc-500">Saved to <strong class="text-zinc-300">/data/trades/trades.json</strong></span> | |
| </div> | |
| <div class="rounded-xl border border-zinc-800/80 overflow-hidden font-mono text-xs"> | |
| <div class="grid grid-cols-12 bg-zinc-950 p-3 text-zinc-500 font-semibold border-b border-zinc-800"> | |
| <span class="col-span-3">TX ID</span> | |
| <span class="col-span-2">PAIR</span> | |
| <span class="col-span-2">SIDE</span> | |
| <span class="col-span-3 text-right">NOTIONAL (USDC)</span> | |
| <span class="col-span-2 text-right">STATUS</span> | |
| </div> | |
| <div id="blotter-table" class="divide-y divide-zinc-900 bg-zinc-925/40"> | |
| <!-- Rendered via JS --> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ============================================================= --> | |
| <!-- TAB 5: STORAGE BUCKET EXPLORER (/data) --> | |
| <!-- ============================================================= --> | |
| <div id="tab-storage" class="space-y-6 hidden"> | |
| <div class="rounded-2xl border border-zinc-800 bg-zinc-925/50 p-6 space-y-4 shadow-xl"> | |
| <div class="flex items-center justify-between border-b border-zinc-800 pb-3"> | |
| <h2 class="text-xs font-mono font-bold tracking-wider uppercase text-zinc-200 flex items-center space-x-2"> | |
| <i data-lucide="hard-drive" class="w-4 h-4 text-sol-green"></i> | |
| <span>Persistent Bucket Storage Status</span> | |
| </h2> | |
| <span class="text-xs font-mono text-zinc-400">Volume: <strong class="text-white">/data</strong></span> | |
| </div> | |
| <div id="storage-status-box" class="p-4 rounded-xl bg-zinc-950 border border-zinc-900 text-zinc-300 font-mono text-xs space-y-2"> | |
| <div>Bucket <strong class="text-white">arudradey/agent-loop-storage</strong> is active and clean.</div> | |
| <div class="text-zinc-500">All trade logs and hedge fund parameters persist across restarts.</div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Clean Minimalist Footer --> | |
| <footer class="border-t border-zinc-800/80 bg-zinc-950 text-zinc-500 text-xs py-5"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 flex flex-col sm:flex-row items-center justify-between gap-3 font-mono"> | |
| <div> | |
| SOLANA QUANT HEDGE FUND • Qwen2.5-0.5B CPU Engine • arudradey/agent-loop | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <span>Volume: <strong class="text-zinc-300">/data</strong></span> | |
| <a href="/docs" class="text-sol-green hover:underline">API Docs</a> | |
| </div> | |
| </div> | |
| </footer> | |
| <!-- Application Logic Scripts --> | |
| <script> | |
| let activeTradeSide = 'BUY'; | |
| function initIcons() { | |
| lucide.createIcons(); | |
| } | |
| function switchTab(tabId) { | |
| const tabs = ['overview', 'ai', 'arbitrage', 'blotter', 'storage']; | |
| tabs.forEach(t => { | |
| const pane = document.getElementById('tab-' + t); | |
| const btn = document.getElementById('btn-tab-' + t); | |
| if (t === tabId) { | |
| pane.classList.remove('hidden'); | |
| btn.className = 'px-3 py-1.5 rounded-md bg-white text-zinc-950 font-bold transition'; | |
| } else { | |
| pane.classList.add('hidden'); | |
| btn.className = 'px-3 py-1.5 rounded-md text-zinc-400 hover:text-white transition'; | |
| } | |
| }); | |
| if (tabId === 'overview') fetchMarket(); | |
| if (tabId === 'arbitrage') fetchMarket(); | |
| if (tabId === 'blotter') fetchTrades(); | |
| initIcons(); | |
| } | |
| function setTradeSide(side) { | |
| activeTradeSide = side; | |
| const buyBtn = document.getElementById('btn-side-buy'); | |
| const sellBtn = document.getElementById('btn-side-sell'); | |
| if (side === 'BUY') { | |
| buyBtn.className = 'py-1.5 rounded-lg border font-bold text-xs bg-sol-green/10 text-sol-green border-sol-green/30'; | |
| sellBtn.className = 'py-1.5 rounded-lg border border-zinc-800 bg-zinc-900 text-zinc-400 hover:text-white font-bold text-xs'; | |
| } else { | |
| sellBtn.className = 'py-1.5 rounded-lg border font-bold text-xs bg-red-500/10 text-red-400 border-red-500/30'; | |
| buyBtn.className = 'py-1.5 rounded-lg border border-zinc-800 bg-zinc-900 text-zinc-400 hover:text-white font-bold text-xs'; | |
| } | |
| } | |
| function setAiPrompt(type) { | |
| const p = document.getElementById('ai-prompt'); | |
| if (type === 'sol_momentum') { | |
| p.value = "Analyze current SOL/USDC momentum, calculate 24h risk-adjusted sizing, and recommend optimal slippage bounds for Raydium liquidity pools."; | |
| } else if (type === 'arb_scan') { | |
| p.value = "Scan Raydium CPMM vs Orca Whirlpools for flash loan cross-DEX arbitrage spreads and calculate net yield."; | |
| } else if (type === 'rebalance') { | |
| p.value = "Simulate portfolio rebalancing: maintain 60% SOL, 15% JUP, 10% RAY, and 15% USDC cash buffers to minimize drawdown."; | |
| } | |
| } | |
| async function fetchMarket() { | |
| try { | |
| const res = await fetch('/api/market'); | |
| const data = await res.json(); | |
| // Ticker | |
| if (data.prices) { | |
| document.getElementById('ticker-sol').textContent = '$' + data.prices.SOL; | |
| document.getElementById('ticker-jup').textContent = '$' + data.prices.JUP; | |
| document.getElementById('ticker-ray').textContent = '$' + data.prices.RAY; | |
| document.getElementById('ticker-wif').textContent = '$' + data.prices.WIF; | |
| } | |
| // Positions | |
| if (data.portfolio && data.portfolio.positions) { | |
| const container = document.getElementById('positions-table'); | |
| container.innerHTML = ''; | |
| data.portfolio.positions.forEach(pos => { | |
| const row = document.createElement('div'); | |
| row.className = 'grid grid-cols-12 p-3 items-center hover:bg-zinc-900/60 transition'; | |
| row.innerHTML = ` | |
| <div class="col-span-4 flex items-center space-x-2 font-bold text-white"> | |
| <span class="w-2 h-2 rounded-full ${pos.symbol === 'SOL' ? 'bg-sol-green' : 'bg-sol-purple'}"></span> | |
| <span>${pos.symbol}</span> | |
| <span class="text-zinc-500 font-normal">(${pos.name})</span> | |
| </div> | |
| <div class="col-span-3 text-right text-zinc-300 font-semibold">${pos.amount.toLocaleString()}</div> | |
| <div class="col-span-3 text-right text-white font-bold">$${pos.value_usdc.toLocaleString()}</div> | |
| <div class="col-span-2 text-right text-sol-green font-bold">${pos.allocation}%</div> | |
| `; | |
| container.appendChild(row); | |
| }); | |
| } | |
| // Arbitrage Cards | |
| if (data.arbitrage_opportunities) { | |
| const arbCont = document.getElementById('arb-cards-container'); | |
| arbCont.innerHTML = ''; | |
| data.arbitrage_opportunities.forEach(arb => { | |
| const card = document.createElement('div'); | |
| card.className = 'p-4 rounded-xl border border-zinc-800 bg-zinc-950 space-y-2 font-mono'; | |
| card.innerHTML = ` | |
| <div class="flex items-center justify-between text-xs font-bold"> | |
| <span class="text-white">${arb.pair}</span> | |
| <span class="px-2 py-0.5 rounded text-[10px] bg-sol-green/10 text-sol-green border border-sol-green/20">+${arb.spread_pct}% SPREAD</span> | |
| </div> | |
| <div class="text-[11px] text-zinc-400 space-y-1"> | |
| <div>Route: <span class="text-white">${arb.buy_venue} → ${arb.sell_venue}</span></div> | |
| <div>Estimated Profit: <span class="text-sol-green font-bold">${arb.net_profit_est}</span></div> | |
| </div> | |
| `; | |
| arbCont.appendChild(card); | |
| }); | |
| } | |
| } catch (err) { | |
| console.error(err); | |
| } | |
| } | |
| async function fetchTrades() { | |
| try { | |
| const res = await fetch('/api/trades'); | |
| const data = await res.json(); | |
| const container = document.getElementById('blotter-table'); | |
| container.innerHTML = ''; | |
| if (!data.trades || data.trades.length === 0) { | |
| container.innerHTML = '<div class="p-6 text-center text-zinc-600">No trades executed yet.</div>'; | |
| return; | |
| } | |
| data.trades.forEach(t => { | |
| const row = document.createElement('div'); | |
| row.className = 'grid grid-cols-12 p-3 items-center hover:bg-zinc-900/60 transition'; | |
| const sideColor = t.side === 'BUY' ? 'text-sol-green' : 'text-red-400'; | |
| row.innerHTML = ` | |
| <div class="col-span-3 text-zinc-400 font-bold">${t.trade_id}</div> | |
| <div class="col-span-2 text-white font-bold">${t.symbol}/USDC</div> | |
| <div class="col-span-2 ${sideColor} font-extrabold">${t.side}</div> | |
| <div class="col-span-3 text-right text-white font-bold">$${t.amount_usdc.toLocaleString()}</div> | |
| <div class="col-span-2 text-right text-sol-green font-bold text-[10px]">CONFIRMED</div> | |
| `; | |
| container.appendChild(row); | |
| }); | |
| } catch (e) { | |
| console.error(e); | |
| } | |
| } | |
| async function submitTradeOrder() { | |
| const sym = document.getElementById('trade-symbol').value; | |
| const amt = parseFloat(document.getElementById('trade-amount').value); | |
| if (!amt || amt <= 0) return; | |
| const btn = document.getElementById('btn-submit-order'); | |
| btn.disabled = true; | |
| btn.textContent = 'EXECUTING ON JUPITER...'; | |
| try { | |
| const res = await fetch('/api/trades/execute', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ symbol: sym, side: activeTradeSide, amount_usdc: amt }) | |
| }); | |
| const data = await res.json(); | |
| btn.textContent = 'ORDER CONFIRMED!'; | |
| setTimeout(() => { | |
| btn.disabled = false; | |
| btn.textContent = 'DISPATCH TO SOLANA'; | |
| }, 1200); | |
| fetchMarket(); | |
| } catch (err) { | |
| alert(err.message); | |
| btn.disabled = false; | |
| btn.textContent = 'DISPATCH TO SOLANA'; | |
| } | |
| } | |
| async function queryQuantAi() { | |
| const prompt = document.getElementById('ai-prompt').value.trim(); | |
| if (!prompt) return; | |
| const btn = document.getElementById('btn-run-ai'); | |
| btn.disabled = true; | |
| btn.className = "px-6 py-2.5 rounded-lg bg-zinc-700 text-zinc-400 font-extrabold text-xs uppercase tracking-wider transition flex items-center space-x-2 cursor-not-allowed"; | |
| btn.innerHTML = '<i data-lucide="loader-2" class="w-4 h-4 animate-spin"></i><span>Analyzing...</span>'; | |
| initIcons(); | |
| const outBox = document.getElementById('ai-output-box'); | |
| outBox.textContent = ''; | |
| try { | |
| const res = await fetch('/api/ai/analyze', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ prompt: prompt, max_tokens: 256 }) | |
| }); | |
| const reader = res.body.getReader(); | |
| const decoder = new TextDecoder('utf-8'); | |
| let buffer = ''; | |
| while (true) { | |
| const { done, value } = await reader.read(); | |
| if (done) break; | |
| buffer += decoder.decode(value, { stream: true }); | |
| const parts = buffer.split('\n\n'); | |
| buffer = parts.pop(); | |
| for (const p of parts) { | |
| if (!p.trim()) continue; | |
| let eventType = ''; | |
| let payload = ''; | |
| for (const line of p.split('\n')) { | |
| if (line.startsWith('event: ')) eventType = line.substring(7).trim(); | |
| if (line.startsWith('data: ')) payload = line.substring(6).trim(); | |
| } | |
| if (payload) { | |
| const data = JSON.parse(payload); | |
| if (eventType === 'token' && data.token) { | |
| outBox.textContent += data.token; | |
| outBox.scrollTop = outBox.scrollHeight; | |
| } | |
| } | |
| } | |
| } | |
| } catch (err) { | |
| outBox.textContent += '\n[Inference Error: ' + err.message + ']'; | |
| } finally { | |
| btn.disabled = false; | |
| btn.className = "px-6 py-2.5 rounded-lg bg-white hover:bg-zinc-200 text-black font-extrabold text-xs uppercase tracking-wider transition flex items-center space-x-2 shadow-lg active:scale-95"; | |
| btn.innerHTML = '<i data-lucide="zap" class="w-4 h-4 fill-black"></i><span>Run Analysis</span>'; | |
| initIcons(); | |
| } | |
| } | |
| function copyAiOutput() { | |
| const text = document.getElementById('ai-output-box').textContent; | |
| navigator.clipboard.writeText(text).then(() => { | |
| const btn = document.getElementById('btn-copy-ai'); | |
| btn.textContent = 'COPIED'; | |
| setTimeout(() => { btn.textContent = 'COPY'; }, 1800); | |
| }); | |
| } | |
| window.addEventListener('DOMContentLoaded', () => { | |
| initIcons(); | |
| fetchMarket(); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |