Merge pull request #50 from rstormsf/core

(Feature) Add dropdown for selecting mining key, add limit notification
This commit is contained in:
Victor Baranov 2018-01-06 10:03:25 +03:00 committed by GitHub
commit 93ded37229
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 291 additions and 142 deletions

5
jsconfig.json Normal file
View File

@ -0,0 +1,5 @@
{
"compilerOptions": {
"experimentalDecorators": true
}
}

30
package-lock.json generated
View File

@ -4588,6 +4588,13 @@
}
}
},
"string_decoder": {
"version": "1.0.1",
"bundled": true,
"requires": {
"safe-buffer": "5.0.1"
}
},
"string-width": {
"version": "1.0.2",
"bundled": true,
@ -4597,13 +4604,6 @@
"strip-ansi": "3.0.1"
}
},
"string_decoder": {
"version": "1.0.1",
"bundled": true,
"requires": {
"safe-buffer": "5.0.1"
}
},
"stringstream": {
"version": "0.0.5",
"bundled": true,
@ -10293,6 +10293,14 @@
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
},
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"requires": {
"safe-buffer": "5.1.1"
}
},
"string-length": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz",
@ -10335,14 +10343,6 @@
"function-bind": "1.1.1"
}
},
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"requires": {
"safe-buffer": "5.1.1"
}
},
"stringstream": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",

View File

