{"version":3,"sources":["components/WalletAddress.js","components/Menu.js","App.js","contract/address.js","contract/execute.js","components/LoadingIndicator/index.js","pages/play.js","pages/guide.js","contract/query.js","pages/leaderboard.js","index.js"],"names":["WalletAddress","connectedWallet","useConnectedWallet","terraAddress","className","slice","menu_options","name","link","Menu","map","mb","index","to","App","useWallet","status","connect","disconnect","availableConnectTypes","console","log","WalletStatus","WALLET_NOT_CONNECTED","src","alt","WALLET_CONNECTED","type","onClick","contractAddress","wallet","config","network","clicker","contractAddresses","default","sleep","ms","Promise","resolve","setTimeout","until","Date","now","untilInterval","_exec","msg","fee","Fee","uluna","a","lcd","LCDClient","URL","chainID","post","msgs","MsgExecuteContract","walletAddress","result","tx","txInfo","txhash","Error","setScore","score","upsert_score","LoadingIndicator","Play","useState","time","setTime","top","left","targetPosition","setTargetPosition","loading","setLoading","useEffect","unsubscribe","setInterval","display","alert","submitScore","execute","window","location","href","id","style","audio","Audio","volume","play","Math","floor","random","Guide","getScores","wasm","contractQuery","get_scores","Leaderboard","scores","setScores","fetchScores","query","then","length","toString","padStart","renderScores","TWITTER_HANDLE","TWITTER_LINK","getChainOptions","chainOptions","ReactDOM","render","StrictMode","path","element","target","rel","document","getElementById"],"mappings":"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","file":"static/js/main.eaa6b7df.chunk.js","sourcesContent":["import { useConnectedWallet } from '@terra-money/wallet-provider';\r\n\r\nconst WalletAddress = () => {\r\n const connectedWallet = useConnectedWallet();\r\n const { terraAddress } = { ...connectedWallet };\r\n \r\n return (\r\n
\r\n {terraAddress && (\r\n \r\n )}\r\n
\r\n );\r\n};\r\n\r\nexport default WalletAddress;","import { Link } from 'react-router-dom';\r\n\r\nconst menu_options = [\r\n { name: 'Play', link: '/play' },\r\n { name: 'Leaderboard', link: '/leaderboard' },\r\n { name: 'How to play', link: '/guide' },\r\n];\r\n\r\nconst Menu = () => {\r\n\r\n const renderMenu = () => {\r\n return menu_options.map((mb, index) => {\r\n\r\n const { name, link } = mb;\r\n \r\n return (\r\n \r\n {name}\r\n \r\n );\r\n });\r\n };\r\n\r\n return
{renderMenu()}
;\r\n};\r\n\r\nexport default Menu;","// Import it first\nimport WalletAddress from './components/WalletAddress';\nimport './App.css';\nimport { useWallet, WalletStatus } from \"@terra-money/wallet-provider\";\n\n// Here's the new import for the file we just added\nimport Menu from './components/Menu';\n\nfunction App() {\n const { status, connect, disconnect, availableConnectTypes } = useWallet();\n\n console.log(\"Wallet status is \", status);\n console.log(\"Available connection types:\", availableConnectTypes);\n\n const renderConnectButton = () => {\n if (status === WalletStatus.WALLET_NOT_CONNECTED) {\n return (\n
\n connect(\"EXTENSION\")}\n className=\"cta-button connect-wallet-button\"\n >\n Connect wallet\n \n
\n );\n }\n else if (status === WalletStatus.WALLET_CONNECTED) {\n return (\n disconnect()}\n className=\"cta-button connect-wallet-button\"\n >\n Disconnect\n \n );\n }\n };\n\n return (\n
\n
\n
\n

⚔ Goblin War ⚔

\n

Only you can save us from Goblin town

\n
\n \n\n
\n\n {/* If not connected, show the goblin GIF! */}\n {status === WalletStatus.WALLET_NOT_CONNECTED && (\n
\n \n
\n )}\n\n {/* Show the menu after connection */}\n {status === WalletStatus.WALLET_CONNECTED && (\n
\n \n
\n )}\n {renderConnectButton()}\n
\n );\n}\n\nexport default App;","import config from \"../refs.terrain.json\"\r\n\r\nexport const contractAddress = (wallet) => config[wallet.network.name].clicker.contractAddresses.default","import { LCDClient, MsgExecuteContract, Fee } from '@terra-money/terra.js';\r\nimport { contractAddress } from './address';\r\n\r\n// ==== utils ====\r\n\r\nconst sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\r\nconst until = Date.now() + 1000 * 60 * 60;\r\nconst untilInterval = Date.now() + 1000 * 60;\r\n\r\nconst _exec =\r\n (msg, fee = new Fee(200000, { uluna: 10000 })) =>\r\n async (wallet) => {\r\n const lcd = new LCDClient({\r\n URL: wallet.network.lcd,\r\n chainID: wallet.network.chainID,\r\n });\r\n\r\n const { result } = await wallet.post({\r\n fee,\r\n msgs: [\r\n new MsgExecuteContract(\r\n wallet.walletAddress,\r\n contractAddress(wallet),\r\n msg\r\n ),\r\n ],\r\n });\r\n\r\n while (true) {\r\n try {\r\n return await lcd.tx.txInfo(result.txhash);\r\n } catch (e) {\r\n if (Date.now() < untilInterval) {\r\n await sleep(500);\r\n } else if (Date.now() < until) {\r\n await sleep(1000 * 10);\r\n } else {\r\n throw new Error(\r\n `Transaction queued. To verify the status, please check the transaction hash: ${result.txhash}`\r\n );\r\n }\r\n }\r\n }\r\n };\r\n\r\n// ==== execute contract ====\r\n// THIS IS ALL I ADDED!!!\r\nexport const setScore = async (wallet, score) =>\r\n _exec({ upsert_score: { score } })(wallet);","import React from 'react';\nimport './LoadingIndicator.css';\n\nconst LoadingIndicator = () => {\n return (\n
\n
\n
\n
\n
\n
\n );\n};\n\nexport default LoadingIndicator;","import React, { useState, useEffect } from \"react\";\r\nimport * as execute from '../contract/execute';\r\nimport { useConnectedWallet } from '@terra-money/wallet-provider';\r\nimport LoadingIndicator from '../components/LoadingIndicator';\r\n\r\nconst Play = () => {\r\n const connectedWallet = useConnectedWallet();\r\n // Configure this as you want, I like shorter games\r\n const playTime = 15;\r\n\r\n const [time, setTime] = useState(playTime);\r\n const [gameOver, setGameOver] = useState(false);\r\n // We use this to track where the target is on the screen\r\n const [targetPosition, setTargetPosition] = useState({ top: \"15%\", left: \"50%\" });\r\n const [loading, setLoading] = useState(false);\r\n const [score, setScore] = useState(0);\r\n \r\n // Every second we're going to lower the value of time.\r\n useEffect(() => {\r\n const unsubscribe = setInterval(() => {\r\n setTime(time => time > 0 ? time - 1 : 0);\r\n }, 1000);\r\n return unsubscribe;\r\n }, []);\r\n \r\n useEffect(() => {\r\n if (time === 0) {\r\n setTargetPosition({ display: 'none' });\r\n // Show alert to let user know it's game over\r\n alert(`Game Over! Your score is ${score}. Please confirm transaction to submit score.`);\r\n submitScore();\r\n }\r\n }, [time]);\r\n\r\n const submitScore = async () => {\r\n if (connectedWallet && connectedWallet.network.name === 'testnet') {\r\n setLoading(true);\r\n const tx = await execute.setScore(connectedWallet, score);\r\n console.log(tx);\r\n // Once the transaction is confirmed, we let the user know and navigate to the leaderboard\r\n alert('Score submitted!');\r\n setLoading(false);\r\n window.location.href = '/leaderboard';\r\n }\r\n };\r\n\r\n const handleClick = () => {\r\n // OGs will know this :)\r\n let audio = new Audio(\"/ウィーアー!.mp3\");\r\n \r\n // Don't let it get too loud!\r\n audio.volume = 0.2;\r\n audio.play();\r\n\r\n setScore(score => score + 1);\r\n \r\n // Play around with this to control bounds!\r\n setTargetPosition({\r\n top: `${Math.floor(Math.random() * 80)}%`,\r\n left: `${Math.floor(Math.random() * 80)}%`\r\n });\r\n };\r\n\r\n return (\r\n
\r\n
\r\n Score: {score}\r\n Fight!\r\n Time left: {time} s\r\n
\r\n\r\n {/* Render loading or game container */}\r\n {loading ? (\r\n \r\n ) : (\r\n
\r\n {/* CHANGE THIS IMAGE! It's loaded from the public folder. */}\r\n \"Target\"\r\n \"Marine\"\r\n
\r\n )}\r\n
\r\n );\r\n};\r\n\r\nexport default Play;","// Import it first\r\nimport WalletAddress from '../components/WalletAddress';\r\nimport { Link } from 'react-router-dom';\r\n\r\nconst Guide = () => {\r\n return (\r\n
\r\n
\r\n \r\n
\r\n

⚔ Goblin War ⚔️

\r\n

Only you can save us from Goblin town

\r\n
\r\n \r\n \r\n
\r\n\r\n
\r\n

How to play

\r\n \r\n
\r\n \r\n Click as many goblins as you can within 15 seconds!\r\n \r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default Guide;","import { LCDClient } from \"@terra-money/terra.js\";\r\nimport { contractAddress } from \"./address\";\r\n\r\nexport const getScores = async (wallet) => {\r\n console.log(\"Contract address is \", contractAddress(wallet));\r\n const lcd = new LCDClient({\r\n URL: wallet.network.lcd,\r\n chainID: wallet.network.chainID,\r\n });\r\n return lcd.wasm.contractQuery(contractAddress(wallet), { get_scores: {} });\r\n};","// Import it first\r\nimport WalletAddress from '../components/WalletAddress';\r\nimport { Link } from 'react-router-dom';\r\nimport * as query from '../contract/query';\r\nimport { useState, useEffect } from 'react';\r\nimport { useConnectedWallet } from '@terra-money/wallet-provider';\r\n\r\nconst Leaderboard = () => {\r\n const [scores, setScores] = useState();\r\n const [loading, setLoading] = useState(true);\r\n const connectedWallet = useConnectedWallet();\r\n\r\n useEffect(() => {\r\n setLoading(true);\r\n const fetchScores = async () => {\r\n if (connectedWallet && connectedWallet.network.name === 'testnet') { \r\n return (await query.getScores(connectedWallet)).scores;\r\n }\r\n };\r\n\r\n fetchScores().then(scores => {\r\n setScores(scores);\r\n setLoading(false);\r\n });\r\n }, [connectedWallet]);\r\n\r\n const renderScores = (scores) => {\r\n if (!scores || scores.length < 1) {\r\n return
No scores available :(
;\r\n }\r\n\r\n return scores.map((score, index) => {\r\n return (\r\n
\r\n {/* Format is address: score */}\r\n {/* Slice address to first 5 and last 4 digits so it looks like terra...a1b2*/}\r\n \r\n {score[0].slice(0, 5) + '...' + score[0].slice(-4)}:{' '}\r\n {score[1].toString().padStart(2, '0')}\r\n \r\n
\r\n );\r\n });\r\n };\r\n\r\n return (\r\n
\r\n
\r\n \r\n
\r\n

⚔ Goblin War ⚔️

\r\n

Only you can save us from Goblin town

\r\n
\r\n \r\n \r\n
\r\n\r\n
\r\n

Scoreboard

\r\n {/* If loading, show loading, else render */}\r\n {loading ? (\r\n
Loading...
\r\n ) : (\r\n renderScores(scores)\r\n )}\r\n \r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default Leaderboard;","import App from './App';\nimport React from 'react';\nimport ReactDOM from 'react-dom';\n\nimport { Route, Routes, BrowserRouter } from 'react-router-dom';\nimport './index.css';\n\n// We import the pages we just created\nimport Play from './pages/play';\nimport Guide from './pages/guide';\nimport Leaderboard from './pages/leaderboard';\n\nimport { getChainOptions, WalletProvider } from '@terra-money/wallet-provider';\n\nconst TWITTER_HANDLE = '_buildspace';\nconst TWITTER_LINK = `https://twitter.com/${TWITTER_HANDLE}`;\n\ngetChainOptions().then((chainOptions) => {\n ReactDOM.render(\n \n \n
\n \n \n } />\n {/* Here are the routes we need to declare.*/}\n {/* These are empty so they will error for now, don't worry! */}\n } />\n } />\n } />\n \n \n\n
\n \n {`Made with @${TWITTER_HANDLE}`}\n
\n
\n
\n
,\n document.getElementById('root')\n );\n})\n"],"sourceRoot":""}