Skip to content

Latest commit

Β 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 

Repository files navigation

<title>GenFlip β€’ Heads or Tails on GenLayer</title> <script src="https://cdn.tailwindcss.com"></script> <style> @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Space+Grotesk:wght@500;600;700&display=swap');
    :root {
        --gen-green: #00ff9d;
    }
    
    * {
        transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
        transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
        transition-duration: 150ms;
    }
    
    body {
        font-family: 'Inter', system_ui, sans-serif;
    }
    
    .title-font {
        font-family: 'Space Grotesk', sans-serif;
    }

    .hero-bg {
        background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 100%);
    }
    
    .coin-container {
        perspective: 1200px;
        width: 280px;
        height: 280px;
        margin: 0 auto;
    }
    
    .coin {
        position: relative;
        width: 100%;
        height: 100%;
        transform-style: preserve-3d;
        transition: transform 3.2s cubic-bezier(0.25, 0.1, 0.25, 1);
        cursor: pointer;
    }
    
    .coin.flipping {
        animation: flipCoin 3.2s cubic-bezier(0.25, 0.1, 0.25, 1) forwards;
    }
    
    .coin-face {
        position: absolute;
        width: 100%;
        height: 100%;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        box-shadow: 
            0 0 60px -10px var(--gen-green),
            inset 0 0 60px -20px rgba(0, 255, 157, 0.5);
        backface-visibility: hidden;
        border: 12px solid #111;
    }
    
    .coin-heads {
        background: linear-gradient(145deg, #facc15, #eab308);
        transform: rotateY(0deg);
    }
    
    .coin-tails {
        background: linear-gradient(145deg, #f1f5f9, #cbd5e1);
        transform: rotateY(180deg);
    }
    
    .coin-label {
        font-size: 6rem;
        font-weight: 700;
        text-shadow: 
            0 10px 20px rgba(0, 0, 0, 0.3),
            0 0 40px rgba(255, 255, 255, 0.6);
    }
    
    @keyframes flipCoin {
        0% { transform: rotateY(0deg); }
        100% { transform: rotateY(2160deg); }
    }
    
    .neon-text {
        text-shadow: 
            0 0 10px var(--gen-green),
            0 0 20px var(--gen-green),
            0 0 40px var(--gen-green);
    }
    
    .result-win {
        animation: popIn 0.6s ease;
    }
    
    @keyframes popIn {
        0% { transform: scale(0.8); opacity: 0; }
        50% { transform: scale(1.15); }
        100% { transform: scale(1); }
    }
    
    .particle {
        position: absolute;
        pointer-events: none;
        animation: particleFloat 2s ease forwards;
    }
</style>
πŸͺ™
GenFlip
LIVE ON GENLAYER
        <!-- Right side -->
        <div class="flex items-center gap-x-8">
            <!-- Wallet -->
            <button onclick="connectWallet()" id="wallet-btn"
                class="flex items-center gap-x-2 bg-white/5 hover:bg-white/10 border border-white/10 hover:border-white/30 px-6 py-3 rounded-3xl font-medium text-sm">
                <i class="fa-solid fa-wallet"></i>
                <span id="wallet-address" class="font-mono">Connect GenLayer Wallet</span>
            </button>

            <!-- Balance -->
            <div class="flex items-center gap-x-3 bg-white/5 border border-white/10 rounded-3xl px-5 py-3">
                <i class="fa-solid fa-coins text-amber-400"></i>
                <div>
                    <span id="balance" class="font-mono text-xl font-semibold">1,337.42</span>
                    <span class="text-xs text-emerald-400 ml-1">GLT</span>
                </div>
            </div>

            <a href="https://www.genlayer.com" target="_blank"
                class="flex items-center gap-x-2 text-sm font-medium hover:text-emerald-400">
                <span>Powered by</span>
                <span class="font-semibold text-emerald-400">GenLayer</span>
                <i class="fa-solid fa-arrow-up-right-from-square text-xs"></i>
            </a>
        </div>
    </div>
</nav>

<div class="max-w-7xl mx-auto px-6 py-12">
    <!-- Hero Header -->
    <div class="text-center mb-12">
        <div class="inline-flex items-center gap-x-2 bg-white/10 text-emerald-400 text-sm font-medium px-6 py-2 rounded-3xl mb-6 border border-emerald-400/30">
            <i class="fa-solid fa-robot"></i>
            AI-VERIFIED β€’ INTELLIGENT CONTRACTS β€’ 100% ON-CHAIN
        </div>
        
        <h1 class="title-font text-7xl md:text-8xl font-bold tracking-tighter neon-text leading-none mb-4">
            HEADS<span class="text-emerald-400">.</span> OR<span class="text-emerald-400">.</span> TAILS
        </h1>
        <p class="text-2xl text-white/70 max-w-md mx-auto">
            The most beautiful coin flip on GenLayer.<br>
            Fair. Instant. AI-powered.
        </p>
        
        <div class="flex justify-center gap-8 mt-8 text-sm">
            <div class="flex items-center gap-2">
                <i class="fa-solid fa-shield-halved text-emerald-400"></i>
                <span>Provably Fair</span>
            </div>
            <div class="flex items-center gap-2">
                <i class="fa-solid fa-bolt text-amber-400"></i>
                <span>Instant Settlement</span>
            </div>
            <div class="flex items-center gap-2">
                <i class="fa-solid fa-brain text-purple-400"></i>
                <span>Intelligent Randomness</span>
            </div>
        </div>
    </div>

    <div class="grid lg:grid-cols-12 gap-8">
        <!-- Game Panel -->
        <div class="lg:col-span-7 bg-white/5 backdrop-blur-2xl border border-white/10 rounded-3xl p-8 shadow-2xl">
            
            <!-- Choice Selection -->
            <div class="flex justify-center gap-8 mb-10">
                <!-- Heads -->
                <button onclick="selectSide('heads')" id="heads-btn"
                    class="group flex-1 max-w-[220px] bg-gradient-to-br from-amber-400 to-yellow-500 text-black rounded-3xl p-6 hover:scale-105 active:scale-95 flex flex-col items-center border-4 border-transparent hover:border-amber-300">
                    <div class="text-7xl mb-3">πŸͺ™</div>
                    <div class="text-4xl font-bold title-font tracking-tighter">HEADS</div>
                    <div class="text-xs font-mono uppercase mt-2 opacity-75">50% chance β€’ 2x payout</div>
                </button>
                
                <!-- Tails -->
                <button onclick="selectSide('tails')" id="tails-btn"
                    class="group flex-1 max-w-[220px] bg-gradient-to-br from-slate-300 to-slate-100 text-black rounded-3xl p-6 hover:scale-105 active:scale-95 flex flex-col items-center border-4 border-transparent hover:border-slate-400">
                    <div class="text-7xl mb-3">πŸͺ™</div>
                    <div class="text-4xl font-bold title-font tracking-tighter">TAILS</div>
                    <div class="text-xs font-mono uppercase mt-2 opacity-75">50% chance β€’ 2x payout</div>
                </button>
            </div>

            <!-- The Coin -->
            <div class="flex flex-col items-center mb-10">
                <div id="coin-container" class="coin-container">
                    <div id="coin" class="coin" onclick="if(!isFlipping) flipCoin()">
                        <!-- Heads Face -->
                        <div class="coin-face coin-heads">
                            <span class="coin-label">H</span>
                        </div>
                        <!-- Tails Face -->
                        <div class="coin-face coin-tails">
                            <span class="coin-label">T</span>
                        </div>
                    </div>
                </div>
                
                <div class="text-center mt-6">
                    <button onclick="flipCoin()" id="flip-button"
                        class="disabled:opacity-50 disabled:cursor-not-allowed bg-emerald-500 hover:bg-emerald-600 text-black font-semibold text-2xl px-16 py-6 rounded-3xl flex items-center gap-x-3 mx-auto shadow-[0_0_40px_-10px] shadow-emerald-500">
                        <i class="fa-solid fa-arrow-rotate-right"></i>
                        <span id="flip-text">FLIP THE COIN</span>
                    </button>
                    <p id="status-text" class="text-white/60 text-sm mt-4 font-mono">Select Heads or Tails β€’ Click coin or button to flip</p>
                </div>
            </div>

            <!-- Result -->
            <div id="result-panel" class="hidden bg-black/30 border border-white/10 rounded-3xl p-6 text-center">
                <div id="result-icon" class="text-8xl mb-4"></div>
                <h3 id="result-title" class="text-5xl title-font font-bold mb-1"></h3>
                <p id="result-subtitle" class="text-xl text-white/70"></p>
                
                <div class="mt-6 flex justify-center gap-8 text-sm font-mono">
                    <div class="text-center">
                        <div class="text-emerald-400">YOU BET</div>
                        <div id="bet-display" class="text-3xl font-bold"></div>
                    </div>
                    <div class="text-center">
                        <div class="text-white/60">RESULT</div>
                        <div id="result-display" class="text-3xl font-bold"></div>
                    </div>
                    <div class="text-center">
                        <div class="text-emerald-400">PAYOUT</div>
                        <div id="payout-display" class="text-3xl font-bold text-emerald-400"></div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Sidebar -->
        <div class="lg:col-span-5 space-y-6">
            
            <!-- Stats -->
            <div class="bg-white/5 backdrop-blur-2xl border border-white/10 rounded-3xl p-6">
                <div class="flex justify-between items-baseline mb-6">
                    <h3 class="text-lg font-semibold">Live Stats</h3>
                    <div class="text-xs font-mono text-emerald-400">ON GENLAYER MAINNET</div>
                </div>
                
                <div class="grid grid-cols-3 gap-4">
                    <div class="text-center bg-black/30 rounded-2xl py-4">
                        <div class="text-4xl font-bold text-emerald-400" id="total-flips">248,419</div>
                        <div class="text-xs font-mono uppercase">Flips Today</div>
                    </div>
                    <div class="text-center bg-black/30 rounded-2xl py-4">
                        <div class="text-4xl font-bold text-amber-400" id="biggest-win">42.8 GLT</div>
                        <div class="text-xs font-mono uppercase">Biggest Win</div>
                    </div>
                    <div class="text-center bg-black/30 rounded-2xl py-4">
                        <div class="text-4xl font-bold" id="win-rate">49.8%</div>
                        <div class="text-xs font-mono uppercase">Heads Win Rate</div>
                    </div>
                </div>
            </div>

            <!-- Flip History -->
            <div class="bg-white/5 backdrop-blur-2xl border border-white/10 rounded-3xl p-6 flex-1 flex flex-col">
                <h3 class="text-lg font-semibold mb-4 flex items-center justify-between">
                    Recent Flips
                    <span onclick="clearHistory()" class="text-xs cursor-pointer hover:text-red-400">CLEAR</span>
                </h3>
                
                <div id="history-list" class="flex-1 overflow-auto space-y-3 text-sm font-mono">
                    <!-- Populated by JS -->
                </div>
            </div>

            <!-- How it works -->
            <div class="text-xs bg-white/5 border border-white/10 rounded-3xl p-6 leading-relaxed">
                <div class="flex gap-2 items-center mb-3 text-emerald-400">
                    <i class="fa-solid fa-circle-info"></i>
                    <strong>Powered by GenLayer Intelligent Contracts</strong>
                </div>
                <p class="opacity-75">
                    Your flip is executed by an AI-augmented Python contract on GenLayer. 
                    True randomness is verified by multiple LLM validators. 
                    No oracles. No trust. Pure decentralized beauty.
                </p>
                <a href="https://docs.genlayer.com" target="_blank" 
                   class="inline-flex items-center gap-1 text-emerald-400 text-xs mt-4 hover:underline">
                    View contract source on GenLayer Studio β†’
                </a>
            </div>
        </div>
    </div>
</div>

<!-- Footer bar -->
<div class="bg-black/70 border-t border-white/10 py-4 text-center text-xs font-mono text-white/40">
    Built as a beautiful demo dApp for GenLayer β€’ Intelligent Contracts in Python β€’ Try it on GenLayer Testnet
</div>

<script>
    // Tailwind script already loaded
    function initializeTailwind() {
        // Already initialized via CDN
    }

    // Game state
    let selectedSide = null
    let isFlipping = false
    let balance = 1337.42
    let history = []

    // Fake GenLayer wallet
    let walletConnected = false
    let walletAddress = "0x7aF8...9kL2"

    function connectWallet() {
        const btn = document.getElementById('wallet-btn')
        if (!walletConnected) {
            // Simulate GenLayer wallet connection
            btn.innerHTML = `
                <i class="fa-solid fa-circle-check text-emerald-400"></i>
                <span class="font-mono">${walletAddress}</span>
            `
            walletConnected = true
            createConfetti()
            showToast("βœ… Connected to GenLayer Wallet", "Now flipping with real on-chain randomness!")
        } else {
            alert("Already connected! (Demo)")
        }
    }

    function selectSide(side) {
        if (isFlipping) return
        
        selectedSide = side
        
        // Reset buttons
        document.getElementById('heads-btn').classList.remove('ring-4', 'ring-offset-4', 'ring-emerald-400')
        document.getElementById('tails-btn').classList.remove('ring-4', 'ring-offset-4', 'ring-emerald-400')
        
        // Highlight chosen
        const chosenBtn = document.getElementById(side + '-btn')
        chosenBtn.classList.add('ring-4', 'ring-offset-4', 'ring-emerald-400')
        
        document.getElementById('flip-text').textContent = `FLIP FOR ${side.toUpperCase()}`
        document.getElementById('status-text').innerHTML = `You chose <span class="text-emerald-400 uppercase">${side}</span> β€’ Ready to flip`
    }

    function flipCoin() {
        if (isFlipping || !selectedSide) {
            if (!selectedSide) showToast("⚠️ First choose Heads or Tails!", "Pick a side above")
            return
        }
        
        isFlipping = true
        const coin = document.getElementById('coin')
        const status = document.getElementById('status-text')
        
        // Start flipping animation
        coin.classList.add('flipping')
        status.textContent = 'FLIPPING ON GENLAYER... AI validators confirming fairness'
        
        // Disable button
        const flipBtn = document.getElementById('flip-button')
        flipBtn.disabled = true
        
        // Simulate on-chain delay + animation
        setTimeout(() => {
            // Determine result
            const result = Math.random() > 0.5 ? 'heads' : 'tails'
            
            // Reset animation
            coin.classList.remove('flipping')
            
            // Force final rotation based on result
            if (result === 'tails') {
                coin.style.transform = 'rotateY(1800deg)'
            } else {
                coin.style.transform = 'rotateY(1980deg)'
            }
            
            // Show result after small delay
            setTimeout(() => {
                handleResult(result)
            }, 600)
        }, 3200)
    }

    function handleResult(result) {
        isFlipping = false
        const coin = document.getElementById('coin')
        
        // Reset coin visual
        setTimeout(() => {
            coin.style.transform = result === 'tails' ? 'rotateY(180deg)' : 'rotateY(0deg)'
        }, 100)
        
        // Calculate win
        const win = result === selectedSide
        let payout = win ? 20 : -10   // Fake 2x bet of 10 GLT
        
        // Update balance
        balance += payout
        document.getElementById('balance').textContent = balance.toFixed(2)
        
        // Show result panel
        const panel = document.getElementById('result-panel')
        panel.classList.remove('hidden')
        panel.classList.add('result-win')
        
        const iconEl = document.getElementById('result-icon')
        const titleEl = document.getElementById('result-title')
        const subtitleEl = document.getElementById('result-subtitle')
        const betEl = document.getElementById('bet-display')
        const resultEl = document.getElementByI

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors