mirror of
https://github.com/status-im/visual-identity.git
synced 2025-02-08 18:53:44 +00:00
Tabulation and determining final result
This commit is contained in:
parent
93d96c07da
commit
9f122d36ff
@ -11,7 +11,10 @@ class Voting extends Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
decision: 0,
|
decision: 0,
|
||||||
finalResult: null
|
finalResult: null,
|
||||||
|
data: null,
|
||||||
|
tabulationAvailable: false,
|
||||||
|
votingAvailable: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,23 +24,26 @@ class Voting extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount(){
|
|
||||||
__embarkContext.execWhenReady(async () => {
|
|
||||||
this._loadProposalData();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async _loadProposalData() {
|
async _loadProposalData() {
|
||||||
ProposalManager.options.address = await ProposalCuration.methods.proposalManager().call();
|
ProposalManager.options.address = await ProposalCuration.methods.proposalManager().call();
|
||||||
let _proposal = await ProposalManager.methods.getVoteInfo(this.props.proposalId, web3.eth.defaultAccount).call();
|
const _votingInfo = await ProposalManager.methods.getVoteInfo(this.props.proposalId, web3.eth.defaultAccount).call();
|
||||||
let blockNum = await web3.eth.getBlockNumber();
|
const _blockNum = await web3.eth.getBlockNumber();
|
||||||
let _data = await ProposalManager.methods.proposals(this.props.proposalId).call();
|
const _data = await ProposalManager.methods.proposals(this.props.proposalId).call();
|
||||||
|
|
||||||
|
const _votingAvailable = await ProposalManager.methods.isVotingAvailable(this.props.proposalId).call();
|
||||||
|
const _tabulationAvailable = await ProposalManager.methods.isTabulationAvailable(this.props.proposalId).call();
|
||||||
|
const _voteTabulated = await ProposalManager.methods.isDelegatorVoteTabulated(this.props.proposalId, web3.eth.defaultAccount).call();
|
||||||
|
const _canCalculateFinalResult = await ProposalManager.methods.canCalculateFinalResult(this.props.proposalId).call();
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
data: _data,
|
data: _data,
|
||||||
decision: _proposal.vote,
|
decision: _votingInfo.vote,
|
||||||
block: blockNum,
|
block: _blockNum,
|
||||||
finalResult: _data.result
|
finalResult: _data.result,
|
||||||
|
votingAvailable: _votingAvailable,
|
||||||
|
tabulationAvailable: _tabulationAvailable,
|
||||||
|
canCalculateFinalResult: _canCalculateFinalResult,
|
||||||
|
voteTabulated: _voteTabulated
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,15 +51,26 @@ class Voting extends Component {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
let receipt = await ProposalManager.methods.finalResult(this.props.proposalId)
|
let receipt = await ProposalManager.methods.finalResult(this.props.proposalId)
|
||||||
.send({from: web3.eth.defaultAccount});
|
.send({from: web3.eth.defaultAccount, gasLimit: 1000000});
|
||||||
|
|
||||||
if(receipt.status == '0x1'){
|
if(receipt.status == '0x1'){
|
||||||
this.setState({
|
this.setState({
|
||||||
finalResult: receipt.events.ProposalResult.returnValues.finalResult
|
finalResult: receipt.events.ProposalResult.returnValues.finalResult,
|
||||||
|
finalResultAvailable: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async tabulateVote(e){
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const receipt = await ProposalManager.methods.tabulateVote(this.props.proposalId, web3.eth.defaultAccount)
|
||||||
|
.send({from: web3.eth.defaultAccount, gasLimit: 1000000});
|
||||||
|
|
||||||
|
// TODO: handle error
|
||||||
|
|
||||||
|
this._loadProposalData();
|
||||||
|
}
|
||||||
|
|
||||||
async handleClick(e, vote){
|
async handleClick(e, vote){
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
@ -63,16 +80,25 @@ class Voting extends Component {
|
|||||||
else
|
else
|
||||||
choice = 1;
|
choice = 1;
|
||||||
|
|
||||||
let proposal = this.props.proposalId;
|
const proposal = this.props.proposalId;
|
||||||
let receipt = await ProposalManager.methods.voteProposal(this.props.proposalId, choice)
|
const receipt = await ProposalManager.methods.voteProposal(this.props.proposalId, choice)
|
||||||
.send({from: web3.eth.defaultAccount});
|
.send({from: web3.eth.defaultAccount});
|
||||||
let blockNum = await web3.eth.getBlockNumber();
|
|
||||||
|
|
||||||
|
const _votingAvailable = await ProposalManager.methods.isVotingAvailable(this.props.proposalId).call();
|
||||||
|
const _tabulationAvailable = await ProposalManager.methods.isTabulationAvailable(this.props.proposalId).call();
|
||||||
|
const _voteTabulated = await ProposalManager.methods.isDelegatorVoteTabulated(this.props.proposalId, web3.eth.defaultAccount).call();
|
||||||
|
const _canCalculateFinalResult = await ProposalManager.methods.canCalculateFinalResult(this.props.proposalId).call();
|
||||||
|
|
||||||
|
const blockNum = await web3.eth.getBlockNumber();
|
||||||
|
|
||||||
if(receipt.status == '0x1'){
|
if(receipt.status == '0x1'){
|
||||||
this.setState({
|
this.setState({
|
||||||
decision: choice,
|
decision: choice,
|
||||||
block: blockNum
|
block: blockNum,
|
||||||
|
votingAvailable: _votingAvailable,
|
||||||
|
tabulationAvailable: _tabulationAvailable,
|
||||||
|
finalResultAvailable: _canCalculateFinalResult,
|
||||||
|
voteTabulated: _voteTabulated
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// TODO: handle error
|
// TODO: handle error
|
||||||
@ -87,7 +113,7 @@ class Voting extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
this.state.data != null && this.state.block < this.state.data.voteBlockEnd ?
|
this.state.data != null && this.state.votingAvailable ?
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Button onClick={(e) => this.handleClick(e, 'APPROVE') }>Approve</Button>
|
<Button onClick={(e) => this.handleClick(e, 'APPROVE') }>Approve</Button>
|
||||||
<Button onClick={(e) => this.handleClick(e, 'REJECT') }>Reject</Button>
|
<Button onClick={(e) => this.handleClick(e, 'REJECT') }>Reject</Button>
|
||||||
@ -96,11 +122,19 @@ class Voting extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
this.state.data != null && this.state.block >= this.state.data.voteBlockEnd && this.state.data.result == 0 ?
|
this.state.data != null && this.state.tabulationAvailable && !this.state.voteTabulated ?
|
||||||
<Button onClick={(e) => this.determineFinalResult(e) }>Determine final result</Button>
|
<Button onClick={(e) => this.tabulateVote(e) }>Tabulate your vote</Button>
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
this.state.finalResultAvailable ?
|
||||||
|
<Button onClick={(e) => this.determineFinalResult(e) }>Determine final result</Button>
|
||||||
|
: !this.state.tabulationAvailable && !this.state.voteTabulated ?
|
||||||
|
<p>Final results aren't available yet</p> : ''
|
||||||
|
}
|
||||||
|
|
||||||
{ this.state.data != null ?
|
{ this.state.data != null ?
|
||||||
<ul>
|
<ul>
|
||||||
<li>Voting ends on block: {this.state.data.voteBlockEnd }</li>
|
<li>Voting ends on block: {this.state.data.voteBlockEnd }</li>
|
||||||
|
@ -51,7 +51,7 @@ contract ProposalManager is Controlled {
|
|||||||
{
|
{
|
||||||
trustNet = _trustNet;
|
trustNet = _trustNet;
|
||||||
token = _token;
|
token = _token;
|
||||||
tabulationBlockDelay = 7 days;
|
tabulationBlockDelay = 10 seconds; // TODO: set 7 days
|
||||||
quorumPercentage = 50;
|
quorumPercentage = 50;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -106,8 +106,10 @@ contract ProposalManager is Controlled {
|
|||||||
Proposal storage proposal = proposals[_proposalId];
|
Proposal storage proposal = proposals[_proposalId];
|
||||||
require(block.number > proposal.voteBlockEnd);
|
require(block.number > proposal.voteBlockEnd);
|
||||||
require(!proposal.tabulated[_delegator]);
|
require(!proposal.tabulated[_delegator]);
|
||||||
proposal.tabulated[_delegator] = true;
|
|
||||||
|
|
||||||
Vote _vote = proposal.voteMap[_delegator];
|
Vote _vote = proposal.voteMap[_delegator];
|
||||||
|
|
||||||
if(_vote == Vote.Null) {
|
if(_vote == Vote.Null) {
|
||||||
address delegate = trustNet.getVoteDelegation(proposal.topic).delegationOfAt(_delegator, proposal.voteBlockEnd);
|
address delegate = trustNet.getVoteDelegation(proposal.topic).delegationOfAt(_delegator, proposal.voteBlockEnd);
|
||||||
_vote = proposal.voteMap[delegate];
|
_vote = proposal.voteMap[delegate];
|
||||||
@ -116,6 +118,8 @@ contract ProposalManager is Controlled {
|
|||||||
if (_vote == Vote.Reject || _vote == Vote.Approve) {
|
if (_vote == Vote.Reject || _vote == Vote.Approve) {
|
||||||
proposal.results[uint8(_vote)] += token.balanceOfAt(_delegator, proposal.voteBlockEnd);
|
proposal.results[uint8(_vote)] += token.balanceOfAt(_delegator, proposal.voteBlockEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proposal.tabulated[_delegator] = true;
|
||||||
proposal.lastTabulationTimestamp = block.timestamp;
|
proposal.lastTabulationTimestamp = block.timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +135,7 @@ contract ProposalManager is Controlled {
|
|||||||
public
|
public
|
||||||
{
|
{
|
||||||
Proposal storage proposal = proposals[_proposalId];
|
Proposal storage proposal = proposals[_proposalId];
|
||||||
|
require(block.number > proposal.voteBlockEnd);
|
||||||
require(proposal.lastTabulationTimestamp + tabulationBlockDelay < block.timestamp);
|
require(proposal.lastTabulationTimestamp + tabulationBlockDelay < block.timestamp);
|
||||||
require(proposal.result == Vote.Null);
|
require(proposal.result == Vote.Null);
|
||||||
uint256 totalTokens = token.totalSupplyAt(proposal.voteBlockEnd);
|
uint256 totalTokens = token.totalSupplyAt(proposal.voteBlockEnd);
|
||||||
@ -194,7 +199,30 @@ contract ProposalManager is Controlled {
|
|||||||
|
|
||||||
function isVotingAvailable(uint _proposalId) public view returns (bool){
|
function isVotingAvailable(uint _proposalId) public view returns (bool){
|
||||||
Proposal memory p = proposals[_proposalId];
|
Proposal memory p = proposals[_proposalId];
|
||||||
return p.voteBlockEnd > block.number && p.result == Vote.Null;
|
return p.voteBlockEnd > block.number && p.result == Vote.Null && p.lastTabulationTimestamp == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function canCalculateFinalResult(uint _proposalId) public view returns (bool){
|
||||||
|
Proposal memory proposal = proposals[_proposalId];
|
||||||
|
return proposal.lastTabulationTimestamp + tabulationBlockDelay < block.timestamp &&
|
||||||
|
proposal.result == Vote.Null &&
|
||||||
|
block.number > proposal.voteBlockEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTabulationAvailable(uint _proposalId) public view returns (bool){
|
||||||
|
Proposal memory p = proposals[_proposalId];
|
||||||
|
return !isVotingAvailable(_proposalId) &&
|
||||||
|
block.timestamp > p.lastTabulationTimestamp + tabulationBlockDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDelegatorVoteTabulated(uint _proposalId, address _delegator)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
Proposal storage proposal = proposals[_proposalId];
|
||||||
|
return proposal.tabulated[_delegator];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVoteInfo(uint _proposalId, address voter)
|
function getVoteInfo(uint _proposalId, address voter)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user