(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;
|
||||
margin: 0;
|
||||
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 REJECT = 2
|
||||
const SEND = 1
|
||||
const BURN = 2
|
||||
const FREEZE = 3
|
||||
const USDateTimeFormat = 'MM/DD/YYYY h:mm:ss A'
|
||||
const maxDetailsLength = 500
|
||||
|
||||
|
@ -102,6 +105,60 @@ export class BallotCard extends React.Component {
|
|||
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')
|
||||
calcTimeTo = () => {
|
||||
const _now = moment()
|
||||
|
@ -202,8 +259,18 @@ export class BallotCard extends React.Component {
|
|||
async tx => {
|
||||
const ballotInfo = await contract.getBallotInfo(id, contractsStore.votingKey)
|
||||
|
||||
if (ballotInfo.hasOwnProperty('totalVoters')) {
|
||||
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)
|
||||
if (ballotInfo.hasOwnProperty('canBeFinalizedNow')) {
|
||||
this.canBeFinalized = Boolean(ballotInfo.canBeFinalizedNow)
|
||||
|
@ -212,8 +279,16 @@ export class BallotCard extends React.Component {
|
|||
}
|
||||
this.hasAlreadyVoted = true
|
||||
|
||||
if (ballotInfo.hasOwnProperty('totalVoters')) {
|
||||
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.canBeFinalized = this.canBeFinalized
|
||||
ballotsStore.ballotCards[pos].props.votingState.hasAlreadyVoted = this.hasAlreadyVoted
|
||||
|
@ -315,6 +390,8 @@ export class BallotCard extends React.Component {
|
|||
return contractsStore.votingToChangeMinThreshold
|
||||
case 'votingToChangeProxy':
|
||||
return contractsStore.votingToChangeProxy
|
||||
case 'votingToManageEmissionFunds':
|
||||
return contractsStore.votingToManageEmissionFunds
|
||||
case 'validatorMetadata':
|
||||
return contractsStore.validatorMetadata
|
||||
default:
|
||||
|
@ -330,6 +407,8 @@ export class BallotCard extends React.Component {
|
|||
return contractsStore.minThresholdBallotThreshold
|
||||
case 'votingToChangeProxy':
|
||||
return contractsStore.proxyBallotThreshold
|
||||
case 'votingToManageEmissionFunds':
|
||||
return contractsStore.emissionFundsBallotThreshold
|
||||
default:
|
||||
return contractsStore.keysBallotThreshold
|
||||
}
|
||||
|
@ -346,9 +425,18 @@ export class BallotCard extends React.Component {
|
|||
this.creator = votingState.creator
|
||||
this.creatorMiningKey = votingState.creatorMiningKey
|
||||
// getTotalVoters
|
||||
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
|
||||
if (votingState.hasOwnProperty('progress')) {
|
||||
this.progress = Number(votingState.progress)
|
||||
}
|
||||
// getIsFinalized
|
||||
this.isFinalized = votingState.isFinalized
|
||||
// canBeFinalizedNow
|
||||
|
@ -397,6 +485,8 @@ export class BallotCard extends React.Component {
|
|||
return 'Keys'
|
||||
case 'votingToChangeProxy':
|
||||
return 'Proxy'
|
||||
case 'votingToManageEmissionFunds':
|
||||
return 'EmissionFunds'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
|
@ -425,66 +515,25 @@ export class BallotCard extends React.Component {
|
|||
) : (
|
||||
''
|
||||
)
|
||||
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>
|
||||
{/* 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>
|
||||
let votingScale
|
||||
if (votingType === 'votingToManageEmissionFunds') {
|
||||
votingScale = (
|
||||
<div className="ballots-i-scale">
|
||||
<div className="ballots-i-scale-column ballots-i-scale-column-3">
|
||||
<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"
|
||||
>
|
||||
Burn
|
||||
</button>
|
||||
<div className="vote-scale--container">
|
||||
<p className="vote-scale--votes">{this.votesAgainstNumber} Votes</p>
|
||||
<p className="vote-scale--percentage">{this.votesAgainstPercents}%</p>
|
||||
<p className="vote-scale--votes">{this.votesBurnNumber} Votes</p>
|
||||
<p className="vote-scale--percentage">{this.votesBurnPercents}%</p>
|
||||
<div className={voteScaleClass}>
|
||||
<div
|
||||
className="vote-scale--fill vote-scale--fill_burn"
|
||||
style={{ width: `${this.votesAgainstPercents}%` }}
|
||||
style={{ width: `${this.votesBurnPercents}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -492,24 +541,45 @@ export class BallotCard extends React.Component {
|
|||
<div className="ballots-i-scale-column ballots-i-scale-column-3">
|
||||
<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"
|
||||
>
|
||||
Freeze
|
||||
</button>
|
||||
<div className="vote-scale--container">
|
||||
<p className="vote-scale--votes">{this.votesAgainstNumber} Votes</p>
|
||||
<p className="vote-scale--percentage">{this.votesAgainstPercents}%</p>
|
||||
<p className="vote-scale--votes">{this.votesFreezeNumber} Votes</p>
|
||||
<p className="vote-scale--percentage">{this.votesFreezePercents}%</p>
|
||||
<div className={voteScaleClass}>
|
||||
<div
|
||||
className="vote-scale--fill vote-scale--fill_freeze"
|
||||
style={{ width: `${this.votesAgainstPercents}%` }}
|
||||
style={{ width: `${this.votesFreezePercents}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
{/* No / yes */}
|
||||
<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: 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-column">
|
||||
<button
|
||||
|
@ -547,6 +617,33 @@ export class BallotCard extends React.Component {
|
|||
</button>
|
||||
</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 info-minimum">
|
||||
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>
|
||||
{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>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -116,6 +116,14 @@ export class Ballots extends React.Component {
|
|||
) {
|
||||
continue
|
||||
}
|
||||
} else if (contractType === ballotStore.BallotType.emissionFunds) {
|
||||
if (
|
||||
String(votingState.receiver)
|
||||
.toLowerCase()
|
||||
.includes(searchTerm)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
ballotCards.splice(i--, 1)
|
||||
|
|
|
@ -7,6 +7,7 @@ import { KeysTypes } from './KeysTypes.jsx'
|
|||
import { BallotKeysMetadata } from './BallotKeysMetadata.jsx'
|
||||
import { BallotMinThresholdMetadata } from './BallotMinThresholdMetadata.jsx'
|
||||
import { BallotProxyMetadata } from './BallotProxyMetadata.jsx'
|
||||
import { BallotEmissionFundsMetadata } from './BallotEmissionFundsMetadata.jsx'
|
||||
import { messages } from '../messages'
|
||||
import { constants } from '../constants'
|
||||
import { sendTransactionByVotingKey } from '../helpers'
|
||||
|
@ -44,6 +45,7 @@ export class NewBallot extends React.Component {
|
|||
return false
|
||||
}
|
||||
|
||||
if (!ballotStore.isBallotForEmissionFunds) {
|
||||
const minBallotDurationInHours = constants.minBallotDurationInDays * 24
|
||||
const startTime = this.getStartTimeUnix()
|
||||
const minEndTime = moment
|
||||
|
@ -79,6 +81,7 @@ export class NewBallot extends React.Component {
|
|||
commonStore.hideLoading()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if (ballotStore.isBallotForKey) {
|
||||
for (let ballotKeysProp in ballotStore.ballotKeys) {
|
||||
|
@ -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) {
|
||||
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')
|
||||
commonStore.hideLoading()
|
||||
return false
|
||||
|
@ -150,11 +174,11 @@ export class NewBallot extends React.Component {
|
|||
return true
|
||||
}
|
||||
|
||||
createBallotForKeys = startTime => {
|
||||
createBallotForKeys = (startTime, endTime) => {
|
||||
const { ballotStore, contractsStore } = this.props
|
||||
const inputToMethod = {
|
||||
startTime: startTime,
|
||||
endTime: ballotStore.endTimeUnix,
|
||||
endTime: endTime,
|
||||
affectedKey: ballotStore.ballotKeys.affectedKey,
|
||||
affectedKeyType: ballotStore.ballotKeys.keyType,
|
||||
newVotingKey: ballotStore.ballotKeys.newVotingKey,
|
||||
|
@ -176,22 +200,22 @@ export class NewBallot extends React.Component {
|
|||
return data
|
||||
}
|
||||
|
||||
createBallotForMinThreshold = startTime => {
|
||||
createBallotForMinThreshold = (startTime, endTime) => {
|
||||
const { ballotStore, contractsStore } = this.props
|
||||
const inputToMethod = {
|
||||
startTime: startTime,
|
||||
endTime: ballotStore.endTimeUnix,
|
||||
endTime: endTime,
|
||||
proposedValue: ballotStore.ballotMinThreshold.proposedValue,
|
||||
memo: ballotStore.memo
|
||||
}
|
||||
return contractsStore.votingToChangeMinThreshold.createBallot(inputToMethod)
|
||||
}
|
||||
|
||||
createBallotForProxy = startTime => {
|
||||
createBallotForProxy = (startTime, endTime) => {
|
||||
const { ballotStore, contractsStore } = this.props
|
||||
const inputToMethod = {
|
||||
startTime: startTime,
|
||||
endTime: ballotStore.endTimeUnix,
|
||||
endTime: endTime,
|
||||
proposedValue: ballotStore.ballotProxy.proposedAddress,
|
||||
contractType: ballotStore.ballotProxy.contractType,
|
||||
memo: ballotStore.memo
|
||||
|
@ -199,6 +223,17 @@ export class NewBallot extends React.Component {
|
|||
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 () => {
|
||||
const { commonStore, contractsStore, ballotStore, ballotsStore } = this.props
|
||||
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 contractType
|
||||
let contractInstance
|
||||
|
@ -259,16 +330,19 @@ export class NewBallot extends React.Component {
|
|||
contractType = 'votingToChangeProxy'
|
||||
contractInstance = contractsStore.votingToChangeProxy.votingToChangeProxyInstance
|
||||
break
|
||||
case ballotStore.BallotType.emissionFunds:
|
||||
methodToCreateBallot = this.createBallotForEmissionFunds
|
||||
contractType = 'votingToManageEmissionFunds'
|
||||
contractInstance = contractsStore.votingToManageEmissionFunds.instance
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
const startTime = this.getStartTimeUnix()
|
||||
|
||||
sendTransactionByVotingKey(
|
||||
this.props,
|
||||
contractInstance.options.address,
|
||||
methodToCreateBallot(startTime),
|
||||
methodToCreateBallot(startTime, endTime),
|
||||
async tx => {
|
||||
const events = await contractInstance.getPastEvents('BallotCreated', {
|
||||
fromBlock: tx.blockNumber,
|
||||
|
@ -322,9 +396,23 @@ export class NewBallot extends React.Component {
|
|||
metadata = <BallotProxyMetadata />
|
||||
minThreshold = contractsStore.proxyBallotThreshold
|
||||
break
|
||||
case ballotStore.BallotType.emissionFunds:
|
||||
metadata = <BallotEmissionFundsMetadata />
|
||||
minThreshold = contractsStore.emissionFundsBallotThreshold
|
||||
break
|
||||
default:
|
||||
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 (
|
||||
<section className="container new">
|
||||
<form action="" className="new-form">
|
||||
|
@ -348,12 +436,13 @@ export class NewBallot extends React.Component {
|
|||
>
|
||||
Modify Proxy Contract Ballot
|
||||
</div>
|
||||
{emissionFundsManagementBallot}
|
||||
</div>
|
||||
<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">
|
||||
Minimum {minThreshold} from {contractsStore.validatorsLength}
|
||||
validators are required to pass the proposal<br />
|
||||
Minimum {minThreshold} from {contractsStore.validatorsLength} validators are required to pass the
|
||||
proposal<br />
|
||||
</div>
|
||||
<div className="info-i">
|
||||
You can create {contractsStore.validatorLimits.keys} ballot(s) for keys<br />
|
||||
|
|
|
@ -6,11 +6,13 @@ constants.ABIsSources = {
|
|||
KeysManager: 'KeysManager.abi.json',
|
||||
PoaNetworkConsensus: 'PoaNetworkConsensus.abi.json',
|
||||
BallotStorage: 'BallotsStorage.abi.json',
|
||||
EmissionFunds: 'EmissionFunds.abi.json',
|
||||
ProxyStorage: 'ProxyStorage.abi.json',
|
||||
ValidatorMetadata: 'ValidatorMetadata.abi.json',
|
||||
VotingToChangeKeys: 'VotingToChangeKeys.abi.json',
|
||||
VotingToChangeMinThreshold: 'VotingToChangeMinThreshold.abi.json',
|
||||
VotingToChangeProxyAddress: 'VotingToChangeProxyAddress.abi.json'
|
||||
VotingToChangeProxyAddress: 'VotingToChangeProxyAddress.abi.json',
|
||||
VotingToManageEmissionFunds: 'VotingToManageEmissionFunds.abi.json'
|
||||
}
|
||||
constants.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 setValidatorMetadata = contractsStore.setValidatorMetadata(web3Config)
|
||||
|
||||
await Promise.all([
|
||||
let promises = [
|
||||
setPoaConsensus,
|
||||
setBallotsStorage,
|
||||
setKeysManager,
|
||||
|
@ -58,7 +58,15 @@ class AppMainRouter extends Component {
|
|||
setVotingToChangeMinThreshold,
|
||||
setVotingToChangeProxy,
|
||||
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.setVotingKey(web3Config)
|
||||
|
@ -67,7 +75,6 @@ class AppMainRouter extends Component {
|
|||
await contractsStore.getAllBallots()
|
||||
|
||||
contractsStore.getKeysBallotThreshold()
|
||||
contractsStore.getMinThresholdBallotThreshold()
|
||||
contractsStore.getProxyBallotThreshold()
|
||||
contractsStore.getBallotsLimits()
|
||||
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.AFFECTED_KEY_IS_NOT_ADDRESS_MSG = "Ballot affectedKey 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.BALLOT_TYPE_IS_EMPTY_MSG = 'Ballot type is empty'
|
||||
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 => {
|
||||
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.
|
||||
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.
|
||||
|
|
|
@ -6,7 +6,8 @@ class BallotStore {
|
|||
BallotType = {
|
||||
keys: 1,
|
||||
minThreshold: 2,
|
||||
proxy: 3
|
||||
proxy: 3,
|
||||
emissionFunds: 4
|
||||
}
|
||||
KeysBallotType = {
|
||||
add: 1,
|
||||
|
@ -34,6 +35,8 @@ class BallotStore {
|
|||
@observable ballotKeys
|
||||
@observable ballotMinThreshold
|
||||
@observable ballotProxy
|
||||
@observable ballotEmissionFunds
|
||||
|
||||
@observable memo
|
||||
|
||||
constructor() {
|
||||
|
@ -59,6 +62,11 @@ class BallotStore {
|
|||
proposedAddress: '',
|
||||
contractType: ''
|
||||
}
|
||||
|
||||
this.ballotEmissionFunds = {
|
||||
receiver: ''
|
||||
}
|
||||
|
||||
this.memo = ''
|
||||
}
|
||||
|
||||
|
@ -83,6 +91,11 @@ class BallotStore {
|
|||
return this.ballotType === this.BallotType.proxy
|
||||
}
|
||||
|
||||
@computed
|
||||
get isBallotForEmissionFunds() {
|
||||
return this.ballotType === this.BallotType.emissionFunds
|
||||
}
|
||||
|
||||
@computed
|
||||
get isAddKeysBallotType() {
|
||||
return this.ballotKeys.keysBallotType === this.KeysBallotType.add
|
||||
|
|
|
@ -1,21 +1,9 @@
|
|||
import { observable } from 'mobx'
|
||||
|
||||
class BallotsStore {
|
||||
@observable activeKeysBallotsLength
|
||||
@observable activeMinThresholdBallotsLength
|
||||
@observable activeProxyBallotsLength
|
||||
@observable ballotCards
|
||||
|
||||
@observable activeMinThresholdBallotsIDs
|
||||
@observable activeProxyBallotsIDs
|
||||
|
||||
constructor() {
|
||||
this.activeKeysBallotsLength = 0
|
||||
this.activeMinThresholdBallotsLength = 0
|
||||
this.activeProxyBallotsLength = 0
|
||||
|
||||
this.activeMinThresholdBallotsIDs = []
|
||||
this.activeProxyBallotsIDs = []
|
||||
this.ballotCards = []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,13 @@ import React from 'react'
|
|||
|
||||
import PoaConsensus from '../contracts/PoaConsensus.contract'
|
||||
import BallotsStorage from '../contracts/BallotsStorage.contract'
|
||||
import EmissionFunds from '../contracts/EmissionFunds.contract'
|
||||
import KeysManager from '../contracts/KeysManager.contract'
|
||||
import ProxyStorage from '../contracts/ProxyStorage.contract'
|
||||
import VotingToChangeKeys from '../contracts/VotingToChangeKeys.contract'
|
||||
import VotingToChangeMinThreshold from '../contracts/VotingToChangeMinThreshold.contract'
|
||||
import VotingToChangeProxy from '../contracts/VotingToChangeProxy.contract'
|
||||
import VotingToManageEmissionFunds from '../contracts/VotingToManageEmissionFunds.contract'
|
||||
import ValidatorMetadata from '../contracts/ValidatorMetadata.contract'
|
||||
import ballotStore from './BallotStore'
|
||||
import ballotsStore from './BallotsStore'
|
||||
|
@ -15,6 +17,7 @@ import commonStore from './CommonStore'
|
|||
import { BallotKeysCard } from '../components/BallotKeysCard.jsx'
|
||||
import { BallotMinThresholdCard } from '../components/BallotMinThresholdCard.jsx'
|
||||
import { BallotProxyCard } from '../components/BallotProxyCard.jsx'
|
||||
import { BallotEmissionFundsCard } from '../components/BallotEmissionFundsCard.jsx'
|
||||
import { constants } from '../constants'
|
||||
|
||||
import 'babel-polyfill'
|
||||
|
@ -22,11 +25,13 @@ import 'babel-polyfill'
|
|||
class ContractsStore {
|
||||
@observable poaConsensus
|
||||
@observable ballotsStorage
|
||||
@observable emissionFunds
|
||||
@observable keysManager
|
||||
@observable proxyStorage
|
||||
@observable votingToChangeKeys
|
||||
@observable votingToChangeMinThreshold
|
||||
@observable votingToChangeProxy
|
||||
@observable votingToManageEmissionFunds
|
||||
@observable validatorMetadata
|
||||
@observable votingKey
|
||||
@observable miningKey
|
||||
|
@ -55,18 +60,13 @@ class ContractsStore {
|
|||
@action('Get keys ballot threshold')
|
||||
getKeysBallotThreshold = async () => {
|
||||
this.keysBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods.getBallotThreshold(1).call()
|
||||
}
|
||||
|
||||
@action('Get min threshold ballot threshold')
|
||||
async getMinThresholdBallotThreshold() {
|
||||
this.minThresholdBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods
|
||||
.getBallotThreshold(1)
|
||||
.call()
|
||||
this.minThresholdBallotThreshold = this.keysBallotThreshold
|
||||
}
|
||||
|
||||
@action('Get proxy ballot threshold')
|
||||
getProxyBallotThreshold = async () => {
|
||||
this.proxyBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods.getProxyThreshold().call()
|
||||
this.emissionFundsBallotThreshold = this.proxyBallotThreshold
|
||||
}
|
||||
|
||||
@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')
|
||||
setKeysManager = async web3Config => {
|
||||
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')
|
||||
setValidatorMetadata = async web3Config => {
|
||||
this.validatorMetadata = new ValidatorMetadata()
|
||||
|
@ -171,12 +189,19 @@ class ContractsStore {
|
|||
getAllBallots = async () => {
|
||||
let keysNextBallotId = 0,
|
||||
minThresholdNextBallotId = 0,
|
||||
proxyNextBallotId = 0
|
||||
proxyNextBallotId = 0,
|
||||
emissionFundsNextBallotId = 0
|
||||
try {
|
||||
;[keysNextBallotId, minThresholdNextBallotId, proxyNextBallotId] = await this.getAllBallotsNextIDs()
|
||||
;[
|
||||
keysNextBallotId,
|
||||
minThresholdNextBallotId,
|
||||
proxyNextBallotId,
|
||||
emissionFundsNextBallotId
|
||||
] = await this.getAllBallotsNextIDs()
|
||||
keysNextBallotId = Number(keysNextBallotId)
|
||||
minThresholdNextBallotId = Number(minThresholdNextBallotId)
|
||||
proxyNextBallotId = Number(proxyNextBallotId)
|
||||
emissionFundsNextBallotId = Number(emissionFundsNextBallotId)
|
||||
} catch (e) {
|
||||
console.log(e.message)
|
||||
}
|
||||
|
@ -184,10 +209,12 @@ class ContractsStore {
|
|||
const allKeysPromise = this.getCards(keysNextBallotId, 'votingToChangeKeys')
|
||||
const allMinThresholdPromise = this.getCards(minThresholdNextBallotId, 'votingToChangeMinThreshold')
|
||||
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) {
|
||||
commonStore.hideLoading()
|
||||
|
@ -315,6 +342,17 @@ class ContractsStore {
|
|||
/>
|
||||
)
|
||||
break
|
||||
case 'votingToManageEmissionFunds':
|
||||
card = (
|
||||
<BallotEmissionFundsCard
|
||||
id={id}
|
||||
type={ballotStore.BallotType.emissionFunds}
|
||||
key={ballotsStore.ballotCards.length}
|
||||
pos={ballotsStore.ballotCards.length}
|
||||
votingState={votingState}
|
||||
/>
|
||||
)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
@ -333,7 +371,10 @@ class ContractsStore {
|
|||
const keysNextBallotId = this.votingToChangeKeys.nextBallotId()
|
||||
const minThresholdNextBallotId = this.votingToChangeMinThreshold.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
|
||||
|
|
Loading…
Reference in New Issue