Skip to content

Instantly share code, notes, and snippets.

@Ellity
Created October 5, 2021 21:57
Show Gist options
  • Save Ellity/00082f40f26525690a78c888d8829ad9 to your computer and use it in GitHub Desktop.
Save Ellity/00082f40f26525690a78c888d8829ad9 to your computer and use it in GitHub Desktop.
gOYBBOp
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="favicon.ico">
<title>Ethereum Coin Flip Game: The best ethereum coin flip game of the world!</title>
<!-- Bootstrap core CSS -->
<link href="node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="css/coinflip.css" rel="stylesheet">
<!-- Cryptocoins icons -->
<link href="node_modules/cryptocoins-icons/webfont/cryptocoins.css" rel="stylesheet">
<!-- Font awesome -->
<link rel="stylesheet" href="node_modules/font-awesome/css/font-awesome.min.css">
<!-- Ethereum -->
<script src="node_modules/web3/dist/web3.min.js"></script>
<!-- Slim -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
</head>
<body>
<nav class="navbar navbar-toggleable-md navbar-inverse fixed-top bg-inverse">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">Coin Flip</a>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
</ul>
<a href="#" onClick="soundOnOff();" id="soundSwitch"><i class="fa fa-2x fa-volume-up soundSwitch" aria-hidden="true"></i></a>
</div>
</nav>
<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
<div class="container">
<p class="text-center" style="margin: 0;"><i class="cc ETH-alt" title="ETH" style="font-size: 6rem;"></i></p>
<h1 class="display-3 text-center">HWDP!</h1>
<p class="text-center">The best ethereum coin flip game of the world</p>
<div class="row">
<div class="col-md-6 offset-md-3">
<div class="input-group input-group-lg">
<span class="input-group-addon">Amount to Bet:</i></span>
<input type="number" class="form-control" required step=".001" min="0.001" max="1" value="0.001" id="amount" placeholder="Ethers to bet..." aria-label="Ethers to bet...">
<!-- <input type="number" class="form-control" required min="0" id="amount" placeholder="WEIs to bet..." aria-label="WEIs to bet..."> -->
<span class="input-group-btn">
<button class="btn btn-success" type="button" id="submit">Play!</button>
</span>
</div>
</div>
</div>
<p class="text-center"><img id="loader" src="C:/Users/Pc/Desktop/ethereum-coinflip-cfe56be842b482dc5bfb08fff15d141573f214a0/btc.gif"></p>
<div id="alert" class="alert alert-dismissible fade show" role="alert">
<button type="button" class="close" onclick="$('#alert').hide()">
<span aria-hidden="true">&times;</span>
</button>
<span id="alertText"><strong>Well done!</strong> You successfully read this important alert message.</span>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2 class="text-center">Last 10 Played Games</h2>
<p>&nbsp;</p>
<div class="table-responsive">
<table id="lastPlayedGamesTable" class="table table-striped">
<thead>
<tr>
<th>Address</th>
<th>Block Number</th>
<th>Block Timestamp</th>
<th>Bet</th>
<th>Prize</th>
<th>Winner</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
<p>&nbsp;</p>
<div class="row">
<div class="col-md-4">
<h2>The Game</h2>
<p>Game is simple, you bet an ether amount and the coin flips, if the coin goes head you'll earn the 190% of your bet. If the coin goes tails you'll loose your bet.</p>
<!--<p><a class="btn btn-secondary" href="#" role="button">View details &raquo;</a></p> -->
</div>
<div class="col-md-4">
<h2>Requirements</h2>
<p>You must install <a href="https://metamask.io/" target="_blank">Metamask</a> in your browser (<a href="https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn" target="_blank">Get Chrome version here!</a>) in order to play the game. Currently we are testing in Rinkeby ethereum network, so be sure to select it when setup Metamask.</p>
<!-- <p><a class="btn btn-secondary" href="#" role="button">View details &raquo;</a></p> -->
</div>
<div class="col-md-4">
<h2>No funds?</h2>
<p>No problem! We are testing this DApp in the Ethereum Rinkeby testnet. So you can just create and address in Metamask, go to <a href="https://faucet.rinkeby.io" target="_blank">faucet.rinkeby.io</a> and follow the instructions to get free ethers from the thin air! ;-)</p>
<!-- <p><a class="btn btn-secondary" href="#" role="button">View details &raquo;</a></p> -->
</div>
</div>
<hr>
<footer>
<p>&copy; 2017 <a href="https://www.quequiereshacer.es" target="_blank">Quequiereshacer.es</a> / <span id="contractInfo"></span></p>
</footer>
</div> <!-- /container -->
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="node_modules/bootstrap/dist/js/ie10-viewport-bug-workaround.js"></script>
<script src="js/coinflip.js"></script>
</body>
</html>
/**
* Coin Flip main javascript file
*
* Author: Mario Pino Uceda <info@quequiereshacer.es>
*
*/
// Ethereum contract address in Rinkeby testnet
contractAddress = '0xdf83258db88333109237b3541e204cc88549dcf5';
// Limit number of played games to fetch and display in UI
lastPlayedGamesLimit = 10;
// Store total number of games played
totalGameCount = 0;
// Sound
winSound = "sound/smb3_coin.wav";
loseSound = "sound/fail-buzzer-04.wav";
AudioOn = true;
// Prevent process a already processed Status Event
processedBlocks = new Array();
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
// Use Mist/MetaMask's provider
window.web3 = new Web3(web3.currentProvider);
} else {
// Shows an error in UI and console if no web3 object is detected
console.log('Error! You must install Metamask in order to play the game!')
$("#alert").removeClass( "alert-success" ).addClass( "alert-danger" );
$("#alertText").html('Error! You must install <a href="https://metamask.io" target="_blank">Metamask</a> in order to play the game!');
$("#alert").show();
}
// ABI
var CoinFlipContract = web3.eth.contract([{"constant":false,"inputs":[],"name":"Play","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"withdrawFunds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"depositFunds","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"index","type":"uint256"}],"name":"getGameEntry","outputs":[{"name":"addr","type":"address"},{"name":"blocknumber","type":"uint256"},{"name":"blocktimestamp","type":"uint256"},{"name":"bet","type":"uint256"},{"name":"prize","type":"uint256"},{"name":"winner","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MaxAmountToBet","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"Kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"amount","type":"uint256"}],"name":"getMaxAmountToBet","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"setMaxAmountToBet","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getGameCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":true,"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_msg","type":"string"},{"indexed":false,"name":"user","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"winner","type":"bool"}],"name":"Status","type":"event"}]);
console.log('Contract Address: ' + contractAddress);
var CoinFlip = CoinFlipContract.at(contractAddress);
var CoinFlipEvent = CoinFlip.Status();
UpdateGamesTable();
UpdateContractInfo();
/**
*
* Watch for Status Event. Smart contract fires a Status Event everytime there is a game state change!
*
*/
CoinFlipEvent.watch(function(error, result) {
if (!error) {
//console.log('Status Event Fired!');
//console.log(result);
// Avoid process a already processed Status Event
if (processedBlocks.lastIndexOf(result.blockNumber) != -1) return;
UpdateGamesTable();
UpdateContractInfo();
$("#loader").hide();
if (result.args.winner) {
$("#alert").removeClass( "alert-danger" ).addClass( "alert-success" );
var Sound = new Audio(winSound);
console.log('Congratulations, you won!');
} else {
$("#alert").removeClass( "alert-success" ).addClass( "alert-danger" );
var Sound = new Audio(loseSound);
console.log('I\'m sorry, you\'ve lost!');
}
$("#alertText").html(result.args._msg);
processedBlocks.push(result.blockNumber);
$("#alert").show();
if (AudioOn) {
Sound.play();
}
$("#submit").prop('disabled', false);
} else {
$("#loader").hide();
console.log('Ooops! Something goes wrong getting Status Event...');
console.log(err);
}
});
/**
* Play the game
* @return {bool}
*/
$("#submit").click(function() {
$("#alert").hide();
if ($("#amount").val() <= 0) {
$("#alert").removeClass( "alert-success" ).addClass( "alert-danger" );
$("#alertText").html('Sorry, minumum amount to bet is 0,001 ether!');
$("#alert").show();
$("#amount").val('0.001');
return;
}
if (jQuery.isEmptyObject(web3.eth.accounts[0])) {
// Shows an error in UI and console if Metamask account is locked
$("#alert").removeClass( "alert-success" ).addClass( "alert-danger" );
$("#alertText").html('Please unlock your Metamask account and <a href="http://coinflip.quequiereshacer.es">reload the page</a> to play the game!');
$("#alert").show();
console.log('Please unlock your Metamask account and reload the page to play the game!');
return;
}
$("#loader").show();
$("#submit").prop('disabled', true);
amount = $("#amount").val() * 1000000000000000000;
//console.log("Amount in WEIs:");
//console.log(amount);
CoinFlip.Play({from: web3.eth.accounts[0], gas: 3000000, value: amount}, (err, res) => {
if (!err) {
} else {
$("#loader").hide();
$("#alert").removeClass( "alert-success" ).addClass( "alert-danger" );
$("#alertText").html('' + err);
$("#alert").show();
console.log('Something goes wrong!');
console.log(err);
}
});
});
/**
* Update smart contract information at the footer
* @return {bool}
*/
function UpdateContractInfo() {
web3.eth.getBalance(contractAddress, function(error, result) {
if (!error) {
console.log('Contract Balance: ' + result / 1000000000000000000 + ' ethers / Total Bets: ' + totalGameCount);
$('#contractInfo').html('Contract Address: <a href="https://rinkeby.etherscan.io/address/' + contractAddress + '" target="_blank">' + contractAddress + '</a> / Contract Balance: ' + result / 1000000000000000000 + ' ethers / Total Bets: ' + totalGameCount);
return true;
} else {
console.log('Error getting Contract Balance: ' + error);
return false;
}
});
}
/**
* Update latest games played table
* @return {bool}
*/
function UpdateGamesTable() {
$('#lastPlayedGamesTable tbody').html('');
CoinFlip.getGameCount(function(error, result) {
if (!error) {
//console.log(result);
totalGameCount = result;
gameCount = result;
var html = '';
counter = 1;
for (gameCount--; gameCount >= 0 ; gameCount--) {
if (lastPlayedGamesLimit < counter) { break; }
//console.log("-> gameCount: " + gameCount);
CoinFlip.getGameEntry(gameCount, function(error, result) {
if (!error) {
//console.log(result);
gameItem = result;
etherBet = gameItem[3] / 1000000000000000000;
etherPrize = gameItem[4] / 1000000000000000000;
//console.log("-> Address: " + gameItem[0] + " Blocknumber: " + gameItem[1] + " BlockTimestamp: " + gameItem[2] + " Bet: " + etherBet + " Prize: " + etherPrize + " Winner: " + gameItem[5] );
if (gameItem[5] == true) {
trClass = "win";
WinnerTrContent = "<i class=\"fa fa-thumbs-o-up\" aria-hidden=\"true\"></i>";
} else {
trClass = "loose";
WinnerTrContent = "<i class=\"fa fa-thumbs-o-down\" aria-hidden=\"true\"></i>";
}
html = "<tr class=\"" + trClass + "\"><td>" + gameItem[0] + "</td><td>" + gameItem[1] + "</td><td>" + gameItem[2] + "</td><td>" + etherBet + "</td><td>" + etherPrize + "</td><td>" + WinnerTrContent + "</td></tr>";
$('#lastPlayedGamesTable tbody').append(html);
} else {
console.log(error);
}
});
counter++;
}
} else {
console.error(error);
return false;
}
});
return true;
}
/**
* Enable / disable sound
* @return {bool}
*/
function soundOnOff() {
if (AudioOn) {
AudioOn = false;
$('#soundSwitch').html('<i class="fa fa-2x fa-volume-off soundSwitch" aria-hidden="true"></i>');
console.log('Sound is Off');
} else {
AudioOn = true;
$('#soundSwitch').html('<i class="fa fa-2x fa-volume-up soundSwitch" aria-hidden="true"></i>');
console.log('Sound is On');
}
return true;
}
/**
* Coin Flip main CSS file
*
* Author: Mario Pino Uceda <info@quequiereshacer.es>
*
*/
/* Move down content because we have a fixed navbar that is 50px tall
*/
body {
padding-top: 2rem;
}
#loader {
width: 150px;
display: none;
}
#alert {
display: none;
}
#lastPlayedGamesTable .win td {
color: green;
}
#lastPlayedGamesTable .loose td {
color: red;
}
.soundSwitch {
color: #fff;
padding: 3px 0 3px 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment