Spaces:
No application file
No application file
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Web3 Smart Contract Adventure</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .blockchain-animation { | |
| background: linear-gradient(90deg, #1a202c 0%, #2d3748 50%, #1a202c 100%); | |
| background-size: 200% 100%; | |
| animation: blockchainFlow 5s linear infinite; | |
| } | |
| @keyframes blockchainFlow { | |
| 0% { background-position: 200% 0; } | |
| 100% { background-position: -200% 0; } | |
| } | |
| .contract-code { | |
| font-family: 'Courier New', monospace; | |
| background-color: #2d3748; | |
| border-left: 4px solid #4299e1; | |
| } | |
| .wallet-pulse { | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { box-shadow: 0 0 0 0 rgba(66, 153, 225, 0.7); } | |
| 70% { box-shadow: 0 0 0 10px rgba(66, 153, 225, 0); } | |
| 100% { box-shadow: 0 0 0 0 rgba(66, 153, 225, 0); } | |
| } | |
| .transaction-animation { | |
| transition: all 0.5s ease; | |
| } | |
| .terminal { | |
| background-color: #1a202c; | |
| font-family: 'Courier New', monospace; | |
| height: 200px; | |
| overflow-y: auto; | |
| } | |
| .terminal-line { | |
| animation: typing 0.5s steps(40, end); | |
| } | |
| @keyframes typing { | |
| from { width: 0 } | |
| to { width: 100% } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-900 text-gray-100 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <header class="flex justify-between items-center mb-12"> | |
| <div class="flex items-center space-x-4"> | |
| <i class="fas fa-cube text-blue-400 text-3xl"></i> | |
| <h1 class="text-3xl font-bold bg-gradient-to-r from-blue-400 to-purple-500 bg-clip-text text-transparent"> | |
| Web3 Smart Contract Adventure | |
| </h1> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <div class="bg-gray-800 px-4 py-2 rounded-full flex items-center"> | |
| <i class="fas fa-coins text-yellow-400 mr-2"></i> | |
| <span id="balance">100</span> ETH | |
| </div> | |
| <div id="wallet" class="wallet-pulse bg-blue-900 px-4 py-2 rounded-full cursor-pointer hover:bg-blue-800 transition"> | |
| <i class="fas fa-wallet mr-2"></i> | |
| <span>0x7f...3a4b</span> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Game Progress --> | |
| <div class="mb-8"> | |
| <div class="flex justify-between mb-2"> | |
| <span class="text-sm">Beginner's Journey</span> | |
| <span class="text-sm">25% Complete</span> | |
| </div> | |
| <div class="w-full bg-gray-700 rounded-full h-2.5"> | |
| <div class="bg-blue-500 h-2.5 rounded-full" style="width: 25%"></div> | |
| </div> | |
| </div> | |
| <!-- Main Game Area --> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
| <!-- Left Panel - Lessons --> | |
| <div class="lg:col-span-2 space-y-8"> | |
| <!-- Current Lesson --> | |
| <div class="bg-gray-800 rounded-xl p-6 shadow-lg border-l-4 border-blue-500"> | |
| <h2 class="text-2xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-file-contract mr-3 text-blue-400"></i> | |
| Lesson 2: Understanding Smart Contracts | |
| </h2> | |
| <div class="mb-6"> | |
| <p class="mb-4">Smart contracts are self-executing contracts with the terms of the agreement directly written into code. They run on blockchain networks like Ethereum.</p> | |
| <div class="contract-code p-4 rounded-lg mb-4 text-sm"> | |
| <p class="text-blue-300">// Simple Storage Contract Example</p> | |
| <p class="text-purple-300">pragma solidity ^0.8.0;</p> | |
| <br> | |
| <p class="text-blue-300">contract SimpleStorage {</p> | |
| <p class="ml-4 text-gray-300"> uint storedData;</p> | |
| <br> | |
| <p class="ml-4 text-blue-300"> function set(uint x) public {</p> | |
| <p class="ml-8 text-gray-300"> storedData = x;</p> | |
| <p class="ml-4 text-blue-300"> }</p> | |
| <br> | |
| <p class="ml-4 text-blue-300"> function get() public view returns (uint) {</p> | |
| <p class="ml-8 text-gray-300"> return storedData;</p> | |
| <p class="ml-4 text-blue-300"> }</p> | |
| <p class="text-blue-300">}</p> | |
| </div> | |
| <p class="mb-4">Key characteristics of smart contracts:</p> | |
| <ul class="list-disc pl-6 space-y-2 mb-4"> | |
| <li><span class="font-semibold">Immutable:</span> Once deployed, the code cannot be changed</li> | |
| <li><span class="font-semibold">Transparent:</span> Code is visible to everyone on the blockchain</li> | |
| <li><span class="font-semibold">Self-executing:</span> Runs automatically when conditions are met</li> | |
| <li><span class="font-semibold">Trustless:</span> No need for intermediaries</li> | |
| </ul> | |
| </div> | |
| <div class="bg-blue-900 bg-opacity-30 p-4 rounded-lg mb-6"> | |
| <h3 class="font-bold text-lg mb-2 flex items-center"> | |
| <i class="fas fa-lightbulb mr-2 text-yellow-300"></i> | |
| Interactive Exercise | |
| </h3> | |
| <p class="mb-4">Let's interact with a simulated smart contract. This contract stores a number that anyone can update.</p> | |
| <div class="flex flex-wrap gap-4 mb-4"> | |
| <button id="readContract" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded-lg flex items-center"> | |
| <i class="fas fa-book-open mr-2"></i> Read Contract | |
| </button> | |
| <button id="writeContract" class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded-lg flex items-center"> | |
| <i class="fas fa-edit mr-2"></i> Update Value | |
| </button> | |
| <button id="deployContract" class="bg-green-600 hover:bg-green-700 px-4 py-2 rounded-lg flex items-center"> | |
| <i class="fas fa-rocket mr-2"></i> Deploy New Contract | |
| </button> | |
| </div> | |
| <div id="contractInteractionResult" class="bg-gray-700 p-3 rounded-lg hidden"> | |
| <p class="text-sm">Transaction result will appear here...</p> | |
| </div> | |
| </div> | |
| <div class="flex justify-between"> | |
| <button class="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded-lg flex items-center"> | |
| <i class="fas fa-arrow-left mr-2"></i> Previous Lesson | |
| </button> | |
| <button class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded-lg flex items-center"> | |
| Next Lesson <i class="fas fa-arrow-right ml-2"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Quiz Section --> | |
| <div id="quizSection" class="bg-gray-800 rounded-xl p-6 shadow-lg border-l-4 border-purple-500 hidden"> | |
| <h2 class="text-2xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-question-circle mr-3 text-purple-400"></i> | |
| Knowledge Check | |
| </h2> | |
| <div class="mb-6"> | |
| <p class="mb-4">Test your understanding of smart contracts with these questions:</p> | |
| <div class="space-y-4"> | |
| <div class="quiz-question bg-gray-700 p-4 rounded-lg"> | |
| <p class="font-semibold mb-2">1. What makes smart contracts different from traditional contracts?</p> | |
| <div class="space-y-2"> | |
| <label class="flex items-center"> | |
| <input type="radio" name="q1" class="mr-2" value="a"> | |
| They are written in programming languages | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="radio" name="q1" class="mr-2" value="b"> | |
| They are stored on a blockchain and execute automatically | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="radio" name="q1" class="mr-2" value="c"> | |
| They require lawyers to interpret them | |
| </label> | |
| </div> | |
| </div> | |
| <div class="quiz-question bg-gray-700 p-4 rounded-lg"> | |
| <p class="font-semibold mb-2">2. What happens when you deploy a smart contract to Ethereum?</p> | |
| <div class="space-y-2"> | |
| <label class="flex items-center"> | |
| <input type="radio" name="q2" class="mr-2" value="a"> | |
| It gets stored on the blockchain and receives an address | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="radio" name="q2" class="mr-2" value="b"> | |
| It gets sent to all Ethereum users' computers | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="radio" name="q2" class="mr-2" value="c"> | |
| It becomes part of the Ethereum core software | |
| </label> | |
| </div> | |
| </div> | |
| <div class="quiz-question bg-gray-700 p-4 rounded-lg"> | |
| <p class="font-semibold mb-2">3. Why are smart contracts considered "trustless"?</p> | |
| <div class="space-y-2"> | |
| <label class="flex items-center"> | |
| <input type="radio" name="q3" class="mr-2" value="a"> | |
| Because you shouldn't trust them | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="radio" name="q3" class="mr-2" value="b"> | |
| Because they eliminate the need for trusted third parties | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="radio" name="q3" class="mr-2" value="c"> | |
| Because they are anonymous | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <button id="submitQuiz" class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded-lg w-full flex items-center justify-center"> | |
| <i class="fas fa-check-circle mr-2"></i> Submit Answers | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Right Panel - Blockchain Simulator --> | |
| <div class="space-y-8"> | |
| <!-- Blockchain Visualization --> | |
| <div class="bg-gray-800 rounded-xl p-6 shadow-lg"> | |
| <h2 class="text-xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-link mr-2 text-green-400"></i> | |
| Blockchain Simulator | |
| </h2> | |
| <div class="blockchain-animation rounded-lg p-4 mb-4"> | |
| <div class="flex overflow-x-auto space-x-4 pb-2"> | |
| <div class="block bg-gray-700 p-3 rounded-lg min-w-[200px]"> | |
| <div class="text-xs text-gray-400 mb-1">Block #1</div> | |
| <div class="text-sm mb-1">Genesis Block</div> | |
| <div class="text-xs text-gray-400">0x000...000</div> | |
| </div> | |
| <div class="block bg-gray-700 p-3 rounded-lg min-w-[200px]"> | |
| <div class="text-xs text-gray-400 mb-1">Block #2</div> | |
| <div class="text-sm mb-1">Your Wallet Created</div> | |
| <div class="text-xs text-gray-400">0x7f3...a4b</div> | |
| </div> | |
| <div id="latestBlock" class="block bg-blue-900 p-3 rounded-lg min-w-[200px]"> | |
| <div class="text-xs text-gray-400 mb-1">Block #3</div> | |
| <div class="text-sm mb-1">Ready for new transactions</div> | |
| <div class="text-xs text-gray-400">Pending...</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="terminal p-3 rounded-lg mb-4"> | |
| <div class="terminal-line text-green-400">$ Welcome to Web3 Adventure!</div> | |
| <div class="terminal-line">$ Your wallet is connected: 0x7f...3a4b</div> | |
| <div class="terminal-line">$ Balance: 100 ETH</div> | |
| <div id="terminalOutput" class="terminal-line"></div> | |
| </div> | |
| <div class="text-center"> | |
| <button id="mineBlock" class="bg-green-600 hover:bg-green-700 px-4 py-2 rounded-lg flex items-center mx-auto"> | |
| <i class="fas fa-hammer mr-2"></i> Mine Block | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Wallet Transactions --> | |
| <div class="bg-gray-800 rounded-xl p-6 shadow-lg"> | |
| <h2 class="text-xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-exchange-alt mr-2 text-yellow-400"></i> | |
| Transaction History | |
| </h2> | |
| <div class="space-y-3"> | |
| <div class="transaction bg-gray-700 p-3 rounded-lg transaction-animation"> | |
| <div class="flex justify-between text-sm"> | |
| <span class="text-blue-300">Wallet Creation</span> | |
| <span class="text-gray-400">2 min ago</span> | |
| </div> | |
| <div class="text-xs text-gray-400">+100 ETH</div> | |
| </div> | |
| <div id="newTransactions" class="space-y-3"> | |
| <!-- New transactions will appear here --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Achievement Badges --> | |
| <div class="bg-gray-800 rounded-xl p-6 shadow-lg"> | |
| <h2 class="text-xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-trophy mr-2 text-yellow-300"></i> | |
| Your Achievements | |
| </h2> | |
| <div class="grid grid-cols-3 gap-3"> | |
| <div class="achievement bg-blue-900 bg-opacity-30 p-2 rounded-lg text-center"> | |
| <div class="mx-auto bg-blue-500 rounded-full w-10 h-10 flex items-center justify-center mb-1"> | |
| <i class="fas fa-check"></i> | |
| </div> | |
| <div class="text-xs">Wallet Setup</div> | |
| </div> | |
| <div class="achievement bg-gray-700 p-2 rounded-lg text-center opacity-50"> | |
| <div class="mx-auto bg-gray-500 rounded-full w-10 h-10 flex items-center justify-center mb-1"> | |
| <i class="fas fa-file-contract"></i> | |
| </div> | |
| <div class="text-xs">First Contract</div> | |
| </div> | |
| <div class="achievement bg-gray-700 p-2 rounded-lg text-center opacity-50"> | |
| <div class="mx-auto bg-gray-500 rounded-full w-10 h-10 flex items-center justify-center mb-1"> | |
| <i class="fas fa-code"></i> | |
| </div> | |
| <div class="text-xs">Solidity Pro</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Game state | |
| let gameState = { | |
| balance: 100, | |
| contractValue: 0, | |
| transactions: [], | |
| quizAnswers: { | |
| q1: null, | |
| q2: null, | |
| q3: null | |
| }, | |
| lessonProgress: 25 | |
| }; | |
| // DOM Elements | |
| const balanceElement = document.getElementById('balance'); | |
| const terminalOutput = document.getElementById('terminalOutput'); | |
| const contractInteractionResult = document.getElementById('contractInteractionResult'); | |
| const newTransactions = document.getElementById('newTransactions'); | |
| const quizSection = document.getElementById('quizSection'); | |
| const latestBlock = document.getElementById('latestBlock'); | |
| // Buttons | |
| const readContractBtn = document.getElementById('readContract'); | |
| const writeContractBtn = document.getElementById('writeContract'); | |
| const deployContractBtn = document.getElementById('deployContract'); | |
| const mineBlockBtn = document.getElementById('mineBlock'); | |
| const submitQuizBtn = document.getElementById('submitQuiz'); | |
| const walletBtn = document.getElementById('wallet'); | |
| // Event Listeners | |
| readContractBtn.addEventListener('click', readContract); | |
| writeContractBtn.addEventListener('click', writeContract); | |
| deployContractBtn.addEventListener('click', deployContract); | |
| mineBlockBtn.addEventListener('click', mineBlock); | |
| submitQuizBtn.addEventListener('click', submitQuiz); | |
| walletBtn.addEventListener('click', showWalletInfo); | |
| // Game Functions | |
| function readContract() { | |
| addTerminalOutput(`> Reading contract value...`); | |
| setTimeout(() => { | |
| contractInteractionResult.classList.remove('hidden'); | |
| contractInteractionResult.innerHTML = ` | |
| <p class="text-green-400">Contract read successful!</p> | |
| <p class="text-sm mt-1">Current stored value: ${gameState.contractValue}</p> | |
| `; | |
| addTerminalOutput(`β Contract value is ${gameState.contractValue}`); | |
| addTransaction('Contract Read', '0 ETH', 'Read operation'); | |
| }, 1000); | |
| } | |
| function writeContract() { | |
| addTerminalOutput(`> Updating contract value...`); | |
| const newValue = Math.floor(Math.random() * 100); | |
| setTimeout(() => { | |
| contractInteractionResult.classList.remove('hidden'); | |
| contractInteractionResult.innerHTML = ` | |
| <p class="text-green-400">Contract write successful!</p> | |
| <p class="text-sm mt-1">Value updated from ${gameState.contractValue} to ${newValue}</p> | |
| <p class="text-xs mt-2 text-gray-400">Gas used: 0.00042 ETH</p> | |
| `; | |
| gameState.contractValue = newValue; | |
| gameState.balance -= 0.00042; | |
| balanceElement.textContent = gameState.balance.toFixed(5); | |
| addTerminalOutput(`β Contract value updated to ${newValue}`); | |
| addTerminalOutput(`- 0.00042 ETH (gas fee)`); | |
| addTransaction('Contract Write', '-0.00042 ETH', 'Value updated'); | |
| // Show quiz after first contract interaction | |
| if (!localStorage.getItem('quizShown')) { | |
| setTimeout(() => { | |
| quizSection.classList.remove('hidden'); | |
| localStorage.setItem('quizShown', 'true'); | |
| }, 1500); | |
| } | |
| }, 1500); | |
| } | |
| function deployContract() { | |
| addTerminalOutput(`> Deploying new contract...`); | |
| setTimeout(() => { | |
| contractInteractionResult.classList.remove('hidden'); | |
| contractInteractionResult.innerHTML = ` | |
| <p class="text-green-400">Contract deployed successfully!</p> | |
| <p class="text-sm mt-1">Contract address: 0x89...f2c1</p> | |
| <p class="text-xs mt-2 text-gray-400">Gas used: 0.024 ETH</p> | |
| `; | |
| gameState.balance -= 0.024; | |
| balanceElement.textContent = gameState.balance.toFixed(5); | |
| addTerminalOutput(`β New contract deployed at 0x89...f2c1`); | |
| addTerminalOutput(`- 0.024 ETH (gas fee)`); | |
| addTransaction('Contract Deploy', '-0.024 ETH', 'New contract'); | |
| // Update achievement | |
| const contractAchievement = document.querySelectorAll('.achievement')[1]; | |
| contractAchievement.classList.remove('bg-gray-700', 'opacity-50'); | |
| contractAchievement.classList.add('bg-purple-900', 'bg-opacity-30'); | |
| }, 2000); | |
| } | |
| function mineBlock() { | |
| addTerminalOutput(`> Mining new block...`); | |
| mineBlockBtn.disabled = true; | |
| mineBlockBtn.innerHTML = `<i class="fas fa-cog fa-spin mr-2"></i> Mining...`; | |
| setTimeout(() => { | |
| // Create new block | |
| const blockNumber = Math.floor(Math.random() * 1000) + 4; | |
| const newBlockHash = `0x${Math.random().toString(16).substr(2, 10)}...${Math.random().toString(16).substr(2, 6)}`; | |
| // Update blockchain visualization | |
| latestBlock.innerHTML = ` | |
| <div class="text-xs text-gray-400 mb-1">Block #${blockNumber}</div> | |
| <div class="text-sm mb-1">Contains ${gameState.transactions.length || 1} txns</div> | |
| <div class="text-xs text-gray-400">${newBlockHash}</div> | |
| `; | |
| // Add new block to chain | |
| const blocksContainer = document.querySelector('.flex.overflow-x-auto.space-x-4'); | |
| const newBlock = document.createElement('div'); | |
| newBlock.className = 'block bg-gray-700 p-3 rounded-lg min-w-[200px]'; | |
| newBlock.innerHTML = ` | |
| <div class="text-xs text-gray-400 mb-1">Block #${blockNumber}</div> | |
| <div class="text-sm mb-1">Contains ${gameState.transactions.length || 1} txns</div> | |
| <div class="text-xs text-gray-400">${newBlockHash}</div> | |
| `; | |
| // Create new pending block | |
| const pendingBlock = document.createElement('div'); | |
| pendingBlock.className = 'block bg-blue-900 p-3 rounded-lg min-w-[200px]'; | |
| pendingBlock.id = 'latestBlock'; | |
| pendingBlock.innerHTML = ` | |
| <div class="text-xs text-gray-400 mb-1">Block #${blockNumber + 1}</div> | |
| <div class="text-sm mb-1">Ready for new transactions</div> | |
| <div class="text-xs text-gray-400">Pending...</div> | |
| `; | |
| blocksContainer.appendChild(newBlock); | |
| blocksContainer.appendChild(pendingBlock); | |
| addTerminalOutput(`β New block mined (#${blockNumber})`); | |
| mineBlockBtn.disabled = false; | |
| mineBlockBtn.innerHTML = `<i class="fas fa-hammer mr-2"></i> Mine Block`; | |
| // Clear transactions | |
| gameState.transactions = []; | |
| document.getElementById('newTransactions').innerHTML = ''; | |
| }, 3000); | |
| } | |
| function submitQuiz() { | |
| // Get selected answers | |
| gameState.quizAnswers.q1 = document.querySelector('input[name="q1"]:checked')?.value; | |
| gameState.quizAnswers.q2 = document.querySelector('input[name="q2"]:checked')?.value; | |
| gameState.quizAnswers.q3 = document.querySelector('input[name="q3"]:checked')?.value; | |
| // Check answers | |
| const correctAnswers = { | |
| q1: 'b', | |
| q2: 'a', | |
| q3: 'b' | |
| }; | |
| let score = 0; | |
| if (gameState.quizAnswers.q1 === correctAnswers.q1) score++; | |
| if (gameState.quizAnswers.q2 === correctAnswers.q2) score++; | |
| if (gameState.quizAnswers.q3 === correctAnswers.q3) score++; | |
| // Display results | |
| quizSection.innerHTML = ` | |
| <h2 class="text-2xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-poll mr-3 text-purple-400"></i> | |
| Quiz Results | |
| </h2> | |
| <div class="mb-6"> | |
| <div class="bg-${score >= 2 ? 'green' : 'red'}-900 bg-opacity-30 p-4 rounded-lg mb-4"> | |
| <p class="text-lg font-semibold">You scored ${score}/3</p> | |
| <p class="text-sm mt-2"> | |
| ${score === 3 ? 'Perfect! You understand smart contracts well.' : | |
| score >= 2 ? 'Good job! Review the incorrect answers to improve.' : | |
| 'Keep practicing! Review the lesson and try again.'} | |
| </p> | |
| </div> | |
| <div class="space-y-4"> | |
| <div class="quiz-result bg-gray-700 p-3 rounded-lg"> | |
| <p class="font-semibold mb-1">1. What makes smart contracts different from traditional contracts?</p> | |
| <p class="text-sm ${gameState.quizAnswers.q1 === 'b' ? 'text-green-400' : 'text-red-400'}"> | |
| ${gameState.quizAnswers.q1 === 'b' ? 'β Correct' : 'β Incorrect'} | |
| </p> | |
| <p class="text-xs text-gray-400 mt-1">Correct answer: They are stored on a blockchain and execute automatically</p> | |
| </div> | |
| <div class="quiz-result bg-gray-700 p-3 rounded-lg"> | |
| <p class="font-semibold mb-1">2. What happens when you deploy a smart contract to Ethereum?</p> | |
| <p class="text-sm ${gameState.quizAnswers.q2 === 'a' ? 'text-green-400' : 'text-red-400'}"> | |
| ${gameState.quizAnswers.q2 === 'a' ? 'β Correct' : 'β Incorrect'} | |
| </p> | |
| <p class="text-xs text-gray-400 mt-1">Correct answer: It gets stored on the blockchain and receives an address</p> | |
| </div> | |
| <div class="quiz-result bg-gray-700 p-3 rounded-lg"> | |
| <p class="font-semibold mb-1">3. Why are smart contracts considered "trustless"?</p> | |
| <p class="text-sm ${gameState.quizAnswers.q3 === 'b' ? 'text-green-400' : 'text-red-400'}"> | |
| ${gameState.quizAnswers.q3 === 'b' ? 'β Correct' : 'β Incorrect'} | |
| </p> | |
| <p class="text-xs text-gray-400 mt-1">Correct answer: Because they eliminate the need for trusted third parties</p> | |
| </div> | |
| </div> | |
| </div> | |
| <button onclick="location.reload()" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded-lg w-full"> | |
| <i class="fas fa-sync-alt mr-2"></i> Continue Learning | |
| </button> | |
| `; | |
| // Reward for good score | |
| if (score >= 2) { | |
| gameState.balance += 0.5; | |
| balanceElement.textContent = gameState.balance.toFixed(5); | |
| addTerminalOutput(`+ 0.5 ETH (quiz reward)`); | |
| addTransaction('Quiz Reward', '+0.5 ETH', 'Good score'); | |
| } | |
| } | |
| function showWalletInfo() { | |
| terminalOutput.innerHTML = ` | |
| <div class="text-blue-300">Wallet Details:</div> | |
| <div class="text-sm">Address: 0x7f3c5a9e1b2d4f6a8c0e3d7b5a4b3a2c1d0e9f8</div> | |
| <div class="text-sm">Network: Ethereum Testnet</div> | |
| <div class="text-sm">Balance: ${gameState.balance} ETH</div> | |
| `; | |
| } | |
| // Helper Functions | |
| function addTerminalOutput(message) { | |
| const line = document.createElement('div'); | |
| line.className = 'terminal-line'; | |
| line.textContent = message; | |
| terminalOutput.appendChild(line); | |
| terminalOutput.scrollTop = terminalOutput.scrollHeight; | |
| } | |
| function addTransaction(title, amount, description) { | |
| const transaction = { | |
| title, | |
| amount, | |
| description, | |
| timestamp: new Date().toLocaleTimeString() | |
| }; | |
| gameState.transactions.push(transaction); | |
| const transactionElement = document.createElement('div'); | |
| transactionElement.className = 'transaction bg-gray-700 p-3 rounded-lg transaction-animation'; | |
| transactionElement.innerHTML = ` | |
| <div class="flex justify-between text-sm"> | |
| <span class="${amount.startsWith('+') ? 'text-green-400' : 'text-blue-300'}">${title}</span> | |
| <span class="text-gray-400">just now</span> | |
| </div> | |
| <div class="text-xs text-gray-400">${amount} (${description})</div> | |
| `; | |
| newTransactions.prepend(transactionElement); | |
| } | |
| // Initialize | |
| addTerminalOutput('$ Ready to learn about smart contracts!'); | |
| </script> | |
| </body> | |
| </html> |