Merge pull request #7 from rstormsf/v2

V2
This commit is contained in:
Victor 2017-12-13 16:46:35 -08:00 committed by GitHub
commit 2d0bf86a4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
91 changed files with 16610 additions and 63681 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
node_modules/
.DS_Store
.DS_Store
build/

21
LICENSE
View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2017 Oracles Network
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2228
README.md

File diff suppressed because it is too large Load Diff

View File

@ -1,396 +0,0 @@
function attachToContract(web3, abi, addr) {
web3.eth.defaultAccount = web3.eth.accounts[0];
console.log("web3.eth.defaultAccount:" + web3.eth.defaultAccount);
let contractInstance = new web3.eth.Contract(abi, addr);
return contractInstance;
}
//check current network page is connected to. Alerts, if not Oracles network
async function checkNetworkVersion(web3, cb) {
var msgNotOracles = "You aren't connected to Oracles network. Please, switch on Oracles plugin and choose Oracles network. Check Oracles network <a href='https://github.com/oraclesorg/oracles-wiki' target='blank'>wiki</a> for more info.";
let config = await getConfig()
web3.eth.net.getId().then(function(connectedNetworkID) {
console.log("connectedNetworkID: " + connectedNetworkID);
connectedNetworkID = parseInt(connectedNetworkID);
switch (connectedNetworkID) {
case 1: {
console.log('This is mainnet');
swal("Warning", msgNotOracles, "warning");
return false;
} break;
case 2: {
console.log('This is the deprecated Morden test network.');
swal("Warning", msgNotOracles, "warning");
return false;
} break;
case 3: {
console.log('This is the ropsten test network.');
swal("Warning", msgNotOracles, "warning");
return false;
} break;
case config.networkID: {
console.log('This is Oracles from Metamask');
return true;
} break;
default: {
console.log('This is an unknown network.');
swal("Warning", msgNotOracles, "warning");
return false;
} break;
}
})
}
function formatDate(date, format, utc) {
//var MMMM = ["\x00", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var MMMM = ["\x00", "января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"];
var MMM = ["\x01", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
var dddd = ["\x02", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var ddd = ["\x03", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
function ii(i, len) {
var s = i + "";
len = len || 2;
while (s.length < len) s = "0" + s;
return s;
}
var y = utc ? date.getUTCFullYear() : date.getFullYear();
format = format.replace(/(^|[^\\])yyyy+/g, "$1" + y);
format = format.replace(/(^|[^\\])yy/g, "$1" + y.toString().substr(2, 2));
format = format.replace(/(^|[^\\])y/g, "$1" + y);
var M = (utc ? date.getUTCMonth() : date.getMonth()) + 1;
format = format.replace(/(^|[^\\])MMMM+/g, "$1" + MMMM[0]);
format = format.replace(/(^|[^\\])MMM/g, "$1" + MMM[0]);
format = format.replace(/(^|[^\\])MM/g, "$1" + ii(M));
format = format.replace(/(^|[^\\])M/g, "$1" + M);
var d = utc ? date.getUTCDate() : date.getDate();
format = format.replace(/(^|[^\\])dddd+/g, "$1" + dddd[0]);
format = format.replace(/(^|[^\\])ddd/g, "$1" + ddd[0]);
format = format.replace(/(^|[^\\])dd/g, "$1" + ii(d));
format = format.replace(/(^|[^\\])d/g, "$1" + d);
var H = utc ? date.getUTCHours() : date.getHours();
format = format.replace(/(^|[^\\])HH+/g, "$1" + ii(H));
format = format.replace(/(^|[^\\])H/g, "$1" + H);
var h = H > 12 ? H - 12 : H == 0 ? 12 : H;
format = format.replace(/(^|[^\\])hh+/g, "$1" + ii(h));
format = format.replace(/(^|[^\\])h/g, "$1" + h);
var m = utc ? date.getUTCMinutes() : date.getMinutes();
format = format.replace(/(^|[^\\])mm+/g, "$1" + ii(m));
format = format.replace(/(^|[^\\])m/g, "$1" + m);
var s = utc ? date.getUTCSeconds() : date.getSeconds();
format = format.replace(/(^|[^\\])ss+/g, "$1" + ii(s));
format = format.replace(/(^|[^\\])s/g, "$1" + s);
var f = utc ? date.getUTCMilliseconds() : date.getMilliseconds();
format = format.replace(/(^|[^\\])fff+/g, "$1" + ii(f, 3));
f = Math.round(f / 10);
format = format.replace(/(^|[^\\])ff/g, "$1" + ii(f));
f = Math.round(f / 10);
format = format.replace(/(^|[^\\])f/g, "$1" + f);
var T = H < 12 ? "AM" : "PM";
format = format.replace(/(^|[^\\])TT+/g, "$1" + T);
format = format.replace(/(^|[^\\])T/g, "$1" + T.charAt(0));
var t = T.toLowerCase();
format = format.replace(/(^|[^\\])tt+/g, "$1" + t);
format = format.replace(/(^|[^\\])t/g, "$1" + t.charAt(0));
var tz = -date.getTimezoneOffset();
var K = utc || !tz ? "Z" : tz > 0 ? "+" : "-";
if (!utc) {
tz = Math.abs(tz);
var tzHrs = Math.floor(tz / 60);
var tzMin = tz % 60;
K += ii(tzHrs) + ":" + ii(tzMin);
}
format = format.replace(/(^|[^\\])K/g, "$1" + K);
var day = (utc ? date.getUTCDay() : date.getDay()) + 1;
format = format.replace(new RegExp(dddd[0], "g"), dddd[day]);
format = format.replace(new RegExp(ddd[0], "g"), ddd[day]);
format = format.replace(new RegExp(MMMM[0], "g"), MMMM[M]);
format = format.replace(new RegExp(MMM[0], "g"), MMM[M]);
format = format.replace(/\\(.)/g, "$1");
return format;
};
function filterValidators(searchInput, validators) {
return validators.map(function(validator, i) {
if (validator) {
var searchValidated = validateSearch(validator, searchInput.toLowerCase());
if (!searchValidated) return null;
else return validator;
} else return null;
})
}
function validateSearch(validator, searchInput) {
var validatorAddress = Object.keys(validator)[0];
if (validatorAddress.indexOf(searchInput) > -1) return true;
var validatorPropsObj = validator[validatorAddress];
if (validatorPropsObj["fullName"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (validatorPropsObj["streetName"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (validatorPropsObj["zip"].toString().indexOf(searchInput) > -1) return true;
else if (validatorPropsObj["licenseID"].toString().indexOf(searchInput) > -1) return true;
else if (validatorPropsObj["state"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (formatDate(new Date(parseInt(validatorPropsObj["licenseExpiredAt"])*1000), "MM/dd/yyyy h:mmTT").toLowerCase().indexOf(searchInput) > -1)
return true;
return false;
}
//gets config file with address of Oracles contract
async function getConfig(cb) {
let config = await $.getJSON("./assets/javascripts/config.json")
let contractAddress = config.Ethereum[config.environment].ValidatorsStorage.addr
let abi = config.Ethereum[config.environment].ValidatorsStorage.abi
let networkID = config.networkID
let configJSON = {
contractAddress,
networkID,
abi
}
if (cb) cb(configJSON)
return configJSON;
}
function getValidators(web3, contractAddress, abi, disabled, cb) {
let ValidatorsStorage = attachToContract(web3, abi, contractAddress)
console.log("attach to oracles contract");
if (!ValidatorsStorage) {
return cb();
}
ValidatorsStorage.methods.getValidators().call(function(err, validatorsArray) {
if (validatorsArray.length == 0) {
return cb(validatorsArray);
}
var validatorsArrayOut = [];
var iasync = 0;
var validatorDataCount = 6;
if (disabled)
validatorDataCount++;
getValidatorsProperties(web3, validatorsArray, contractAddress, abi, iasync, validatorDataCount, disabled, validatorsArrayOut, cb)
})
}
function getValidatorsProperties(web3, validatorsArray, contractAddress, abi, iasync, validatorDataCount, disabled, validatorsArrayOut, cb) {
for (var i = 0; i < validatorsArray.length; i++) {
var addr = validatorsArray[i]
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorFullName", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("fullName", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorStreetName", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("streetName", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorState", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("state", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorLicenseExpiredAt", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("licenseExpiredAt", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorZip", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("zip", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorLicenseID", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("licenseID", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
if (disabled) {
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorDisablingDate", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("disablingDate", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
}
}
}
function getPropertyCallback(prop, resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb) {
if (validatorsArrayOut.length == _i) {
var validator = {};
validator[validatorsArray[_i]] = {};
validator[validatorsArray[_i]][prop] = resp;
validatorsArrayOut.push(validator);
} else {
validatorsArrayOut[_i][validatorsArray[_i]][prop] = resp;
}
return validatorsArrayOut;
}
function finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb) {
if (iasync == validatorsArray.length * validatorDataCount) {cb(validatorsArrayOut)};
}
function callContractMethod(web3, addr, i, contractAddr, abi, method, cb) {
let ValidatorsStorage = attachToContract(web3, abi, contractAddr)
console.log("attach to oracles contract");
if (!ValidatorsStorage) {
return cb();
}
ValidatorsStorage.methods[method](addr).call(function(err, res) {
cb(i, res);
})
}
function getValidatorView(validatorAddress, validatorPropsObj) {
var stateCode = validatorPropsObj["state"].toString();
return `<div class="validators-i">
<div class="validators-header">
0x` + validatorAddress + `
</div>
<div class="validators-body">
<div class="validators-notary left">
<p class="validators-title">Notary</p>
<div class="validators-table">
<div class="validators-table-tr">
<p class="validators-table-td left">
Full Name
</p>
<p class="validators-table-td right">
` + validatorPropsObj["fullName"] + `
</p>
</div>
<div class="validators-table-tr">
<p class="validators-table-td left">
Address
</p>
<p class="validators-table-td right">
` + validatorPropsObj["streetName"] + `
</p>
</div>
<div class="validators-table-tr">
<p class="validators-table-td left">
State
</p>
<p class="validators-table-td right">
` + stateCode + `
</p>
</div>
<div class="validators-table-tr">
<p class="validators-table-td left">
Zip Code
</p>
<p class="validators-table-td right">
` + validatorPropsObj["zip"] + `
</p>
</div>
</div>
</div>
<div class="validators-license right">
<p class="validators-title">Notary license</p>
<div class="validators-table">
<div class="validators-table-tr">
<p class="validators-table-td left">
License ID
</p>
<p class="validators-table-td right">
` + validatorPropsObj["licenseID"] + `
</p>
</div>
<div class="validators-table-tr">
<p class="validators-table-td left">
License Expiration
</p>
<p class="validators-table-td right">
` + formatDate(new Date(parseInt(validatorPropsObj["licenseExpiredAt"])*1000), "MM/dd/yyyy"/*"MM/dd/yyyy h:mmTT"*/) + `
</p>
</div>
</div>
</div>
</div>
</div>`;
}
//gets web3 object from MetaMask or Parity
function getWeb3(callback) {
if (typeof window.web3 === 'undefined') {
// no web3, use fallback
console.error("Please use a web3 browser");
var msgNotEthereum = "You aren't connected to Oracles Network. Please, switch on Oracles plugin and refresh the page. Check Oracles network <a href='https://github.com/oraclesorg/oracles-wiki' target='blank'>wiki</a> for more info.";
swal("Warning", msgNotEthereum, "warning");
callback(myWeb3, false);
} else {
// window.web3 == web3 most of the time. Don't override the provided,
// web3, just wrap it in your Web3.
var myWeb3 = new Web3(window.web3.currentProvider);
// the default account doesn't seem to be persisted, copy it to our
// new instance
myWeb3.eth.defaultAccount = window.web3.eth.defaultAccount;
let isOraclesNetwork = checkNetworkVersion(myWeb3)
callback(myWeb3, isOraclesNetwork);
}
}
//launches main application
function startDapp(web3, isOraclesNetwork) {
if (!isOraclesNetwork) {
$(".loading-container").hide();
return;
}
$(function() {
startDappInner(web3);
});
}
async function startDappInner(web3) {
var validators;
let config = await getConfig()
getValidators(web3, config.contractAddress, config.abi, false, function(_validatorsArray) {
$(".loading-container").hide();
validators = _validatorsArray;
for(var i = 0; i < _validatorsArray.length; i++) {
var validator = _validatorsArray[i];
var validatorAddress = Object.keys(validator)[0];
var validatorPropsObj = validator[validatorAddress];
$(".validators").append(getValidatorView(validatorAddress, validatorPropsObj));
}
$(".search-input").on("keyup", function() {
var searchInput = $(this).val();
var filteredValidators = filterValidators(searchInput, validators);
$(".validators").empty();
for(var i = 0; i < filteredValidators.length; i++) {
var validator = filteredValidators[i];
if (validator) {
var validatorAddress = Object.keys(validator)[0];
var validatorPropsObj = validator[validatorAddress];
$(".validators").append(getValidatorView(validatorAddress, validatorPropsObj));
}
}
});
});
}
window.addEventListener('load', function() {
getWeb3(startDapp);
});

View File

@ -1,8 +0,0 @@
function attachToContract(web3, abi, addr) {
web3.eth.defaultAccount = web3.eth.accounts[0];
console.log("web3.eth.defaultAccount:" + web3.eth.defaultAccount);
let contractInstance = new web3.eth.Contract(abi, addr);
return contractInstance;
}

View File

@ -1,35 +0,0 @@
//check current network page is connected to. Alerts, if not Oracles network
async function checkNetworkVersion(web3, cb) {
var msgNotOracles = "You aren't connected to Oracles network. Please, switch on Oracles plugin and choose Oracles network. Check Oracles network <a href='https://github.com/oraclesorg/oracles-wiki' target='blank'>wiki</a> for more info.";
let config = await getConfig()
web3.eth.net.getId().then(function(connectedNetworkID) {
console.log("connectedNetworkID: " + connectedNetworkID);
connectedNetworkID = parseInt(connectedNetworkID);
switch (connectedNetworkID) {
case 1: {
console.log('This is mainnet');
swal("Warning", msgNotOracles, "warning");
return false;
} break;
case 2: {
console.log('This is the deprecated Morden test network.');
swal("Warning", msgNotOracles, "warning");
return false;
} break;
case 3: {
console.log('This is the ropsten test network.');
swal("Warning", msgNotOracles, "warning");
return false;
} break;
case config.networkID: {
console.log('This is Oracles from Metamask');
return true;
} break;
default: {
console.log('This is an unknown network.');
swal("Warning", msgNotOracles, "warning");
return false;
} break;
}
})
}

View File

@ -1,83 +0,0 @@
function formatDate(date, format, utc) {
//var MMMM = ["\x00", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var MMMM = ["\x00", "января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"];
var MMM = ["\x01", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
var dddd = ["\x02", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var ddd = ["\x03", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
function ii(i, len) {
var s = i + "";
len = len || 2;
while (s.length < len) s = "0" + s;
return s;
}
var y = utc ? date.getUTCFullYear() : date.getFullYear();
format = format.replace(/(^|[^\\])yyyy+/g, "$1" + y);
format = format.replace(/(^|[^\\])yy/g, "$1" + y.toString().substr(2, 2));
format = format.replace(/(^|[^\\])y/g, "$1" + y);
var M = (utc ? date.getUTCMonth() : date.getMonth()) + 1;
format = format.replace(/(^|[^\\])MMMM+/g, "$1" + MMMM[0]);
format = format.replace(/(^|[^\\])MMM/g, "$1" + MMM[0]);
format = format.replace(/(^|[^\\])MM/g, "$1" + ii(M));
format = format.replace(/(^|[^\\])M/g, "$1" + M);
var d = utc ? date.getUTCDate() : date.getDate();
format = format.replace(/(^|[^\\])dddd+/g, "$1" + dddd[0]);
format = format.replace(/(^|[^\\])ddd/g, "$1" + ddd[0]);
format = format.replace(/(^|[^\\])dd/g, "$1" + ii(d));
format = format.replace(/(^|[^\\])d/g, "$1" + d);
var H = utc ? date.getUTCHours() : date.getHours();
format = format.replace(/(^|[^\\])HH+/g, "$1" + ii(H));
format = format.replace(/(^|[^\\])H/g, "$1" + H);
var h = H > 12 ? H - 12 : H == 0 ? 12 : H;
format = format.replace(/(^|[^\\])hh+/g, "$1" + ii(h));
format = format.replace(/(^|[^\\])h/g, "$1" + h);
var m = utc ? date.getUTCMinutes() : date.getMinutes();
format = format.replace(/(^|[^\\])mm+/g, "$1" + ii(m));
format = format.replace(/(^|[^\\])m/g, "$1" + m);
var s = utc ? date.getUTCSeconds() : date.getSeconds();
format = format.replace(/(^|[^\\])ss+/g, "$1" + ii(s));
format = format.replace(/(^|[^\\])s/g, "$1" + s);
var f = utc ? date.getUTCMilliseconds() : date.getMilliseconds();
format = format.replace(/(^|[^\\])fff+/g, "$1" + ii(f, 3));
f = Math.round(f / 10);
format = format.replace(/(^|[^\\])ff/g, "$1" + ii(f));
f = Math.round(f / 10);
format = format.replace(/(^|[^\\])f/g, "$1" + f);
var T = H < 12 ? "AM" : "PM";
format = format.replace(/(^|[^\\])TT+/g, "$1" + T);
format = format.replace(/(^|[^\\])T/g, "$1" + T.charAt(0));
var t = T.toLowerCase();
format = format.replace(/(^|[^\\])tt+/g, "$1" + t);
format = format.replace(/(^|[^\\])t/g, "$1" + t.charAt(0));
var tz = -date.getTimezoneOffset();
var K = utc || !tz ? "Z" : tz > 0 ? "+" : "-";
if (!utc) {
tz = Math.abs(tz);
var tzHrs = Math.floor(tz / 60);
var tzMin = tz % 60;
K += ii(tzHrs) + ":" + ii(tzMin);
}
format = format.replace(/(^|[^\\])K/g, "$1" + K);
var day = (utc ? date.getUTCDay() : date.getDay()) + 1;
format = format.replace(new RegExp(dddd[0], "g"), dddd[day]);
format = format.replace(new RegExp(ddd[0], "g"), ddd[day]);
format = format.replace(new RegExp(MMMM[0], "g"), MMMM[M]);
format = format.replace(new RegExp(MMM[0], "g"), MMM[M]);
format = format.replace(/\\(.)/g, "$1");
return format;
};

View File

@ -1,25 +0,0 @@
function filterValidators(searchInput, validators) {
return validators.map(function(validator, i) {
if (validator) {
var searchValidated = validateSearch(validator, searchInput.toLowerCase());
if (!searchValidated) return null;
else return validator;
} else return null;
})
}
function validateSearch(validator, searchInput) {
var validatorAddress = Object.keys(validator)[0];
if (validatorAddress.indexOf(searchInput) > -1) return true;
var validatorPropsObj = validator[validatorAddress];
if (validatorPropsObj["fullName"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (validatorPropsObj["streetName"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (validatorPropsObj["zip"].toString().indexOf(searchInput) > -1) return true;
else if (validatorPropsObj["licenseID"].toString().indexOf(searchInput) > -1) return true;
else if (validatorPropsObj["state"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (formatDate(new Date(parseInt(validatorPropsObj["licenseExpiredAt"])*1000), "MM/dd/yyyy h:mmTT").toLowerCase().indexOf(searchInput) > -1)
return true;
return false;
}

View File

@ -1,14 +0,0 @@
//gets config file with address of Oracles contract
async function getConfig(cb) {
let config = await $.getJSON("./assets/javascripts/config.json")
let contractAddress = config.Ethereum[config.environment].ValidatorsStorage.addr
let abi = config.Ethereum[config.environment].ValidatorsStorage.abi
let networkID = config.networkID
let configJSON = {
contractAddress,
networkID,
abi
}
if (cb) cb(configJSON)
return configJSON;
}

View File

@ -1,87 +0,0 @@
function getValidators(web3, contractAddress, abi, disabled, cb) {
let ValidatorsStorage = attachToContract(web3, abi, contractAddress)
console.log("attach to oracles contract");
if (!ValidatorsStorage) {
return cb();
}
ValidatorsStorage.methods.getValidators().call(function(err, validatorsArray) {
if (validatorsArray.length == 0) {
return cb(validatorsArray);
}
var validatorsArrayOut = [];
var iasync = 0;
var validatorDataCount = 6;
if (disabled)
validatorDataCount++;
getValidatorsProperties(web3, validatorsArray, contractAddress, abi, iasync, validatorDataCount, disabled, validatorsArrayOut, cb)
})
}
function getValidatorsProperties(web3, validatorsArray, contractAddress, abi, iasync, validatorDataCount, disabled, validatorsArrayOut, cb) {
for (var i = 0; i < validatorsArray.length; i++) {
var addr = validatorsArray[i]
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorFullName", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("fullName", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorStreetName", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("streetName", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorState", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("state", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorLicenseExpiredAt", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("licenseExpiredAt", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorZip", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("zip", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorLicenseID", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("licenseID", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
if (disabled) {
callContractMethod(web3, addr, i, contractAddress, abi, "getValidatorDisablingDate", function(_i, resp) {
iasync++;
validatorsArrayOut = getPropertyCallback("disablingDate", resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb);
finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb)
});
}
}
}
function getPropertyCallback(prop, resp, _i, validatorsArray, validatorDataCount, validatorsArrayOut, cb) {
if (validatorsArrayOut.length == _i) {
var validator = {};
validator[validatorsArray[_i]] = {};
validator[validatorsArray[_i]][prop] = resp;
validatorsArrayOut.push(validator);
} else {
validatorsArrayOut[_i][validatorsArray[_i]][prop] = resp;
}
return validatorsArrayOut;
}
function finish(iasync, validatorsArray, validatorDataCount, validatorsArrayOut, cb) {
if (iasync == validatorsArray.length * validatorDataCount) {cb(validatorsArrayOut)};
}

View File

@ -1,11 +0,0 @@
function callContractMethod(web3, addr, i, contractAddr, abi, method, cb) {
let ValidatorsStorage = attachToContract(web3, abi, contractAddr)
console.log("attach to oracles contract");
if (!ValidatorsStorage) {
return cb();
}
ValidatorsStorage.methods[method](addr).call(function(err, res) {
cb(i, res);
})
}

View File

@ -1,68 +0,0 @@
function getValidatorView(validatorAddress, validatorPropsObj) {
var stateCode = validatorPropsObj["state"].toString();
return `<div class="validators-i">
<div class="validators-header">
0x` + validatorAddress + `
</div>
<div class="validators-body">
<div class="validators-notary left">
<p class="validators-title">Notary</p>
<div class="validators-table">
<div class="validators-table-tr">
<p class="validators-table-td left">
Full Name
</p>
<p class="validators-table-td right">
` + validatorPropsObj["fullName"] + `
</p>
</div>
<div class="validators-table-tr">
<p class="validators-table-td left">
Address
</p>
<p class="validators-table-td right">
` + validatorPropsObj["streetName"] + `
</p>
</div>
<div class="validators-table-tr">
<p class="validators-table-td left">
State
</p>
<p class="validators-table-td right">
` + stateCode + `
</p>
</div>
<div class="validators-table-tr">
<p class="validators-table-td left">
Zip Code
</p>
<p class="validators-table-td right">
` + validatorPropsObj["zip"] + `
</p>
</div>
</div>
</div>
<div class="validators-license right">
<p class="validators-title">Notary license</p>
<div class="validators-table">
<div class="validators-table-tr">
<p class="validators-table-td left">
License ID
</p>
<p class="validators-table-td right">
` + validatorPropsObj["licenseID"] + `
</p>
</div>
<div class="validators-table-tr">
<p class="validators-table-td left">
License Expiration
</p>
<p class="validators-table-td right">
` + formatDate(new Date(parseInt(validatorPropsObj["licenseExpiredAt"])*1000), "MM/dd/yyyy"/*"MM/dd/yyyy h:mmTT"*/) + `
</p>
</div>
</div>
</div>
</div>
</div>`;
}

View File

@ -1,21 +0,0 @@
//gets web3 object from MetaMask or Parity
function getWeb3(callback) {
if (typeof window.web3 === 'undefined') {
// no web3, use fallback
console.error("Please use a web3 browser");
var msgNotEthereum = "You aren't connected to Oracles Network. Please, switch on Oracles plugin and refresh the page. Check Oracles network <a href='https://github.com/oraclesorg/oracles-wiki' target='blank'>wiki</a> for more info.";
swal("Warning", msgNotEthereum, "warning");
callback(myWeb3, false);
} else {
// window.web3 == web3 most of the time. Don't override the provided,
// web3, just wrap it in your Web3.
var myWeb3 = new Web3(window.web3.currentProvider);
// the default account doesn't seem to be persisted, copy it to our
// new instance
myWeb3.eth.defaultAccount = window.web3.eth.defaultAccount;
let isOraclesNetwork = checkNetworkVersion(myWeb3)
callback(myWeb3, isOraclesNetwork);
}
}

View File

@ -1,44 +0,0 @@
//launches main application
function startDapp(web3, isOraclesNetwork) {
if (!isOraclesNetwork) {
$(".loading-container").hide();
return;
}
$(function() {
startDappInner(web3);
});
}
async function startDappInner(web3) {
var validators;
let config = await getConfig()
getValidators(web3, config.contractAddress, config.abi, false, function(_validatorsArray) {
$(".loading-container").hide();
validators = _validatorsArray;
for(var i = 0; i < _validatorsArray.length; i++) {
var validator = _validatorsArray[i];
var validatorAddress = Object.keys(validator)[0];
var validatorPropsObj = validator[validatorAddress];
$(".validators").append(getValidatorView(validatorAddress, validatorPropsObj));
}
$(".search-input").on("keyup", function() {
var searchInput = $(this).val();
var filteredValidators = filterValidators(searchInput, validators);
$(".validators").empty();
for(var i = 0; i < filteredValidators.length; i++) {
var validator = filteredValidators[i];
if (validator) {
var validatorAddress = Object.keys(validator)[0];
var validatorPropsObj = validator[validatorAddress];
$(".validators").append(getValidatorView(validatorAddress, validatorPropsObj));
}
}
});
});
}
window.addEventListener('load', function() {
getWeb3(startDapp);
});

View File

@ -1,613 +0,0 @@
{
"environment": "live",
"networkID": 12648430,
"Ethereum": {
"live": {
"ValidatorsStorage": {
"addr": "0xf472e0e43570b9afaab67089615080cf7c20018d",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "miningKey",
"type": "address"
},
{
"name": "fullName",
"type": "string"
},
{
"name": "streetName",
"type": "string"
},
{
"name": "state",
"type": "string"
},
{
"name": "zip",
"type": "uint256"
},
{
"name": "licenseID",
"type": "string"
},
{
"name": "licenseExpiredAt",
"type": "uint256"
},
{
"name": "disablingDate",
"type": "uint256"
},
{
"name": "disablingTX",
"type": "string"
}
],
"name": "setValidator",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "disableValidator",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "validator",
"outputs": [
{
"name": "fullName",
"type": "string"
},
{
"name": "streetName",
"type": "string"
},
{
"name": "state",
"type": "string"
},
{
"name": "zip",
"type": "uint256"
},
{
"name": "licenseID",
"type": "string"
},
{
"name": "licenseExpiredAt",
"type": "uint256"
},
{
"name": "disablingDate",
"type": "uint256"
},
{
"name": "disablingTX",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getLastBlockHash",
"outputs": [
{
"name": "",
"type": "bytes32"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "getValidatorFullName",
"outputs": [
{
"name": "value",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "validators",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getDisabledValidators",
"outputs": [
{
"name": "value",
"type": "address[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "addValidator",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "x",
"type": "address"
}
],
"name": "toString",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "getValidatorState",
"outputs": [
{
"name": "value",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "getValidatorStreetName",
"outputs": [
{
"name": "value",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "ballotsManager",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "keysStorage",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "setValidatorsManager",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "setBallotsManager",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "getValidatorLicenseID",
"outputs": [
{
"name": "value",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "getValidatorLicenseExpiredAt",
"outputs": [
{
"name": "value",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "disabledValidators",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "getValidatorDisablingDate",
"outputs": [
{
"name": "value",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "miningKey",
"type": "address"
}
],
"name": "isMiningKeyDataExists",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "validatorsManager",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getValidators",
"outputs": [
{
"name": "value",
"type": "address[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "validatorsManagerAddr",
"type": "address"
},
{
"name": "keysStorageAddr",
"type": "address"
},
{
"name": "ballotsManagerAddr",
"type": "address"
}
],
"name": "initialize",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getDisabledValidatorsLength",
"outputs": [
{
"name": "value",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "setkeysStorage",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "getValidatorZip",
"outputs": [
{
"name": "value",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "i",
"type": "uint256"
}
],
"name": "getValidatorAtPosition",
"outputs": [
{
"name": "value",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "i",
"type": "uint256"
}
],
"name": "getDisabledValidatorAtPosition",
"outputs": [
{
"name": "value",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "index",
"type": "uint256"
}
],
"name": "removeValidator",
"outputs": [
{
"name": "",
"type": "address[]"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getValidatorsLength",
"outputs": [
{
"name": "value",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_parent_hash",
"type": "bytes32"
},
{
"indexed": false,
"name": "_new_set",
"type": "address[]"
}
],
"name": "InitiateChange",
"type": "event"
}
]
}
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
@import './index/*';

View File

@ -1,33 +0,0 @@
%stretch-width {
left: 0;
right: 0;
}
%title {
color: #333;
text-transform: uppercase;
font-size: 16px;
font-weight: bold;
}
%description {
color: #8197a2;
line-height: 24px;
font-size: 14px;
font-weight: normal;
}
%btn {
transition: 0.3s background-color;
border-radius: 3px;
padding: 0 15px 0 32px;
background-repeat: no-repeat;
background-size: 12px 12px;
background-position: left 15px center;
color: #fff;
line-height: 36px;
font-size: 13px;
text-decoration: none;
text-transform: uppercase;
font-weight: bold;
}

View File

@ -1,19 +0,0 @@
.header {
@extend %stretch-width;
position: absolute;
z-index: 1;
top: 0;
padding: 18px 10px;
background-image: url(../images/bg_header.png);
background-repeat: no-repeat;
background-size: cover;
&-logo {
@include image-2x('../images/VALIDATORS@2x.png', 149px, 35px);
float: left;
width: 149px;
height: 35px;
background-image: url(../images/VALIDATORS.png);
background-position: 0 0;
}
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

View File

@ -1,39 +0,0 @@
'use strict';
const gulp = require('gulp');
const sass = require('gulp-sass');
const sassGlob = require('gulp-sass-glob');
const autoprefixer = require('gulp-autoprefixer');
const uglifycss = require('gulp-uglifycss');
const include = require('gulp-include');
const addsrc = require('gulp-add-src');
const order = require('gulp-order');
const concat = require('gulp-concat');
const uglify = require('gulp-uglify');
const gutil = require('gulp-util');
gulp.task('sass', function() {
return gulp.src(['assets/stylesheets/*.scss'])
.pipe(sassGlob())
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer())
.pipe(uglifycss())
.pipe(gulp.dest('assets/stylesheets/'));
});
gulp.task('javascript', function() {
return gulp.src('assets/javascripts/application/*.js')
.pipe(order([
"assets/javascripts/application/*.js"
], {base: '.'}))
.pipe(include())
.pipe(concat('application.js'))
//.pipe(uglify())
.on('error', function (err) { gutil.log(gutil.colors.red('[Error]'), err.toString()); })
.pipe(gulp.dest('assets/javascripts'));
});
gulp.task('watch', function() {
gulp.watch('assets/stylesheets/**/*.scss', ['sass']);
gulp.watch('assets/javascripts/application/*.js', ['javascript']);
});

View File

@ -1,67 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="theme-color" content="#6151cc">
<meta name="msapplication-config" content="./favicons/browserconfig.xml">
<meta property="og:title" content="Oracles Network">
<meta property="og:description" content="An open network based on Ethereum protocol with Proof of Authority consensus by independent actors. Public notaries with known identity serve as private validators to secure the network.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://oracles.org">
<meta property="og:image" content="https://oracles.org/assets/images/og_image.jpg">
<meta property="fb:app_id" content="249580292197732"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./assets/stylesheets/index.css">
<link rel="apple-touch-icon" href="./favicons/favicon-192x192.png">
<link rel="icon" type="image/png" sizes="192x192" href="./favicons/favicon-192x192.png">
<link rel="mask-icon" color="#6151cc" href="./favicons/safari-pinned-tab.svg">
<link rel="manifest" href="./favicons/manifest.webmanifest">
<link href="./favicons/favicon.ico" rel="icon" type="image/x-icon">
</head>
<body>
<header class="header">
<div class="container">
<a href="#" class="header-logo"></a>
</div>
</header>
<section class="content">
<div class="search">
<div class="container">
<p class="search-title">List of active validators</p>
<form action="" class="search-form">
<input type="text" class="search-input">
</form>
</div>
</div>
<div class="container validators">
</div>
</section>
<div class="loading-container">
<div class="loading">
<div class="loading-i"></div>
<div class="loading-i"></div>
<div class="loading-i"></div>
<div class="loading-i"></div>
<div class="loading-i"></div>
<div class="loading-i"></div>
</div>
</div>
<footer class="footer">
<div class="container">
<a href="#" class="footer-logo"></a>
<div class="socials">
<a href="#" class="socials-i socials-i_reddit"></a>
<a href="https://twitter.com/oraclesorg" class="socials-i socials-i_twitter"></a>
<a href="#" class="socials-i socials-i_bitcoin"></a>
</div>
<p class="footer-rights">2017 Oracles Network. All rights reserved.</p>
</div>
</footer>
<script src="./assets/javascripts/modules.js"></script>
<script src="./assets/javascripts/application.js?v=1.20"></script>
</body>
</html>

View File

@ -1,8 +0,0 @@
{
"id": "ValidatorsList",
"name": "Validators list",
"description": "Oracles Validators list",
"version": "1.0.0",
"author": "Oracles",
"iconUrl": "./favicons/fav_2.png"
}

View File

@ -1,7 +0,0 @@
let jquery = require("jquery");
let sweetalert2 = require("sweetalert2");
let Web3 = require("web3");
window.$ = jquery;
window.swal = sweetalert2;
window.Web3 = Web3;

13122
package-lock.json generated

File diff suppressed because it is too large Load Diff

63
package.json Executable file → Normal file
View File

@ -1,40 +1,35 @@
{
"name": "oracles-dapps-validators",
"version": "1.0.0",
"description": "Oracles network Validators Dapp",
"main": "gulpfile.js",
"devDependencies": {
"gulp": "^3.9.1",
"gulp-add-src": "^0.2.0",
"gulp-autoprefixer": "^3.1.1",
"gulp-concat": "^2.6.1",
"gulp-include": "^2.3.1",
"gulp-order": "^1.1.1",
"gulp-postcss": "^6.2.0",
"gulp-sass": "^2.3.2",
"gulp-sass-glob": "^1.0.6",
"gulp-uglify": "^2.0.0",
"gulp-uglifycss": "^1.0.6",
"gulp-util": "^3.0.8",
"http-server": "^0.9.0"
"version": "0.1.0",
"private": true,
"homepage": "https://rstormsf.github.io/oracles-dapps-validators",
"dependencies": {
"clipboard": "^1.7.1",
"gh-pages": "^1.1.0",
"keythereum": "^1.0.2",
"moment": "^2.19.3",
"node-sass-chokidar": "0.0.3",
"npm-run-all": "^4.1.2",
"password-generator": "^2.2.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-places-autocomplete": "^5.4.3",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-scripts": "1.0.17",
"sweetalert": "^2.0.8",
"web3": "^1.0.0-beta.26"
},
"scripts": {
"sass": "gulp sass",
"coffee": "gulp javascript",
"watch": "gulp watch",
"start": "gulp javascript && http-server -a localhost -p 8000"
},
"repository": {
"type": "git",
"url": "https://github.com/oraclesorg/oracles-dapps-validators"
},
"keywords": [],
"author": "oraclesorg",
"license": "MIT",
"homepage": "https://oracles.org/",
"dependencies": {
"jquery": "^3.2.1",
"sweetalert2": "^7.0.3",
"web3": "^1.0.0-beta.26"
"predeploy": "npm run build",
"deploy": "gh-pages -d build -o rstorm",
"build-css": "node-sass-chokidar src/index/index.scss -o src/index",
"watch-css": "npm run build-css && node-sass-chokidar src/index/index.scss -o src/index --watch --recursive",
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"build-js": "react-scripts build",
"build": "npm-run-all build-css build-js",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

0
favicons/fav_2.png → public/favicons/fav_2.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

0
favicons/favicon.ico → public/favicons/favicon.ico Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

View File

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

61
public/index.html Normal file
View File

@ -0,0 +1,61 @@
<!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="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/favicons/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicons/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyD97qDOBYZ2fH86Wq1vzhDOiSUsZGVqbVQ&libraries=places"></script>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<header class="header">
<div class="container">
<a href="#" class="header-logo"></a>
</div>
</header>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<footer class="footer">
<div class="container">
<a href="#" class="footer-logo"></a>
<div class="socials">
<a href="#" class="socials-i socials-i_reddit"></a>
<a href="https://twitter.com/oraclesorg" class="socials-i socials-i_twitter"></a>
<a href="#" class="socials-i socials-i_bitcoin"></a>
</div>
<p class="footer-rights">2017 Oracles Network. All rights reserved.</p>
</div>
</footer>
</body>
</html>

15
public/manifest.json Normal file
View File

@ -0,0 +1,15 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

58
src/AllValidators.js Normal file
View File

@ -0,0 +1,58 @@
import React, {Component, Children} from 'react';
import Validator from './Validator'
export default class AllValidators extends Component {
constructor(props){
super(props);
this.getMetadataContract = this.getMetadataContract.bind(this);
this.state = {
validators: []
}
this.getValidatorsData.call(this);
}
async getValidatorsData() {
this.getMetadataContract()[this.props.methodToCall]().then((data) => {
this.setState({
validators: data
})
})
}
getMetadataContract(){
return this.props.web3Config.metadataContract;
}
render() {
const filtered = this.state.validators.filter((validator, index) => {
return Object.values(validator).some( val =>
String(val).toLowerCase().includes(this.props.searchTerm)
);
})
let validators = [];
let confirmations = [];
for(let [index, validator] of filtered.entries()) {
let childrenWithProps = React.Children.map(this.props.children, (child) => {
return React.cloneElement(child, { miningkey: validator.address });
})
validators.push(
<Validator
key={index}
address={validator.address}
firstName={validator.firstName}
lastName={validator.lastName}
fullAddress={validator.fullAddress}
us_state={validator.us_state}
postal_code={validator.postal_code}
licenseId={validator.licenseId}
expirationDate={validator.expirationDate}
createdDate={validator.createdDate}
updatedDate={validator.updatedDate}
metadataContract={this.props.web3Config.metadataContract}
methodToCall={this.props.methodToCall}
>{childrenWithProps}</Validator>)
}
return (<div className="container">
{validators}
</div>)
}
}

28
src/App.css Normal file
View File

@ -0,0 +1,28 @@
.App {
text-align: center;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 80px;
}
.App-header {
background-color: #222;
height: 150px;
padding: 20px;
color: white;
}
.App-title {
font-size: 1.5em;
}
.App-intro {
font-size: large;
}
@keyframes App-logo-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}

244
src/App.js Normal file
View File

@ -0,0 +1,244 @@
import React, { Component } from 'react';
import getWeb3 from './getWeb3'
import KeysManager from './contracts/KeysManager.contract';
import MetadataContract from './contracts/Metadata.contract';
import swal from 'sweetalert';
import './index/index.css';
import ReactDOM from 'react-dom';
import PlacesAutocomplete, { geocodeByAddress, geocodeByPlaceId } from 'react-places-autocomplete';
import moment from 'moment';
import Metadata from './contracts/Metadata.contract';
import Loading from './Loading';
class App extends Component {
constructor(props){
super(props);
this.checkValidation = this.checkValidation.bind(this)
this.onClick = this.onClick.bind(this);
this.onChangeFormField = this.onChangeFormField.bind(this);
this.getKeysManager = this.getKeysManager.bind(this);
this.getMetadataContract = this.getMetadataContract.bind(this);
this.getVotingKey = this.getVotingKey.bind(this);
this.onChangeAutoComplete = ((address) => {
const form = this.state.form;
form.fullAddress = address;
this.setState({form})
})
this.onSelect = this.onSelectAutocomplete.bind(this)
this.state = {
web3Config: {},
form: {
fullAddress: '',
expirationDate: '',
postal_code: '',
us_state: '',
firstName: '',
lastName: '',
licenseId: ''
},
hasData: false
}
this.defaultValues = null;
this.setMetadata.call(this);
}
async setMetadata(){
const currentData = await this.getMetadataContract().getValidatorData({votingKey: this.getVotingKey()});
const hasData = Number(currentData.postal_code) > 0 ? true : false
this.defaultValues = currentData;
const pendingChange = await this.getMetadataContract().getPendingChange({votingKey: this.getVotingKey()});
if(Number(pendingChange.minThreshold) > 0 ) {
var content = document.createElement("div");
content.innerHTML = `<div>
First Name: ${pendingChange.firstName} <br/>
Last Name: ${pendingChange.lastName} <br/>
Full Address: ${pendingChange.fullAddress} <br/>
Expiration Date: ${pendingChange.expirationDate} <br />
License ID: ${pendingChange.licenseId} <br/>
US state: ${pendingChange.us_state} <br/>
Zip Code: ${pendingChange.postal_code} <br/>
</div>`;
swal({
icon: 'warning',
title: 'You have pending changes!',
content: content
});
}
this.setState({
form: {
fullAddress: currentData.fullAddress,
expirationDate: currentData.expirationDate,
postal_code: currentData.postal_code,
us_state: currentData.us_state,
firstName: currentData.firstName,
lastName: currentData.lastName,
licenseId: currentData.licenseId,
},
hasData
});
}
getKeysManager(){
return this.props.web3Config.keysManager;
}
getMetadataContract(){
return this.props.web3Config.metadataContract;
}
getVotingKey(){
return this.props.web3Config.votingKey;
}
checkValidation() {
const isAfter = moment(this.state.form.expirationDate).isAfter(moment());
let keys = Object.keys(this.state.form);
keys.forEach((key) => {
if(!this.state.form[key]){
this.setState({loading: false})
swal("Warning!", `${key} cannot be empty`, "warning");
return false;
}
})
if(isAfter){
} else {
this.setState({loading: false})
swal("Warning!", "Expiration date should be valid", "warning");
return false;
}
return true;
}
async onSelectAutocomplete(data) {
let place = await geocodeByAddress(data)
let address_components = {};
for (var i = 0; i < place[0].address_components.length; i++) {
var addressType = place[0].address_components[i].types[0];
switch(addressType) {
case "postal_code":
address_components.postal_code = Number(place[0].address_components[i].short_name);
break;
case "street_number":
address_components.street_number = place[0].address_components[i].short_name;
break;
case "route":
address_components.route = place[0].address_components[i].short_name;
break;
case "locality":
address_components.locality = place[0].address_components[i].short_name;
break;
case "administrative_area_level_1":
address_components.administrative_area_level_1 = place[0].address_components[i].short_name;
break;
}
let form = this.state.form;
form.fullAddress= `${address_components.street_number} ${address_components.route} ${address_components.locality}`;
form.us_state= address_components.administrative_area_level_1;
form.postal_code= address_components.postal_code;
this.setState({
form
});
}
}
async onClick() {
this.setState({loading:true});
const isFormValid = this.checkValidation();
if(isFormValid){
const votingKey = this.getVotingKey();
console.log('voting', votingKey)
const isValid = await this.getKeysManager().isVotingActive(votingKey);
console.log(isValid);
if(isValid){
// // add loading screen
await this.sendTxToContract()
} else {
this.setState({loading:false});
swal("Warning!", "The key is not valid voting Key! Please make sure you have loaded correct voting key in metamask", "warning");
return;
}
}
}
async sendTxToContract(){
this.getMetadataContract().createMetadata({
firstName: this.state.form.firstName,
lastName: this.state.form.lastName,
licenseId: this.state.form.licenseId,
fullAddress: this.state.form.fullAddress,
state: this.state.form.us_state,
zipcode: this.state.form.postal_code,
expirationDate: moment(this.state.form.expirationDate).unix(),
votingKey: this.getVotingKey(),
hasData: this.state.hasData
}).then((receipt) => {
console.log(receipt);
this.setState({loading: false})
swal("Congratulations!", "Your metadata was sent!", "success");
}).catch((error) => {
console.error(error.message);
this.setState({loading: false})
var content = document.createElement("div");
content.innerHTML = `<div>
Something went wrong!<br/><br/>
${error.message}
</div>`;
swal({
icon: 'error',
title: 'Error',
content: content
});
})
}
onChangeFormField(event) {
const field = event.target.id;
const value = event.target.value;
let form = this.state.form;
form[field] = value;
this.setState({form});
}
render() {
const BtnAction = this.state.hasData ? "Update" : "Set";
const AutocompleteItem = ({ formattedSuggestion }) => (
<div className="custom-container">
<strong>{ formattedSuggestion.mainText }</strong>{' '}
<small>{ formattedSuggestion.secondaryText }</small>
</div>
)
const inputProps = {
value: this.state.form.fullAddress,
onChange: this.onChangeAutoComplete,
id: 'address'
}
let loader = this.state.loading ? <Loading /> : '';
let createKeyBtn = (<div className="create-keys">
<form className="create-keys-inputs">
<div className="left">
<label htmlFor="first-name">First name </label>
<input type="text" id="firstName" value={this.state.form.firstName} onChange={this.onChangeFormField}/>
<label htmlFor="last-name">Last name</label>
<input type="text" id="lastName" value={this.state.form.lastName} onChange={this.onChangeFormField}/>
<label htmlFor="address">Address</label>
<PlacesAutocomplete onSelect={this.onSelect} inputProps={inputProps} autocompleteItem={AutocompleteItem} />
<label htmlFor="state">State</label>
<input type="text" id="us_state" value={this.state.form.us_state} onChange={this.onChangeFormField}/>
</div>
<div className="right">
<label htmlFor="zip">Zip code</label>
<input type="number" id="postal_code" value={this.state.form.postal_code} onChange={this.onChangeFormField}/>
<label htmlFor="licenseId">License id</label>
<input type="text" id="licenseId" value={this.state.form.licenseId} onChange={this.onChangeFormField}/>
<label htmlFor="expirationDate">License expiration</label>
<input type="date" id="expirationDate" value={this.state.form.expirationDate} onChange={this.onChangeFormField}/>
</div>
</form>
<button onClick={this.onClick} className="create-keys-button set">{BtnAction} Metadata</button>
</div>)
let content = createKeyBtn;
return (
<div className="container">
{loader}
{content}
</div>
);
}
}
export default App;

8
src/App.test.js Normal file
View File

@ -0,0 +1,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
});

0
src/DownloadBtn.js Normal file
View File

14
src/Loading.js Normal file
View File

@ -0,0 +1,14 @@
import React, { Component } from 'react';
const Loading = () => (
<div className="loading-container">
<div className="loading">
<div className="loading-i"></div>
<div className="loading-i"></div>
<div className="loading-i"></div>
<div className="loading-i"></div>
<div className="loading-i"></div>
<div className="loading-i"></div>
</div>
</div>
)
export default Loading;

127
src/Validator.js Normal file
View File

@ -0,0 +1,127 @@
import React, {Component, Children} from 'react';
class Validator extends Component {
constructor(props) {
super(props);
this.state = {
confirmation: null
}
this.props.metadataContract.getConfirmations({miningKey: this.props.address}).then((confirmation) => {
this.setState({confirmation})
})
}
render(){
let {
address,
firstName,
lastName,
fullAddress,
us_state,
postal_code,
licenseId,
expirationDate,
createdDate,
updatedDate,
children,
} = this.props;
let confirmations = this.props.methodToCall === 'getAllValidatorsData' ? '' : <div className="confirmations">
<div>{this.state.confirmation} confirmations</div>
</div>
return(
<div className="validators-i">
<div className="validators-header">
<div className="left">
<div>
{address}
</div>
{confirmations}
</div>
<div>
</div>
<div className="right">
{children}
</div>
</div>
<div className="validators-body">
<div className="validators-notary left">
<p className="validators-title">Notary</p>
<div className="validators-table">
<div className="validators-table-tr">
<p className="validators-table-td left">
Full Name
</p>
<p className="validators-table-td right">
{firstName} {lastName}
</p>
</div>
<div className="validators-table-tr">
<p className="validators-table-td left">
Address
</p>
<p className="validators-table-td right">
{fullAddress}
</p>
</div>
<div className="validators-table-tr">
<p className="validators-table-td left">
State
</p>
<p className="validators-table-td right">
{us_state}
</p>
</div>
<div className="validators-table-tr">
<p className="validators-table-td left">
Zip Code
</p>
<p className="validators-table-td right">
{postal_code}
</p>
</div>
</div>
</div>
<div className="validators-license right">
<p className="validators-title">Notary license</p>
<div className="validators-table">
<div className="validators-table-tr">
<p className="validators-table-td left">
License ID
</p>
<p className="validators-table-td right">
{licenseId}
</p>
</div>
<div className="validators-table-tr">
<p className="validators-table-td left">
License Expiration
</p>
<p className="validators-table-td right">
{expirationDate}
</p>
</div>
<div className="validators-table-tr">
<p className="validators-table-td left">
Miner Creation Date
</p>
<p className="validators-table-td right">
{createdDate}
</p>
</div>
<div className="validators-table-tr">
<p className="validators-table-td left">
Pending Change Requested Date
</p>
<p className="validators-table-td right">
{updatedDate}
</p>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default Validator;

View File

@ -0,0 +1,15 @@
import KeysManagerAbi from './keysManager.abi.json'
import Web3 from 'web3';
const KEYS_MANAGER_ADDRESS = '0xafb147e450f0375bc3e61709b053238f5804c9a6';
export default class KeysManager {
constructor(){
if(window.web3.currentProvider){
let web3_10 = new Web3(window.web3.currentProvider);
this.keysInstance = new web3_10.eth.Contract(KeysManagerAbi, KEYS_MANAGER_ADDRESS);
}
}
async isVotingActive(votingKey) {
return await this.keysInstance.methods.isVotingActive(votingKey).call();
}
}

View File

@ -0,0 +1,144 @@
import PoaConsensus from './PoaConsensus.contract'
import MetadataAbi from './metadata.abi.json'
import Web3 from 'web3';
import moment from 'moment';
var toAscii = function(hex) {
var str = '',
i = 0,
l = hex.length;
if (hex.substring(0, 2) === '0x') {
i = 2;
}
for (; i < l; i+=2) {
var code = parseInt(hex.substr(i, 2), 16);
if (code === 0) continue; // this is added
str += String.fromCharCode(code);
}
return str;
};
const METADATA_ADDRESS = '0x3111c94b9243a8a99d5a867e00609900e437e2c0';
export default class Metadata {
constructor(){
if(window.web3.currentProvider){
this.web3_10 = new Web3(window.web3.currentProvider);
this.metadataInstance = new this.web3_10.eth.Contract(MetadataAbi, METADATA_ADDRESS);
}
}
async createMetadata({
firstName,
lastName,
licenseId,
fullAddress,
state,
zipcode,
expirationDate,
votingKey,
hasData
}) {
let methodToCall = hasData ? 'changeRequest' : 'createMetadata'
return await this.metadataInstance.methods[methodToCall](
this.web3_10.utils.fromAscii(firstName),
this.web3_10.utils.fromAscii(lastName),
this.web3_10.utils.fromAscii(licenseId),
fullAddress,
this.web3_10.utils.fromAscii(state),
zipcode,
expirationDate
).send({from: votingKey});
}
async getValidatorData({votingKey, miningKey}){
miningKey = miningKey || await this.getMiningByVoting(votingKey);
let validatorData = await this.metadataInstance.methods.validators(miningKey).call();
let createdDate = validatorData.createdDate > 0 ? moment.unix(validatorData.createdDate).format('YYYY-MM-DD') : ''
let updatedDate = validatorData.updatedDate > 0 ? moment.unix(validatorData.updatedDate).format('YYYY-MM-DD') : ''
let expirationDate = validatorData.expirationDate > 0 ? moment.unix(validatorData.expirationDate).format('YYYY-MM-DD') : ''
let postal_code = Number(validatorData.zipcode) || ''
return {
firstName: toAscii(validatorData.firstName),
lastName: toAscii(validatorData.lastName),
fullAddress: validatorData.fullAddress,
createdDate,
updatedDate,
expirationDate,
licenseId: toAscii(validatorData.licenseId),
us_state: toAscii(validatorData.state),
postal_code,
}
}
async getMiningByVoting(votingKey){
return await this.metadataInstance.methods.getMiningByVotingKey(votingKey).call();
}
async getAllValidatorsData(){
let all = [];
return new Promise(async(resolve, reject) => {
const poaInstance = new PoaConsensus({web3: this.web3_10})
const keys = await poaInstance.getValidators()
for (let key of keys) {
let data = await this.getValidatorData({miningKey: key})
data.address = key
all.push(data)
}
resolve(all);
})
}
async getPendingChange({votingKey, miningKey}){
miningKey = miningKey || await this.getMiningByVoting(votingKey);
let pendingChanges = await this.metadataInstance.methods.pendingChanges(miningKey).call();
let createdDate = pendingChanges.createdDate > 0 ? moment.unix(pendingChanges.createdDate).format('YYYY-MM-DD') : ''
let updatedDate = pendingChanges.updatedDate > 0 ? moment.unix(pendingChanges.updatedDate).format('YYYY-MM-DD') : ''
let expirationDate = pendingChanges.expirationDate > 0 ? moment.unix(pendingChanges.expirationDate).format('YYYY-MM-DD') : ''
let postal_code = Number(pendingChanges.zipcode) || ''
return {
firstName: toAscii(pendingChanges.firstName),
lastName: toAscii(pendingChanges.lastName),
fullAddress: pendingChanges.fullAddress,
createdDate,
updatedDate,
expirationDate,
licenseId: toAscii(pendingChanges.licenseId),
us_state: toAscii(pendingChanges.state),
postal_code,
minThreshold: pendingChanges.minThreshold
}
}
async getAllPendingChanges() {
let allChanges = await this.metadataInstance.getPastEvents('ChangeRequestInitiated', {fromBlock: 0});
let miningKeys = allChanges.map((event) => event.returnValues.miningKey)
let pendingChanges = []
for (let key of miningKeys) {
let pendingChange = await this.getPendingChange({miningKey: key})
pendingChange.address = key;
if(pendingChange.postal_code > 0){
pendingChanges.push(pendingChange)
}
}
return pendingChanges
}
async confirmPendingChange({miningKeyToConfirm, senderVotingKey}) {
// you can't confirm your own
// you can't confirm twice
//
return await this.metadataInstance.methods.confirmPendingChange(miningKeyToConfirm).send({from: senderVotingKey});
}
async getConfirmations({miningKey}) {
return await this.metadataInstance.methods.confirmations(miningKey).call();
}
async getMinThreshold({miningKey}) {
let validatorData = await this.metadataInstance.methods.validators(miningKey).call();
return validatorData.minThreshold;
}
async finalize({miningKeyToConfirm, senderVotingKey}) {
return await this.metadataInstance.methods.finalize(miningKeyToConfirm).send({from: senderVotingKey});
}
}

View File

@ -0,0 +1,15 @@
import poaConsensusAbi from './poaConsensus.abi.json'
import Web3 from 'web3';
const KEYS_MANAGER_ADDRESS = '0xf472E0e43570B9AfaAB67089615080cF7C20018d';
export default class POAConsensus {
constructor(){
if(window.web3.currentProvider){
let web3_10 = new Web3(window.web3.currentProvider);
this.poaInstance = new web3_10.eth.Contract(poaConsensusAbi, KEYS_MANAGER_ADDRESS);
}
}
async getValidators(){
return await this.poaInstance.methods.getValidators().call();
}
}

View File

@ -0,0 +1,621 @@
[
{
"constant": false,
"inputs": [
{
"name": "_miningKey",
"type": "address"
}
],
"name": "removePayoutKey",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_miningKey",
"type": "address"
}
],
"name": "removeVotingKey",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_miningKey",
"type": "address"
}
],
"name": "getVotingByMining",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "getMiningKeyByVoting",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_key",
"type": "address"
}
],
"name": "addMiningKey",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "poaNetworkConsensus",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "miningKeyHistory",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getVotingToChangeKeys",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getTime",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "validatorKeys",
"outputs": [
{
"name": "votingKey",
"type": "address"
},
{
"name": "payoutKey",
"type": "address"
},
{
"name": "isMiningActive",
"type": "bool"
},
{
"name": "isVotingActive",
"type": "bool"
},
{
"name": "isPayoutActive",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_votingKey",
"type": "address"
}
],
"name": "isVotingActive",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_key",
"type": "address"
},
{
"name": "_miningKey",
"type": "address"
}
],
"name": "addPayoutKey",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "initialKeys",
"outputs": [
{
"name": "",
"type": "uint8"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_key",
"type": "address"
},
{
"name": "_miningKey",
"type": "address"
}
],
"name": "swapPayoutKey",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_miningKey",
"type": "address"
}
],
"name": "getPayoutByMining",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_key",
"type": "address"
}
],
"name": "removeMiningKey",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "maxLimitValidators",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_initialKey",
"type": "address"
}
],
"name": "initiateKeys",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_key",
"type": "address"
},
{
"name": "_miningKey",
"type": "address"
}
],
"name": "addVotingKey",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_key",
"type": "address"
}
],
"name": "isMiningActive",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "proxyStorage",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "votingContract",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_miningKey",
"type": "address"
},
{
"name": "_votingKey",
"type": "address"
},
{
"name": "_payoutKey",
"type": "address"
}
],
"name": "createKeys",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "initialKeysCount",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_key",
"type": "address"
},
{
"name": "_miningKey",
"type": "address"
}
],
"name": "swapVotingKey",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_key",
"type": "address"
},
{
"name": "_oldMiningKey",
"type": "address"
}
],
"name": "swapMiningKey",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "maxNumberOfInitialKeys",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "masterOfCeremony",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_miningKey",
"type": "address"
}
],
"name": "isPayoutActive",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"name": "_proxyStorage",
"type": "address"
},
{
"name": "_poaConsensus",
"type": "address"
},
{
"name": "_masterOfCeremony",
"type": "address"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "key",
"type": "address"
},
{
"indexed": true,
"name": "miningKey",
"type": "address"
},
{
"indexed": false,
"name": "action",
"type": "string"
}
],
"name": "PayoutKeyChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "key",
"type": "address"
},
{
"indexed": true,
"name": "miningKey",
"type": "address"
},
{
"indexed": false,
"name": "action",
"type": "string"
}
],
"name": "VotingKeyChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "key",
"type": "address"
},
{
"indexed": false,
"name": "action",
"type": "string"
}
],
"name": "MiningKeyChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "miningKey",
"type": "address"
},
{
"indexed": true,
"name": "votingKey",
"type": "address"
},
{
"indexed": true,
"name": "payoutKey",
"type": "address"
}
],
"name": "ValidatorInitialized",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "initialKey",
"type": "address"
},
{
"indexed": false,
"name": "time",
"type": "uint256"
},
{
"indexed": false,
"name": "initialKeysCount",
"type": "uint256"
}
],
"name": "InitialKeyCreated",
"type": "event"
}
]

View File

@ -0,0 +1,628 @@
[
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "pendingChanges",
"outputs": [
{
"name": "firstName",
"type": "bytes32"
},
{
"name": "lastName",
"type": "bytes32"
},
{
"name": "licenseId",
"type": "bytes32"
},
{
"name": "fullAddress",
"type": "string"
},
{
"name": "state",
"type": "bytes32"
},
{
"name": "zipcode",
"type": "uint256"
},
{
"name": "expirationDate",
"type": "uint256"
},
{
"name": "createdDate",
"type": "uint256"
},
{
"name": "updatedDate",
"type": "uint256"
},
{
"name": "minThreshold",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_miningKey",
"type": "address"
}
],
"name": "getBallotsStorage",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "confirmations",
"outputs": [
{
"name": "count",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_miningKey",
"type": "address"
}
],
"name": "finalize",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_firstName",
"type": "bytes32"
},
{
"name": "_lastName",
"type": "bytes32"
},
{
"name": "_licenseId",
"type": "bytes32"
},
{
"name": "_fullAddress",
"type": "string"
},
{
"name": "_state",
"type": "bytes32"
},
{
"name": "_zipcode",
"type": "uint256"
},
{
"name": "_expirationDate",
"type": "uint256"
}
],
"name": "getTime",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_votingKey",
"type": "address"
}
],
"name": "getMiningByVotingKey",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_firstName",
"type": "bytes32"
},
{
"name": "_lastName",
"type": "bytes32"
},
{
"name": "_licenseId",
"type": "bytes32"
},
{
"name": "_fullAddress",
"type": "string"
},
{
"name": "_state",
"type": "bytes32"
},
{
"name": "_zipcode",
"type": "uint256"
},
{
"name": "_expirationDate",
"type": "uint256"
}
],
"name": "changeRequest",
"outputs": [
{
"components": [
{
"name": "firstName",
"type": "bytes32"
},
{
"name": "lastName",
"type": "bytes32"
},
{
"name": "licenseId",
"type": "bytes32"
},
{
"name": "fullAddress",
"type": "string"
},
{
"name": "state",
"type": "bytes32"
},
{
"name": "zipcode",
"type": "uint256"
},
{
"name": "expirationDate",
"type": "uint256"
},
{
"name": "createdDate",
"type": "uint256"
},
{
"name": "updatedDate",
"type": "uint256"
},
{
"name": "minThreshold",
"type": "uint256"
},
{
"name": "requestNonce",
"type": "uint256"
}
],
"name": "",
"type": "bool"
},
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_miningKey",
"type": "address"
}
],
"name": "getKeysManager",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_miningKey",
"type": "address"
}
],
"name": "confirmPendingChange",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "proxyStorage",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_firstName",
"type": "bytes32"
},
{
"name": "_lastName",
"type": "bytes32"
},
{
"name": "_licenseId",
"type": "bytes32"
},
{
"name": "_fullAddress",
"type": "string"
},
{
"name": "_state",
"type": "bytes32"
},
{
"name": "_zipcode",
"type": "uint256"
},
{
"name": "_expirationDate",
"type": "uint256"
}
],
"name": "getMinThreshold",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_miningKey",
"type": "address"
},
{
"name": "_voter",
"type": "address"
}
],
"name": "isAddressAlreadyVoted",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_firstName",
"type": "bytes32"
},
{
"name": "_lastName",
"type": "bytes32"
},
{
"name": "_licenseId",
"type": "bytes32"
},
{
"name": "_fullAddress",
"type": "string"
},
{
"name": "_state",
"type": "bytes32"
},
{
"name": "_zipcode",
"type": "uint256"
},
{
"name": "_expirationDate",
"type": "uint256"
}
],
"name": "createMetadata",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "cancelPendingChange",
"outputs": [
{
"name": "",
"type": "bool"
},
{
"name": "lastName",
"type": "bytes32"
},
{
"name": "licenseId",
"type": "bytes32"
},
{
"name": "fullAddress",
"type": "string"
},
{
"name": "state",
"type": "bytes32"
},
{
"name": "zipcode",
"type": "uint256"
},
{
"name": "expirationDate",
"type": "uint256"
},
{
"name": "createdDate",
"type": "uint256"
},
{
"name": "updatedDate",
"type": "uint256"
},
{
"name": "minThreshold",
"type": "uint256"
},
{
"name": "requestNonce",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"constant": true,
"name": "validators",
"outputs": [
{
"name": "firstName",
"type": "bytes32"
},
{
"name": "lastName",
"type": "bytes32"
},
{
"name": "licenseId",
"type": "bytes32"
},
{
"name": "fullAddress",
"type": "string"
},
{
"name": "state",
"type": "bytes32"
},
{
"name": "zipcode",
"type": "uint256"
},
{
"name": "expirationDate",
"type": "uint256"
},
{
"name": "createdDate",
"type": "uint256"
},
{
"name": "updatedDate",
"type": "uint256"
},
{
"name": "minThreshold",
"type": "uint256"
}
]
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_proxyStorage",
"type": "address"
}
],
"name": "MetadataCreated",
"type": "constructor",
"payable": false,
"stateMutability": "nonpayable"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "miningKey",
"type": "address"
}
],
"name": "MetadataCreated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "miningKey",
"type": "address"
}
],
"name": "ChangeRequestInitiated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "miningKey",
"type": "address"
},
{
"indexed": false,
"name": "votingSender",
"type": "address"
}
],
"name": "CancelledRequest",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "miningKey",
"type": "address"
},
{
"indexed": false,
"name": "votingSender",
"type": "address"
}
],
"name": "Confirmed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "miningKey",
"type": "address"
}
],
"name": "FinalizedChange",
"type": "event"
}
]

View File

@ -0,0 +1,342 @@
[
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "pendingList",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_newAddress",
"type": "address"
}
],
"name": "setProxyStorage",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_validator",
"type": "address"
}
],
"name": "removeValidator",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "currentValidatorsLength",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "validatorsState",
"outputs": [
{
"name": "isValidator",
"type": "bool"
},
{
"name": "index",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getPendingList",
"outputs": [
{
"name": "",
"type": "address[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getVotingToChangeKeys",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_validator",
"type": "address"
}
],
"name": "addValidator",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "finalizeChange",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "currentValidators",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getKeysManager",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "isMasterOfCeremonyInitialized",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "proxyStorage",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "finalized",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getValidators",
"outputs": [
{
"name": "",
"type": "address[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "systemAddress",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "masterOfCeremony",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_someone",
"type": "address"
}
],
"name": "isValidator",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"name": "_masterOfCeremony",
"type": "address"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "parentHash",
"type": "bytes32"
},
{
"indexed": false,
"name": "newSet",
"type": "address[]"
}
],
"name": "InitiateChange",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "newSet",
"type": "address[]"
}
],
"name": "ChangeFinalized",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "nameOfContract",
"type": "string"
},
{
"indexed": false,
"name": "newAddress",
"type": "address"
}
],
"name": "ChangeReference",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "proxyStorage",
"type": "address"
}
],
"name": "MoCInitializedProxyStorage",
"type": "event"
}
]

