Commit efbeb2dd authored by Rob Myers's avatar Rob Myers

Deploy Lottery Symbol to main net.

parent 71434cd6
{
"extends": "airbnb/base",
"env": {
"browser": true,
"node": false
},
"rules": {
"comma-dangle": [0],
"func-names": ["error", "never"],
"no-alert": 0,
"no-console": 0,
"spaced-comment": ["error", "always", { "exceptions": ["/"] }]
}
}
node_modules
\ No newline at end of file
{
"custom-rules-filename": null,
"rules": {
"imports-on-top": true,
"variable-declarations": true,
"array-declarations": true,
"operator-whitespace": true,
"lbrace": true,
"mixedcase": true,
"camelcase": true,
"uppercase": true,
"no-with": true,
"no-empty-blocks": true,
"no-unused-vars": true,
"double-quotes": true,
"blank-lines": true,
"indentation": true,
"whitespace": true,
"deprecated-suicide": true,
"pragma-on-top": true
}
}
#symbol {
background-color: lightgrey;
text-align: center;
line-height: 100%;
font-size: 75vmin;
width: 75vmin;
height: 75vmin;
position: absolute;
top:0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
#symbol-gui {
/* Work out how to get panels to size to largest... */
width: 590px;
height: 580px;
}
#gui-current-entries-table {
width: 100%;
}
.gui-current-entries-symbol {
/*text-align: right;*/
}
/* Make sure all tabs are displayed the same size (...with the same height) */
.tab-pane {
display: block;
visbility: hidden;
}
.tab-pane>.active {
visibility: visible;
}
/*
* Lottery Symbol - A symbol you can change via a lottery.
* Copyright (C) 2017 Rob Myers <rob@robmyers.org>
*
* This file is part of Lottery Symbol.
*
* Lottery Symbol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Lottery Symbol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Lottery Symbol. If not, see <http://www.gnu.org/licenses/>.
*/
/* global $ Shared LotterySymbol */
////////////////////////////////////////////////////////////////////////////////
// The main contract behaviour object
////////////////////////////////////////////////////////////////////////////////
const LotterySymbolGui = {};
LotterySymbolGui.setSymbolRepresentation = function (symbol) {
$('#symbol').text(symbol);
};
LotterySymbolGui.updateSymbol = function () {
this.contract.symbol.call().then(symbol =>
this.setSymbolRepresentation(String.fromCharCode(symbol.toNumber()))
);
};
LotterySymbolGui.setGuiSymbol = function (symbol) {
$('#symbol-gui-symbol').val(symbol);
};
LotterySymbolGui.initialiseGuiSymbol = function () {
this.contract.symbol.call()
.then(symbol => this.setGuiSymbol(String.fromCharCode(symbol.toNumber())));
};
LotterySymbolGui.finalizeRound = function () {
const account = Shared.selectedGasAccount();
this.contract.finalizeRound({ from: account, gas: 60000 });
};
LotterySymbolGui.getGuiSymbol = function () {
return $('#symbol-gui-symbol').val();
};
LotterySymbolGui.symbolIsValid = function (symbol) {
return (symbol.length === 1) // Correct length
&& (!symbol.match(/\s/)); // Not whitespace
};
LotterySymbolGui.commitNetworkEntry = function (symbol) {
const account = Shared.selectedGasAccount();
this.contract.enterLottery(
symbol.charCodeAt(0),
{ from: account,
gas: 130000 }
).catch((error) => {
console.log(error);
alert('Something went wrong. Maybe the account doesn\'t have enough Ether to pay for gas? See the console log for details.');
}).finally(() => Shared.hideUpdating());
};
////////////////////////////////////////////////////////////////////////////////
// Contract manipulation GUI
////////////////////////////////////////////////////////////////////////////////
// Pad the number with a leading zero if needed to make it two digits
LotterySymbolGui.pad2 = function (number) {
const str = number.toString();
return str.length === 1 ? `0${str}` : str;
};
LotterySymbolGui.nextLotteryFinishes = function () {
let previous;
this.contract.currentRoundEnds.call().then(
(currentRoundEnds) => {
const date = new Date(currentRoundEnds * 1000);
previous = date <= (new Date().getTime());
let prefix = 'Next round ends at';
if (previous) {
prefix = 'Previous round ended at';
}
$('.gui-next-round').text(
`${prefix}: ${this.pad2(date.getHours())}:${this.pad2(date.getMinutes())}:${this.pad2(date.getSeconds())} on ${date.getFullYear()}-${this.pad2(date.getMonth())}-${this.pad2(date.getDate())}`
);
return this.contract.numEntries.call();
}).then(numEntries =>
$('#gui-finalize-button').prop('disabled',
! ((numEntries > 0) && previous)));
};
LotterySymbolGui.clearCurrentEntries = function () {
$('#gui-current-entries').empty();
};
LotterySymbolGui.renderCurrentEntries = function () {
LotterySymbolGui.contract.getEntries.call()
.then((entries) => {
this.clearCurrentEntries();
const numEntries = entries[0].length;
if (numEntries > 0) {
const entrants = entries[0];
const symbols = entries[1];
let html = '<tr><th>Entrant</th><th class="gui-current-entries-symbol">Symbol</th></tr>';
for (var i = 0; i < numEntries; i++) {
const entrant = entrants[i]
const symbol = String.fromCharCode(symbols[i].toNumber());
html += `<tr><td>${entrant}</td><td class="gui-current-entries-symbol">${symbol}</td></tr>`;
}
$('#gui-current-entries').append(html);
}
});
};
// Called from Shared, so be careful with the value of 'this'.
LotterySymbolGui.guiDisplayHook = function () {
$('#symbol').hide();
this.initialiseGuiSymbol();
this.nextLotteryFinishes();
this.guiLotteryTimer = setInterval(() => {
this.nextLotteryFinishes();
}, 10000);
};
LotterySymbolGui.hideGui = function () {
Shared.hideGui();
$('#symbol').show();
clearInterval(this.guiLotteryTimer);
this.guiLotteryTimer = null;
};
LotterySymbolGui.userSelectedUpdate = function (event) {
event.stopPropagation();
const symbol = this.getGuiSymbol();
if (this.symbolIsValid(symbol)) {
this.commitNetworkEntry(symbol);
Shared.showUpdating('Entering&hellip;');
this.hideGui();
$('#symbol').show();
} else {
alert('Invalid symbol. Make sure you enter a visible character in the "Symbol" field.');
}
};
LotterySymbolGui.userSelectedCancel = function (event) {
event.stopPropagation();
this.hideGui();
};
LotterySymbolGui.userSelectedFinalize = function (event) {
event.stopPropagation();
Shared.showUpdating('Finalizing&hellip;');
this.hideGui();
$('#symbol').show();
this.finalizeRound();
};
////////////////////////////////////////////////////////////////////////////////
// Main Program Lifecycle
////////////////////////////////////////////////////////////////////////////////
LotterySymbolGui.setupGui = function () {
$('#representation').click((event) => {
if (!Shared.gui_is_showing) {
Shared.showGui();
}
});
$(document).keydown((event) => {
// 27 is ESC
if (event.keyCode === 27 && Shared.gui_is_showing) {
this.userSelectedCancel(event);
}
});
// Arrow functions so 'this' is LotterySymbolGui not the button when called
$('#gui-update-button').click(event => this.userSelectedUpdate(event));
$('#gui-cancel-button').click(event => this.userSelectedCancel(event));
$('#gui-finalize-button').click(event => this.userSelectedFinalize(event));
$('#gui-cancel-finalize-button')
.click(event => this.userSelectedCancel(event));
$('#gui-tabs a:first').tab('show');
// Shared assumes a single gas select, so move it between tabs as needed
$('a[aria-controls="enter"]').on('show.bs.tab', () => {
$('#gui-gas-enter').append($('#gui-gas'));
});
$('a[aria-controls="finalize"]').on('show.bs.tab', () => {
$('#gui-gas-finalize').append($('#gui-gas'));
});
};
LotterySymbolGui.initialise = function () {
Shared.init(() => this.guiDisplayHook());
this.setupGui();
// Shared.setGasAccountChangedCallback(
// () => this.gasAccountChanged(),
// true
// );
LotterySymbol.deployed().then((instance) => {
this.contract = instance;
// Race conditions between this and the event handlers
// SO we always use renderCurrentEntries in the event handlers
// to make sure we render the current state atomically
this.renderCurrentEntries();
this.contract
.SymbolChanged({}, (error) => {
if (!error) {
this.renderCurrentEntries();
this.updateSymbol();
Shared.hideUpdating();
}
});
this.contract
.NewEntry({}, (error, event) => {
this.renderCurrentEntries();
});
this.updateSymbol();
// Silence 'a promise was created in a handler but was not returned from it'
// resulting from all the promises created in describeArt().
// http://bluebirdjs.com/docs/warning-explanations.html
return null;
});
};
$(window).on('load', () => LotterySymbolGui.initialise());
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lottery Symbol</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:700"
rel="stylesheet">
<link href="app.css" rel="stylesheet">
</head>
<body>
<div id="updating">Entering...</div>
<div id="status"></div>
<div id="representation"
class="d-flex align-items-center justify-content-center">
<div id="symbol">&hellip;</div>
<div class="gui" id="symbol-gui">
<ul class="nav nav-tabs" id="gui-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#enter"
role="tab" aria-controls="enter">Enter</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#entries"
role="tab" aria-controls="entries">Entries</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#finalize"
role="tab" aria-controls="finalize">Finalize</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" role="tabpanel" id="enter">
<h2>Enter Lottery</h2>
<h4 class="gui-next-round">Next lottery ends at...</h4>
<form>
<div class="form-group">
<label class="gui-label"
for="symbol-gui-symbol">Symbol</label>
<input class="form-control"
type="text"
maxLength="1"
id="symbol-gui-symbol"
aria-describedby="symbolGuiSymbolHelpInline">
<small id="symbolGuiSymbolHelpInline"
class="text-muted">Any unicode character</small>
</div>
<div id="enter-gui-gas">
<div id="gui-gas" class="form-group">
<label for="gui-gas-account">Account to pay gas from</label>
<select class="form-control" id="gui-gas-account"></select>
</div>
</div>
<button type="button" class="btn btn-primary"
id="gui-update-button">Enter</button>
&nbsp;
<button type="button" class="btn btn-default"
id="gui-cancel-button">Cancel</button>
</form>
<p><b><i>Note that entering the lottery to update the symbol will
cost gas! Like any lottery, your entry may not
win.</i></b></p>
<p>To enter the lottery, choose a new symbol in the text field
above. Then press &quot;Enter&quot;.</p>
<p>If you do not wish to update the symbol, just press
&quot;Cancel&quot;.</p>
</div>
<div class="tab-pane" role="tabpanel" id="entries">
<h2>Current Entries</h2>
<h4 class="gui-next-round">Next lottery ends at...</h4>
<table id="gui-current-entries-table">
<tbody id="gui-current-entries"></tbody>
</table>
</div>
<div class="tab-pane" role="tabpanel" id="finalize">
<h2>Finalize Current Round</h2>
<h4 class="gui-next-round">Next lottery ends at...</h4>
<div id="gui-gas-finalize"></div>
<p>If the current round of the lottery has not yet been finalized,
you can do so using this button.</p>
<p>This will use the account from the &quot;Enter Lottery&quot;
tab, change it there if needed!<p>
<button type="button" class="btn btn-primary"
id="gui-finalize-button">Finalize</button>
&nbsp;
<button type="button" class="btn btn-default"
id="gui-cancel-finalize-button">Cancel</button>
</div>
</div>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
{
"contract_name": "ConvertLib",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "amount",
"type": "uint256"
},
{
"name": "conversionRate",
"type": "uint256"
}
],
"name": "convert",
"outputs": [
{
"name": "convertedAmount",
"type": "uint256"
}
],
"payable": false,
"type": "function"
}
],
"unlinked_binary": "0x6060604052346000575b6076806100176000396000f300606060405263ffffffff60e060020a60003504166396e4ee3d81146022575b6000565b602e6004356024356040565b60408051918252519081900360200190f35b8181025b929150505600a165627a7a72305820adb63cb47a858a394c0d086fd6797cefcee1dc04db24302b04dd001540f4fe340029",
"networks": {},
"schema_version": "0.0.5",
"updated_at": 1500611720127
}
\ No newline at end of file
This diff is collapsed.
{
"contract_name": "MetaCoin",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "getBalanceInEth",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "receiver",
"type": "address"
},
{
"name": "amount",
"type": "uint256"
}
],
"name": "sendCoin",
"outputs": [
{
"name": "sufficient",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "getBalance",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"inputs": [],
"payable": false,
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
},
{
"indexed": true,
"name": "_to",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
}
],
"unlinked_binary": "0x606060405234610000575b600160a060020a033216600090815260208190526040902061271090555b5b610223806100386000396000f300606060405263ffffffff60e060020a6000350416637bd703e8811461003a57806390b98a1114610065578063f8b2cb4f14610095575b610000565b3461000057610053600160a060020a03600435166100c0565b60408051918252519081900360200190f35b3461000057610081600160a060020a0360043516602435610140565b604080519115158252519081900360200190f35b3461000057610053600160a060020a03600435166101d8565b60408051918252519081900360200190f35b600073__ConvertLib____________________________6396e4ee3d6100e5846101d8565b60026000604051602001526040518363ffffffff1660e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100005760325a03f415610000575050604051519150505b919050565b600160a060020a03331660009081526020819052604081205482901015610169575060006101d2565b600160a060020a0333811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060015b92915050565b600160a060020a0381166000908152602081905260409020545b9190505600a165627a7a72305820b129130fb364433d69a3185899792903a93461b7772a197a9e18799f46b8a70e0029",
"networks": {},
"schema_version": "0.0.5",
"updated_at": 1500611720127
}
\ No newline at end of file
{
"contract_name": "Migrations",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "new_address",
"type": "address"
}
],
"name": "upgrade",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "last_completed_migration",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "completed",
"type": "uint256"
}
],
"name": "setCompleted",
"outputs": [],
"payable": false,
"type": "function"
},
{
"inputs": [],
"payable": false,
"type": "constructor"
}
],
"unlinked_binary": "0x606060405234610000575b60008054600160a060020a03191633600160a060020a03161790555b5b610190806100366000396000f300606060405263ffffffff60e060020a6000350416630900f0108114610045578063445df0ac146100605780638da5cb5b1461007f578063fdacd576146100a8575b610000565b346100005761005e600160a060020a03600435166100ba565b005b346100005761006d61012d565b60408051918252519081900360200190f35b346100005761008c610133565b60408051600160a060020a039092168252519081900360200190f35b346100005761005e600435610142565b005b6000805433600160a060020a03908116911614156101275781905080600160a060020a031663fdacd5766001546040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b156100005760325a03f115610000575050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a039081169116141561015f5760018190555b5b5b505600a165627a7a7230582070e8bd654e1941d3b7edae27271f2e52b06deb26c322d61b0c6a60acd353ee4e0029",
"networks": {
"1": {
"events": {},
"links": {},
"address": "0x19536575150a553108e261c270f9e3dd3b4d7ab6",
"updated_at": 1502253274116
},
"1501304838468": {
"events": {},
"links": {},
"address": "0x3432dd553c638e759d2a6450555ec913d196e511",
"updated_at": 1501304863973
},
"default": {
"links": {},
"events": {},
"updated_at": 1502137026167,
"address": "0x856fb9ef0b44792aefb7790f39021de70cb7251f"
}
},
"schema_version": "0.0.5",
"updated_at": 1502253274116
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lottery Symbol</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:700"
rel="stylesheet">
<link href="app.css" rel="stylesheet">
</head>
<body>
<div id="updating">Entering...</div>
<div id="status"></div>
<div id="representation"
class="d-flex align-items-center justify-content-center">
<div id="symbol">&hellip;</div>
<div class="gui" id="symbol-gui">
<ul class="nav nav-tabs" id="gui-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#enter"
role="tab" aria-controls="enter">Enter</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#entries"
role="tab" aria-controls="entries">Entries</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#finalize"
role="tab" aria-controls="finalize">Finalize</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" role="tabpanel" id="enter">
<h2>Enter Lottery</h2>
<h4 class="gui-next-round">Next lottery ends at...</h4>
<form>
<div class="form-group">
<label class="gui-label"
for="symbol-gui-symbol">Symbol</label>
<input class="form-control"
type="text"
maxLength="1"
id="symbol-gui-symbol"
aria-describedby="symbolGuiSymbolHelpInline">
<small id="symbolGuiSymbolHelpInline"
class="text-muted">Any unicode character</small>
</div>
<div id="enter-gui-gas">
<div id="gui-gas" class="form-group">
<label for="gui-gas-account">Account to pay gas from</label>
<select class="form-control" id="gui-gas-account"></select>
</div>
</div>
<button type="button" class="btn btn-primary"
id="gui-update-button">Enter</button>
&nbsp;
<button type="button" class="btn btn-default"
id="gui-cancel-button">Cancel</button>
</form>
<p><b><i>Note that entering the lottery to update the symbol will
cost gas! Like any lottery, your entry may not
win.</i></b></p>
<p>To enter the lottery, choose a new symbol in the text field
above. Then press &quot;Enter&quot;.</p>
<p>If you do not wish to update the symbol, just press
&quot;Cancel&quot;.</p>