@ -2,7 +2,7 @@
"name": "poa-dapps-voting",
"version": "0.1.0",
"private": true,
"homepage": "https://poanetwork.github.io/poa-dapps-voting",
"homepage": "https://poanetwork.github.io/",
"dependencies": {
"autoprefixer": "7.1.6",
"babel-core": "6.26.0",

View File

@ -38,9 +38,10 @@ class App extends Component {
const { commonStore } = this.props;
const currentPath = this.props.location.pathname;
let showNavPan =
currentPath == `${commonStore.rootPath}`
|| currentPath == `${commonStore.rootPath}/`
|| currentPath == `${commonStore.rootPath}/active`;
currentPath === `${commonStore.rootPath}`
|| currentPath === "/"
|| currentPath === `${commonStore.rootPath}/`
|| currentPath === `${commonStore.rootPath}/active`;
return showNavPan;
}
@ -61,6 +62,7 @@ class App extends Component {
{loading}
<Header />
{nav}
<Route exact path={`/`} render={this.onBallotsRender}/>
<Route exact path={`${commonStore.rootPath}/`} render={this.onBallotsRender}/>
<Route exact path={`${commonStore.rootPath}/active`} render={this.onActiveBallotsRender}/>
<Route path={`${commonStore.rootPath}/new`} render={this.onNewBallotRender}/>

View File

@ -772,7 +772,11 @@ button {
.ballots-footer {
display: flex;
align-items: center; }
align-items: center;
justify-content: space-between; }
.ballots-footer-left {
display: inline-flex;
align-items: center; }
@media screen and (max-width: 768px) {
.ballots-footer {
padding-top: 20px; } }

View File

@ -1,7 +1,12 @@
.ballots-footer {
display: flex;
align-items: center;
justify-content: space-between;
&-left {
display: inline-flex;
align-items: center;
}
@media screen and (max-width: $tablet-width) {
padding-top: $tablet-indent;
}

View File

@ -1,6 +1,6 @@
import React from 'react';
import moment from 'moment';
import { observable, action, computed } from "mobx";
import { observable, action, computed, autorun } from "mobx";
import { inject, observer } from "mobx-react";
import { toAscii } from "../helpers";
import { constants } from "../constants";
@ -265,6 +265,15 @@ export class BallotKeysCard extends React.Component {
this.getProgress();
this.getIsFinalized();
}
componentDidMount() {
this.interval = setInterval(() => {
this.calcTimeToFinish()
}, 1000)
}
componentWillUnmount() {
window.clearInterval(this.interval);
}
hideCard = () => {
let { commonStore } = this.props;
@ -360,8 +369,11 @@ export class BallotKeysCard extends React.Component {
</div>
<hr />
<div className="ballots-footer">
<button type="button" onClick={(e) => this.finalize(e)} className="ballots-footer-finalize">Finalize ballot</button>
<p>{constants.CARD_FINALIZE_DESCRIPTION}</p>
<div className="ballots-footer-left">
<button type="button" onClick={(e) => this.finalize(e)} className="ballots-footer-finalize">Finalize ballot</button>
<p>{constants.CARD_FINALIZE_DESCRIPTION}</p>
</div>
<div type="button" className="ballots-i--vote ballots-i--vote_no">Keys Ballot ID: {this.props.id}</div>
</div>
</div>
);

View File

@ -1,10 +1,13 @@
import React from 'react';
import React from "react";
import { inject, observer } from "mobx-react";
import Select from "react-select";
import "react-select/dist/react-select.css";
@inject("ballotStore")
@inject("ballotStore", "contractsStore")
@observer
export class BallotKeysMetadata extends React.Component {
render() {
const options = this.props.contractsStore.validatorsMetadata.slice();
const { ballotStore } = this.props;
return (
<div>
@ -24,9 +27,12 @@ export class BallotKeysMetadata extends React.Component {
<div className="right">
<div className="form-el">
<label htmlFor="key">Mining Key</label>
<input type="text" id="key"
<Select.Creatable
name="form-field-name"
id="key"
value={ballotStore.ballotKeys.miningKey}
onChange={e => ballotStore.changeBallotMetadata(e, "miningKey", "ballotKeys")}
onChange={ballotStore.setMiningKey}
options={options}
/>
<p className="hint">
Mining key address of validator to vote for. Example: 0xc70760D23557A4FDE612C0bE63b26EBD023C51Ee.

View File

@ -6,6 +6,8 @@ import { toAscii } from "../helpers";
import { constants } from "../constants";
import swal from 'sweetalert2';
const ACCEPT = 1;
const REJECT = 2;
@inject("commonStore", "contractsStore", "routing")
@observer
export class BallotMinThresholdCard extends React.Component {
@ -132,7 +134,7 @@ export class BallotMinThresholdCard extends React.Component {
return isActive;
}
vote = async (e, _type) => {
vote = async ({choice}) => {
const { commonStore, contractsStore, id } = this.props;
const { push } = this.props.routing;
if (!contractsStore.isValidVotingKey) {
@ -146,7 +148,7 @@ export class BallotMinThresholdCard extends React.Component {
swal("Warning!", constants.INVALID_VOTE_MSG, "warning");
return;
}
contractsStore.votingToChangeMinThreshold.vote(id, _type, contractsStore.votingKey)
contractsStore.votingToChangeMinThreshold.vote(id, choice, contractsStore.votingKey)
.on("receipt", () => {
commonStore.hideLoading();
swal("Congratulations!", constants.VOTED_SUCCESS_MSG, "success").then((result) => {
@ -249,26 +251,26 @@ export class BallotMinThresholdCard extends React.Component {
</div>
<div className="ballots-i-scale">
<div className="ballots-i-scale-column">
<button type="button" onClick={(e) => this.vote(e, this.props.id, 1)} className="ballots-i--vote ballots-i--vote_yes">Vote</button>
<div className="vote-scale--container">
<p className="vote-scale--value">Yes</p>
<p className="vote-scale--votes">Votes: {this.votesForNumber}</p>
<p className="vote-scale--percentage">{this.votesForPercents}%</p>
<div className="vote-scale">
<div className="vote-scale--fill vote-scale--fill_yes" style={{width: `${this.votesForPercents}%`}}></div>
</div>
</div>
</div>
<div className="ballots-i-scale-column">
<button type="button" onClick={(e) => this.vote({choice: REJECT})} className="ballots-i--vote ballots-i--vote_no">No</button>
<div className="vote-scale--container">
<p className="vote-scale--value">No</p>
<p className="vote-scale--votes">Votes: {this.votesAgainstNumber}</p>
<p className="vote-scale--percentage">{this.votesAgainstPercents}%</p>
<div className="vote-scale">
<div className="vote-scale--fill vote-scale--fill_no" style={{width: `${this.votesAgainstPercents}%`}}></div>
<div className="vote-scale--fill vote-scale--fill_yes" style={{width: `${this.votesAgainstPercents}%`}}></div>
</div>
</div>
<button type="button" onClick={(e) => this.vote(e, 2)} className="ballots-i--vote ballots-i--vote_no">Vote</button>
</div>
<div className="ballots-i-scale-column">
<div className="vote-scale--container">
<p className="vote-scale--value">Yes</p>
<p className="vote-scale--votes">Votes: {this.votesForNumber}</p>
<p className="vote-scale--percentage">{this.votesForPercents}%</p>
<div className="vote-scale">
<div className="vote-scale--fill vote-scale--fill_no" style={{width: `${this.votesForPercents}%`}}></div>
</div>
</div>
<button type="button" onClick={(e) => this.vote({choice: ACCEPT})} className="ballots-i--vote ballots-i--vote_yes">Yes</button>
</div>
</div>
<div className="info">
@ -276,8 +278,11 @@ export class BallotMinThresholdCard extends React.Component {
</div>
<hr />
<div className="ballots-footer">
<button type="button" onClick={(e) => this.finalize(e)} className="ballots-footer-finalize">Finalize ballot</button>
<p>{constants.CARD_FINALIZE_DESCRIPTION}</p>
<div className="ballots-footer-left">
<button type="button" onClick={(e) => this.finalize(e)} className="ballots-footer-finalize">Finalize ballot</button>
<p>{constants.CARD_FINALIZE_DESCRIPTION}</p>
</div>
<div type="button" className="ballots-i--vote ballots-i--vote_no">Consensus Ballot ID: {this.props.id}</div>
</div>
</div>
);

View File

@ -6,6 +6,8 @@ import { toAscii } from "../helpers";
import { constants } from "../constants";
import swal from 'sweetalert2';
const ACCEPT = 1;
const REJECT = 2;
@inject("commonStore", "contractsStore", "ballotStore", "routing")
@observer
export class BallotProxyCard extends React.Component {
@ -140,7 +142,7 @@ export class BallotProxyCard extends React.Component {
return isActive;
}
vote = async (e, _type) => {
vote = async ({choice}) => {
const { commonStore, contractsStore, id } = this.props;
const { push } = this.props.routing;
if (!contractsStore.isValidVotingKey) {
@ -154,7 +156,7 @@ export class BallotProxyCard extends React.Component {
swal("Warning!", constants.INVALID_VOTE_MSG, "warning");
return;
}
contractsStore.votingToChangeProxy.vote(id, _type, contractsStore.votingKey)
contractsStore.votingToChangeProxy.vote(id, choice, contractsStore.votingKey)
.on("receipt", () => {
commonStore.hideLoading();
swal("Congratulations!", constants.VOTED_SUCCESS_MSG, "success").then((result) => {
@ -267,26 +269,26 @@ export class BallotProxyCard extends React.Component {
</div>
<div className="ballots-i-scale">
<div className="ballots-i-scale-column">
<button type="button" onClick={(e) => this.vote(e, 1)} className="ballots-i--vote ballots-i--vote_yes">Vote</button>
<div className="vote-scale--container">
<p className="vote-scale--value">Yes</p>
<p className="vote-scale--votes">Votes: {this.votesForNumber}</p>
<p className="vote-scale--percentage">{this.votesForPercents}%</p>
<div className="vote-scale">
<div className="vote-scale--fill vote-scale--fill_yes" style={{width: `${this.votesForPercents}%`}}></div>
</div>
</div>
</div>
<div className="ballots-i-scale-column">
<button type="button" onClick={(e) => this.vote({choice: REJECT})} className="ballots-i--vote ballots-i--vote_no">No</button>
<div className="vote-scale--container">
<p className="vote-scale--value">No</p>
<p className="vote-scale--votes">Votes: {this.votesAgainstNumber}</p>
<p className="vote-scale--percentage">{this.votesAgainstPercents}%</p>
<div className="vote-scale">
<div className="vote-scale--fill vote-scale--fill_no" style={{width: `${this.votesAgainstPercents}%`}}></div>
<div className="vote-scale--fill vote-scale--fill_yes" style={{width: `${this.votesAgainstPercents}%`}}></div>
</div>
</div>
<button type="button" onClick={(e) => this.vote(e, 2)} className="ballots-i--vote ballots-i--vote_no">Vote</button>
</div>
<div className="ballots-i-scale-column">
<div className="vote-scale--container">
<p className="vote-scale--value">Yes</p>
<p className="vote-scale--votes">Votes: {this.votesForNumber}</p>
<p className="vote-scale--percentage">{this.votesForPercents}%</p>
<div className="vote-scale">
<div className="vote-scale--fill vote-scale--fill_no" style={{width: `${this.votesForPercents}%`}}></div>
</div>
</div>
<button type="button" onClick={(e) => this.vote({choice: ACCEPT})} className="ballots-i--vote ballots-i--vote_yes">Yes</button>
</div>
</div>
<div className="info">
@ -294,8 +296,11 @@ export class BallotProxyCard extends React.Component {
</div>
<hr />
<div className="ballots-footer">
<button type="button" onClick={(e) => this.finalize(e)} className="ballots-footer-finalize">Finalize ballot</button>
<p>{constants.CARD_FINALIZE_DESCRIPTION}</p>
<div className="ballots-footer-left">
<button type="button" onClick={(e) => this.finalize(e)} className="ballots-footer-finalize">Finalize ballot</button>
<p>{constants.CARD_FINALIZE_DESCRIPTION}</p>
</div>
<div type="button" className="ballots-i--vote ballots-i--vote_no">Proxy Ballot ID: {this.props.id}</div>
</div>
</div>
);

View File

@ -53,7 +53,6 @@ export class NewBallot extends React.Component {
commonStore.hideLoading();
return false;
}
let isMiningKeyAddress = contractsStore.web3Instance.isAddress(ballotStore.ballotKeys.miningKey);
if (!isMiningKeyAddress) {
@ -105,7 +104,6 @@ export class NewBallot extends React.Component {
ballotStore.ballotKeys.keysBallotType,
contractsStore.votingKey
];
console.log(inputToMethod)
let method = contractsStore.votingToChangeKeys.createVotingForKeys(
...inputToMethod
);
@ -120,7 +118,6 @@ export class NewBallot extends React.Component {
ballotStore.ballotMinThreshold.proposedValue,
contractsStore.votingKey
];
console.log(inputToMethod)
let method = contractsStore.votingToChangeMinThreshold.createBallotToChangeThreshold(
...inputToMethod
);
@ -189,7 +186,7 @@ export class NewBallot extends React.Component {
let validator = ballotStore.isNewValidatorPersonalData ? <Validator />: "";
let keysTypes = ballotStore.isBallotForKey ? <KeysTypes />: "";
let metadata
let minThreshold
let minThreshold = 0;
switch (ballotStore.ballotType) {
case ballotStore.BallotType.keys:
metadata = <BallotKeysMetadata />;
@ -218,7 +215,7 @@ export class NewBallot extends React.Component {
checked={ballotStore.isBallotForKey}
onChange={e => ballotStore.changeBallotType(e, ballotStore.BallotType.keys)}
/>
<label htmlFor="ballot-for-validators" className="radio">Ballot for validators</label>
<label htmlFor="ballot-for-validators" className="radio">Validator Management Ballot</label>
<p className="hint">
Ballot to add, remove or swap any type of key for existing or new validators.
</p>
@ -231,7 +228,7 @@ export class NewBallot extends React.Component {
checked={ballotStore.isBallotForMinThreshold}
onChange={e => ballotStore.changeBallotType(e, ballotStore.BallotType.minThreshold)}
/>
<label htmlFor="ballot-for-consensus" className="radio">Ballot for consensus</label>
<label htmlFor="ballot-for-consensus" className="radio">Consenus Threshold Ballot</label>
<p className="hint">
Ballot to change the minimum threshold for consensus to vote for keys.
</p>
@ -244,7 +241,7 @@ export class NewBallot extends React.Component {
checked={ballotStore.isBallotForProxy}
onChange={e => ballotStore.changeBallotType(e, ballotStore.BallotType.proxy)}
/>
<label htmlFor="ballot-for-proxy" className="radio">Ballot for proxy</label>
<label htmlFor="ballot-for-proxy" className="radio">Modify Proxy Contract Ballot</label>
<p className="hint">
Ballot to change one of the proxy contracts.
</p>
@ -257,7 +254,10 @@ export class NewBallot extends React.Component {
{metadata}
<div className="new-form-footer">
<div className="info">
Minimum {minThreshold} from {contractsStore.validatorsLength} validators required to pass the proposal
Minimum {minThreshold} from {contractsStore.validatorsLength} validators required to pass the proposal<br />
You can create {contractsStore.validatorLimits.keys} ballot for keys<br />
You can create {contractsStore.validatorLimits.minThreshold} ballot for consensus<br />
You can create {contractsStore.validatorLimits.proxy} ballot for proxy<br />
</div>
<button type="button" className="add-ballot" onClick={e => this.onClick(e)}>Add ballot</button>
</div>

View File

@ -1,13 +1,12 @@
import ballotsStorageAbi from './ballotsStorage.abi.json'
import Web3 from 'web3';
import {BALLOTS_STORAGE_ADDRESS} from './addresses';
import networkAddresses from './addresses';
console.log('Ballots Storage Address ' , BALLOTS_STORAGE_ADDRESS)
export default class POAConsensus {
constructor(){
if(window.web3.currentProvider){
let web3_10 = new Web3(window.web3.currentProvider);
constructor({web3, netId}){
const {BALLOTS_STORAGE_ADDRESS} = networkAddresses(netId);
console.log('Ballots Storage Address ' , BALLOTS_STORAGE_ADDRESS);
let web3_10 = new Web3(web3.currentProvider);
this.ballotsStorageInstance = new web3_10.eth.Contract(ballotsStorageAbi, BALLOTS_STORAGE_ADDRESS);
}
}
}

View File

@ -1,14 +1,13 @@
import poaConsensusAbi from './poaConsensus.abi.json'
import Web3 from 'web3';
import {POA_ADDRESS} from './addresses';
import networkAddresses from './addresses';
console.log('POA Address ' , POA_ADDRESS)
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, POA_ADDRESS);
}
constructor({web3, netId}){
const {POA_ADDRESS} = networkAddresses(netId);
console.log('POA Address ' , POA_ADDRESS)
let web3_10 = new Web3(web3.currentProvider);
this.poaInstance = new web3_10.eth.Contract(poaConsensusAbi, POA_ADDRESS);
}
async getValidators(){
return await this.poaInstance.methods.getValidators().call();

View File

@ -1,7 +1,7 @@
import MetadataAbi from './validatorMetadata.abi.json'
import Web3 from 'web3';
import moment from 'moment';
import {METADATA_ADDRESS} from './addresses';
import networkAddresses from './addresses';
var toAscii = function(hex) {
var str = '',
i = 0,
@ -17,13 +17,13 @@ var toAscii = function(hex) {
return str;
};
console.log('Metadata contract:', METADATA_ADDRESS)
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);
}
constructor({web3, netId}){
const {METADATA_ADDRESS} = networkAddresses(netId);
console.log('Metadata contract:', METADATA_ADDRESS)
this.web3_10 = new Web3(web3.currentProvider);
this.metadataInstance = new this.web3_10.eth.Contract(MetadataAbi, METADATA_ADDRESS);
}
async getValidatorData({votingKey, miningKey}){

View File

@ -1,14 +1,13 @@
import votingToChangeKeysABI from './votingToChangeKeys.abi.json'
import Web3 from 'web3';
import {VOTING_TO_CHANGE_KEYS_ADDRESS} from './addresses'
console.log('VotingToChangeKeys ', VOTING_TO_CHANGE_KEYS_ADDRESS)
import networkAddresses from './addresses';
export default class VotingToChangeKeys {
constructor(){
if(window.web3.currentProvider){
let web3_10 = new Web3(window.web3.currentProvider);
this.votingToChangeKeysInstance = new web3_10.eth.Contract(votingToChangeKeysABI, VOTING_TO_CHANGE_KEYS_ADDRESS);
}
constructor({web3, netId}){
const {VOTING_TO_CHANGE_KEYS_ADDRESS} = networkAddresses(netId);
console.log('VotingToChangeKeys ', VOTING_TO_CHANGE_KEYS_ADDRESS);
let web3_10 = new Web3(web3.currentProvider);
this.votingToChangeKeysInstance = new web3_10.eth.Contract(votingToChangeKeysABI, VOTING_TO_CHANGE_KEYS_ADDRESS);
}
//setters
@ -68,4 +67,18 @@ export default class VotingToChangeKeys {
getAffectedKey(_id) {
return this.votingToChangeKeysInstance.methods.getAffectedKey(_id).call();
}
getMiningByVotingKey(_votingKey) {
return this.votingToChangeKeysInstance.methods.getMiningByVotingKey(_votingKey).call();
}
async getValidatorActiveBallots(_votingKey) {
const miningKey = await this.getMiningByVotingKey(_votingKey);
return await this.votingToChangeKeysInstance.methods.validatorActiveBallots(miningKey).call();
}
async getBallotLimit(_votingKey) {
const currentLimit = await this.votingToChangeKeysInstance.methods.getBallotLimitPerValidator().call();
return currentLimit - await this.getValidatorActiveBallots(_votingKey);
}
}

View File

@ -1,14 +1,13 @@
import votingToChangeMinThresholdABI from './votingToChangeMinThreshold.abi.json'
import Web3 from 'web3';
import {VOTING_TO_CHANGE_MIN_THRESHOLD} from './addresses'
import networkAddresses from './addresses';
console.log('VotingToChangeMinThreshold ', VOTING_TO_CHANGE_MIN_THRESHOLD)
export default class VotingToChangeMinThreshold {
constructor(){
if(window.web3.currentProvider){
let web3_10 = new Web3(window.web3.currentProvider);
this.votingToChangeMinThresholdInstance = new web3_10.eth.Contract(votingToChangeMinThresholdABI, VOTING_TO_CHANGE_MIN_THRESHOLD);
}
constructor({web3, netId}){
const {VOTING_TO_CHANGE_MIN_THRESHOLD} = networkAddresses(netId);
let web3_10 = new Web3(web3.currentProvider);
console.log('VotingToChangeMinThreshold ', VOTING_TO_CHANGE_MIN_THRESHOLD)
this.votingToChangeMinThresholdInstance = new web3_10.eth.Contract(votingToChangeMinThresholdABI, VOTING_TO_CHANGE_MIN_THRESHOLD);
}
//setters
@ -60,4 +59,18 @@ export default class VotingToChangeMinThreshold {
getProposedValue(_id) {
return this.votingToChangeMinThresholdInstance.methods.getProposedValue(_id).call();
}
getMiningByVotingKey(_votingKey) {
return this.votingToChangeMinThresholdInstance.methods.getMiningByVotingKey(_votingKey).call();
}
async getValidatorActiveBallots(_votingKey) {
const miningKey = await this.getMiningByVotingKey(_votingKey);
return await this.votingToChangeMinThresholdInstance.methods.validatorActiveBallots(miningKey).call();
}
async getBallotLimit(_votingKey) {
const currentLimit = await this.votingToChangeMinThresholdInstance.methods.getBallotLimitPerValidator().call();
return currentLimit - await this.getValidatorActiveBallots(_votingKey);
}
}

View File

@ -1,14 +1,13 @@
import votingToChangeProxyABI from './votingToChangeProxy.abi.json'
import Web3 from 'web3';
import {VOTING_TO_CHANGE_PROXY} from './addresses'
import networkAddresses from './addresses';
console.log('VotingToChangeProxy ', VOTING_TO_CHANGE_PROXY)
export default class VotingToChangeProxy {
constructor(){
if(window.web3.currentProvider){
let web3_10 = new Web3(window.web3.currentProvider);
this.votingToChangeProxyInstance = new web3_10.eth.Contract(votingToChangeProxyABI, VOTING_TO_CHANGE_PROXY);
}
constructor({web3, netId}){
const {VOTING_TO_CHANGE_PROXY} = networkAddresses(netId);
console.log('VotingToChangeProxy ', VOTING_TO_CHANGE_PROXY)
let web3_10 = new Web3(web3.currentProvider);
this.votingToChangeProxyInstance = new web3_10.eth.Contract(votingToChangeProxyABI, VOTING_TO_CHANGE_PROXY);
}
//setters
@ -64,4 +63,18 @@ export default class VotingToChangeProxy {
getContractType(_id) {
return this.votingToChangeProxyInstance.methods.getContractType(_id).call();
}
getMiningByVotingKey(_votingKey) {
return this.votingToChangeProxyInstance.methods.getMiningByVotingKey(_votingKey).call();
}
async getValidatorActiveBallots(_votingKey) {
const miningKey = await this.getMiningByVotingKey(_votingKey);
return await this.votingToChangeProxyInstance.methods.validatorActiveBallots(miningKey).call();
}
async getBallotLimit(_votingKey) {
const currentLimit = await this.votingToChangeProxyInstance.methods.getBallotLimitPerValidator().call();
return currentLimit - await this.getValidatorActiveBallots(_votingKey);
}
}

View File

@ -1,8 +1,38 @@
module.exports = {
VOTING_TO_CHANGE_KEYS_ADDRESS: '0x49df4ec19243263e5db22da5865b4f482b8323a0',
// const local = {
// VOTING_TO_CHANGE_KEYS_ADDRESS: '0x758492834ed6454f41d6d3d6b73d6e46d4555429',
// VOTING_TO_CHANGE_MIN_THRESHOLD: '0xcbf043db3498b5064bd62341be0c0e3fb0344b1b',
// VOTING_TO_CHANGE_PROXY: '0xcb3f870269a3f7215eb87d9548ee5b7eff6396dd',
// BALLOTS_STORAGE_ADDRESS: '0x144947d78b932ea0dff14d75e1f7cd1b2f131426',
// METADATA_ADDRESS: '0x3111c94b9243a8a99d5a867e00609900e437e2c0',
// POA_ADDRESS: '0xf472e0e43570b9afaab67089615080cf7c20018d',
// }
const CORE_ADDRESSES = {
VOTING_TO_CHANGE_KEYS_ADDRESS: '0x49df4ec19243263e5db22da5865b4f482b8323a0',
VOTING_TO_CHANGE_MIN_THRESHOLD: '0x8829ebe113535826e8af17ed51f83755f675789a',
VOTING_TO_CHANGE_PROXY: '0x6b728399b41a38d4109f7af2213d4cc31ca87812',
BALLOTS_STORAGE_ADDRESS: '0x0d7590c7aedf1e7e85fc9a1ee88f6f17d3ba762f',
METADATA_ADDRESS: '0xcBB2912666c7e8023B7ec78B6842702eB26336aC',
POA_ADDRESS: '0x8bf38d4764929064f2d4d3a56520a76ab3df415b',
BALLOTS_STORAGE_ADDRESS: '0x0d7590c7aedf1e7e85fc9a1ee88f6f17d3ba762f'
}
}
const SOKOL_ADDRESSES = {
VOTING_TO_CHANGE_KEYS_ADDRESS: '0x145a3d3bd5db8a0ad863b4949b6088d133726cdb',
VOTING_TO_CHANGE_MIN_THRESHOLD: '0xad623f870298774765bc5e56ebeafac721028867',
VOTING_TO_CHANGE_PROXY: '0x6fb85b2030a68a76ab237d2392b09e28e6f03fa9',
BALLOTS_STORAGE_ADDRESS: '0x1e0eaa06d02f965be2dfe0bc9ff52b2d82133461',
METADATA_ADDRESS: '0xce9ff1123223d13672cce06dd073d3749764daa6',
POA_ADDRESS: '0x8bf38d4764929064f2d4d3a56520a76ab3df415b',
}
module.exports = (netId) => {
switch (netId) {
case '77':
return SOKOL_ADDRESSES
case '99':
return CORE_ADDRESSES
default:
return CORE_ADDRESSES
}
}

View File

@ -29,6 +29,7 @@ let getWeb3 = () => {
errorMsg = constants.WRONG_NETWORK_MSG
console.log('This is an unknown network.', netId)
}
document.title = `${netIdName} - POA Network Governance DApp`
var defaultAccount = web3.eth.defaultAccount || null;
if(defaultAccount === null){
reject({message: constants.NO_METAMASK_MSG})

View File

@ -27,24 +27,27 @@ class AppMainRouter extends Component {
commonStore.showLoading();
getWeb3().then(async (web3Config) => {
contractsStore.setWeb3Instance(web3Config);
await contractsStore.setWeb3Instance(web3Config);
await contractsStore.setPoaConsensus(web3Config);
contractsStore.setBallotsStorage(web3Config);
await contractsStore.setBallotsStorage(web3Config);
await contractsStore.setVotingToChangeKeys(web3Config);
await contractsStore.setVotingToChangeMinThreshold(web3Config);
await contractsStore.setVotingToChangeProxy(web3Config);
await contractsStore.setValidatorMetadata(web3Config);
contractsStore.getValidatorsLength();
await contractsStore.getKeysBallotThreshold();
contractsStore.getKeysBallotThreshold();
contractsStore.getMinThresholdBallotThreshold();
contractsStore.getProxyBallotThreshold();
contractsStore.setVotingToChangeKeys(web3Config);
contractsStore.setVotingToChangeMinThreshold(web3Config);
contractsStore.setVotingToChangeProxy(web3Config);
contractsStore.setValidatorMetadata(web3Config);
contractsStore.setVotingKey(web3Config);
contractsStore.getAllKeysBallots();
contractsStore.getAllMinThresholdBallots();
contractsStore.getAllProxyBallots();
contractsStore.setVotingKey(web3Config);
await contractsStore.setMiningKey(web3Config);
console.log("votingKey", contractsStore.votingKey)
console.log("miningKey", contractsStore.miningKey)
contractsStore.getValidatorActiveBallots();
contractsStore.getAllValidatorMetadata();
console.log("votingKey", contractsStore.votingKey);
console.log("miningKey", contractsStore.miningKey);
commonStore.hideLoading();
}).catch((error) => {
commonStore.hideLoading();
swal({

View File

@ -1,4 +1,4 @@
import { observable, computed, action } from 'mobx';
import { observable, computed, action, toJS } from 'mobx';
import moment from 'moment';
class BallotStore {
@ -25,6 +25,7 @@ class BallotStore {
5: 'BallotsStorage'
}
@observable ballotType;
@observable keysBallotType;
@observable endTime;
@observable ballotKeys;
@ -33,12 +34,12 @@ class BallotStore {
constructor() {
this.ballotType = this.BallotType.keys;
this.ballotType = null;
this.endTime = "";
this.ballotKeys = {
keyType: this.KeyType.mining,
keysBallotType: this.KeysBallotType.add,
keyType: null,
keysBallotType: null,
//memo: "",
affectedKey: "",
miningKey: ""
@ -126,7 +127,12 @@ class BallotStore {
this[parent][field] = newVal;
else
this[field] = newVal;
console.log("ballot metadata", field, parent?this[parent][field]:this[field])
console.log("ballot metadata", field, parent?this[parent][field]:this[field]);
}
@action("change ballot metadata")
setMiningKey = (value) => {
this.ballotKeys.miningKey = value;
console.log("ballot mining key", toJS(value));
}
}

View File

@ -19,7 +19,6 @@ import "babel-polyfill";
class ContractsStore {
@observable activeKeysBallotsIDs;
@observable poaConsensus;
@observable ballotsStorage;
@observable votingToChangeKeys;
@ -33,15 +32,18 @@ class ContractsStore {
@observable keysBallotThreshold;
@observable minThresholdBallotThreshold;
@observable proxyBallotThreshold;
@observable validatorLimits;
@observable validatorsMetadata;
constructor() {
this.votingKey = null;
this.miningKey = null;
this.activeKeysBallotsIDs = [];
this.validatorsMetadata = [];
this.validatorLimits = {keys: null, minThreshold: null, proxy: null};
getWeb3().then(async (web3Config) => {
contractsStore.setWeb3Instance(web3Config);
})
contractsStore.setWeb3Instance(web3Config);
})
}
@computed get isValidVotingKey() {
@ -55,8 +57,8 @@ class ContractsStore {
}
@action("Get min threshold ballot threshold")
getMinThresholdBallotThreshold() {
this.minThresholdBallotThreshold = this.keysBallotThreshold;
async getMinThresholdBallotThreshold() {
this.minThresholdBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods.getBallotThreshold(1).call();
}
@action("get proxy ballot threshold")
@ -67,47 +69,54 @@ class ContractsStore {
@action("Set web3Instance")
setWeb3Instance = (web3Config) => {
this.web3Instance = web3Config.web3Instance;
this.netId = web3Config.netId;
}
@action("Set PoA Consensus contract")
setPoaConsensus = (web3Config) => {
this.poaConsensus = new PoaConsensus({
web3: web3Config.web3Instance
web3: web3Config.web3Instance,
netId: web3Config.netId
});
}
@action("Set Ballots Storage contract")
setBallotsStorage = (web3Config) => {
this.ballotsStorage = new BallotsStorage({
web3: web3Config.web3Instance
web3: web3Config.web3Instance,
netId: web3Config.netId
});
}
@action("Set VotingToChangeKeys contract")
setVotingToChangeKeys = (web3Config) => {
this.votingToChangeKeys = new VotingToChangeKeys({
web3: web3Config.web3Instance
web3: web3Config.web3Instance,
netId: web3Config.netId
});
}
@action("Set VotingToChangeMinThreshold contract")
setVotingToChangeMinThreshold = (web3Config) => {
this.votingToChangeMinThreshold = new VotingToChangeMinThreshold({
web3: web3Config.web3Instance
web3: web3Config.web3Instance,
netId: web3Config.netId
});
}
@action("Set VotingToChangeProxy contract")
setVotingToChangeProxy = (web3Config) => {
this.votingToChangeProxy = new VotingToChangeProxy({
web3: web3Config.web3Instance
web3: web3Config.web3Instance,
netId: web3Config.netId
});
}
@action("Set ValidatorMetadata contract")
setValidatorMetadata = (web3Config) => {
this.validatorMetadata = new ValidatorMetadata({
web3: web3Config.web3Instance
web3: web3Config.web3Instance,
netId: web3Config.netId
});
}
@ -173,6 +182,25 @@ class ContractsStore {
commonStore.hideLoading();
}
}
@action
async getValidatorActiveBallots() {
if(this.web3Instance && this.netId){
await this.setVotingToChangeKeys({web3Instance: this.web3Instance, netId: this.netId})
await this.setVotingToChangeMinThreshold({web3Instance: this.web3Instance, netId: this.netId})
await this.setVotingToChangeProxy({web3Instance: this.web3Instance, netId: this.netId})
this.validatorLimits.keys = await this.votingToChangeKeys.getBallotLimit(this.web3Instance.eth.defaultAccount);
this.validatorLimits.minThreshold = await this.votingToChangeMinThreshold.getBallotLimit(this.web3Instance.eth.defaultAccount);
this.validatorLimits.proxy = await this.votingToChangeProxy.getBallotLimit(this.web3Instance.eth.defaultAccount);
}
}
@action
async getAllValidatorMetadata() {
const keys = await this.poaConsensus.getValidators();
keys.forEach(async (key) => {
const metadata = await this.validatorMetadata.getValidatorData({miningKey: key})
this.validatorsMetadata.push({label: `${key} ${metadata.lastName}`, value: key})
})
}
}
const contractsStore = new ContractsStore();