Hi All,
Please See below my Github Repository Link
https://github.com/Suveett/CoinFlip-Phase-2.git
Also, some Screenshots of my Code:
Also My solidity code as Follows :
import "./provableAPI.sol";
import { SafeMath } from "./SafeMath.sol";
pragma solidity 0.5.12;
contract Coinflip is usingProvable{
using SafeMath for uint;
//Events to listen for :
event RandomNumberGenerated(uint randomNumber);
event LogNewProvableQuery(address indexedPlayer);
event FlipResult(address user, uint amountWon, bool won);
event ContractFunded(address contractOwner, uint amount);
// Constructors and Modifiers :
constructor() public {
provable_setProof(proofType_Ledger);
contractBalance = 0;
contractOwner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == contractOwner, "You are not the owner");
_;
}
modifier costs(uint cost) {
require(msg.value >= cost, "Minimum amount >= 0.01 ether");
_;
}
//addresses and other such state Variables:
address public contractOwner;
uint public contractBalance;
address public contractAddress;
uint private constant NUM_RANDOM_BYTES_REQUESTED = 1;
struct Temp {
bytes32 id;
address playerAddress;
}
struct PlayerByAddress {
address playerAddress;
uint playerBalance;
bool inGame;
uint betAmount;
}
mapping(bytes32 => Temp) public temps;
mapping(address => PlayerByAddress) public playersByAddress;
//Flip the Coin and check whether user won or lost;
function flipCoin() public payable costs(0.01 ether) {
require(address(this).balance >= msg.value, "The contract doesnt have enough balance to play right now. Come Back later");
require(_isPlaying(msg.sender) == false, "The User currently is in Game");
playersByAddress[msg.sender].playerAddress = msg.sender;
playersByAddress[msg.sender].betAmount = msg.value.sub(provable_getPrice("random")); // Contract keeps oracle's fee.
playersByAddress[msg.sender].inGame = true;
_update();
}
// @dev Calls the oracle random function.
// Sets Temp for the given player.
function _update() internal {
uint QUERY_EXECUTION_DELAY = 0;
uint GAS_FOR_CALLBACK =200000;
bytes32 query_id = provable_newRandomDSQuery(QUERY_EXECUTION_DELAY, NUM_RANDOM_BYTES_REQUESTED, GAS_FOR_CALLBACK);
temps[query_id].id = query_id;
temps[query_id].playerAddress = msg.sender;
emit LogNewProvableQuery(msg.sender);
}
// @dev The callback function called by the oracle once the random number is created.
// @param _queryId The query unique identifier that is the key to the player Temp.
// @param _result The random number generated by the oracle.
// @param _proof Used to check if the result has been tampered.
function __callback(bytes32 _queryId, string memory _result, bytes memory _proof) public {
require(msg.sender == provable_cbAddress());
if (provable_randomDS_proofVerify__returnCode(_queryId, _result, _proof) == 0){
uint randomNumber = uint(keccak256(abi.encodePacked(_result)))%2;
_verifyResult (randomNumber, _queryId);
emit RandomNumberGenerated(randomNumber);
}
}
function _verifyResult(uint _randomNumber, bytes32 _queryId) internal {
address player = temps[_queryId].playerAddress;
if(_randomNumber == 1){
playersByAddress[player].playerBalance = playersByAddress[player].playerBalance.add(playersByAddress[player].betAmount.mul(2));
emit FlipResult(player, playersByAddress[player].betAmount, true);
}
else {
contractBalance = contractBalance.add(playersByAddress[player].betAmount);
emit FlipResult(player,playersByAddress[player].betAmount, false );
}
delete(temps[_queryId]);
playersByAddress[player].betAmount = 0;
playersByAddress[player].inGame = false;
}
function getBalance() public view returns(address, uint, uint) {
return(address(this), address(this).balance, contractBalance);
}
// withdraw all funds possible only though contractOwner address;
function withdrawAll() public onlyOwner returns(uint){
require(playersByAddress[msg.sender].playerBalance > 0, "You are not the Owner");
msg.sender.transfer(address(this).balance);
assert(address(this).balance == 0);
return address(this).balance;
}
function fundContract() public payable onlyOwner returns(uint) {
require(msg.value != 0);
emit ContractFunded(msg.sender, msg.value);
return msg.value;
}
function _isPlaying(address _player) public view returns(bool){
return playersByAddress[msg.sender].inGame;
}
}
Also, see below my main.js file
var web3 = new Web3(Web3.givenProvider);
var contractInstance;
const contractAddress = "";
$(document).ready(async function(){
contractInstance = new web3.eth.Contract(abi,contractAddress);
await connectMetamask();
console.log(contractInstance);
console.log(`Use Contract address: ${contractInstance._address}`)
$("#flip_button").click(flipCoin);
$("#get_balance").click(fetchAndDisplay);
$("#fund_contract_button").click(fundContract);
$("#withdraw_funds").click(withdrawAll);
});
//EVENT LISTENERS
contractInstance.once('LogNewProvableQuery',
{
filter: { player: await getPlayerAddress() },
fromBlock: 'latest'
}, (error, event) => {
if(error) throw("Error fetching events");
jQuery("#events").text(`User ${event.returnValues.player} is waiting for the flip result`);
});
contractInstance.once('FlipResult',
{
filter: { player: await getPlayerAddress() },
fromBlock: 'latest'
}, (error, event) => {
if(error) throw("Error fetching events");
jQuery("#events").text(`User ${event.returnValues.player} won: ${event.returnValues.won}`);
});
});
async function connectMetamask() {
if (typeof window.ethereum !== undefined) {
const accounts = await web3.eth.requestAccounts();
let p = await getPlayerAddress();
jQuery("#playerAddress").text(p);
}
}
async function getPlayerAddress() {
const playerAddr = await web3.eth.getAccounts();
if(playerAddr[0] !== undefined) {
return web3.utils.toChecksumAddress(playerAddr[0]);
}
}
async function flipCoin(){
var bet = $("#bet_input").val();
var config = {
value: web3.utils.toWei(bet,"ether")
}
contractInstance.methods.flipCoin().send(config, {from : await getPlayerAddress()})
.on("transactionHash", function(hash){
console.log(hash);
})
.on("confirmation", function(confirmationNr){
console.log(confirmationNr);
})
.on("receipt", function(receipt){
console.log(receipt);
if(receipt.events.betPlaced.returnValues[2] === false){
alert("You lost " + bet + " Ether!");
}
else if(receipt.events.betPlaced.returnValues[2] === true){
alert("You won " + bet + " Ether!");
}
})
};
async function fetchAndDisplay(){
contractInstance.methods.getBalance().call({from : await getPlayerAddress()}).then(function(res){
$("#jackpot_output").text("The Contract has : " + web3.utils.fromWei(res[1], "ether") + "Ether");
})
};
async function fundContract(){
var fund = $("#fund_contract").val();
var config = {
value : web3.utils.toWei(fund, "ether")
}
contractInstance.methods.fundContract().send(config, {from : await getPlayerAddress()})
.on("transactionHash", function(hash){
console.log(hash);
})
.on("confirmation", function(confirmationNr){
console.log(confirmationNr);
})
.on("receipt", function(receipt){
contractInstance.methods.getBalance().call().then(function(res){
$("#jackpot_output").text("The Contract has : " + web3.utils.fromWei(res[1], "ether") + "Ether");
})
};
async function withdrawAll(){
contractInstance.methods.withdrawAll().send({from : await getPlayerAddress()});
};
Dear @dan-i
**I HAVE A QUESTION : **
**I DEPLOYED THE CONTRACT SUCCESSFULLY ON THE ROPSTEN NETWORK , BUT I AM UNABLE TO SEE WHERE I CAN FIND THE CONTRACT ADDRESS ?**
**AND BECAUSE I AM UNABLE TO LOACTE THIS CONTRACT ADDRESS, MY main.js file is incomplete**
**Can you please help me with this, because i was unable to see it in the Terminal ?**
Please let me know where I am going wrong because I am unable to interact with Metamask?
Also, see screenshot below : it shows error âUnexpected identifierâ in main.js 27
*Whereas I think my Code is correct *

Thanks and Regards
Su.kal Crypto