Skip to content

Instantly share code, notes, and snippets.

@merlox
Created October 16, 2018 22:24
Show Gist options
  • Save merlox/1df819b047b25bfebc89bd8dd37703a4 to your computer and use it in GitHub Desktop.
Save merlox/1df819b047b25bfebc89bd8dd37703a4 to your computer and use it in GitHub Desktop.
let activeDice = 0
let game = {}
let isThisPlayer1 = false
let isThisPlayer2 = false
let sequence = 1
start()
// In the start we get the initial data needed to get the contract address
async function start() {
window.addEventListener('load', () => {
socket = io()
setListeners()
})
}
// 1. Connect, send socketid and address to server
// 2. Server responds with the game Data
// 3. When both are connected, server sends player addresses
function setListeners() {
socket.on('connect', () => {
console.log('Socket id connected to server', socket.id)
// Because we reloaded the page when redirecting, we need to update the socket id of all addresses
socket.emit('setup-game', {
socket: socket.id,
address: web3.eth.defaultAccount
})
})
socket.on('initial-game-data', gameData => {
game = gameData
// Who's this?
if(game.addressPlayer1 == web3.eth.defaultAccount) isThisPlayer1 = true
else isThisPlayer2 = true
// Show some game information
updateVisualData(gameData)
})
socket.on('error', message => {
status(message)
})
socket.on('received-both-messages', gameData => {
game = gameData
updateVisualData(gameData)
if(isThisPlayer1 && gameData.winner == 1)
status(`You win ${web3.fromWei(gameData.betPlayer1)} ether! The balances has been updated`)
else if(isThisPlayer2 && gameData.winner == 2)
status(`You win ${web3.fromWei(gameData.betPlayer2)} ether! The balances has been updated`)
})
document.querySelectorAll('.dice-image').forEach(dice => {
dice.addEventListener('click', e => {
// Set the active dice data
activeDice = parseInt(e.target.id.substr(-1))
// Remove all the past selected dices classes
let dices = document.querySelectorAll('.dice-image')
for(let i = 0; i < dices.length; i++) {
dices[i].className = 'dice-image'
}
// Set the active class
e.target.className = e.target.className + " dice-active"
})
})
document.querySelector('.place-bet').addEventListener('click', () => {
let bet = document.querySelector('.bet-input').value
if(activeDice == 0) return status('You must select a dice before placing the bet')
if(bet == 0) return status('You must place a bet larger than zero')
if(bet > getGameBalance()) return status("You can't bet higher than your current balance of " + web3.fromWei(getGameBalance()) + ' ether')
if(bet > getGameEscrow()) return status("You can't bet higher than your escrow of " + web3.fromWei(getGameEscrow()) + ' ether')
placeBet(web3.toWei(bet))
})
}
function status(message) {
document.querySelector('.status').innerHTML = message
setTimeout(() => {
document.querySelector('.status').innerHTML = ''
}, 3e3)
}
function getGameBalance() {
if(isThisPlayer1) return game.balancePlayer1
else return game.balancePlayer2
}
function getOtherGameBalance() {
if(isThisPlayer1) return game.balancePlayer2
else return game.balancePlayer1
}
function getGameEscrow() {
if(isThisPlayer1) return game.escrowPlayer1
else return game.escrowPlayer2
}
// This function takes care of generating the messages with the 'activeDice' and the bet used
async function placeBet(bet) {
if(parseInt(bet) > parseInt(getGameBalance())) return status("You can't bet more than your current balance")
if(parseInt(bet) > parseInt(getOtherGameBalance())) return status("You can't bet more than your opponent's current balance")
if(parseInt(bet) > parseInt(getGameEscrow())) return status("You can't bet more than your escrow")
const nonce = Math.floor(Math.random() * 1e16)
const hash = generateHash(nonce, activeDice, bet, getGameBalance(), sequence)
const signedMessage = await signMessage(hash)
let data = {
signedMessage: signedMessage,
nonce: nonce,
call: activeDice,
bet: bet,
sequence: sequence,
sender: web3.eth.defaultAccount
}
if(isThisPlayer1) {
socket.emit('signed-message-player-1', data)
} else {
socket.emit('signed-message-player-2', data)
}
sequence++
}
function generateHash(nonce, call, bet, balance, sequence) {
const hash = '0x' + ethereumjs.ABI.soliditySHA3(
['uint256', 'uint256', 'uint256', 'uint256', 'uint256'],
[String(nonce), String(call), String(bet), String(balance), String(sequence)]
).toString('hex')
return hash
}
function signMessage(hash) {
return new Promise((resolve, reject) => {
web3.personal.sign(hash, web3.eth.defaultAccount, (err, result) => {
if(err) return reject(err)
resolve(result)
})
})
}
function updateVisualData(gameData) {
document.querySelector('.game-info').innerHTML = `
Contract: <b>${gameData.contractAddress}</b> <br/>
You are: <b>${(isThisPlayer1) ? 'player 1' : 'player 2'}</b> <br/>
Address player 1: <b>${game.addressPlayer1}</b> <br/>
Address player 2: <b>${game.addressPlayer2}</b> <br/>
Balance player 1: <b>${web3.fromWei(gameData.balancePlayer1)} ether</b> <br/>
Balance player 2: <b>${web3.fromWei(gameData.balancePlayer2)} ether</b> <br/>
Escrow player 1: <b>${web3.fromWei(gameData.escrowPlayer1)} ether</b> <br/>
Escrow player 2: <b>${web3.fromWei(gameData.escrowPlayer2)} ether</b> <br/>
Current game: <b>${gameData.sequence}</b>
`
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment