(Feature) Add voting to manage emission funds
This commit is contained in:
parent
12719ebd8c
commit
5639487713
File diff suppressed because one or more lines are too long
|
@ -136,4 +136,12 @@ button {
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $primary-color;
|
||||||
|
|
||||||
|
.sokol & {
|
||||||
|
color: $primary-color-sokol;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,9 @@ import swal from 'sweetalert2'
|
||||||
|
|
||||||
const ACCEPT = 1
|
const ACCEPT = 1
|
||||||
const REJECT = 2
|
const REJECT = 2
|
||||||
|
const SEND = 1
|
||||||
|
const BURN = 2
|
||||||
|
const FREEZE = 3
|
||||||
const USDateTimeFormat = 'MM/DD/YYYY h:mm:ss A'
|
const USDateTimeFormat = 'MM/DD/YYYY h:mm:ss A'
|
||||||
const maxDetailsLength = 500
|
const maxDetailsLength = 500
|
||||||
|
|
||||||
|
@ -102,6 +105,60 @@ export class BallotCard extends React.Component {
|
||||||
return votesPercents
|
return votesPercents
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
get votesBurnNumber() {
|
||||||
|
let votes = this.burnVotes
|
||||||
|
if (isNaN(votes)) votes = 0
|
||||||
|
return votes
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
get votesBurnPercents() {
|
||||||
|
if (this.totalVoters <= 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
let votesPercents = Math.round((this.votesBurnNumber / this.totalVoters) * 100)
|
||||||
|
if (isNaN(votesPercents)) votesPercents = 0
|
||||||
|
return votesPercents
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
get votesFreezeNumber() {
|
||||||
|
let votes = this.freezeVotes
|
||||||
|
if (isNaN(votes)) votes = 0
|
||||||
|
return votes
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
get votesFreezePercents() {
|
||||||
|
if (this.totalVoters <= 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
let votesPercents = Math.round((this.votesFreezeNumber / this.totalVoters) * 100)
|
||||||
|
if (isNaN(votesPercents)) votesPercents = 0
|
||||||
|
return votesPercents
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
get votesSendNumber() {
|
||||||
|
let votes = this.sendVotes
|
||||||
|
if (isNaN(votes)) votes = 0
|
||||||
|
return votes
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
get votesSendPercents() {
|
||||||
|
if (this.totalVoters <= 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
let votesPercents = Math.round((this.votesSendNumber / this.totalVoters) * 100)
|
||||||
|
if (isNaN(votesPercents)) votesPercents = 0
|
||||||
|
return votesPercents
|
||||||
|
}
|
||||||
|
|
||||||
@action('Calculate time to start/finish')
|
@action('Calculate time to start/finish')
|
||||||
calcTimeTo = () => {
|
calcTimeTo = () => {
|
||||||
const _now = moment()
|
const _now = moment()
|
||||||
|
@ -202,8 +259,18 @@ export class BallotCard extends React.Component {
|
||||||
async tx => {
|
async tx => {
|
||||||
const ballotInfo = await contract.getBallotInfo(id, contractsStore.votingKey)
|
const ballotInfo = await contract.getBallotInfo(id, contractsStore.votingKey)
|
||||||
|
|
||||||
this.totalVoters = Number(ballotInfo.totalVoters)
|
if (ballotInfo.hasOwnProperty('totalVoters')) {
|
||||||
this.progress = Number(ballotInfo.progress)
|
this.totalVoters = Number(ballotInfo.totalVoters)
|
||||||
|
} else {
|
||||||
|
this.burnVotes = ballotInfo.burnVotes
|
||||||
|
this.freezeVotes = ballotInfo.freezeVotes
|
||||||
|
this.sendVotes = ballotInfo.sendVotes
|
||||||
|
this.totalVoters =
|
||||||
|
Number(ballotInfo.burnVotes) + Number(ballotInfo.freezeVotes) + Number(ballotInfo.sendVotes)
|
||||||
|
}
|
||||||
|
if (ballotInfo.hasOwnProperty('progress')) {
|
||||||
|
this.progress = Number(ballotInfo.progress)
|
||||||
|
}
|
||||||
this.isFinalized = Boolean(ballotInfo.isFinalized)
|
this.isFinalized = Boolean(ballotInfo.isFinalized)
|
||||||
if (ballotInfo.hasOwnProperty('canBeFinalizedNow')) {
|
if (ballotInfo.hasOwnProperty('canBeFinalizedNow')) {
|
||||||
this.canBeFinalized = Boolean(ballotInfo.canBeFinalizedNow)
|
this.canBeFinalized = Boolean(ballotInfo.canBeFinalizedNow)
|
||||||
|
@ -212,8 +279,16 @@ export class BallotCard extends React.Component {
|
||||||
}
|
}
|
||||||
this.hasAlreadyVoted = true
|
this.hasAlreadyVoted = true
|
||||||
|
|
||||||
ballotsStore.ballotCards[pos].props.votingState.totalVoters = this.totalVoters
|
if (ballotInfo.hasOwnProperty('totalVoters')) {
|
||||||
ballotsStore.ballotCards[pos].props.votingState.progress = this.progress
|
ballotsStore.ballotCards[pos].props.votingState.totalVoters = this.totalVoters
|
||||||
|
} else {
|
||||||
|
ballotsStore.ballotCards[pos].props.votingState.burnVotes = this.burnVotes
|
||||||
|
ballotsStore.ballotCards[pos].props.votingState.freezeVotes = this.freezeVotes
|
||||||
|
ballotsStore.ballotCards[pos].props.votingState.sendVotes = this.sendVotes
|
||||||
|
}
|
||||||
|
if (ballotInfo.hasOwnProperty('progress')) {
|
||||||
|
ballotsStore.ballotCards[pos].props.votingState.progress = this.progress
|
||||||
|
}
|
||||||
ballotsStore.ballotCards[pos].props.votingState.isFinalized = this.isFinalized
|
ballotsStore.ballotCards[pos].props.votingState.isFinalized = this.isFinalized
|
||||||
ballotsStore.ballotCards[pos].props.votingState.canBeFinalized = this.canBeFinalized
|
ballotsStore.ballotCards[pos].props.votingState.canBeFinalized = this.canBeFinalized
|
||||||
ballotsStore.ballotCards[pos].props.votingState.hasAlreadyVoted = this.hasAlreadyVoted
|
ballotsStore.ballotCards[pos].props.votingState.hasAlreadyVoted = this.hasAlreadyVoted
|
||||||
|
@ -315,6 +390,8 @@ export class BallotCard extends React.Component {
|
||||||
return contractsStore.votingToChangeMinThreshold
|
return contractsStore.votingToChangeMinThreshold
|
||||||
case 'votingToChangeProxy':
|
case 'votingToChangeProxy':
|
||||||
return contractsStore.votingToChangeProxy
|
return contractsStore.votingToChangeProxy
|
||||||
|
case 'votingToManageEmissionFunds':
|
||||||
|
return contractsStore.votingToManageEmissionFunds
|
||||||
case 'validatorMetadata':
|
case 'validatorMetadata':
|
||||||
return contractsStore.validatorMetadata
|
return contractsStore.validatorMetadata
|
||||||
default:
|
default:
|
||||||
|
@ -330,6 +407,8 @@ export class BallotCard extends React.Component {
|
||||||
return contractsStore.minThresholdBallotThreshold
|
return contractsStore.minThresholdBallotThreshold
|
||||||
case 'votingToChangeProxy':
|
case 'votingToChangeProxy':
|
||||||
return contractsStore.proxyBallotThreshold
|
return contractsStore.proxyBallotThreshold
|
||||||
|
case 'votingToManageEmissionFunds':
|
||||||
|
return contractsStore.emissionFundsBallotThreshold
|
||||||
default:
|
default:
|
||||||
return contractsStore.keysBallotThreshold
|
return contractsStore.keysBallotThreshold
|
||||||
}
|
}
|
||||||
|
@ -346,9 +425,18 @@ export class BallotCard extends React.Component {
|
||||||
this.creator = votingState.creator
|
this.creator = votingState.creator
|
||||||
this.creatorMiningKey = votingState.creatorMiningKey
|
this.creatorMiningKey = votingState.creatorMiningKey
|
||||||
// getTotalVoters
|
// getTotalVoters
|
||||||
this.totalVoters = Number(votingState.totalVoters)
|
if (votingState.hasOwnProperty('totalVoters')) {
|
||||||
|
this.totalVoters = Number(votingState.totalVoters)
|
||||||
|
} else {
|
||||||
|
this.burnVotes = Number(votingState.burnVotes)
|
||||||
|
this.freezeVotes = Number(votingState.freezeVotes)
|
||||||
|
this.sendVotes = Number(votingState.sendVotes)
|
||||||
|
this.totalVoters = this.burnVotes + this.freezeVotes + this.sendVotes
|
||||||
|
}
|
||||||
// getProgress
|
// getProgress
|
||||||
this.progress = Number(votingState.progress)
|
if (votingState.hasOwnProperty('progress')) {
|
||||||
|
this.progress = Number(votingState.progress)
|
||||||
|
}
|
||||||
// getIsFinalized
|
// getIsFinalized
|
||||||
this.isFinalized = votingState.isFinalized
|
this.isFinalized = votingState.isFinalized
|
||||||
// canBeFinalizedNow
|
// canBeFinalizedNow
|
||||||
|
@ -397,6 +485,8 @@ export class BallotCard extends React.Component {
|
||||||
return 'Keys'
|
return 'Keys'
|
||||||
case 'votingToChangeProxy':
|
case 'votingToChangeProxy':
|
||||||
return 'Proxy'
|
return 'Proxy'
|
||||||
|
case 'votingToManageEmissionFunds':
|
||||||
|
return 'EmissionFunds'
|
||||||
default:
|
default:
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
@ -425,66 +515,25 @@ export class BallotCard extends React.Component {
|
||||||
) : (
|
) : (
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
return (
|
let votingScale
|
||||||
<div className={ballotClass}>
|
if (votingType === 'votingToManageEmissionFunds') {
|
||||||
<div className="ballots-about">
|
votingScale = (
|
||||||
<div className="ballots-about-i ballots-about-i_name">
|
<div className="ballots-i-scale">
|
||||||
<div className="ballots-about-td ballots-about-td-title">
|
|
||||||
<p className="ballots-about-i--title">Proposer</p>
|
|
||||||
</div>
|
|
||||||
<div className="ballots-about-td ballots-about-td-value">
|
|
||||||
<p className="ballots-i--name">{this.creator}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{children}
|
|
||||||
<div className="ballots-about-i ballots-about-i_time">
|
|
||||||
<div className="ballots-about-td ballots-about-td-title">
|
|
||||||
<p className="ballots-about-i--title">Ballot Time</p>
|
|
||||||
</div>
|
|
||||||
<div className="ballots-about-td ballots-about-td-value">
|
|
||||||
<p className="ballots-i--created">{this.startTime}</p>
|
|
||||||
<p className="ballots-i--time">
|
|
||||||
{this.timeTo.displayValue} ({this.timeTo.title})
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* TODO: Send / Burn / Freeze */}
|
|
||||||
{/* <div className="ballots-i-scale">
|
|
||||||
<div className="ballots-i-scale-column ballots-i-scale-column-3">
|
|
||||||
<button
|
|
||||||
className="btn btn-success ballots-i--vote_btn xl m-r-20"
|
|
||||||
onClick={e => this.vote({ choice: ACCEPT })}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
Send
|
|
||||||
</button>
|
|
||||||
<div className="vote-scale--container">
|
|
||||||
<p className="vote-scale--votes">{this.votesForNumber} Votes</p>
|
|
||||||
<p className="vote-scale--percentage">{this.votesForPercents}%</p>
|
|
||||||
<div className={voteScaleClass}>
|
|
||||||
<div
|
|
||||||
className="vote-scale--fill vote-scale--fill_send"
|
|
||||||
style={{ width: `${this.votesForPercents}%` }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="ballots-i-scale-column ballots-i-scale-column-3">
|
<div className="ballots-i-scale-column ballots-i-scale-column-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={e => this.vote({ choice: REJECT })}
|
onClick={e => this.vote({ choice: BURN })}
|
||||||
className="btn btn-danger ballots-i--vote_btn xl m-r-20"
|
className="btn btn-danger ballots-i--vote_btn xl m-r-20"
|
||||||
>
|
>
|
||||||
Burn
|
Burn
|
||||||
</button>
|
</button>
|
||||||
<div className="vote-scale--container">
|
<div className="vote-scale--container">
|
||||||
<p className="vote-scale--votes">{this.votesAgainstNumber} Votes</p>
|
<p className="vote-scale--votes">{this.votesBurnNumber} Votes</p>
|
||||||
<p className="vote-scale--percentage">{this.votesAgainstPercents}%</p>
|
<p className="vote-scale--percentage">{this.votesBurnPercents}%</p>
|
||||||
<div className={voteScaleClass}>
|
<div className={voteScaleClass}>
|
||||||
<div
|
<div
|
||||||
className="vote-scale--fill vote-scale--fill_burn"
|
className="vote-scale--fill vote-scale--fill_burn"
|
||||||
style={{ width: `${this.votesAgainstPercents}%` }}
|
style={{ width: `${this.votesBurnPercents}%` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -492,24 +541,45 @@ export class BallotCard extends React.Component {
|
||||||
<div className="ballots-i-scale-column ballots-i-scale-column-3">
|
<div className="ballots-i-scale-column ballots-i-scale-column-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={e => this.vote({ choice: REJECT })}
|
onClick={e => this.vote({ choice: FREEZE })}
|
||||||
className="btn btn-freeze ballots-i--vote_btn xl m-r-20"
|
className="btn btn-freeze ballots-i--vote_btn xl m-r-20"
|
||||||
>
|
>
|
||||||
Freeze
|
Freeze
|
||||||
</button>
|
</button>
|
||||||
<div className="vote-scale--container">
|
<div className="vote-scale--container">
|
||||||
<p className="vote-scale--votes">{this.votesAgainstNumber} Votes</p>
|
<p className="vote-scale--votes">{this.votesFreezeNumber} Votes</p>
|
||||||
<p className="vote-scale--percentage">{this.votesAgainstPercents}%</p>
|
<p className="vote-scale--percentage">{this.votesFreezePercents}%</p>
|
||||||
<div className={voteScaleClass}>
|
<div className={voteScaleClass}>
|
||||||
<div
|
<div
|
||||||
className="vote-scale--fill vote-scale--fill_freeze"
|
className="vote-scale--fill vote-scale--fill_freeze"
|
||||||
style={{ width: `${this.votesAgainstPercents}%` }}
|
style={{ width: `${this.votesFreezePercents}%` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> */}
|
<div className="ballots-i-scale-column ballots-i-scale-column-3">
|
||||||
{/* No / yes */}
|
<button
|
||||||
|
className="btn btn-success ballots-i--vote_btn xl m-r-20"
|
||||||
|
onClick={e => this.vote({ choice: SEND })}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</button>
|
||||||
|
<div className="vote-scale--container">
|
||||||
|
<p className="vote-scale--votes">{this.votesSendNumber} Votes</p>
|
||||||
|
<p className="vote-scale--percentage">{this.votesSendPercents}%</p>
|
||||||
|
<div className={voteScaleClass}>
|
||||||
|
<div
|
||||||
|
className="vote-scale--fill vote-scale--fill_send"
|
||||||
|
style={{ width: `${this.votesSendPercents}%` }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
votingScale = (
|
||||||
<div className="ballots-i-scale">
|
<div className="ballots-i-scale">
|
||||||
<div className="ballots-i-scale-column">
|
<div className="ballots-i-scale-column">
|
||||||
<button
|
<button
|
||||||
|
@ -547,6 +617,33 @@ export class BallotCard extends React.Component {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className={ballotClass}>
|
||||||
|
<div className="ballots-about">
|
||||||
|
<div className="ballots-about-i ballots-about-i_name">
|
||||||
|
<div className="ballots-about-td ballots-about-td-title">
|
||||||
|
<p className="ballots-about-i--title">Proposer</p>
|
||||||
|
</div>
|
||||||
|
<div className="ballots-about-td ballots-about-td-value">
|
||||||
|
<p className="ballots-i--name">{this.creator}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{children}
|
||||||
|
<div className="ballots-about-i ballots-about-i_time">
|
||||||
|
<div className="ballots-about-td ballots-about-td-title">
|
||||||
|
<p className="ballots-about-i--title">Ballot Time</p>
|
||||||
|
</div>
|
||||||
|
<div className="ballots-about-td ballots-about-td-value">
|
||||||
|
<p className="ballots-i--created">{this.startTime}</p>
|
||||||
|
<p className="ballots-i--time">
|
||||||
|
{this.timeTo.displayValue} ({this.timeTo.title})
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{votingScale}
|
||||||
<div className="info-container">
|
<div className="info-container">
|
||||||
<div className="info info-minimum">
|
<div className="info info-minimum">
|
||||||
Minimum {threshold} from {contractsStore.validatorsLength} validators are required to pass the proposal
|
Minimum {threshold} from {contractsStore.validatorsLength} validators are required to pass the proposal
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { inject, observer } from 'mobx-react'
|
||||||
|
import { BallotCard } from './BallotCard.jsx'
|
||||||
|
|
||||||
|
@inject('contractsStore')
|
||||||
|
@observer
|
||||||
|
export class BallotEmissionFundsCard extends React.Component {
|
||||||
|
render() {
|
||||||
|
let { id, votingState, pos, contractsStore } = this.props
|
||||||
|
const amount = contractsStore.web3Instance.fromWei(votingState.amount, 'ether')
|
||||||
|
return (
|
||||||
|
<BallotCard votingType="votingToManageEmissionFunds" votingState={votingState} id={id} pos={pos}>
|
||||||
|
<div className="ballots-about-i ballots-about-i_proposed_receiver">
|
||||||
|
<div className="ballots-about-td ballots-about-td-title">
|
||||||
|
<p className="ballots-about-i--title">Proposed Receiver</p>
|
||||||
|
</div>
|
||||||
|
<div className="ballots-about-td ballots-about-td-value">
|
||||||
|
<p>{votingState.receiver}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="ballots-about-i ballots-about-i_funds_amount">
|
||||||
|
<div className="ballots-about-td ballots-about-td-title">
|
||||||
|
<p className="ballots-about-i--title">Funds Amount</p>
|
||||||
|
</div>
|
||||||
|
<div className="ballots-about-td ballots-about-td-value">
|
||||||
|
<p>{amount} POA</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BallotCard>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { observable, action } from 'mobx'
|
||||||
|
import { inject, observer } from 'mobx-react'
|
||||||
|
import moment from 'moment'
|
||||||
|
|
||||||
|
@inject('ballotStore', 'contractsStore')
|
||||||
|
@observer
|
||||||
|
export class BallotEmissionFundsMetadata extends React.Component {
|
||||||
|
@observable emissionFundsBalance
|
||||||
|
@observable noActiveBallotExists
|
||||||
|
@observable beginDateTime
|
||||||
|
@observable endDateTime
|
||||||
|
|
||||||
|
@action('Get EmissionFunds balance')
|
||||||
|
getEmissionFundsBalance = async () => {
|
||||||
|
this.emissionFundsBalance = 'Loading...'
|
||||||
|
this.emissionFundsBalance = await this.props.contractsStore.emissionFunds.balance()
|
||||||
|
}
|
||||||
|
|
||||||
|
@action('Get VotingToManageEmissionFunds.noActiveBallotExists')
|
||||||
|
getNoActiveBallotExists = async () => {
|
||||||
|
this.noActiveBallotExists = await this.props.contractsStore.votingToManageEmissionFunds.noActiveBallotExists()
|
||||||
|
}
|
||||||
|
|
||||||
|
@action('Get beginDateTime and endDateTime')
|
||||||
|
getDateTimeLimits = async () => {
|
||||||
|
const { votingToManageEmissionFunds } = this.props.contractsStore
|
||||||
|
const dateTimeFormat = 'MM/DD/YYYY HH:mm'
|
||||||
|
|
||||||
|
this.beginDateTime = '...loading date...'
|
||||||
|
this.endDateTime = '...loading date...'
|
||||||
|
|
||||||
|
let emissionReleaseTime = Number(await votingToManageEmissionFunds.emissionReleaseTime())
|
||||||
|
let emissionReleaseThreshold = 0
|
||||||
|
const currentTime = Number(await votingToManageEmissionFunds.getTime())
|
||||||
|
const distributionThreshold = Number(await votingToManageEmissionFunds.distributionThreshold())
|
||||||
|
if (currentTime > emissionReleaseTime) {
|
||||||
|
emissionReleaseThreshold = Number(await votingToManageEmissionFunds.emissionReleaseThreshold())
|
||||||
|
const diff = Math.floor((currentTime - emissionReleaseTime) / emissionReleaseThreshold)
|
||||||
|
if (diff > 0) {
|
||||||
|
emissionReleaseTime += emissionReleaseThreshold * diff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const releasePlusDistribution = emissionReleaseTime + distributionThreshold
|
||||||
|
|
||||||
|
if (currentTime < releasePlusDistribution) {
|
||||||
|
this.beginDateTime = moment.unix(emissionReleaseTime).format(dateTimeFormat)
|
||||||
|
this.endDateTime = moment.unix(releasePlusDistribution).format(dateTimeFormat)
|
||||||
|
} else {
|
||||||
|
if (emissionReleaseThreshold === 0) {
|
||||||
|
emissionReleaseThreshold = Number(await votingToManageEmissionFunds.emissionReleaseThreshold())
|
||||||
|
}
|
||||||
|
const futureEmissionReleaseTime = emissionReleaseTime + emissionReleaseThreshold
|
||||||
|
this.beginDateTime = moment.unix(futureEmissionReleaseTime).format(dateTimeFormat)
|
||||||
|
this.endDateTime = moment.unix(futureEmissionReleaseTime + distributionThreshold).format(dateTimeFormat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
this.getEmissionFundsBalance()
|
||||||
|
this.getNoActiveBallotExists()
|
||||||
|
this.getDateTimeLimits()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { ballotStore, contractsStore } = this.props
|
||||||
|
let note, explorerLink
|
||||||
|
if (this.noActiveBallotExists === true) {
|
||||||
|
note = (
|
||||||
|
<p>
|
||||||
|
The ballot can be created starting from <b>{this.beginDateTime}</b> and will end on <b>{this.endDateTime}</b>.
|
||||||
|
</p>
|
||||||
|
)
|
||||||
|
} else if (this.noActiveBallotExists !== true) {
|
||||||
|
note = <p>To be able to create a new ballot, the previous ballot of this type must be finalized.</p>
|
||||||
|
}
|
||||||
|
if (contractsStore.netId === '77') {
|
||||||
|
explorerLink = `https://sokol-explorer.poa.network/account/${contractsStore.emissionFunds.address}`
|
||||||
|
} else {
|
||||||
|
explorerLink = `https://poaexplorer.com/address/${contractsStore.emissionFunds.address}`
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="hidden">
|
||||||
|
<div className="left">
|
||||||
|
<div className="form-el">
|
||||||
|
<label htmlFor="receiver">Address of funds receiver</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="receiver"
|
||||||
|
value={ballotStore.ballotEmissionFunds.receiver}
|
||||||
|
onChange={e => ballotStore.changeBallotMetadata(e, 'receiver', 'ballotEmissionFunds')}
|
||||||
|
/>
|
||||||
|
<p className="hint">
|
||||||
|
The address to which the funds will be sent if `Send` operation obtains the majority of votes.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="right">
|
||||||
|
<div className="form-el">
|
||||||
|
<label htmlFor="amount">Current amount of funds</label>
|
||||||
|
<input type="text" id="amount" value={this.emissionFundsBalance} disabled="disabled" />
|
||||||
|
<p className="hint">
|
||||||
|
Current balance of
|
||||||
|
<a href={explorerLink} target="_blank">
|
||||||
|
EmissionFunds contract
|
||||||
|
</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
{note}
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,23 +63,6 @@ export class BallotKeysCard extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{miningKeyDiv}
|
{miningKeyDiv}
|
||||||
{/* TODO: New ballot type */}
|
|
||||||
{/* <div className="ballots-about-i ballots-about-i_proposed_receiver">
|
|
||||||
<div className="ballots-about-td ballots-about-td-title">
|
|
||||||
<p className="ballots-about-i--title">Proposed Receiver</p>
|
|
||||||
</div>
|
|
||||||
<div className="ballots-about-td ballots-about-td-value">
|
|
||||||
<p>0x4432c441EE96ef387CEC496709967Be6E27f57C8</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="ballots-about-i ballots-about-i_funds_amount">
|
|
||||||
<div className="ballots-about-td ballots-about-td-title">
|
|
||||||
<p className="ballots-about-i--title">Funds Amount</p>
|
|
||||||
</div>
|
|
||||||
<div className="ballots-about-td ballots-about-td-value">
|
|
||||||
<p>10000 POA</p>
|
|
||||||
</div>
|
|
||||||
</div> */}
|
|
||||||
</BallotCard>
|
</BallotCard>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,14 @@ export class Ballots extends React.Component {
|
||||||
) {
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
} else if (contractType === ballotStore.BallotType.emissionFunds) {
|
||||||
|
if (
|
||||||
|
String(votingState.receiver)
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(searchTerm)
|
||||||
|
) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ballotCards.splice(i--, 1)
|
ballotCards.splice(i--, 1)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { KeysTypes } from './KeysTypes.jsx'
|
||||||
import { BallotKeysMetadata } from './BallotKeysMetadata.jsx'
|
import { BallotKeysMetadata } from './BallotKeysMetadata.jsx'
|
||||||
import { BallotMinThresholdMetadata } from './BallotMinThresholdMetadata.jsx'
|
import { BallotMinThresholdMetadata } from './BallotMinThresholdMetadata.jsx'
|
||||||
import { BallotProxyMetadata } from './BallotProxyMetadata.jsx'
|
import { BallotProxyMetadata } from './BallotProxyMetadata.jsx'
|
||||||
|
import { BallotEmissionFundsMetadata } from './BallotEmissionFundsMetadata.jsx'
|
||||||
import { messages } from '../messages'
|
import { messages } from '../messages'
|
||||||
import { constants } from '../constants'
|
import { constants } from '../constants'
|
||||||
import { sendTransactionByVotingKey } from '../helpers'
|
import { sendTransactionByVotingKey } from '../helpers'
|
||||||
|
@ -44,40 +45,42 @@ export class NewBallot extends React.Component {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const minBallotDurationInHours = constants.minBallotDurationInDays * 24
|
if (!ballotStore.isBallotForEmissionFunds) {
|
||||||
const startTime = this.getStartTimeUnix()
|
const minBallotDurationInHours = constants.minBallotDurationInDays * 24
|
||||||
const minEndTime = moment
|
const startTime = this.getStartTimeUnix()
|
||||||
.utc()
|
const minEndTime = moment
|
||||||
.add(minBallotDurationInHours, 'hours')
|
.utc()
|
||||||
.format()
|
.add(minBallotDurationInHours, 'hours')
|
||||||
let neededMinutes = moment(minEndTime).diff(moment(ballotStore.endTime), 'minutes')
|
.format()
|
||||||
let neededHours = Math.floor(neededMinutes / 60)
|
let neededMinutes = moment(minEndTime).diff(moment(ballotStore.endTime), 'minutes')
|
||||||
let duration = moment.unix(ballotStore.endTimeUnix).diff(moment.unix(startTime), 'hours')
|
let neededHours = Math.floor(neededMinutes / 60)
|
||||||
|
let duration = moment.unix(ballotStore.endTimeUnix).diff(moment.unix(startTime), 'hours')
|
||||||
|
|
||||||
if (duration < 0) {
|
if (duration < 0) {
|
||||||
duration = 0
|
duration = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if (neededMinutes > 0) {
|
if (neededMinutes > 0) {
|
||||||
neededMinutes = Math.abs(neededHours * 60 - neededMinutes)
|
neededMinutes = Math.abs(neededHours * 60 - neededMinutes)
|
||||||
swal(
|
swal(
|
||||||
'Warning!',
|
'Warning!',
|
||||||
messages.SHOULD_BE_MORE_THAN_MIN_DURATION(minBallotDurationInHours, duration, neededHours, neededMinutes),
|
messages.SHOULD_BE_MORE_THAN_MIN_DURATION(minBallotDurationInHours, duration, neededHours, neededMinutes),
|
||||||
'warning'
|
'warning'
|
||||||
)
|
)
|
||||||
commonStore.hideLoading()
|
commonStore.hideLoading()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const twoWeeks = moment
|
const twoWeeks = moment
|
||||||
.utc()
|
.utc()
|
||||||
.add(14, 'days')
|
.add(14, 'days')
|
||||||
.format()
|
.format()
|
||||||
let exceededMinutes = moment(ballotStore.endTime).diff(moment(twoWeeks), 'minutes')
|
let exceededMinutes = moment(ballotStore.endTime).diff(moment(twoWeeks), 'minutes')
|
||||||
if (exceededMinutes > 0) {
|
if (exceededMinutes > 0) {
|
||||||
swal('Warning!', messages.SHOULD_BE_LESS_OR_EQUAL_14_DAYS(duration), 'warning')
|
swal('Warning!', messages.SHOULD_BE_LESS_OR_EQUAL_14_DAYS(duration), 'warning')
|
||||||
commonStore.hideLoading()
|
commonStore.hideLoading()
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ballotStore.isBallotForKey) {
|
if (ballotStore.isBallotForKey) {
|
||||||
|
@ -132,7 +135,7 @@ export class NewBallot extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let isAddress = contractsStore.web3Instance.isAddress(ballotStore.ballotProxy.proposedAddress)
|
const isAddress = contractsStore.web3Instance.isAddress(ballotStore.ballotProxy.proposedAddress)
|
||||||
|
|
||||||
if (!isAddress) {
|
if (!isAddress) {
|
||||||
swal('Warning!', messages.PROPOSED_ADDRESS_IS_NOT_ADDRESS_MSG, 'warning')
|
swal('Warning!', messages.PROPOSED_ADDRESS_IS_NOT_ADDRESS_MSG, 'warning')
|
||||||
|
@ -141,7 +144,28 @@ export class NewBallot extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ballotStore.isBallotForKey && !ballotStore.isBallotForMinThreshold && !ballotStore.isBallotForProxy) {
|
if (ballotStore.isBallotForEmissionFunds) {
|
||||||
|
if (ballotStore.ballotEmissionFunds.receiver.length === 0) {
|
||||||
|
swal('Warning!', `Address of funds receiver is empty`, 'warning')
|
||||||
|
commonStore.hideLoading()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAddress = contractsStore.web3Instance.isAddress(ballotStore.ballotEmissionFunds.receiver)
|
||||||
|
|
||||||
|
if (!isAddress) {
|
||||||
|
swal('Warning!', messages.PROPOSED_ADDRESS_IS_NOT_ADDRESS_MSG, 'warning')
|
||||||
|
commonStore.hideLoading()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!ballotStore.isBallotForKey &&
|
||||||
|
!ballotStore.isBallotForMinThreshold &&
|
||||||
|
!ballotStore.isBallotForProxy &&
|
||||||
|
!ballotStore.isBallotForEmissionFunds
|
||||||
|
) {
|
||||||
swal('Warning!', messages.BALLOT_TYPE_IS_EMPTY_MSG, 'warning')
|
swal('Warning!', messages.BALLOT_TYPE_IS_EMPTY_MSG, 'warning')
|
||||||
commonStore.hideLoading()
|
commonStore.hideLoading()
|
||||||
return false
|
return false
|
||||||
|
@ -150,11 +174,11 @@ export class NewBallot extends React.Component {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
createBallotForKeys = startTime => {
|
createBallotForKeys = (startTime, endTime) => {
|
||||||
const { ballotStore, contractsStore } = this.props
|
const { ballotStore, contractsStore } = this.props
|
||||||
const inputToMethod = {
|
const inputToMethod = {
|
||||||
startTime: startTime,
|
startTime: startTime,
|
||||||
endTime: ballotStore.endTimeUnix,
|
endTime: endTime,
|
||||||
affectedKey: ballotStore.ballotKeys.affectedKey,
|
affectedKey: ballotStore.ballotKeys.affectedKey,
|
||||||
affectedKeyType: ballotStore.ballotKeys.keyType,
|
affectedKeyType: ballotStore.ballotKeys.keyType,
|
||||||
newVotingKey: ballotStore.ballotKeys.newVotingKey,
|
newVotingKey: ballotStore.ballotKeys.newVotingKey,
|
||||||
|
@ -176,22 +200,22 @@ export class NewBallot extends React.Component {
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
createBallotForMinThreshold = startTime => {
|
createBallotForMinThreshold = (startTime, endTime) => {
|
||||||
const { ballotStore, contractsStore } = this.props
|
const { ballotStore, contractsStore } = this.props
|
||||||
const inputToMethod = {
|
const inputToMethod = {
|
||||||
startTime: startTime,
|
startTime: startTime,
|
||||||
endTime: ballotStore.endTimeUnix,
|
endTime: endTime,
|
||||||
proposedValue: ballotStore.ballotMinThreshold.proposedValue,
|
proposedValue: ballotStore.ballotMinThreshold.proposedValue,
|
||||||
memo: ballotStore.memo
|
memo: ballotStore.memo
|
||||||
}
|
}
|
||||||
return contractsStore.votingToChangeMinThreshold.createBallot(inputToMethod)
|
return contractsStore.votingToChangeMinThreshold.createBallot(inputToMethod)
|
||||||
}
|
}
|
||||||
|
|
||||||
createBallotForProxy = startTime => {
|
createBallotForProxy = (startTime, endTime) => {
|
||||||
const { ballotStore, contractsStore } = this.props
|
const { ballotStore, contractsStore } = this.props
|
||||||
const inputToMethod = {
|
const inputToMethod = {
|
||||||
startTime: startTime,
|
startTime: startTime,
|
||||||
endTime: ballotStore.endTimeUnix,
|
endTime: endTime,
|
||||||
proposedValue: ballotStore.ballotProxy.proposedAddress,
|
proposedValue: ballotStore.ballotProxy.proposedAddress,
|
||||||
contractType: ballotStore.ballotProxy.contractType,
|
contractType: ballotStore.ballotProxy.contractType,
|
||||||
memo: ballotStore.memo
|
memo: ballotStore.memo
|
||||||
|
@ -199,6 +223,17 @@ export class NewBallot extends React.Component {
|
||||||
return contractsStore.votingToChangeProxy.createBallot(inputToMethod)
|
return contractsStore.votingToChangeProxy.createBallot(inputToMethod)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createBallotForEmissionFunds = (startTime, endTime) => {
|
||||||
|
const { ballotStore, contractsStore } = this.props
|
||||||
|
const inputToMethod = {
|
||||||
|
startTime: startTime,
|
||||||
|
endTime: endTime,
|
||||||
|
receiver: ballotStore.ballotEmissionFunds.receiver,
|
||||||
|
memo: ballotStore.memo
|
||||||
|
}
|
||||||
|
return contractsStore.votingToManageEmissionFunds.createBallot(inputToMethod)
|
||||||
|
}
|
||||||
|
|
||||||
onClick = async () => {
|
onClick = async () => {
|
||||||
const { commonStore, contractsStore, ballotStore, ballotsStore } = this.props
|
const { commonStore, contractsStore, ballotStore, ballotsStore } = this.props
|
||||||
const { push } = this.props.routing
|
const { push } = this.props.routing
|
||||||
|
@ -240,6 +275,42 @@ export class NewBallot extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let startTime = this.getStartTimeUnix()
|
||||||
|
let endTime = ballotStore.endTimeUnix
|
||||||
|
|
||||||
|
if (ballotStore.ballotType === ballotStore.BallotType.emissionFunds) {
|
||||||
|
const votingContract = contractsStore.votingToManageEmissionFunds
|
||||||
|
let emissionReleaseTime = Number(await votingContract.emissionReleaseTime())
|
||||||
|
const currentTime = Number(await votingContract.getTime())
|
||||||
|
if (currentTime > emissionReleaseTime) {
|
||||||
|
const emissionReleaseThreshold = Number(await votingContract.emissionReleaseThreshold())
|
||||||
|
const diff = Math.floor((currentTime - emissionReleaseTime) / emissionReleaseThreshold)
|
||||||
|
if (diff > 0) {
|
||||||
|
emissionReleaseTime += emissionReleaseThreshold * diff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTime < emissionReleaseTime) {
|
||||||
|
const emissionReleaseTimeString = moment
|
||||||
|
.unix(emissionReleaseTime)
|
||||||
|
.utc()
|
||||||
|
.format('MMM Do YYYY, h:mm:ss a')
|
||||||
|
swal('Warning!', messages.EMISSION_RELEASE_TIME_IN_FUTURE(emissionReleaseTimeString), 'warning')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const noActiveBallotExists = await votingContract.noActiveBallotExists()
|
||||||
|
if (!noActiveBallotExists) {
|
||||||
|
swal('Warning!', messages.PREVIOUS_BALLOT_NOT_FINALIZED, 'warning')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const distributionThreshold = Number(await votingContract.distributionThreshold())
|
||||||
|
|
||||||
|
startTime = currentTime + constants.startTimeOffsetInMinutes * 60
|
||||||
|
endTime = emissionReleaseTime + distributionThreshold
|
||||||
|
}
|
||||||
|
|
||||||
let methodToCreateBallot
|
let methodToCreateBallot
|
||||||
let contractType
|
let contractType
|
||||||
let contractInstance
|
let contractInstance
|
||||||
|
@ -259,16 +330,19 @@ export class NewBallot extends React.Component {
|
||||||
contractType = 'votingToChangeProxy'
|
contractType = 'votingToChangeProxy'
|
||||||
contractInstance = contractsStore.votingToChangeProxy.votingToChangeProxyInstance
|
contractInstance = contractsStore.votingToChangeProxy.votingToChangeProxyInstance
|
||||||
break
|
break
|
||||||
|
case ballotStore.BallotType.emissionFunds:
|
||||||
|
methodToCreateBallot = this.createBallotForEmissionFunds
|
||||||
|
contractType = 'votingToManageEmissionFunds'
|
||||||
|
contractInstance = contractsStore.votingToManageEmissionFunds.instance
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
const startTime = this.getStartTimeUnix()
|
|
||||||
|
|
||||||
sendTransactionByVotingKey(
|
sendTransactionByVotingKey(
|
||||||
this.props,
|
this.props,
|
||||||
contractInstance.options.address,
|
contractInstance.options.address,
|
||||||
methodToCreateBallot(startTime),
|
methodToCreateBallot(startTime, endTime),
|
||||||
async tx => {
|
async tx => {
|
||||||
const events = await contractInstance.getPastEvents('BallotCreated', {
|
const events = await contractInstance.getPastEvents('BallotCreated', {
|
||||||
fromBlock: tx.blockNumber,
|
fromBlock: tx.blockNumber,
|
||||||
|
@ -322,9 +396,23 @@ export class NewBallot extends React.Component {
|
||||||
metadata = <BallotProxyMetadata />
|
metadata = <BallotProxyMetadata />
|
||||||
minThreshold = contractsStore.proxyBallotThreshold
|
minThreshold = contractsStore.proxyBallotThreshold
|
||||||
break
|
break
|
||||||
|
case ballotStore.BallotType.emissionFunds:
|
||||||
|
metadata = <BallotEmissionFundsMetadata />
|
||||||
|
minThreshold = contractsStore.emissionFundsBallotThreshold
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
const emissionFundsManagementBallot = contractsStore.votingToManageEmissionFunds ? (
|
||||||
|
<div
|
||||||
|
className={this.menuItemActive(ballotStore.BallotType.emissionFunds)}
|
||||||
|
onClick={e => ballotStore.changeBallotType(e, ballotStore.BallotType.emissionFunds)}
|
||||||
|
>
|
||||||
|
Emission Funds Ballot
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)
|
||||||
return (
|
return (
|
||||||
<section className="container new">
|
<section className="container new">
|
||||||
<form action="" className="new-form">
|
<form action="" className="new-form">
|
||||||
|
@ -348,12 +436,13 @@ export class NewBallot extends React.Component {
|
||||||
>
|
>
|
||||||
Modify Proxy Contract Ballot
|
Modify Proxy Contract Ballot
|
||||||
</div>
|
</div>
|
||||||
|
{emissionFundsManagementBallot}
|
||||||
</div>
|
</div>
|
||||||
<div className="info">
|
<div className="info">
|
||||||
<p className="info-title">Information of the ballot</p>
|
<p className="info-title">Limits of the ballot</p>
|
||||||
<div className="info-i">
|
<div className="info-i">
|
||||||
Minimum {minThreshold} from {contractsStore.validatorsLength}
|
Minimum {minThreshold} from {contractsStore.validatorsLength} validators are required to pass the
|
||||||
validators are required to pass the proposal<br />
|
proposal<br />
|
||||||
</div>
|
</div>
|
||||||
<div className="info-i">
|
<div className="info-i">
|
||||||
You can create {contractsStore.validatorLimits.keys} ballot(s) for keys<br />
|
You can create {contractsStore.validatorLimits.keys} ballot(s) for keys<br />
|
||||||
|
|
|
@ -6,11 +6,13 @@ constants.ABIsSources = {
|
||||||
KeysManager: 'KeysManager.abi.json',
|
KeysManager: 'KeysManager.abi.json',
|
||||||
PoaNetworkConsensus: 'PoaNetworkConsensus.abi.json',
|
PoaNetworkConsensus: 'PoaNetworkConsensus.abi.json',
|
||||||
BallotStorage: 'BallotsStorage.abi.json',
|
BallotStorage: 'BallotsStorage.abi.json',
|
||||||
|
EmissionFunds: 'EmissionFunds.abi.json',
|
||||||
ProxyStorage: 'ProxyStorage.abi.json',
|
ProxyStorage: 'ProxyStorage.abi.json',
|
||||||
ValidatorMetadata: 'ValidatorMetadata.abi.json',
|
ValidatorMetadata: 'ValidatorMetadata.abi.json',
|
||||||
VotingToChangeKeys: 'VotingToChangeKeys.abi.json',
|
VotingToChangeKeys: 'VotingToChangeKeys.abi.json',
|
||||||
VotingToChangeMinThreshold: 'VotingToChangeMinThreshold.abi.json',
|
VotingToChangeMinThreshold: 'VotingToChangeMinThreshold.abi.json',
|
||||||
VotingToChangeProxyAddress: 'VotingToChangeProxyAddress.abi.json'
|
VotingToChangeProxyAddress: 'VotingToChangeProxyAddress.abi.json',
|
||||||
|
VotingToManageEmissionFunds: 'VotingToManageEmissionFunds.abi.json'
|
||||||
}
|
}
|
||||||
constants.NEW_MINING_KEY = {
|
constants.NEW_MINING_KEY = {
|
||||||
label: 'New Mining Key',
|
label: 'New Mining Key',
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import Web3 from 'web3'
|
||||||
|
import { networkAddresses } from './addresses'
|
||||||
|
|
||||||
|
export default class EmissionFunds {
|
||||||
|
async init({ web3, netId }) {
|
||||||
|
const { EMISSION_FUNDS_ADDRESS } = networkAddresses(netId)
|
||||||
|
console.log('EmissionFunds address', EMISSION_FUNDS_ADDRESS)
|
||||||
|
this.web3_10 = new Web3(web3.currentProvider)
|
||||||
|
this.address = EMISSION_FUNDS_ADDRESS
|
||||||
|
}
|
||||||
|
|
||||||
|
balance() {
|
||||||
|
return this.web3_10.eth.getBalance(this.address)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
import Web3 from 'web3'
|
||||||
|
import { networkAddresses } from './addresses'
|
||||||
|
import helpers from './helpers'
|
||||||
|
|
||||||
|
export default class VotingToManageEmissionFunds {
|
||||||
|
async init({ web3, netId }) {
|
||||||
|
const { VOTING_TO_MANAGE_EMISSION_FUNDS_ADDRESS } = networkAddresses(netId)
|
||||||
|
console.log('VotingToManageEmissionFunds address', VOTING_TO_MANAGE_EMISSION_FUNDS_ADDRESS)
|
||||||
|
const web3_10 = new Web3(web3.currentProvider)
|
||||||
|
|
||||||
|
const branch = helpers.getBranch(netId)
|
||||||
|
|
||||||
|
const votingToManageEmissionFundsABI = await helpers.getABI(branch, 'VotingToManageEmissionFunds')
|
||||||
|
|
||||||
|
this.instance = new web3_10.eth.Contract(votingToManageEmissionFundsABI, VOTING_TO_MANAGE_EMISSION_FUNDS_ADDRESS)
|
||||||
|
this.address = VOTING_TO_MANAGE_EMISSION_FUNDS_ADDRESS
|
||||||
|
}
|
||||||
|
|
||||||
|
// setters
|
||||||
|
cancelNewBallot() {
|
||||||
|
return this.instance.methods.cancelNewBallot().encodeABI()
|
||||||
|
}
|
||||||
|
|
||||||
|
createBallot({ startTime, endTime, receiver, memo }) {
|
||||||
|
return this.instance.methods.createBallot(startTime, endTime, receiver, memo).encodeABI()
|
||||||
|
}
|
||||||
|
|
||||||
|
finalize(_id) {
|
||||||
|
return this.instance.methods.finalize(_id).encodeABI()
|
||||||
|
}
|
||||||
|
|
||||||
|
vote(_id, choice) {
|
||||||
|
return this.instance.methods.vote(_id, choice).encodeABI()
|
||||||
|
}
|
||||||
|
|
||||||
|
// getters
|
||||||
|
ballotCancelingThreshold() {
|
||||||
|
return this.instance.methods.ballotCancelingThreshold().call()
|
||||||
|
}
|
||||||
|
|
||||||
|
canBeFinalizedNow(_id) {
|
||||||
|
return this.instance.methods.canBeFinalizedNow(_id).call()
|
||||||
|
}
|
||||||
|
|
||||||
|
distributionThreshold() {
|
||||||
|
return this.instance.methods.distributionThreshold().call()
|
||||||
|
}
|
||||||
|
|
||||||
|
emissionReleaseThreshold() {
|
||||||
|
return this.instance.methods.emissionReleaseThreshold().call()
|
||||||
|
}
|
||||||
|
|
||||||
|
emissionReleaseTime() {
|
||||||
|
return this.instance.methods.emissionReleaseTime().call()
|
||||||
|
}
|
||||||
|
|
||||||
|
getBallotInfo(_id, _votingKey) {
|
||||||
|
return this.instance.methods.getBallotInfo(_id).call()
|
||||||
|
}
|
||||||
|
|
||||||
|
getTime() {
|
||||||
|
return this.instance.methods.getTime().call()
|
||||||
|
}
|
||||||
|
|
||||||
|
hasAlreadyVoted(_id, _votingKey) {
|
||||||
|
return this.instance.methods.hasAlreadyVoted(_id, _votingKey).call()
|
||||||
|
}
|
||||||
|
|
||||||
|
isActive(_id) {
|
||||||
|
return this.instance.methods.isActive(_id).call()
|
||||||
|
}
|
||||||
|
|
||||||
|
isValidVote(_id, _votingKey) {
|
||||||
|
return this.instance.methods.isValidVote(_id, _votingKey).call()
|
||||||
|
}
|
||||||
|
|
||||||
|
nextBallotId() {
|
||||||
|
return this.instance.methods.nextBallotId().call()
|
||||||
|
}
|
||||||
|
|
||||||
|
noActiveBallotExists() {
|
||||||
|
return this.instance.methods.noActiveBallotExists().call()
|
||||||
|
}
|
||||||
|
}
|
13
src/index.js
13
src/index.js
|
@ -49,7 +49,7 @@ class AppMainRouter extends Component {
|
||||||
let setVotingToChangeProxy = contractsStore.setVotingToChangeProxy(web3Config)
|
let setVotingToChangeProxy = contractsStore.setVotingToChangeProxy(web3Config)
|
||||||
let setValidatorMetadata = contractsStore.setValidatorMetadata(web3Config)
|
let setValidatorMetadata = contractsStore.setValidatorMetadata(web3Config)
|
||||||
|
|
||||||
await Promise.all([
|
let promises = [
|
||||||
setPoaConsensus,
|
setPoaConsensus,
|
||||||
setBallotsStorage,
|
setBallotsStorage,
|
||||||
setKeysManager,
|
setKeysManager,
|
||||||
|
@ -58,7 +58,15 @@ class AppMainRouter extends Component {
|
||||||
setVotingToChangeMinThreshold,
|
setVotingToChangeMinThreshold,
|
||||||
setVotingToChangeProxy,
|
setVotingToChangeProxy,
|
||||||
setValidatorMetadata
|
setValidatorMetadata
|
||||||
])
|
]
|
||||||
|
|
||||||
|
if (web3Config.netId === '77') {
|
||||||
|
// if we're in Sokol
|
||||||
|
promises.push(contractsStore.setEmissionFunds(web3Config))
|
||||||
|
promises.push(contractsStore.setVotingToManageEmissionFunds(web3Config))
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises)
|
||||||
|
|
||||||
await contractsStore.setMiningKey(web3Config)
|
await contractsStore.setMiningKey(web3Config)
|
||||||
await contractsStore.setVotingKey(web3Config)
|
await contractsStore.setVotingKey(web3Config)
|
||||||
|
@ -67,7 +75,6 @@ class AppMainRouter extends Component {
|
||||||
await contractsStore.getAllBallots()
|
await contractsStore.getAllBallots()
|
||||||
|
|
||||||
contractsStore.getKeysBallotThreshold()
|
contractsStore.getKeysBallotThreshold()
|
||||||
contractsStore.getMinThresholdBallotThreshold()
|
|
||||||
contractsStore.getProxyBallotThreshold()
|
contractsStore.getProxyBallotThreshold()
|
||||||
contractsStore.getBallotsLimits()
|
contractsStore.getBallotsLimits()
|
||||||
console.log('votingKey', contractsStore.votingKey)
|
console.log('votingKey', contractsStore.votingKey)
|
||||||
|
|
|
@ -10,7 +10,7 @@ messages.INVALID_VOTE_MSG = "You can't vote on this ballot"
|
||||||
messages.INVALID_FINALIZE_MSG = "You can't finalize this ballot"
|
messages.INVALID_FINALIZE_MSG = "You can't finalize this ballot"
|
||||||
messages.AFFECTED_KEY_IS_NOT_ADDRESS_MSG = "Ballot affectedKey isn't address"
|
messages.AFFECTED_KEY_IS_NOT_ADDRESS_MSG = "Ballot affectedKey isn't address"
|
||||||
messages.MINING_KEY_IS_NOT_ADDRESS_MSG = "Ballot miningKey isn't address"
|
messages.MINING_KEY_IS_NOT_ADDRESS_MSG = "Ballot miningKey isn't address"
|
||||||
messages.PROPOSED_ADDRESS_IS_NOT_ADDRESS_MSG = "Ballot proposedAddress isn't address"
|
messages.PROPOSED_ADDRESS_IS_NOT_ADDRESS_MSG = "Proposed address isn't address"
|
||||||
messages.END_TIME_SHOULD_BE_GREATER_THAN_NOW_MSG = 'Ballot end time should be greater than now'
|
messages.END_TIME_SHOULD_BE_GREATER_THAN_NOW_MSG = 'Ballot end time should be greater than now'
|
||||||
messages.BALLOT_TYPE_IS_EMPTY_MSG = 'Ballot type is empty'
|
messages.BALLOT_TYPE_IS_EMPTY_MSG = 'Ballot type is empty'
|
||||||
messages.NO_METAMASK_MSG = `You haven't chosen any account in MetaMask.
|
messages.NO_METAMASK_MSG = `You haven't chosen any account in MetaMask.
|
||||||
|
@ -30,6 +30,10 @@ messages.SHOULD_BE_MORE_THAN_MIN_DURATION = (minDuration, duration, neededHours,
|
||||||
messages.SHOULD_BE_LESS_OR_EQUAL_14_DAYS = duration => {
|
messages.SHOULD_BE_LESS_OR_EQUAL_14_DAYS = duration => {
|
||||||
return `Ballot end time should not be more than 14 days from now in UTC time. Current duration is ${duration} hours.`
|
return `Ballot end time should not be more than 14 days from now in UTC time. Current duration is ${duration} hours.`
|
||||||
}
|
}
|
||||||
|
messages.EMISSION_RELEASE_TIME_IN_FUTURE = emissionReleaseTime => {
|
||||||
|
return `You cannot create ballot right now. You'll be able to do that after ${emissionReleaseTime} UTC.`
|
||||||
|
}
|
||||||
|
messages.PREVIOUS_BALLOT_NOT_FINALIZED = 'Previous ballot should be finalized first.'
|
||||||
messages.BALLOT_CREATE_FAILED_TX = `Your transaction was failed. Please make sure you set correct parameters for ballot creation.
|
messages.BALLOT_CREATE_FAILED_TX = `Your transaction was failed. Please make sure you set correct parameters for ballot creation.
|
||||||
Make sure you don't have Transaction Error. Exception thrown in contract code message in Metamask before you sign it.`
|
Make sure you don't have Transaction Error. Exception thrown in contract code message in Metamask before you sign it.`
|
||||||
messages.VOTE_FAILED_TX = `Your transaction was failed. Please make sure you haven't already voted for this ballot.
|
messages.VOTE_FAILED_TX = `Your transaction was failed. Please make sure you haven't already voted for this ballot.
|
||||||
|
|
|
@ -6,7 +6,8 @@ class BallotStore {
|
||||||
BallotType = {
|
BallotType = {
|
||||||
keys: 1,
|
keys: 1,
|
||||||
minThreshold: 2,
|
minThreshold: 2,
|
||||||
proxy: 3
|
proxy: 3,
|
||||||
|
emissionFunds: 4
|
||||||
}
|
}
|
||||||
KeysBallotType = {
|
KeysBallotType = {
|
||||||
add: 1,
|
add: 1,
|
||||||
|
@ -34,6 +35,8 @@ class BallotStore {
|
||||||
@observable ballotKeys
|
@observable ballotKeys
|
||||||
@observable ballotMinThreshold
|
@observable ballotMinThreshold
|
||||||
@observable ballotProxy
|
@observable ballotProxy
|
||||||
|
@observable ballotEmissionFunds
|
||||||
|
|
||||||
@observable memo
|
@observable memo
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -59,6 +62,11 @@ class BallotStore {
|
||||||
proposedAddress: '',
|
proposedAddress: '',
|
||||||
contractType: ''
|
contractType: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.ballotEmissionFunds = {
|
||||||
|
receiver: ''
|
||||||
|
}
|
||||||
|
|
||||||
this.memo = ''
|
this.memo = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +91,11 @@ class BallotStore {
|
||||||
return this.ballotType === this.BallotType.proxy
|
return this.ballotType === this.BallotType.proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
get isBallotForEmissionFunds() {
|
||||||
|
return this.ballotType === this.BallotType.emissionFunds
|
||||||
|
}
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
get isAddKeysBallotType() {
|
get isAddKeysBallotType() {
|
||||||
return this.ballotKeys.keysBallotType === this.KeysBallotType.add
|
return this.ballotKeys.keysBallotType === this.KeysBallotType.add
|
||||||
|
|
|
@ -1,21 +1,9 @@
|
||||||
import { observable } from 'mobx'
|
import { observable } from 'mobx'
|
||||||
|
|
||||||
class BallotsStore {
|
class BallotsStore {
|
||||||
@observable activeKeysBallotsLength
|
|
||||||
@observable activeMinThresholdBallotsLength
|
|
||||||
@observable activeProxyBallotsLength
|
|
||||||
@observable ballotCards
|
@observable ballotCards
|
||||||
|
|
||||||
@observable activeMinThresholdBallotsIDs
|
|
||||||
@observable activeProxyBallotsIDs
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.activeKeysBallotsLength = 0
|
|
||||||
this.activeMinThresholdBallotsLength = 0
|
|
||||||
this.activeProxyBallotsLength = 0
|
|
||||||
|
|
||||||
this.activeMinThresholdBallotsIDs = []
|
|
||||||
this.activeProxyBallotsIDs = []
|
|
||||||
this.ballotCards = []
|
this.ballotCards = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,13 @@ import React from 'react'
|
||||||
|
|
||||||
import PoaConsensus from '../contracts/PoaConsensus.contract'
|
import PoaConsensus from '../contracts/PoaConsensus.contract'
|
||||||
import BallotsStorage from '../contracts/BallotsStorage.contract'
|
import BallotsStorage from '../contracts/BallotsStorage.contract'
|
||||||
|
import EmissionFunds from '../contracts/EmissionFunds.contract'
|
||||||
import KeysManager from '../contracts/KeysManager.contract'
|
import KeysManager from '../contracts/KeysManager.contract'
|
||||||
import ProxyStorage from '../contracts/ProxyStorage.contract'
|
import ProxyStorage from '../contracts/ProxyStorage.contract'
|
||||||
import VotingToChangeKeys from '../contracts/VotingToChangeKeys.contract'
|
import VotingToChangeKeys from '../contracts/VotingToChangeKeys.contract'
|
||||||
import VotingToChangeMinThreshold from '../contracts/VotingToChangeMinThreshold.contract'
|
import VotingToChangeMinThreshold from '../contracts/VotingToChangeMinThreshold.contract'
|
||||||
import VotingToChangeProxy from '../contracts/VotingToChangeProxy.contract'
|
import VotingToChangeProxy from '../contracts/VotingToChangeProxy.contract'
|
||||||
|
import VotingToManageEmissionFunds from '../contracts/VotingToManageEmissionFunds.contract'
|
||||||
import ValidatorMetadata from '../contracts/ValidatorMetadata.contract'
|
import ValidatorMetadata from '../contracts/ValidatorMetadata.contract'
|
||||||
import ballotStore from './BallotStore'
|
import ballotStore from './BallotStore'
|
||||||
import ballotsStore from './BallotsStore'
|
import ballotsStore from './BallotsStore'
|
||||||
|
@ -15,6 +17,7 @@ import commonStore from './CommonStore'
|
||||||
import { BallotKeysCard } from '../components/BallotKeysCard.jsx'
|
import { BallotKeysCard } from '../components/BallotKeysCard.jsx'
|
||||||
import { BallotMinThresholdCard } from '../components/BallotMinThresholdCard.jsx'
|
import { BallotMinThresholdCard } from '../components/BallotMinThresholdCard.jsx'
|
||||||
import { BallotProxyCard } from '../components/BallotProxyCard.jsx'
|
import { BallotProxyCard } from '../components/BallotProxyCard.jsx'
|
||||||
|
import { BallotEmissionFundsCard } from '../components/BallotEmissionFundsCard.jsx'
|
||||||
import { constants } from '../constants'
|
import { constants } from '../constants'
|
||||||
|
|
||||||
import 'babel-polyfill'
|
import 'babel-polyfill'
|
||||||
|
@ -22,11 +25,13 @@ import 'babel-polyfill'
|
||||||
class ContractsStore {
|
class ContractsStore {
|
||||||
@observable poaConsensus
|
@observable poaConsensus
|
||||||
@observable ballotsStorage
|
@observable ballotsStorage
|
||||||
|
@observable emissionFunds
|
||||||
@observable keysManager
|
@observable keysManager
|
||||||
@observable proxyStorage
|
@observable proxyStorage
|
||||||
@observable votingToChangeKeys
|
@observable votingToChangeKeys
|
||||||
@observable votingToChangeMinThreshold
|
@observable votingToChangeMinThreshold
|
||||||
@observable votingToChangeProxy
|
@observable votingToChangeProxy
|
||||||
|
@observable votingToManageEmissionFunds
|
||||||
@observable validatorMetadata
|
@observable validatorMetadata
|
||||||
@observable votingKey
|
@observable votingKey
|
||||||
@observable miningKey
|
@observable miningKey
|
||||||
|
@ -55,18 +60,13 @@ class ContractsStore {
|
||||||
@action('Get keys ballot threshold')
|
@action('Get keys ballot threshold')
|
||||||
getKeysBallotThreshold = async () => {
|
getKeysBallotThreshold = async () => {
|
||||||
this.keysBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods.getBallotThreshold(1).call()
|
this.keysBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods.getBallotThreshold(1).call()
|
||||||
}
|
this.minThresholdBallotThreshold = this.keysBallotThreshold
|
||||||
|
|
||||||
@action('Get min threshold ballot threshold')
|
|
||||||
async getMinThresholdBallotThreshold() {
|
|
||||||
this.minThresholdBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods
|
|
||||||
.getBallotThreshold(1)
|
|
||||||
.call()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@action('Get proxy ballot threshold')
|
@action('Get proxy ballot threshold')
|
||||||
getProxyBallotThreshold = async () => {
|
getProxyBallotThreshold = async () => {
|
||||||
this.proxyBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods.getProxyThreshold().call()
|
this.proxyBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods.getProxyThreshold().call()
|
||||||
|
this.emissionFundsBallotThreshold = this.proxyBallotThreshold
|
||||||
}
|
}
|
||||||
|
|
||||||
@action('Set web3Instance')
|
@action('Set web3Instance')
|
||||||
|
@ -93,6 +93,15 @@ class ContractsStore {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action('Set EmissionFunds contract')
|
||||||
|
setEmissionFunds = async web3Config => {
|
||||||
|
this.emissionFunds = new EmissionFunds()
|
||||||
|
await this.emissionFunds.init({
|
||||||
|
web3: web3Config.web3Instance,
|
||||||
|
netId: web3Config.netId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
@action('Set KeysManager contract')
|
@action('Set KeysManager contract')
|
||||||
setKeysManager = async web3Config => {
|
setKeysManager = async web3Config => {
|
||||||
this.keysManager = new KeysManager()
|
this.keysManager = new KeysManager()
|
||||||
|
@ -138,6 +147,15 @@ class ContractsStore {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action('Set VotingToManageEmissionFunds contract')
|
||||||
|
setVotingToManageEmissionFunds = async web3Config => {
|
||||||
|
this.votingToManageEmissionFunds = new VotingToManageEmissionFunds()
|
||||||
|
await this.votingToManageEmissionFunds.init({
|
||||||
|
web3: web3Config.web3Instance,
|
||||||
|
netId: web3Config.netId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
@action('Set ValidatorMetadata contract')
|
@action('Set ValidatorMetadata contract')
|
||||||
setValidatorMetadata = async web3Config => {
|
setValidatorMetadata = async web3Config => {
|
||||||
this.validatorMetadata = new ValidatorMetadata()
|
this.validatorMetadata = new ValidatorMetadata()
|
||||||
|
@ -171,12 +189,19 @@ class ContractsStore {
|
||||||
getAllBallots = async () => {
|
getAllBallots = async () => {
|
||||||
let keysNextBallotId = 0,
|
let keysNextBallotId = 0,
|
||||||
minThresholdNextBallotId = 0,
|
minThresholdNextBallotId = 0,
|
||||||
proxyNextBallotId = 0
|
proxyNextBallotId = 0,
|
||||||
|
emissionFundsNextBallotId = 0
|
||||||
try {
|
try {
|
||||||
;[keysNextBallotId, minThresholdNextBallotId, proxyNextBallotId] = await this.getAllBallotsNextIDs()
|
;[
|
||||||
|
keysNextBallotId,
|
||||||
|
minThresholdNextBallotId,
|
||||||
|
proxyNextBallotId,
|
||||||
|
emissionFundsNextBallotId
|
||||||
|
] = await this.getAllBallotsNextIDs()
|
||||||
keysNextBallotId = Number(keysNextBallotId)
|
keysNextBallotId = Number(keysNextBallotId)
|
||||||
minThresholdNextBallotId = Number(minThresholdNextBallotId)
|
minThresholdNextBallotId = Number(minThresholdNextBallotId)
|
||||||
proxyNextBallotId = Number(proxyNextBallotId)
|
proxyNextBallotId = Number(proxyNextBallotId)
|
||||||
|
emissionFundsNextBallotId = Number(emissionFundsNextBallotId)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e.message)
|
console.log(e.message)
|
||||||
}
|
}
|
||||||
|
@ -184,10 +209,12 @@ class ContractsStore {
|
||||||
const allKeysPromise = this.getCards(keysNextBallotId, 'votingToChangeKeys')
|
const allKeysPromise = this.getCards(keysNextBallotId, 'votingToChangeKeys')
|
||||||
const allMinThresholdPromise = this.getCards(minThresholdNextBallotId, 'votingToChangeMinThreshold')
|
const allMinThresholdPromise = this.getCards(minThresholdNextBallotId, 'votingToChangeMinThreshold')
|
||||||
const allProxyPromise = this.getCards(proxyNextBallotId, 'votingToChangeProxy')
|
const allProxyPromise = this.getCards(proxyNextBallotId, 'votingToChangeProxy')
|
||||||
|
const allEmissionFundsPromise = this.getCards(emissionFundsNextBallotId, 'votingToManageEmissionFunds')
|
||||||
|
|
||||||
await Promise.all([allKeysPromise, allMinThresholdPromise, allProxyPromise])
|
await Promise.all([allKeysPromise, allMinThresholdPromise, allProxyPromise, allEmissionFundsPromise])
|
||||||
|
|
||||||
const allBallotsIDsLength = keysNextBallotId + minThresholdNextBallotId + proxyNextBallotId
|
const allBallotsIDsLength =
|
||||||
|
keysNextBallotId + minThresholdNextBallotId + proxyNextBallotId + emissionFundsNextBallotId
|
||||||
|
|
||||||
if (allBallotsIDsLength === 0) {
|
if (allBallotsIDsLength === 0) {
|
||||||
commonStore.hideLoading()
|
commonStore.hideLoading()
|
||||||
|
@ -315,6 +342,17 @@ class ContractsStore {
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
|
case 'votingToManageEmissionFunds':
|
||||||
|
card = (
|
||||||
|
<BallotEmissionFundsCard
|
||||||
|
id={id}
|
||||||
|
type={ballotStore.BallotType.emissionFunds}
|
||||||
|
key={ballotsStore.ballotCards.length}
|
||||||
|
pos={ballotsStore.ballotCards.length}
|
||||||
|
votingState={votingState}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -333,7 +371,10 @@ class ContractsStore {
|
||||||
const keysNextBallotId = this.votingToChangeKeys.nextBallotId()
|
const keysNextBallotId = this.votingToChangeKeys.nextBallotId()
|
||||||
const minThresholdNextBallotId = this.votingToChangeMinThreshold.nextBallotId()
|
const minThresholdNextBallotId = this.votingToChangeMinThreshold.nextBallotId()
|
||||||
const proxyNextBallotId = this.votingToChangeProxy.nextBallotId()
|
const proxyNextBallotId = this.votingToChangeProxy.nextBallotId()
|
||||||
return Promise.all([keysNextBallotId, minThresholdNextBallotId, proxyNextBallotId])
|
const emissionFundsNextBallotId = this.votingToManageEmissionFunds
|
||||||
|
? this.votingToManageEmissionFunds.nextBallotId()
|
||||||
|
: 0
|
||||||
|
return Promise.all([keysNextBallotId, minThresholdNextBallotId, proxyNextBallotId, emissionFundsNextBallotId])
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|
Loading…
Reference in New Issue