67
src/getWeb3.js Normal file
View File

@ -0,0 +1,67 @@
let errorMsgNoMetamaskAccount = `You haven't chosen any account in MetaMask.
Please, choose your initial key in MetaMask and reload the page.
Check Oracles network <a href='https://github.com/oraclesorg/oracles-wiki' target='blank'>wiki</a> for more info.`;
function generateElement(msg){
let errorNode = document.createElement("div");
errorNode.innerHTML = `<div>
${msg}
</div>`;
return errorNode;
}
let getWeb3 = () => {
return new Promise(function (resolve, reject) {
// Wait for loading completion to avoid race conditions with web3 injection timing.
window.addEventListener('load', function () {
var results
var web3 = window.web3
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
// Use Mist/MetaMask's provider.
var errorMsg = null;
web3 = new window.Web3(web3.currentProvider)
web3.version.getNetwork((err, netId) => {
let netIdName;
switch (netId) {
case "12648430":
netIdName = 'Oracles'
console.log('This is oracles')
break
default:
netIdName = 'ERROR'
errorMsg = `You aren't connected to Oracles Network.
Please, switch on Oracles plugin and refresh the page.
Check Oracles network <a href='https://github.com/oraclesorg/oracles-wiki' target='blank'>wiki</a> for more info.`
console.log('This is an unknown network.')
}
var defaultAccount = web3.eth.defaultAccount || null;
if(defaultAccount === null){
reject({msg: errorMsgNoMetamaskAccount, node: generateElement(errorMsgNoMetamaskAccount)})
}
if(errorMsg !== null){
reject({msg: errorMsg, node: generateElement(errorMsg)})
}
results = {
web3Instance: web3,
netIdName,
netId,
injectedWeb3: true,
defaultAccount
}
resolve(results)
})
console.log('Injected web3 detected.');
} else {
reject({msg: errorMsgNoMetamaskAccount, node: generateElement(errorMsgNoMetamaskAccount)})
console.error('Metamask not found');
}
})
})
}
export default getWeb3

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

