Files

657 lines
21 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>💎🙌 DIAMOND HANDS TRADING BOT 🙌💎</title>
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&family=Russo+One&family=Bangers&display=swap" rel="stylesheet">
<style>
:root {
--wsb-orange: #ff4500;
--moon-yellow: #ffd700;
--tendies-green: #00ff88;
--loss-red: #ff3366;
--degen-purple: #9b30ff;
--diamond-blue: #00d4ff;
--bg-dark: #0a0a0f;
--bg-card: #12121a;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Russo One', sans-serif;
background: var(--bg-dark);
color: #fff;
min-height: 100vh;
overflow-x: hidden;
}
/* Animated background */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
radial-gradient(ellipse at 20% 80%, rgba(255, 69, 0, 0.15) 0%, transparent 50%),
radial-gradient(ellipse at 80% 20%, rgba(155, 48, 255, 0.15) 0%, transparent 50%),
radial-gradient(ellipse at 50% 50%, rgba(0, 212, 255, 0.08) 0%, transparent 50%);
pointer-events: none;
z-index: -1;
}
.header {
text-align: center;
padding: 30px 20px;
background: linear-gradient(135deg, var(--wsb-orange) 0%, var(--degen-purple) 50%, var(--diamond-blue) 100%);
background-size: 200% 200%;
animation: gradient-shift 5s ease infinite;
border-bottom: 4px solid var(--moon-yellow);
box-shadow: 0 0 50px rgba(255, 215, 0, 0.3);
}
@keyframes gradient-shift {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
.header h1 {
font-family: 'Bangers', cursive;
font-size: 3rem;
text-shadow:
3px 3px 0 #000,
-1px -1px 0 #000,
0 0 20px var(--moon-yellow);
letter-spacing: 4px;
animation: pulse-text 2s ease-in-out infinite;
}
@keyframes pulse-text {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.02); }
}
.header .subtitle {
font-family: 'Press Start 2P', cursive;
font-size: 0.7rem;
margin-top: 10px;
opacity: 0.9;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
.dashboard {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-bottom: 20px;
}
.card {
background: var(--bg-card);
border-radius: 16px;
padding: 24px;
border: 2px solid transparent;
background-clip: padding-box;
position: relative;
overflow: hidden;
transition: transform 0.3s, box-shadow 0.3s;
}
.card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 16px;
padding: 2px;
background: linear-gradient(135deg, var(--wsb-orange), var(--degen-purple), var(--diamond-blue));
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 40px rgba(255, 69, 0, 0.2);
}
.card-title {
font-family: 'Bangers', cursive;
font-size: 1.5rem;
color: var(--moon-yellow);
margin-bottom: 15px;
letter-spacing: 2px;
}
.stat-value {
font-size: 2.5rem;
font-weight: bold;
margin: 10px 0;
}
.stat-value.positive { color: var(--tendies-green); text-shadow: 0 0 20px var(--tendies-green); }
.stat-value.negative { color: var(--loss-red); text-shadow: 0 0 20px var(--loss-red); }
.stat-value.neutral { color: var(--diamond-blue); text-shadow: 0 0 20px var(--diamond-blue); }
.trade-button {
display: block;
width: 100%;
padding: 20px 40px;
font-family: 'Bangers', cursive;
font-size: 2rem;
color: #fff;
background: linear-gradient(135deg, var(--wsb-orange), var(--loss-red));
border: none;
border-radius: 12px;
cursor: pointer;
letter-spacing: 3px;
text-transform: uppercase;
transition: all 0.3s;
box-shadow: 0 10px 30px rgba(255, 69, 0, 0.4);
animation: button-glow 2s ease-in-out infinite;
}
@keyframes button-glow {
0%, 100% { box-shadow: 0 10px 30px rgba(255, 69, 0, 0.4); }
50% { box-shadow: 0 10px 50px rgba(255, 69, 0, 0.7); }
}
.trade-button:hover {
transform: scale(1.05);
background: linear-gradient(135deg, var(--tendies-green), var(--diamond-blue));
}
.trade-button:active {
transform: scale(0.98);
}
.auto-trade {
display: flex;
align-items: center;
justify-content: center;
gap: 15px;
margin-top: 15px;
font-size: 1.1rem;
}
.toggle-switch {
position: relative;
width: 60px;
height: 30px;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.toggle-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #333;
border-radius: 30px;
transition: 0.4s;
}
.toggle-slider::before {
position: absolute;
content: "";
height: 22px;
width: 22px;
left: 4px;
bottom: 4px;
background: white;
border-radius: 50%;
transition: 0.4s;
}
.toggle-switch input:checked + .toggle-slider {
background: linear-gradient(135deg, var(--tendies-green), var(--diamond-blue));
}
.toggle-switch input:checked + .toggle-slider::before {
transform: translateX(30px);
}
.trades-list {
max-height: 400px;
overflow-y: auto;
}
.trades-list::-webkit-scrollbar {
width: 8px;
}
.trades-list::-webkit-scrollbar-track {
background: var(--bg-dark);
border-radius: 4px;
}
.trades-list::-webkit-scrollbar-thumb {
background: var(--degen-purple);
border-radius: 4px;
}
.trade-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 15px;
margin: 8px 0;
background: rgba(255, 255, 255, 0.05);
border-radius: 10px;
border-left: 4px solid;
animation: slide-in 0.3s ease-out;
}
@keyframes slide-in {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.trade-item.buy { border-left-color: var(--tendies-green); }
.trade-item.sell { border-left-color: var(--loss-red); }
.trade-info {
display: flex;
flex-direction: column;
gap: 4px;
}
.trade-ticker {
font-weight: bold;
font-size: 1.1rem;
}
.trade-details {
font-size: 0.85rem;
opacity: 0.7;
}
.trade-message {
font-size: 0.9rem;
color: var(--moon-yellow);
}
.trade-value {
text-align: right;
}
.trade-pnl {
font-weight: bold;
}
.trade-pnl.profit { color: var(--tendies-green); }
.trade-pnl.loss { color: var(--loss-red); }
.prices-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 10px;
}
.price-item {
text-align: center;
padding: 15px 10px;
background: rgba(255, 255, 255, 0.05);
border-radius: 10px;
transition: transform 0.2s;
}
.price-item:hover {
transform: scale(1.05);
background: rgba(255, 255, 255, 0.1);
}
.price-ticker {
font-weight: bold;
font-size: 1rem;
color: var(--moon-yellow);
}
.price-value {
font-size: 0.85rem;
margin-top: 5px;
color: var(--diamond-blue);
}
.holdings-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.holding-item {
display: flex;
justify-content: space-between;
padding: 12px;
background: rgba(0, 212, 255, 0.1);
border-radius: 8px;
border: 1px solid rgba(0, 212, 255, 0.3);
}
.rocket-rain {
position: fixed;
pointer-events: none;
z-index: 1000;
font-size: 2rem;
animation: rocket-fly 2s ease-out forwards;
}
@keyframes rocket-fly {
0% {
opacity: 1;
transform: translateY(0) rotate(-45deg);
}
100% {
opacity: 0;
transform: translateY(-500px) rotate(-45deg);
}
}
.message-popup {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
font-family: 'Bangers', cursive;
font-size: 2.5rem;
color: var(--moon-yellow);
text-shadow: 3px 3px 0 #000, 0 0 30px var(--moon-yellow);
z-index: 1000;
animation: popup-message 1.5s ease-out forwards;
text-align: center;
white-space: nowrap;
}
@keyframes popup-message {
0% { transform: translate(-50%, -50%) scale(0); opacity: 0; }
20% { transform: translate(-50%, -50%) scale(1.2); opacity: 1; }
40% { transform: translate(-50%, -50%) scale(1); }
100% { transform: translate(-50%, -50%) scale(1); opacity: 0; }
}
.empty-state {
text-align: center;
padding: 30px;
opacity: 0.6;
}
.empty-state .emoji {
font-size: 3rem;
margin-bottom: 10px;
}
@media (max-width: 768px) {
.header h1 {
font-size: 1.8rem;
}
.stat-value {
font-size: 1.8rem;
}
.trade-button {
font-size: 1.5rem;
padding: 15px 30px;
}
}
</style>
</head>
<body>
<header class="header">
<h1>💎🙌 DIAMOND HANDS BOT 🙌💎</h1>
<p class="subtitle">🚀 APE TOGETHER STRONG • TENDIES OR BUST 🚀</p>
</header>
<div class="container">
<div class="dashboard">
<div class="card">
<div class="card-title">💰 CASH BALANCE</div>
<div class="stat-value neutral" id="balance">$10,000.00</div>
</div>
<div class="card">
<div class="card-title">📊 PORTFOLIO VALUE</div>
<div class="stat-value neutral" id="total-value">$10,000.00</div>
</div>
<div class="card">
<div class="card-title">📈 TOTAL GAINS</div>
<div class="stat-value" id="total-gains">$0.00</div>
</div>
</div>
<div class="card" style="margin-bottom: 20px;">
<button class="trade-button" id="trade-btn" onclick="executeTrade()">
🎰 YOLO TRADE 🎰
</button>
<div class="auto-trade">
<span>🤖 AUTO-DEGEN MODE:</span>
<label class="toggle-switch">
<input type="checkbox" id="auto-trade" onchange="toggleAutoTrade()">
<span class="toggle-slider"></span>
</label>
</div>
</div>
<div class="dashboard">
<div class="card">
<div class="card-title">💹 LIVE PRICES</div>
<div class="prices-grid" id="prices-grid">
<!-- Prices will be loaded here -->
</div>
</div>
<div class="card">
<div class="card-title">🎒 YOUR BAGS</div>
<div class="holdings-list" id="holdings-list">
<div class="empty-state">
<div class="emoji">🦍</div>
<p>No bags yet, ape!</p>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-title">📜 TRADE HISTORY</div>
<div class="trades-list" id="trades-list">
<div class="empty-state">
<div class="emoji">🚀</div>
<p>Hit that YOLO button to start trading!</p>
</div>
</div>
</div>
</div>
<script>
let autoTradeInterval = null;
async function fetchPortfolio() {
try {
const res = await fetch('/api/portfolio');
const data = await res.json();
updateUI(data);
} catch (e) {
console.error('Failed to fetch portfolio:', e);
}
}
async function fetchPrices() {
try {
const res = await fetch('/api/prices');
const prices = await res.json();
updatePrices(prices);
} catch (e) {
console.error('Failed to fetch prices:', e);
}
}
function updateUI(data) {
// Update balance
document.getElementById('balance').textContent = `$${data.balance.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2})}`;
// Update total value
document.getElementById('total-value').textContent = `$${data.total_value.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2})}`;
// Update gains with color
const gainsEl = document.getElementById('total-gains');
const gains = data.total_gains;
gainsEl.textContent = `${gains >= 0 ? '+' : ''}$${gains.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2})}`;
gainsEl.className = 'stat-value ' + (gains >= 0 ? 'positive' : 'negative');
// Update holdings
const holdingsList = document.getElementById('holdings-list');
if (Object.keys(data.holdings).length === 0) {
holdingsList.innerHTML = `
<div class="empty-state">
<div class="emoji">🦍</div>
<p>No bags yet, ape!</p>
</div>
`;
} else {
holdingsList.innerHTML = Object.entries(data.holdings).map(([ticker, info]) => `
<div class="holding-item">
<span><strong>${ticker}</strong></span>
<span>${info.quantity.toLocaleString()} @ $${info.avg_price.toFixed(6)}</span>
</div>
`).join('');
}
// Update trades
const tradesList = document.getElementById('trades-list');
if (data.trades.length === 0) {
tradesList.innerHTML = `
<div class="empty-state">
<div class="emoji">🚀</div>
<p>Hit that YOLO button to start trading!</p>
</div>
`;
} else {
tradesList.innerHTML = data.trades.map(trade => `
<div class="trade-item ${trade.action.toLowerCase()}">
<div class="trade-info">
<span class="trade-ticker">${trade.action} ${trade.ticker}</span>
<span class="trade-details">${trade.quantity.toLocaleString()} @ $${trade.price}</span>
<span class="trade-message">${trade.message}</span>
</div>
<div class="trade-value">
<div>$${trade.value.toLocaleString()}</div>
${trade.pnl !== 0 ? `<div class="trade-pnl ${trade.pnl >= 0 ? 'profit' : 'loss'}">${trade.pnl >= 0 ? '+' : ''}$${trade.pnl.toFixed(2)}</div>` : ''}
<div style="font-size: 0.75rem; opacity: 0.6;">${trade.timestamp}</div>
</div>
</div>
`).join('');
}
}
function updatePrices(prices) {
const grid = document.getElementById('prices-grid');
grid.innerHTML = Object.entries(prices).map(([ticker, price]) => `
<div class="price-item">
<div class="price-ticker">${ticker}</div>
<div class="price-value">$${price < 0.01 ? price.toFixed(8) : price.toFixed(2)}</div>
</div>
`).join('');
}
async function executeTrade() {
const btn = document.getElementById('trade-btn');
btn.disabled = true;
btn.textContent = '🎲 ROLLING... 🎲';
try {
const res = await fetch('/api/trade', { method: 'POST' });
const trade = await res.json();
if (trade.error) {
showMessage(trade.error);
} else {
showMessage(trade.message);
spawnRockets();
}
await fetchPortfolio();
} catch (e) {
console.error('Trade failed:', e);
showMessage('💀 TRADE FAILED 💀');
}
btn.disabled = false;
btn.textContent = '🎰 YOLO TRADE 🎰';
}
function showMessage(msg) {
const popup = document.createElement('div');
popup.className = 'message-popup';
popup.textContent = msg;
document.body.appendChild(popup);
setTimeout(() => popup.remove(), 1500);
}
function spawnRockets() {
for (let i = 0; i < 5; i++) {
setTimeout(() => {
const rocket = document.createElement('div');
rocket.className = 'rocket-rain';
rocket.textContent = '🚀';
rocket.style.left = Math.random() * window.innerWidth + 'px';
rocket.style.top = window.innerHeight + 'px';
document.body.appendChild(rocket);
setTimeout(() => rocket.remove(), 2000);
}, i * 100);
}
}
function toggleAutoTrade() {
const isAuto = document.getElementById('auto-trade').checked;
if (isAuto) {
showMessage('🤖 DEGEN MODE ACTIVATED! 🤖');
autoTradeInterval = setInterval(executeTrade, 2000);
} else {
showMessage('🛑 DEGEN MODE OFF 🛑');
clearInterval(autoTradeInterval);
autoTradeInterval = null;
}
}
// Initial load
fetchPortfolio();
fetchPrices();
// Refresh prices every 5 seconds
setInterval(fetchPrices, 5000);
</script>
</body>
</html>