View File

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

BIN
src/images/copy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
src/images/copy@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 541 B

After

Width:  |  Height:  |  Size: 541 B

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

1
src/images/warning.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="20"><path fill="#FBFBFB" fill-rule="evenodd" d="M21.377 14.326L14.152 1.82a3.645 3.645 0 0 0-6.312 0L.488 14.54a3.636 3.636 0 0 0 0 3.64A3.645 3.645 0 0 0 3.644 20h14.712A3.643 3.643 0 0 0 22 16.36c0-.753-.23-1.455-.623-2.034zm-8.821 1.217c0 .861-.663 1.519-1.556 1.519s-1.556-.658-1.556-1.519v-.035c0-.857.663-1.519 1.556-1.519s1.556.658 1.556 1.519v.035zm.036-10.238l-.77 6.717c-.052.484-.373.785-.822.785-.449 0-.77-.305-.822-.785l-.77-6.721c-.051-.519.23-.912.715-.912h1.75c.485.004.771.397.719.916z"/></svg>

After

Width:  |  Height:  |  Size: 571 B

165
src/index.js Normal file
View File

@ -0,0 +1,165 @@
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import swal from 'sweetalert';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import KeysManager from './contracts/KeysManager.contract'
import Metadata from './contracts/Metadata.contract'
import getWeb3 from './getWeb3'
import { setTimeout } from 'timers';
import {
Router,
Route,
Link,
NavLink
} from 'react-router-dom'
import createBrowserHistory from 'history/createBrowserHistory'
import Loading from './Loading'
import AllValidators from './AllValidators'
const history = createBrowserHistory()
function generateElement(msg){
let errorNode = document.createElement("div");
errorNode.innerHTML = `<div>
${msg}
</div>`;
return errorNode;
}
class AppMainRouter extends Component {
constructor(props){
super(props);
this.rootPath = '/oracles-dapps-validators'
history.listen(this.onRouteChange.bind(this));
this.onSetRender = this.onSetRender.bind(this);
this.onPendingChangesRender = this.onPendingChangesRender.bind(this);
this.onAllValidatorsRender = this.onAllValidatorsRender.bind(this)
this.onConfirmPendingChange = this.onConfirmPendingChange.bind(this);
this.onFinalize = this.onFinalize.bind(this);
this.onSearch = this.onSearch.bind(this);
this.state = {
showSearch: true,
web3loaded: false,
keysManager :null,
metadataContract: null,
poaConsensus: null,
votingKey :null,
loading: true,
searchTerm: ''
}
getWeb3().then(async (web3Config) => {
const keysManager = new KeysManager({
web3: web3Config.web3Instance
});
const metadataContract = new Metadata({
web3: web3Config.web3Instance
})
this.setState({
votingKey: web3Config.defaultAccount,
keysManager,
metadataContract,
loading: false,
})
}).catch((error) => {
console.error(error.message);
this.setState({loading: false})
swal({
icon: 'error',
title: 'Error',
content: generateElement(error.message)
});
})
}
onRouteChange(){
const setMetadata = this.rootPath + "/set";
if(history.location.pathname === setMetadata){
this.setState({showSearch: false})
} else {
this.setState({showSearch: true})
}
}
onSetRender() {
return this.state.votingKey ? <App web3Config={this.state}/> : '';
}
async _onBtnClick({event, methodToCall, successMsg}){
event.preventDefault();
this.setState({loading: true})
const miningKey = event.currentTarget.getAttribute('miningkey');
try{
let result = await this.state.metadataContract[methodToCall]({
miningKeyToConfirm: miningKey,
senderVotingKey: this.state.votingKey
});
console.log(result);
this.setState({loading: false})
swal("Congratulations!", successMsg, "success");
} catch(error) {
this.setState({loading: false})
console.error(error.message);
swal({
icon: 'error',
title: 'Error',
content: generateElement(error.message)
});
}
}
async onConfirmPendingChange(event) {
await this._onBtnClick({
event,
methodToCall: 'confirmPendingChange',
successMsg: 'You have successfully confirmed the change!'
});
}
async onFinalize(event){
await this._onBtnClick({
event,
methodToCall: 'finalize',
successMsg: 'You have successfully finalized the change!'
});
}
onPendingChangesRender() {
return this.state.votingKey ? <AllValidators
methodToCall="getAllPendingChanges"
searchTerm={this.state.searchTerm}
web3Config={this.state}>
<button onClick={this.onFinalize} className="create-keys-button finalize">Finalize</button>
<button onClick={this.onConfirmPendingChange} className="create-keys-button">Confirm</button>
</AllValidators> : '';
}
onAllValidatorsRender() {
return this.state.votingKey ? <AllValidators searchTerm={this.state.searchTerm} methodToCall="getAllValidatorsData" web3Config={this.state} /> : '';
}
onSearch(term){
this.setState({searchTerm: term.target.value.toLowerCase()})
}
render(){
console.log('v2.03')
const search = this.state.showSearch ? <input type="search" className="search-input" onChange={this.onSearch}/> : ''
const loading = this.state.loading ? <Loading /> : ''
return (
<Router history={history}>
<section className="content">
{loading}
<div className="search">
<div className="container flex-container">
<div className="nav">
<NavLink className="nav-i" exact activeClassName="nav-i_active" to={`${this.rootPath}/`}>All</NavLink>
<NavLink className="nav-i" activeClassName="nav-i_active" to={`${this.rootPath}/set`}>Set metadata</NavLink>
<NavLink className="nav-i" activeClassName="nav-i_active" to={`${this.rootPath}/pending-changes`}>Pending changes</NavLink>
</div>
{search}
</div>
</div>
<Route exact path={`${this.rootPath}/`} render={this.onAllValidatorsRender} web3Config={this.state}/>
<Route path={`${this.rootPath}/set`} render={this.onSetRender} />
<Route path={`${this.rootPath}/pending-changes`} render={this.onPendingChangesRender} />
</section>
</Router>
)
}
}
ReactDOM.render(<AppMainRouter />, document.getElementById('root'));
registerServiceWorker();

View File

@ -0,0 +1,43 @@
%stretch-width {
left: 0;
right: 0;
}
%btn {
cursor: pointer;
transition: 0.3s background-color;
border-radius: 3px;
border: 0;
padding: 0 15px 0 32px;
background-color: #08b3f2;
background-repeat: no-repeat;
background-position: left 15px center;
color: #fff;
line-height: 36px;
font-size: 13px;
text-decoration: none;
text-transform: uppercase;
font-weight: bold;
&:hover {
background-color: #20bdf7;
}
&-new {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAFVBMVEX///////////////////////////9nSIHRAAAABnRSTlMASUrk5udXTd49AAAAOUlEQVR42tXQsQEAIAgDQcAn+4+snRZxAK79KokrIcNBwgYdc0Migwxk8Qsd1TJWDf/KQWobqt+9G4coA99W7as5AAAAAElFTkSuQmCC);
background-size: 12px 12px;
}
&-vote {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAASCAMAAAB2Mu6sAAAAgVBMVEX///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+xZKUEAAAAKnRSTlMAAQIDPVBWYmNkZmpxeHp7fIOEhYaHiZeZmp6foKGio6TV2dze5unx9f63Mu9fAAAAgElEQVR4AXXO1w7CMBSD4VM2lFE2lD0I1O//gIBrCUUn/Hf5rCixRI3V695KeLMEcEn4Dp+C9z2+DZ0f6IXz4x8/0Sf63c/P9DEP7fDM5VkpZw8Ao9rX9JnVBWjJNvSlqW7F67GzAZdiS1+QooXNLaqvRe/6ZWquXuVcdW7XPJY3R9MVHwqyyb8AAAAASUVORK5CYII=);
background-size: 12px 9px;
}
}
%item {
margin-bottom: 30px;
border-radius: 8px;
border: 1px solid #eee;
background-color: #fff;
color: #333;
}

View File

@ -3,7 +3,10 @@ body {
margin: 0;
padding: 0;
}
#root {
display: table;
width: 100%;
}
p, h1, h2, h3, h4 {
margin: 0;
padding: 0;
@ -33,10 +36,21 @@ body {
margin: 0 auto;
}
.flex-container {
display: flex;
justify-content: space-between;
align-items: center;
}
.content {
display: table-cell;
vertical-align: top;
padding: 0px 10px;
background-color: #fbfbfb;
}
.key-content {
display: table-cell;
vertical-align: middle;
background-color: #fbfbfb;
text-align: center;
}

View File

@ -1,3 +1,7 @@
.hidden {
display:none;
}
button:focus {
outline: none;
}

66
src/index/choose-key.scss Normal file
View File

@ -0,0 +1,66 @@
%title {
color: #333;
text-transform: uppercase;
font-size: 16px;
font-weight: bold;
}
%description {
color: #8197a2;
line-height: 24px;
font-size: 14px;
font-weight: normal;
}
.choose-key {
@extend %item;
padding: 30px;
display: inline-block;
h1 {
@extend %title;
margin-bottom: 20px;
}
h2 {
@extend %description;
margin-bottom: 20px;
}
&-button {
@extend %btn;
display: inline-block;
background-color: #08b3f2;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAYAAACALL/6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAMLWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjarVdnVBOJFv6mJIEQakIEpATpIIooTaR3QUA6rC0kAQIhxBRU7K7LKrh2sWBFV0VcdS2grAVR17qIvftQF5WVdbF3eT8ScNf3/rxz3j1nZr5z57v3fvfOnDlzAeMhQoVCRpoAxXK1MiUmXJCVnSNgtYEACQ64sBCKVIqw5OQEAOi5/tNeXwUBAJc8hQqFDP+bmYolKhFAJAPIFatExQCxF6CtRAqlGmC0AnCYoFaoAcZLADxlVnYOwNQDwMvXYmsAvFwt9gLAU6alRADMSECPIxQq8wGjZACCUlG+GjBSAPCSi6VywGg9gGBRgVAMGLUB6F9cXCIGjDkAXHP/lif/Hzlze3MKhfm9WNsLAEAvUqpSyIST8P+2Ypmmp0Y/AJwCZWwKAB5AbC0qiU8BwAGIg/LcxCQAZgBxSioGdPhmgSY2XcfvFKkicgDwARJiYWQ8AGuA5GuK0sN02FuoBLR8MlGqjkvT4VxlSYouP1kqlyUm6PLMKZDE9eC1ElVUag8nTxodB8AEIPeWFaRlanWSx0ulGYkAjACyVVWUGq+LvVtWEJHYw1FqUtIBOALkyzxldIqWQ1kUq3r6ogaIhFGpACwAKlRdkBarjaWyJKqshB4NYklklFYDJZbI03XaKLVCHZ6iiy1XyJJ1fGqtRBaTop0ztUtVmtoTe1GtTNPNnLpfKByerNVPvVaok9O02mgaCYhAJATQQIBclKAQ0pbOhk4IdHeiIYQS+ZDAU+fpiciEEErIIUQqyvAn5JBA1RsXDiGUkKAUcnzq9WrPnsiDEEqUQgIVivAQShTTVnQwHUgn0MF0KB1Me9P+dEBPnMC4pyozihnJjGVGM916dYhQAhlKoIT0v/jiIYMEGighgbynhy/5GA8ZFxj3GVcYbYwbyMDvUELawxornaX8SrkAI9AGjW4qEuRCjo4eDu1Me9M+dDgdRAfTARDQfNoKnvQQ2p8Oo0PoQNqHDviHQk2vti+z/LqeBPJ/9KPzG7kb+ehU5PY+mYhe1tdZIv42IzFKEP81k5pD7aFOUkep09RBqgEC6gi1nzpHHaIa/vYm/A4l8nurpUACOYogg7SH41Xn1eH18T+qC3UKlJBABaglE9UAEFGimKSU5heoBWEKhUwiiJOLBvQXeHsN8gWysnME2s/HCz4IAAT/zBff+CYgoAIg8r/4hA7AgYcA9/UXn8NzgLMQONQq0ihLtT4aABhgwxg8WMIWDnCFJ7zhi0CEIgrDkYQ0ZGMMRChAMZSYgCmYiXJUYiGWYRXWYSO24ifsRgMO4ih+xVm04gpuoQ3teIIuvMYHgiBYhCHBJSwJO8KJ8CC8CX8imIgiEogUIpsYR+QTckJDTCG+JSqJxcQqYgNRS/xMHCCOEqeJC8QN4h7RQTwn3pMUySF5pA3pTA4k/ckwMp5MI0eT+eR4soycTc4nV5A15HaynjxKniWvkG3kE/IVBcqA4lP2lCflT0VQSVQOlUcpqWlUBVVF1VA7qEbqJHWJaqM6qXc0k+bSAtqTDqRj6XRaRI+np9Hz6FX0VrqePk5fou/RXfRnhiHDmuHBGMqIY2Qx8hkTGOWMKsZmxj7GCcYVRjvjNZPJ5DNdmH7MWGY2s5A5mTmPuYa5k9nEvMB8wHzFYrEsWR6sIFYSS8hSs8pZK1nbWUdYF1ntrLd6Bnp2et560Xo5enK9WXpVetv0Dutd1Huk90HfRN9Jf6h+kr5Yf5L+Av1N+o365/Xb9T+wTdku7CB2GruQPZO9gr2DfYJ9m/3CwMCgn0GAwUgDqcEMgxUGuwxOGdwzeMcx47hzIjijOBrOfM4WThPnBueFoaGhs2GoYY6h2nC+Ya3hMcO7hm+NuEYDjOKMxEbTjaqN6o0uGj011jd2Mg4zHmNcZlxlvMf4vHGnib6Js0mEidBkmkm1yQGTayavTLmmg0yTTItN55luMz1t+tiMZeZsFmUmNpttttHsmNkDLsV14EZwRdxvuZu4J7jtPCbPhRfHK+RV8n7itfC6zM3Mh5hnmE80rzY/ZN7Gp/jO/Di+jL+Av5t/lf++j02fsD6SPnP77Ohzsc8bi74WoRYSiwqLnRZXLN5bCiyjLIssF1k2WN6xoq3crUZaTbBaa3XCqrMvr29gX1Hfir67+960Jq3drVOsJ1tvtD5n/crG1ibGRmGz0uaYTact3zbUttB2qe1h2w47rl2wndRuqd0Ruz8E5oIwgUywQnBc0GVvbR9rr7HfYN9i/6GfS7/0frP67ex3x4Ht4O+Q57DUodmhy9HOcYTjFMc6x5tO+k7+TgVOy51OOr1xdnHOdP7eucH5sYuFS5xLmUudy21XQ9cQ1/GuNa6X3Zhu/m5FbmvcWt1Jdx/3Avdq9/MepIevh9RjjceF/oz+Af3l/Wv6X/PkeIZ5lnrWed4bwB+QMGDWgIYBTwc6DswZuGjgyYGfvXy8ZF6bvG4NMhs0fNCsQY2Dnnu7e4u8q70vDzYcHD14+uD9g58N8RgiGbJ2yHUfrs8In+99mn0++fr5Kn13+Hb4OfqN81vtd82f55/sP8//VAAjIDxgesDBgHdDfYeqh+4e+legZ2BR4LbAx8NchkmGbRr2IKhfkDBoQ1BbsCB4XPD64LYQ+xBhSE3I/VCHUHHo5tBHYW5hhWHbw56Ge4Urw/eFv4kYGjE1oimSioyJrIhsiTKLSo9aFXU3ul90fnRddFeMT8zkmKZYRmx87KLYa3E2caK42riu4X7Dpw4/Hs+JT41fFX8/wT1BmdA4ghwxfMSSEbcTnRLliQ1JSIpLWpJ0J9kleXzyLyOZI5NHVo98mDIoZUrKyVRu6tjUbamv08LTFqTdSndN16Q3ZxhnjMqozXiTGZm5OLMta2DW1Kyz2VbZ0uz9OaycjJzNOa++ifpm2Tfto3xGlY+6Otpl9MTRp8dYjZGNOTTWeKxw7J5xjHGZ47aN+yhMEtYIX+XG5a7O7RJFiJaLnohDxUvFHZIgyWLJo7ygvMV5j/OD8pfkdxSEFFQVdEojpKukzwpjC9cVvilKKtpS1C3LlO0s1iseV3xAbiYvkh8vsS2ZWHJB4aEoV7SNHzp+2fguZbxys4pQjVbtV/PUCvU5javmO8290uDS6tK3EzIm7JloOlE+8dwk90lzJz0qiy77cTI9WTS5eYr9lJlT7k0Nm7phGjEtd1rzdIfps6e3z4iZsXUme2bRzN9mec1aPOvlt5nfNs62mT1j9oPvYr6rKzcqV5Zf+z7w+3Vz6DnSOS1zB89dOfdzhbjiTKVXZVXlx3mieWd+GPTDih+65+fNb1ngu2DtQuZC+cKri0IWbV1surhs8YMlI5bULxUsrVj6ctnYZaerhlStW85erlnetiJhxf6VjisXrvy4qmDVlerw6p2rrVfPXf1mjXjNxbWha3ess1lXue79eun66xtiNtTXONdUbWRuLN34cFPGppM/+v9Yu9lqc+XmT1vkW9q2pmw9XutXW7vNetuCOrJOU9exfdT21p8if9q/w3PHhp38nZW7sEuz64+fx/18dXf87uY9/nt27HXau3ofd19FPVE/qb6roaChbX/2/gsHhh9obgxs3PfLgF+2HLQ/WH3I/NCCw+zDsw93Hyk78qpJ0dR5NP/og+axzbeOZR27fHzk8ZYT8SdO/Rr967GTYSePnAo6dfD00NMHzvifaTjre7b+nM+5fb/5/Lavxbel/rzf+f2tAa2NF4ZdOHwx5OLRS5GXfr0cd/nslcQrF66mX71+bdS1tuvi649vyG48u1l688OtGbcZtyvumNypumt9t+Zfbv/a2ebbduhe5L1z91Pv33ogevDkd9XvH9tnPzR8WPXI7lHtY+/HBzuiO1r/+OaP9ieKJx86y/80/XP1U9ene/8K/etcV1ZX+zPls+7n815YvtjycsjL5lfJr+6+Ln794U3FW8u3W9/5vzv5PvP9ow8TPrI+rvjk9qnxc/zn293F3d0KoVIIAKAAkHl5wPMtgGE2wG0F2Eba/QsAQGh3RkD7D/LfsXZHAwD4AltCgfQZQEITsLYJcJoBcJqAZABpoSAHD+49dKbKG+ytzcVRAoy33d0vbABWI/BJ2d39YU1396dNAHUDaBqv3fsAgGkCrHcDgJZz7Clf71//BlLWbMT30dyZAAAAIGNIUk0AAG11AABzoAAA/N0AAINkAABw6AAA7GgAADA+AAAQkOTsmeoAAABmSURBVHjalJE5CoBAEARLMV8fZGjok40Uo32NH7AMPBBxVy2YZJiG7ulCJcEELEAHzMeyJM0CNEAPhHOrpqZWoxtRDWpW8ChCHf1OzGV45sVSuFmqfx2/hR7uH1KzPVR7ee21uHUAspX6H0FQzIIAAAAASUVORK5CYII=);
&:hover {
background-color: #079dd4;
}
}
select {
font-size: 14px;
}
}
select {
outline: none;
font-family: 'Open Sans', sans-serif;
}
select {
transition: 0.3s border-color;
width: 100%;
border-radius: 3px;
box-sizing: border-box;
border: 1px solid #eee;
&:focus {
border-color: #08b3f2;
}
}
select {
padding: 0 15px;
height: 36px;
font-size: 11px;
background: #fff;
}

View File

@ -0,0 +1,99 @@
.create-keys-button-container {
display: flex;
align-items: center;
justify-content: center
}
.create-keys {
@extend %item;
padding: 30px 20px;
h1 {
margin-bottom: 20px;
}
h2 {
margin-bottom: 20px;
}
.set {
margin-top: 20px;
}
&-button {
@extend %btn;
display: inline-block;
background-color: #08b3f2;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAFVBMVEX///////////////////////////9nSIHRAAAABnRSTlMASUrk5udXTd49AAAAOUlEQVR42tXQsQEAIAgDQcAn+4+snRZxAK79KokrIcNBwgYdc0Migwxk8Qsd1TJWDf/KQWobqt+9G4coA99W7as5AAAAAElFTkSuQmCC);
background-size: 12px 12px;
&[disabled] {
background-color: #079dd4;
}
}
&-inputs {
display: table;
width: 100%;
}
.left {
padding-right: 10px;
}
.right {
padding-left: 10px;
}
.left,
.right {
display: table-cell;
width: 48%;
}
label {
&:not(.radio) {
display: block;
margin-bottom: 15px;
margin-top: 20px;
text-transform: uppercase;
font-size: 12px;
font-weight: bold;
}
}
button,
input,
textarea {
outline: none;
font-family: 'Open Sans', sans-serif;
}
input,
textarea {
transition: 0.3s border-color;
width: 100%;
border-radius: 3px;
box-sizing: border-box;
border: 1px solid #eee;
&:focus {
border-color: #08b3f2;
}
}
textarea {
padding: 15px;
height: 110px;
resize: none;
}
input {
padding: 0 15px;
height: 36px;
}
input[type="radio"] {
display: none;
&:checked + .radio:after {
opacity: 1;
}
}
}

View File

@ -7,7 +7,7 @@
color: #fff;
line-height: 30px;
font-size: 12px;
background-image: url(../images/bg_footer.png);
background-image: url('../images/bg_footer.png');
background-repeat: no-repeat;
background-size: cover;
@ -17,14 +17,14 @@
}
&-logo {
@include image-2x('../images/VALIDATORS_footer@2x.png', 100px, 24px);
@include image-2x('../images/CEREMONY_footer@2x.png', 100px, 24px);
position: relative;
z-index: 2;
display: inline-block;
vertical-align: middle;
width: 100px;
height: 24px;
background-image: url(../images/VALIDATORS_footer.png);
background-image: url('../images/CEREMONY_footer.png');
background-position: 0 0;
}

37
src/index/header.scss Normal file
View File

@ -0,0 +1,37 @@
.header {
@extend %stretch-width;
position: absolute;
z-index: 1;
top: 0;
padding: 18px 10px;
background-image: url('../images/bg_header.png');
background-repeat: no-repeat;
background-size: cover;
&-settings {
float: right;
text-transform: uppercase;
color: #fff;
text-decoration: none;
line-height: 39px;
margin-right: 40px;
font-size: 13px;
font-weight: bold;
}
&-logo {
@include image-2x('../images/CEREMONY@2x.png', 149px, 35px);
float: left;
width: 149px;
height: 35px;
background-image: url('../images/CEREMONY.png');
background-position: 0 0;
}
&-new-ballot {
@extend %btn;
@extend %btn-new;
float: right;
margin-top: 3px;
}
}

467
src/index/index.css Normal file
View File

@ -0,0 +1,467 @@
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local("Open Sans"), local("OpenSans"), url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; }
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local("Open Sans Bold"), local("OpenSans-Bold"), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzBampu5_7CjHW5spxoeN3Vs.woff2) format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; }
html,
body {
color: #333;
line-height: 1;
font-size: 14px;
font-family: 'Open Sans', sans-serif;
-webkit-font-smoothing: antialiased; }
.footer, .footer-rights, .header {
left: 0;
right: 0; }
.create-keys-button, .header-new-ballot {
cursor: pointer;
transition: 0.3s background-color;
border-radius: 3px;
border: 0;
padding: 0 15px 0 32px;
background-color: #08b3f2;
background-repeat: no-repeat;
background-position: left 15px center;
color: #fff;
line-height: 36px;
font-size: 13px;
text-decoration: none;
text-transform: uppercase;
font-weight: bold; }
.create-keys-button:hover, .header-new-ballot:hover {
background-color: #20bdf7; }
.header-new-ballot {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAFVBMVEX///////////////////////////9nSIHRAAAABnRSTlMASUrk5udXTd49AAAAOUlEQVR42tXQsQEAIAgDQcAn+4+snRZxAK79KokrIcNBwgYdc0Migwxk8Qsd1TJWDf/KQWobqt+9G4coA99W7as5AAAAAElFTkSuQmCC);
background-size: 12px 12px; }
.create-keys {
margin-bottom: 30px;
border-radius: 8px;
border: 1px solid #eee;
background-color: #fff;
color: #333; }
html,
body {
margin: 0;
padding: 0; }
#root {
display: table;
width: 100%; }
p, h1, h2, h3, h4 {
margin: 0;
padding: 0;
font-family: 'Open Sans', sans-serif; }
html {
height: 100%;
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
background-position: center center; }
body {
position: relative;
display: table;
width: 100%;
min-width: 960px;
height: 100%;
box-sizing: border-box;
padding: 80px 0 60px; }
.container {
max-width: 960px;
margin: 0 auto; }
.flex-container {
display: flex;
justify-content: space-between;
align-items: center; }
.content {
display: table-cell;
vertical-align: top;
background-color: #fbfbfb; }
.key-content {
display: table-cell;
vertical-align: middle;
background-color: #fbfbfb;
text-align: center; }
.left {
float: left; }
.right {
float: right; }
.hidden {
display: none; }
button:focus {
outline: none; }
.create-keys-button-container {
display: flex;
align-items: center;
justify-content: center; }
.create-keys {
padding: 30px 20px; }
.create-keys h1 {
margin-bottom: 20px; }
.create-keys h2 {
margin-bottom: 20px; }
.create-keys-button {
display: inline-block;
background-color: #08b3f2;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAFVBMVEX///////////////////////////9nSIHRAAAABnRSTlMASUrk5udXTd49AAAAOUlEQVR42tXQsQEAIAgDQcAn+4+snRZxAK79KokrIcNBwgYdc0Migwxk8Qsd1TJWDf/KQWobqt+9G4coA99W7as5AAAAAElFTkSuQmCC);
background-size: 12px 12px; }
.create-keys-button[disabled] {
background-color: #079dd4; }
.create-keys-inputs {
display: table;
width: 100%; }
.create-keys .left {
padding-right: 10px; }
.create-keys .right {
padding-left: 10px; }
.create-keys .left,
.create-keys .right {
display: table-cell;
width: 48%; }
.create-keys label:not(.radio) {
display: block;
margin-bottom: 15px;
margin-top: 20px;
text-transform: uppercase;
font-size: 12px;
font-weight: bold; }
.create-keys button,
.create-keys input,
.create-keys textarea {
outline: none;
font-family: 'Open Sans', sans-serif; }
.create-keys input,
.create-keys textarea {
transition: 0.3s border-color;
width: 100%;
border-radius: 3px;
box-sizing: border-box;
border: 1px solid #eee; }
.create-keys input:focus,
.create-keys textarea:focus {
border-color: #08b3f2; }
.create-keys textarea {
padding: 15px;
height: 110px;
resize: none; }
.create-keys input {
padding: 0 15px;
height: 36px; }
.create-keys input[type="radio"] {
display: none; }
.create-keys input[type="radio"]:checked + .radio:after {
opacity: 1; }
.footer {
position: absolute;
z-index: 1;
bottom: 0;
padding: 15px 10px;
color: #fff;
line-height: 30px;
font-size: 12px;
background-image: url("../images/bg_footer.png");
background-repeat: no-repeat;
background-size: cover; }
.footer .container {
position: relative;
overflow: hidden; }
.footer-logo {
position: relative;
z-index: 2;
display: inline-block;
vertical-align: middle;
width: 100px;
height: 24px;
background-image: url("../images/CEREMONY_footer.png");
background-position: 0 0; }
@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx) {
.footer-logo {
background-image: url("../images/CEREMONY_footer@2x.png");
background-size: 100px 24px; } }
.footer-rights {
position: absolute;
z-index: 1;
top: 0;
text-align: center; }
.header {
position: absolute;
z-index: 1;
top: 0;
padding: 18px 10px;
background-image: url("../images/bg_header.png");
background-repeat: no-repeat;
background-size: cover; }
.header-settings {
float: right;
text-transform: uppercase;
color: #fff;
text-decoration: none;
line-height: 39px;
margin-right: 40px;
font-size: 13px;
font-weight: bold; }
.header-logo {
float: left;
width: 149px;
height: 35px;
background-image: url("../images/CEREMONY.png");
background-position: 0 0; }
@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx) {
.header-logo {
background-image: url("../images/CEREMONY@2x.png");
background-size: 149px 35px; } }
.header-new-ballot {
float: right;
margin-top: 3px; }
@keyframes fadeOut {
0% {
opacity: .2; }
20% {
opacity: 1;
transform: scale(1); }
100% {
opacity: .2;
transform: scale(0.3); } }
.loading {
display: flex;
justify-content: space-between;
position: absolute;
left: 50%;
top: 50%;
width: 146px;
margin: -30px 0 0 -81.5px;
padding-top: 50px; }
.loading:before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 146px;
height: 35px;
background-image: url("../images/loading.png");
background-position: 0 0; }
@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx) {
.loading:before {
background-image: url("../images/loading.png");
background-size: 100% 100%; } }
.loading-container {
position: fixed;
z-index: 1000000;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(35, 29, 115, 0.8); }
.loading-i {
animation-duration: 2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: fadeOut;
animation-timing-function: linear;
opacity: .2;
width: 9px;
height: 9px;
border-radius: 50%;
background-color: #fff; }
.loading-i:nth-child(2) {
animation-delay: .1s; }
.loading-i:nth-child(3) {
animation-delay: .2s; }
.loading-i:nth-child(4) {
animation-delay: .3s; }
.loading-i:nth-child(5) {
animation-delay: .4s; }
.loading-i:nth-child(6) {
animation-delay: .5s; }
.socials {
position: relative;
z-index: 2;
float: right;
font-size: 0; }
.socials-i {
transition: 0.3s background-color;
position: relative;
display: inline-block;
vertical-align: top;
width: 30px;
height: 30px;
margin-left: 10px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.2); }
@media screen and (min-width: 768px) {
.socials-i:hover {
background-color: rgba(255, 255, 255, 0.4); } }
.socials-i:before {
content: '';
position: absolute;
left: 50%;
top: 50%;
background-image: url(../images/socials.png); }
@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx) {
.socials-i:before {
background-image: url("../images/socials@2x.png");
background-size: 15px 40px; } }
.socials-i_reddit:before {
width: 15px;
height: 13px;
margin: -6.5px 0 0 -7.5px;
background-position: 0 -15px; }
.socials-i_twitter:before {
width: 15px;
height: 12px;
margin: -6px 0 0 -7.5px;
background-position: 0 -28px; }
.socials-i_bitcoin:before {
width: 11px;
height: 15px;
margin: -7.5px 0 0 -5.5px;
background-position: 0 0; }
.validators {
text-align: left; }
.validators-i {
margin-bottom: 30px;
border-radius: 8px;
border: 1px solid #eee;
background-color: #fff;
color: #333; }
.validators-i .confirmations {
font-weight: normal;
font-size: 12px;
padding-top: 5px; }
.validators-header {
border-bottom: 1px solid #eee;
padding: 25px 20px;
font-size: 16px;
font-weight: bold;
display: flex;
justify-content: space-between;
align-items: center; }
.validators-header .left {
flex: 1; }
.validators-header .finalize {
margin-right: 20px; }
.validators-body {
overflow: hidden;
padding: 0 20px 20px; }
.validators-notary, .validators-license {
width: 48%; }
.validators-title {
text-transform: uppercase;
margin: 20px 0;
color: #8197a2;
font-size: 12px;
font-weight: bold; }
.validators-table {
border: 1px solid #eee; }
.validators-table-tr {
overflow: hidden;
padding: 0 10px; }
.validators-table-tr:not(:last-child) {
border-bottom: 1px solid #eee; }
.validators-table-td {
padding: 10px 0;
font-size: 12px; }
.nav {
font-size: 0; }
.nav-i {
transition: 0.3s color;
position: relative;
display: inline-block;
vertical-align: middle;
margin-right: 40px;
color: #8197a2;
text-transform: uppercase;
text-decoration: none;
line-height: normal;
font-size: 14px;
font-weight: bold; }
.nav-i:hover, .nav-i_active {
color: #444; }
.nav-i_active:before {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: -30px;
height: 3px;
background-color: #08b3f2; }
.search {
margin-bottom: 30px;
border-bottom: 1px solid #eee;
background-color: #fff;
line-height: 80px;
text-align: left; }
.search .back {
transition: 0.3s opacity;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAUCAMAAACgaw2xAAAAjVBMVEUAtfX///8AtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUmVRXZAAAALnRSTlMAAAQKDxAXISIpKzc+P1laYm1vdneQlJWjpKyvs7W2ycrP0NLY3uDh4u3u+f3+FQ2PgAAAAJlJREFUGNOV0ckSgjAQRdEWghMiKiLihBOiIPf/P88FSEEiC98yp6o79VrkG3uZPRYigzrN+zAEChMme6CMDfASoNgoHfwUeAWWdMFa50A6F+mCExXAeSYajA/AO1SigXsFKJPd8dTKdip3fubWD+6lZ5SMquWOvlxEVd/1DBAryIHUN6CuJDcqaUqMVE/txH8cSsRePbPWaT+TOR0SIiH2HAAAAABJRU5ErkJggg==);
background-repeat: no-repeat;
background-position: left center;
background-size: 12px 10px;
padding-left: 20px;
color: #08b3f2;
text-decoration: none;
font-size: 14px;
font-weight: bold; }
.search .back:hover {
opacity: 0.8; }
.search .container {
position: relative; }
.search-input {
display: block;
transition: 0.3s width, 0.3s border-color;
cursor: pointer;
position: absolute;
z-index: 1;
right: 0;
top: 50%;
width: 80px;
height: 40px;
margin: -20px 0 0;
outline: none;
border-radius: 5px;
border: 1px solid transparent;
box-sizing: border-box;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAA6lBMVEWAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6PrSx+9AAAATXRSTlMAAgMGCAkKDA0UFRYXISIjJDM0NTo7PD0/QEFERUlQWVpoaWp0dXaZm5ydnqSlpra4ub/AwcTFxsjKzM3Oz9bX2N3e6ers7fX5+vz9/pKojzsAAAGRSURBVHgBjZRtX4IwFMUXmKaBYmhWauSzEmkl+ZAaaJGo8P2/TnejEGHrt/PqcM9f2cbdRVHJDWPhuK6zMBoyYkrQJp4fyptoAp2rWn5MVpWCpXo+Rb1UnMvNg/eZ3bIkilK5YwarmOdinI2rB105lhT9gGv2CZme4dpGPf21usHVWTpS6uPKaxbFlDVxvR/ZL35+EVFC4jNOwr2ffeC1XCCKMnjt1t95avCwVxFV6h5C7ffhDbyOGBpAOAmsDCfmKSxQwWme2Cb8ZoyYGkPcJM4A12WDXYgN4lbgrtlgBeIlcQ44iQ1KEH8T54IT2aAIscsP8r+abzMr4p7AdXiOh/vA8/9/wgP5hGFTDDiaImizKzpXjLaZYOHuzFAbl0TCyVUY0a7CCCe1Y+GRkIn/zBBOT1xXqxhbXzBj6rQBUDiWCjAAiLY3UfLy3Seo2S7hkVJqmxijkef0IVXfJkhUs+OYDfu9o5CCNvUi2PSBnN9tkgTJreHS2e2c5bBFRjOVpCskK7zkGnGSn4hHlfXX/Q90qIZ+dL9jIAAAAABJRU5ErkJggg==);
background-size: 20px 20px;
background-repeat: no-repeat;
background-position: right 10px center;
color: #333;
font-size: 14px; }
.search-input:focus {
cursor: text;
width: 300px;
border-color: #eee;
padding: 0 40px 0 10px; }

15
src/index/index.scss Normal file
View File

@ -0,0 +1,15 @@
@import './_0_fonts';
@import './_1_mixins';
@import './_2_placeholders';
@import './_3_base';
@import './addition';
@import './create-keys';
@import './footer';
@import './header';
@import './loading';
@import './socials';
@import './validators.scss';
@import './nav';
@import './search';
// @import './new-ballot';
// @import './vote';

124
src/index/keys.scss Normal file
View File

@ -0,0 +1,124 @@
.keys {
display: table;
width: 100%;
margin-bottom: 60px;
text-align: left;
$_this: &;
&-i {
position: relative;
display: table-cell;
vertical-align: top;
width: 33.33%;
box-sizing: border-box;
padding: 0 15px 60px 15px;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
&:not(:first-child) {
border-left: 1px solid #e1e1e1;
}
}
&-title {
margin-bottom: 10px;
@extend %title;
}
&-hash {
height: 30px;
color: #6d2eae;
line-height: 16px;
font-size: 12px;
display: table-cell;
}
&-hash-container {
display: table;
}
&-description {
@extend %description;
line-height: 18px;
font-size: 12px;
}
&-footer {
position: absolute;
left: 15px;
right: 15px;
bottom: 0;
#{$_this}-i:first-child & {
left: 0;
}
}
&-download,
&-read-more {
display: inline-block;
vertical-align: middle;
}
&-download {
@extend %btn;
background-color: #6d2eae;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAANlBMVEX///////////////////////////////////////////////////////////////////////8BOg0gAAAAEXRSTlMASUtWV1hZXF1e5ebn6Orr/GN0dVoAAABnSURBVHja1cnJDYBADENRDzBsYYn7bxaCFFmMaADf/B+0YlbwNSPtE3jvv9Ad29DCsB0dVtKnN8xOGowhCdm5o/eUgOw+AktKQPYFkDygLglQhyRAXZLzWV2iLlFvRb2V7O3qeVa9C41xDOyv+UmuAAAAAElFTkSuQmCC);
&:hover {
background-color: #5d2795;
}
}
&-read-more {
margin-left: 10px;
color: #6d2eae;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
&-note {
overflow: hidden;
position: relative;
border: 1px solid #6d2eae;
border-radius: 5px;
padding: 20px 15px 20px 53px;
background-color: rgba(109, 46, 174, 0.1);
color: #6d2eae;
text-align: left;
&:before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 42px;
background-color: #6d2eae;
background-image: url(../images/warning.svg);
background-repeat: no-repeat;
background-position: center center;
}
&-title {
margin-bottom: 10px;
text-transform: uppercase;
font-size: 14px;
font-weight: bold;
}
&-description {
font-size: 12px;
}
}
}

View File

@ -23,14 +23,14 @@
padding-top: 50px;
&:before {
@include image-2x('../images/loading@2x.png');
@include image-2x('../images/loading.png');
content: '';
position: absolute;
left: 0;
top: 0;
width: 146px;
height: 35px;
background-image: url(../images/loading.png);
background-image: url('../images/loading.png');
background-position: 0 0;
}

34
src/index/nav.scss Normal file
View File

@ -0,0 +1,34 @@
.nav {
font-size: 0;
&-i {
transition: 0.3s color;
position: relative;
display: inline-block;
vertical-align: middle;
margin-right: 40px;
color: #8197a2;
text-transform: uppercase;
text-decoration: none;
line-height: normal;
font-size: 14px;
font-weight: bold;
&:hover,
&_active {
color: #444;
}
&_active {
&:before {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: -30px;
height: 3px;
background-color: #08b3f2;
}
}
}
}

117
src/index/new-ballot.scss Normal file
View File

@ -0,0 +1,117 @@
.new-ballot {
@extend %item;
padding: 10px 20px;
margin-bottom: 30px;
text-align: left;
box-sizing: border-box;
&-inputs {
overflow: hidden;
}
.left,
.right {
width: 48%;
}
label {
&:not(.radio) {
display: block;
margin-bottom: 15px;
margin-top: 20px;
text-transform: uppercase;
font-size: 12px;
font-weight: bold;
}
}
button,
input,
textarea {
outline: none;
font-family: 'Open Sans', sans-serif;
}
input,
textarea {
transition: 0.3s border-color;
width: 100%;
border-radius: 3px;
box-sizing: border-box;
border: 1px solid #eee;
&:focus {
border-color: #08b3f2;
}
}
textarea {
padding: 15px;
height: 110px;
resize: none;
}
input {
padding: 0 15px;
height: 36px;
}
input[type="radio"] {
display: none;
&:checked + .radio:after {
opacity: 1;
}
}
.radio {
cursor: pointer;
display: inline-block;
vertical-align: top;
position: relative;
padding-left: 30px;
margin-top: 20px;
margin-right: 40px;
font-size: 12px;
&:before,
&:after {
content: '';
position: absolute;
top: 50%;
border-radius: 50%;
}
&:before {
left: 0;
width: 20px;
height: 20px;
margin-top: -10px;
box-sizing: border-box;
border: 1px solid #d8d9db;
}
&:after {
transition: 0.3s opacity;
opacity: 0;
left: 5px;
width: 10px;
height: 10px;
margin-top: -5px;
background-color: #08b3f2;
}
}
&-description {
margin-top: 10px;
color: #8197a2;
font-size: 12px;
line-height: 18px;
}
&-add {
@extend %btn;
@extend %btn-vote;
margin-top: 20px;
}
}

View File

@ -5,15 +5,25 @@
line-height: 80px;
text-align: left;
.container {
position: relative;
}
&-title {
color: #333;
text-transform: uppercase;
.back {
transition: 0.3s opacity;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAUCAMAAACgaw2xAAAAjVBMVEUAtfX///8AtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUmVRXZAAAALnRSTlMAAAQKDxAXISIpKzc+P1laYm1vdneQlJWjpKyvs7W2ycrP0NLY3uDh4u3u+f3+FQ2PgAAAAJlJREFUGNOV0ckSgjAQRdEWghMiKiLihBOiIPf/P88FSEEiC98yp6o79VrkG3uZPRYigzrN+zAEChMme6CMDfASoNgoHfwUeAWWdMFa50A6F+mCExXAeSYajA/AO1SigXsFKJPd8dTKdip3fubWD+6lZ5SMquWOvlxEVd/1DBAryIHUN6CuJDcqaUqMVE/txH8cSsRePbPWaT+TOR0SIiH2HAAAAABJRU5ErkJggg==);
background-repeat: no-repeat;
background-position: left center;
background-size: 12px 10px;
padding-left: 20px;
color: #08b3f2;
text-decoration: none;
font-size: 14px;
font-weight: bold;
&:hover {
opacity: 0.8;
}
}
.container {
position: relative;
}
&-input {
@ -25,7 +35,7 @@
z-index: 1;
right: 0;
top: 50%;
width: 40px;
width: 80px;
height: 40px;
margin: -20px 0 0;
outline: none;

View File

@ -7,6 +7,12 @@
border: 1px solid #eee;
background-color: #fff;
color: #333;
.confirmations {
font-weight: normal;
font-size: 12px;
padding-top: 5px;
}
}
&-header {
@ -14,6 +20,17 @@
padding: 25px 20px;
font-size: 16px;
font-weight: bold;
display: flex;
justify-content: space-between;
align-items: center;
.left {
flex: 1;
}
.finalize {
margin-right: 20px;
}
}
&-body {
@ -51,4 +68,4 @@
font-size: 12px;
}
}
}
}

285
src/index/vote.scss Normal file
View File

@ -0,0 +1,285 @@
.vote {
text-align: left;
&-i {
@extend %item;
}
&-body {
display: table;
width: 100%;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
font-size: 0;
&-i {
display: table-cell;
vertical-align: top;
width: 33.333%;
box-sizing: border-box;
padding: 30px 20px;
&:not(:first-child) {
border-left: 1px solid #eee;
}
&:nth-child(2n) {
word-break: break-all;
}
}
%title {
position: relative;
margin-bottom: 20px;
color: #8197a2;
text-transform: uppercase;
font-size: 12px;
font-weight: bold;
}
&-title {
@extend %title;
&-secondary {
@extend %title;
margin-top: 30px;
}
}
&-description {
color: #444;
line-height: 24px;
font-size: 14px;
}
}
&-header {
overflow: hidden;
padding: 20px;
}
&-now {
@extend %btn;
@extend %btn-vote;
margin-right: 20px;
}
&-person {
position: relative;
padding-left: 50px;
&-img {
position: absolute;
left: 0;
top: 0;
width: 36px;
height: 36px;
}
&-name {
margin-bottom: 8px;
color: #333;
font-size: 14px;
font-weight: bold;
}
&-choose {
padding-left: 20px;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAw1BMVEWAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6M9jT1MAAAAQHRSTlMAAQIDBQYHDA0bHB8gISQmJyg+P0BGR0lKU1RZYmNrbHV2iYqLo6Spqqusra7Cw8TFysvM29zk5ufo6/Lz+Pn8DzgVHgAAATNJREFUeNplk+1agkAQhQfRykQTrJTEUjSCvtTQECPk/q+qPQ7LsnR+7DOzL898LiRlOP46zfN0vXQM0tXydkWlndeqs/620LTtK3Z7LBo6OpLd5fDzl6nVubSnIXv3zIY/8N4HVGrwBj8bwjaR77SgmhYn5DWF5eE7ZoribkZkoIeI78ZJMmYrQkcGjZD9mq+SokjY6qKqEfniDIiFYMR6FqZPn+J8+A9dYX5QKs5eBaFz3p4wUkLwizrkvB2UcoZXJUwYHiqIsDclnBzAvicyrFYQpBW0lK0oqVbkEHR1fzEEHl/YhCHG1yKaoYi5zubl4Mn8wsqe6uwRK4tNmHaG717VsiP4mV1uih9G4FrttuUG7GGGTLOioUwyRI51Ftv6o94rtNcfNbCz2uB32KycCv0BfU5XCrQEyKwAAAAASUVORK5CYII=);
background-size: 14px 14px;
background-repeat: no-repeat;
background-position: left center;
color: #8197a2;
line-height: 14px;
font-size: 12px;
}
}
&-time {
color: #8197a2;
&-timer {
font-size: 24px;
font-weight: bold;
}
&-to {
width: 100%;
text-align: right;
text-transform: uppercase;
font-size: 12px;
}
}
&-rating {
overflow: hidden;
padding: 30px 20px;
&-i {
width: 48%;
color: #8197a2;
text-transform: uppercase;
font-size: 12px;
strong {
margin-right: 5px;
color: #333;
font-weight: bold;
}
p {
display: inline;
}
}
&-value,
&-got {
margin-bottom: 10px;
}
&-scale {
clear: left;
height: 10px;
border-radius: 5px;
background-color: #efefef;
$this: &;
&-active {
height: 100%;
border-radius: 5px;
}
&_yes {
#{$this}-active {
background-color: #08b3f2;
}
}
&_no {
#{$this}-active {
background-color: #6d2eae;
}
}
}
}
&-tooltip {
transform: translate3d(0,-10px,0);
opacity: 0;
pointer-events: none;
position: absolute;
z-index: 2;
transition: opacity 0.3s, transform 0.3s;
left: -275px;
top: 0;
width: 578px;
padding-top: 30px;
box-sizing: border-box;
&:before {
transform: rotate(-45deg);
content: '';
position: absolute;
z-index: 1;
left: 50%;
top: 22px;
width: 20px;
height: 20px;
margin-left: -12px;
border-radius: 2px;
background-color: #fff;
box-shadow: 0px 0 20px 0 fade-out(#000, 0.9);
}
$this: &;
&-text {
display: block;
position: relative;
z-index: 2;
text-align: left;
box-sizing: border-box;
border-radius: 5px;
padding: 25px;
background-color: #fff;
color: #333;
}
&-shadow {
content: '';
position: absolute;
left: 0;
right: 0;
top: 30px;
bottom: 0;
border-radius: 5px;
box-shadow: 0px 20px 40px 0 fade-out(#000, 0.7);
}
&-title {
display: block;
margin-bottom: 15px;
font-size: 16px;
}
&-description {
line-height: 24px;
font-size: 14px;
font-weight: normal;
text-transform: none;
a {
color: #08b3f2;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
&-icon {
position: relative;
display: block;
width: 24px;
height: 24px;
margin-top: -6px;
border-radius: 50%;
background-color: #08b3f2;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAYCAMAAADqO6ysAAAAFVBMVEX///////////////////////////9nSIHRAAAABnRSTlMASUrk5udXTd49AAAAJUlEQVQI12NgZGFhZGBhY2MBEawMTKzMTAzYAEIdGxCQS8DtAABR5AGfy9XNLgAAAABJRU5ErkJggg==);
background-repeat: no-repeat;
background-position: center center;
background-size: 2px 12px;
}
&-container {
position: relative;
z-index: 10;
float: right;
&:hover {
#{$this} {
pointer-events: auto;
opacity: 1;
transform: translate3d(0,0,0) rotate3d(0,0,0,0);
}
}
}
}
.vote-rating-yes,
.vote-rating-no {
@extend %btn;
@extend %btn-vote;
margin-top: 20px;
}
.vote-rating-no {
background-color: #6d2eae;
&:hover {
background-color: #5d2795;
}
}
}

7
src/logo.svg Normal file
View File

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
<g fill="#61DAFB">
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
<circle cx="420.9" cy="296.5" r="45.7"/>
<path d="M520.5 78.1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,108 @@
// In production, we register a service worker to serve assets from local cache.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on the "N+1" visit to a page, since previously
// cached resources are updated in the background.
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export default function register() {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Lets check if a service worker still exists or not.
checkValidServiceWorker(swUrl);
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl);
}
});
}
}
function registerValidSW(swUrl) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log('New content is available; please refresh.');
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}